hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mailbox/tegra-hsp.c
....@@ -1,25 +1,32 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
2
- * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms and conditions of the GNU General Public License,
6
- * version 2, as published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11
- * more details.
3
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
124 */
135
6
+#include <linux/delay.h>
147 #include <linux/interrupt.h>
158 #include <linux/io.h>
169 #include <linux/mailbox_controller.h>
1710 #include <linux/of.h>
1811 #include <linux/of_device.h>
1912 #include <linux/platform_device.h>
13
+#include <linux/pm.h>
2014 #include <linux/slab.h>
2115
16
+#include <soc/tegra/fuse.h>
17
+
2218 #include <dt-bindings/mailbox/tegra186-hsp.h>
19
+
20
+#include "mailbox.h"
21
+
22
+#define HSP_INT_IE(x) (0x100 + ((x) * 4))
23
+#define HSP_INT_IV 0x300
24
+#define HSP_INT_IR 0x304
25
+
26
+#define HSP_INT_EMPTY_SHIFT 0
27
+#define HSP_INT_EMPTY_MASK 0xff
28
+#define HSP_INT_FULL_SHIFT 8
29
+#define HSP_INT_FULL_MASK 0xff
2330
2431 #define HSP_INT_DIMENSIONING 0x380
2532 #define HSP_nSM_SHIFT 0
....@@ -33,6 +40,11 @@
3340 #define HSP_DB_ENABLE 0x4
3441 #define HSP_DB_RAW 0x8
3542 #define HSP_DB_PENDING 0xc
43
+
44
+#define HSP_SM_SHRD_MBOX 0x0
45
+#define HSP_SM_SHRD_MBOX_FULL BIT(31)
46
+#define HSP_SM_SHRD_MBOX_FULL_INT_IE 0x04
47
+#define HSP_SM_SHRD_MBOX_EMPTY_INT_IE 0x08
3648
3749 #define HSP_DB_CCPLEX 1
3850 #define HSP_DB_BPMP 3
....@@ -55,6 +67,12 @@
5567 unsigned int index;
5668 };
5769
70
+struct tegra_hsp_mailbox {
71
+ struct tegra_hsp_channel channel;
72
+ unsigned int index;
73
+ bool producer;
74
+};
75
+
5876 struct tegra_hsp_db_map {
5977 const char *name;
6078 unsigned int master;
....@@ -63,13 +81,18 @@
6381
6482 struct tegra_hsp_soc {
6583 const struct tegra_hsp_db_map *map;
84
+ bool has_per_mb_ie;
6685 };
6786
6887 struct tegra_hsp {
88
+ struct device *dev;
6989 const struct tegra_hsp_soc *soc;
70
- struct mbox_controller mbox;
90
+ struct mbox_controller mbox_db;
91
+ struct mbox_controller mbox_sm;
7192 void __iomem *regs;
72
- unsigned int irq;
93
+ unsigned int doorbell_irq;
94
+ unsigned int *shared_irqs;
95
+ unsigned int shared_irq;
7396 unsigned int num_sm;
7497 unsigned int num_as;
7598 unsigned int num_ss;
....@@ -78,13 +101,10 @@
78101 spinlock_t lock;
79102
80103 struct list_head doorbells;
81
-};
104
+ struct tegra_hsp_mailbox *mailboxes;
82105
83
-static inline struct tegra_hsp *
84
-to_tegra_hsp(struct mbox_controller *mbox)
85
-{
86
- return container_of(mbox, struct tegra_hsp, mbox);
87
-}
106
+ unsigned long mask;
107
+};
88108
89109 static inline u32 tegra_hsp_readl(struct tegra_hsp *hsp, unsigned int offset)
90110 {
....@@ -158,7 +178,7 @@
158178
159179 spin_lock(&hsp->lock);
160180
161
- for_each_set_bit(master, &value, hsp->mbox.num_chans) {
181
+ for_each_set_bit(master, &value, hsp->mbox_db.num_chans) {
162182 struct tegra_hsp_doorbell *db;
163183
164184 db = __tegra_hsp_doorbell_get(hsp, master);
....@@ -182,6 +202,71 @@
182202 return IRQ_HANDLED;
183203 }
184204
205
+static irqreturn_t tegra_hsp_shared_irq(int irq, void *data)
206
+{
207
+ struct tegra_hsp *hsp = data;
208
+ unsigned long bit, mask;
209
+ u32 status, value;
210
+ void *msg;
211
+
212
+ status = tegra_hsp_readl(hsp, HSP_INT_IR) & hsp->mask;
213
+
214
+ /* process EMPTY interrupts first */
215
+ mask = (status >> HSP_INT_EMPTY_SHIFT) & HSP_INT_EMPTY_MASK;
216
+
217
+ for_each_set_bit(bit, &mask, hsp->num_sm) {
218
+ struct tegra_hsp_mailbox *mb = &hsp->mailboxes[bit];
219
+
220
+ if (mb->producer) {
221
+ /*
222
+ * Disable EMPTY interrupts until data is sent with
223
+ * the next message. These interrupts are level-
224
+ * triggered, so if we kept them enabled they would
225
+ * constantly trigger until we next write data into
226
+ * the message.
227
+ */
228
+ spin_lock(&hsp->lock);
229
+
230
+ hsp->mask &= ~BIT(HSP_INT_EMPTY_SHIFT + mb->index);
231
+ tegra_hsp_writel(hsp, hsp->mask,
232
+ HSP_INT_IE(hsp->shared_irq));
233
+
234
+ spin_unlock(&hsp->lock);
235
+
236
+ mbox_chan_txdone(mb->channel.chan, 0);
237
+ }
238
+ }
239
+
240
+ /* process FULL interrupts */
241
+ mask = (status >> HSP_INT_FULL_SHIFT) & HSP_INT_FULL_MASK;
242
+
243
+ for_each_set_bit(bit, &mask, hsp->num_sm) {
244
+ struct tegra_hsp_mailbox *mb = &hsp->mailboxes[bit];
245
+
246
+ if (!mb->producer) {
247
+ value = tegra_hsp_channel_readl(&mb->channel,
248
+ HSP_SM_SHRD_MBOX);
249
+ value &= ~HSP_SM_SHRD_MBOX_FULL;
250
+ msg = (void *)(unsigned long)value;
251
+ mbox_chan_received_data(mb->channel.chan, msg);
252
+
253
+ /*
254
+ * Need to clear all bits here since some producers,
255
+ * such as TCU, depend on fields in the register
256
+ * getting cleared by the consumer.
257
+ *
258
+ * The mailbox API doesn't give the consumers a way
259
+ * of doing that explicitly, so we have to make sure
260
+ * we cover all possible cases.
261
+ */
262
+ tegra_hsp_channel_writel(&mb->channel, 0x0,
263
+ HSP_SM_SHRD_MBOX);
264
+ }
265
+ }
266
+
267
+ return IRQ_HANDLED;
268
+}
269
+
185270 static struct tegra_hsp_channel *
186271 tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
187272 unsigned int master, unsigned int index)
....@@ -190,17 +275,17 @@
190275 unsigned int offset;
191276 unsigned long flags;
192277
193
- db = kzalloc(sizeof(*db), GFP_KERNEL);
278
+ db = devm_kzalloc(hsp->dev, sizeof(*db), GFP_KERNEL);
194279 if (!db)
195280 return ERR_PTR(-ENOMEM);
196281
197
- offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) << 16;
282
+ offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) * SZ_64K;
198283 offset += index * 0x100;
199284
200285 db->channel.regs = hsp->regs + offset;
201286 db->channel.hsp = hsp;
202287
203
- db->name = kstrdup_const(name, GFP_KERNEL);
288
+ db->name = devm_kstrdup_const(hsp->dev, name, GFP_KERNEL);
204289 db->master = master;
205290 db->index = index;
206291
....@@ -209,13 +294,6 @@
209294 spin_unlock_irqrestore(&hsp->lock, flags);
210295
211296 return &db->channel;
212
-}
213
-
214
-static void __tegra_hsp_doorbell_destroy(struct tegra_hsp_doorbell *db)
215
-{
216
- list_del(&db->list);
217
- kfree_const(db->name);
218
- kfree(db);
219297 }
220298
221299 static int tegra_hsp_doorbell_send_data(struct mbox_chan *chan, void *data)
....@@ -235,8 +313,8 @@
235313 unsigned long flags;
236314 u32 value;
237315
238
- if (db->master >= hsp->mbox.num_chans) {
239
- dev_err(hsp->mbox.dev,
316
+ if (db->master >= chan->mbox->num_chans) {
317
+ dev_err(chan->mbox->dev,
240318 "invalid master ID %u for HSP channel\n",
241319 db->master);
242320 return -EINVAL;
....@@ -246,7 +324,12 @@
246324 if (!ccplex)
247325 return -ENODEV;
248326
249
- if (!tegra_hsp_doorbell_can_ring(db))
327
+ /*
328
+ * On simulation platforms the BPMP hasn't had a chance yet to mark
329
+ * the doorbell as ringable by the CCPLEX, so we want to skip extra
330
+ * checks here.
331
+ */
332
+ if (tegra_is_silicon() && !tegra_hsp_doorbell_can_ring(db))
250333 return -ENODEV;
251334
252335 spin_lock_irqsave(&hsp->lock, flags);
....@@ -281,46 +364,172 @@
281364 spin_unlock_irqrestore(&hsp->lock, flags);
282365 }
283366
284
-static const struct mbox_chan_ops tegra_hsp_doorbell_ops = {
367
+static const struct mbox_chan_ops tegra_hsp_db_ops = {
285368 .send_data = tegra_hsp_doorbell_send_data,
286369 .startup = tegra_hsp_doorbell_startup,
287370 .shutdown = tegra_hsp_doorbell_shutdown,
288371 };
289372
290
-static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
373
+static int tegra_hsp_mailbox_send_data(struct mbox_chan *chan, void *data)
374
+{
375
+ struct tegra_hsp_mailbox *mb = chan->con_priv;
376
+ struct tegra_hsp *hsp = mb->channel.hsp;
377
+ unsigned long flags;
378
+ u32 value;
379
+
380
+ if (WARN_ON(!mb->producer))
381
+ return -EPERM;
382
+
383
+ /* copy data and mark mailbox full */
384
+ value = (u32)(unsigned long)data;
385
+ value |= HSP_SM_SHRD_MBOX_FULL;
386
+
387
+ tegra_hsp_channel_writel(&mb->channel, value, HSP_SM_SHRD_MBOX);
388
+
389
+ /* enable EMPTY interrupt for the shared mailbox */
390
+ spin_lock_irqsave(&hsp->lock, flags);
391
+
392
+ hsp->mask |= BIT(HSP_INT_EMPTY_SHIFT + mb->index);
393
+ tegra_hsp_writel(hsp, hsp->mask, HSP_INT_IE(hsp->shared_irq));
394
+
395
+ spin_unlock_irqrestore(&hsp->lock, flags);
396
+
397
+ return 0;
398
+}
399
+
400
+static int tegra_hsp_mailbox_flush(struct mbox_chan *chan,
401
+ unsigned long timeout)
402
+{
403
+ struct tegra_hsp_mailbox *mb = chan->con_priv;
404
+ struct tegra_hsp_channel *ch = &mb->channel;
405
+ u32 value;
406
+
407
+ timeout = jiffies + msecs_to_jiffies(timeout);
408
+
409
+ while (time_before(jiffies, timeout)) {
410
+ value = tegra_hsp_channel_readl(ch, HSP_SM_SHRD_MBOX);
411
+ if ((value & HSP_SM_SHRD_MBOX_FULL) == 0) {
412
+ mbox_chan_txdone(chan, 0);
413
+
414
+ /* Wait until channel is empty */
415
+ if (chan->active_req != NULL)
416
+ continue;
417
+
418
+ return 0;
419
+ }
420
+
421
+ udelay(1);
422
+ }
423
+
424
+ return -ETIME;
425
+}
426
+
427
+static int tegra_hsp_mailbox_startup(struct mbox_chan *chan)
428
+{
429
+ struct tegra_hsp_mailbox *mb = chan->con_priv;
430
+ struct tegra_hsp_channel *ch = &mb->channel;
431
+ struct tegra_hsp *hsp = mb->channel.hsp;
432
+ unsigned long flags;
433
+
434
+ chan->txdone_method = TXDONE_BY_IRQ;
435
+
436
+ /*
437
+ * Shared mailboxes start out as consumers by default. FULL and EMPTY
438
+ * interrupts are coalesced at the same shared interrupt.
439
+ *
440
+ * Keep EMPTY interrupts disabled at startup and only enable them when
441
+ * the mailbox is actually full. This is required because the FULL and
442
+ * EMPTY interrupts are level-triggered, so keeping EMPTY interrupts
443
+ * enabled all the time would cause an interrupt storm while mailboxes
444
+ * are idle.
445
+ */
446
+
447
+ spin_lock_irqsave(&hsp->lock, flags);
448
+
449
+ if (mb->producer)
450
+ hsp->mask &= ~BIT(HSP_INT_EMPTY_SHIFT + mb->index);
451
+ else
452
+ hsp->mask |= BIT(HSP_INT_FULL_SHIFT + mb->index);
453
+
454
+ tegra_hsp_writel(hsp, hsp->mask, HSP_INT_IE(hsp->shared_irq));
455
+
456
+ spin_unlock_irqrestore(&hsp->lock, flags);
457
+
458
+ if (hsp->soc->has_per_mb_ie) {
459
+ if (mb->producer)
460
+ tegra_hsp_channel_writel(ch, 0x0,
461
+ HSP_SM_SHRD_MBOX_EMPTY_INT_IE);
462
+ else
463
+ tegra_hsp_channel_writel(ch, 0x1,
464
+ HSP_SM_SHRD_MBOX_FULL_INT_IE);
465
+ }
466
+
467
+ return 0;
468
+}
469
+
470
+static void tegra_hsp_mailbox_shutdown(struct mbox_chan *chan)
471
+{
472
+ struct tegra_hsp_mailbox *mb = chan->con_priv;
473
+ struct tegra_hsp_channel *ch = &mb->channel;
474
+ struct tegra_hsp *hsp = mb->channel.hsp;
475
+ unsigned long flags;
476
+
477
+ if (hsp->soc->has_per_mb_ie) {
478
+ if (mb->producer)
479
+ tegra_hsp_channel_writel(ch, 0x0,
480
+ HSP_SM_SHRD_MBOX_EMPTY_INT_IE);
481
+ else
482
+ tegra_hsp_channel_writel(ch, 0x0,
483
+ HSP_SM_SHRD_MBOX_FULL_INT_IE);
484
+ }
485
+
486
+ spin_lock_irqsave(&hsp->lock, flags);
487
+
488
+ if (mb->producer)
489
+ hsp->mask &= ~BIT(HSP_INT_EMPTY_SHIFT + mb->index);
490
+ else
491
+ hsp->mask &= ~BIT(HSP_INT_FULL_SHIFT + mb->index);
492
+
493
+ tegra_hsp_writel(hsp, hsp->mask, HSP_INT_IE(hsp->shared_irq));
494
+
495
+ spin_unlock_irqrestore(&hsp->lock, flags);
496
+}
497
+
498
+static const struct mbox_chan_ops tegra_hsp_sm_ops = {
499
+ .send_data = tegra_hsp_mailbox_send_data,
500
+ .flush = tegra_hsp_mailbox_flush,
501
+ .startup = tegra_hsp_mailbox_startup,
502
+ .shutdown = tegra_hsp_mailbox_shutdown,
503
+};
504
+
505
+static struct mbox_chan *tegra_hsp_db_xlate(struct mbox_controller *mbox,
291506 const struct of_phandle_args *args)
292507 {
508
+ struct tegra_hsp *hsp = container_of(mbox, struct tegra_hsp, mbox_db);
509
+ unsigned int type = args->args[0], master = args->args[1];
293510 struct tegra_hsp_channel *channel = ERR_PTR(-ENODEV);
294
- struct tegra_hsp *hsp = to_tegra_hsp(mbox);
295
- unsigned int type = args->args[0];
296
- unsigned int master = args->args[1];
297511 struct tegra_hsp_doorbell *db;
298512 struct mbox_chan *chan;
299513 unsigned long flags;
300514 unsigned int i;
301515
302
- switch (type) {
303
- case TEGRA_HSP_MBOX_TYPE_DB:
304
- db = tegra_hsp_doorbell_get(hsp, master);
305
- if (db)
306
- channel = &db->channel;
516
+ if (type != TEGRA_HSP_MBOX_TYPE_DB || !hsp->doorbell_irq)
517
+ return ERR_PTR(-ENODEV);
307518
308
- break;
309
-
310
- default:
311
- break;
312
- }
519
+ db = tegra_hsp_doorbell_get(hsp, master);
520
+ if (db)
521
+ channel = &db->channel;
313522
314523 if (IS_ERR(channel))
315524 return ERR_CAST(channel);
316525
317526 spin_lock_irqsave(&hsp->lock, flags);
318527
319
- for (i = 0; i < hsp->mbox.num_chans; i++) {
320
- chan = &hsp->mbox.chans[i];
528
+ for (i = 0; i < mbox->num_chans; i++) {
529
+ chan = &mbox->chans[i];
321530 if (!chan->con_priv) {
322
- chan->con_priv = channel;
323531 channel->chan = chan;
532
+ chan->con_priv = db;
324533 break;
325534 }
326535
....@@ -332,17 +541,27 @@
332541 return chan ?: ERR_PTR(-EBUSY);
333542 }
334543
335
-static void tegra_hsp_remove_doorbells(struct tegra_hsp *hsp)
544
+static struct mbox_chan *tegra_hsp_sm_xlate(struct mbox_controller *mbox,
545
+ const struct of_phandle_args *args)
336546 {
337
- struct tegra_hsp_doorbell *db, *tmp;
338
- unsigned long flags;
547
+ struct tegra_hsp *hsp = container_of(mbox, struct tegra_hsp, mbox_sm);
548
+ unsigned int type = args->args[0], index;
549
+ struct tegra_hsp_mailbox *mb;
339550
340
- spin_lock_irqsave(&hsp->lock, flags);
551
+ index = args->args[1] & TEGRA_HSP_SM_MASK;
341552
342
- list_for_each_entry_safe(db, tmp, &hsp->doorbells, list)
343
- __tegra_hsp_doorbell_destroy(db);
553
+ if (type != TEGRA_HSP_MBOX_TYPE_SM || !hsp->shared_irqs ||
554
+ index >= hsp->num_sm)
555
+ return ERR_PTR(-ENODEV);
344556
345
- spin_unlock_irqrestore(&hsp->lock, flags);
557
+ mb = &hsp->mailboxes[index];
558
+
559
+ if ((args->args[1] & TEGRA_HSP_SM_FLAG_TX) == 0)
560
+ mb->producer = false;
561
+ else
562
+ mb->producer = true;
563
+
564
+ return mb->channel.chan;
346565 }
347566
348567 static int tegra_hsp_add_doorbells(struct tegra_hsp *hsp)
....@@ -353,12 +572,69 @@
353572 while (map->name) {
354573 channel = tegra_hsp_doorbell_create(hsp, map->name,
355574 map->master, map->index);
356
- if (IS_ERR(channel)) {
357
- tegra_hsp_remove_doorbells(hsp);
575
+ if (IS_ERR(channel))
358576 return PTR_ERR(channel);
359
- }
360577
361578 map++;
579
+ }
580
+
581
+ return 0;
582
+}
583
+
584
+static int tegra_hsp_add_mailboxes(struct tegra_hsp *hsp, struct device *dev)
585
+{
586
+ int i;
587
+
588
+ hsp->mailboxes = devm_kcalloc(dev, hsp->num_sm, sizeof(*hsp->mailboxes),
589
+ GFP_KERNEL);
590
+ if (!hsp->mailboxes)
591
+ return -ENOMEM;
592
+
593
+ for (i = 0; i < hsp->num_sm; i++) {
594
+ struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i];
595
+
596
+ mb->index = i;
597
+
598
+ mb->channel.hsp = hsp;
599
+ mb->channel.regs = hsp->regs + SZ_64K + i * SZ_32K;
600
+ mb->channel.chan = &hsp->mbox_sm.chans[i];
601
+ mb->channel.chan->con_priv = mb;
602
+ }
603
+
604
+ return 0;
605
+}
606
+
607
+static int tegra_hsp_request_shared_irq(struct tegra_hsp *hsp)
608
+{
609
+ unsigned int i, irq = 0;
610
+ int err;
611
+
612
+ for (i = 0; i < hsp->num_si; i++) {
613
+ irq = hsp->shared_irqs[i];
614
+ if (irq <= 0)
615
+ continue;
616
+
617
+ err = devm_request_irq(hsp->dev, irq, tegra_hsp_shared_irq, 0,
618
+ dev_name(hsp->dev), hsp);
619
+ if (err < 0) {
620
+ dev_err(hsp->dev, "failed to request interrupt: %d\n",
621
+ err);
622
+ continue;
623
+ }
624
+
625
+ hsp->shared_irq = i;
626
+
627
+ /* disable all interrupts */
628
+ tegra_hsp_writel(hsp, 0, HSP_INT_IE(hsp->shared_irq));
629
+
630
+ dev_dbg(hsp->dev, "interrupt requested: %u\n", irq);
631
+
632
+ break;
633
+ }
634
+
635
+ if (i == hsp->num_si) {
636
+ dev_err(hsp->dev, "failed to find available interrupt\n");
637
+ return -ENOENT;
362638 }
363639
364640 return 0;
....@@ -368,6 +644,7 @@
368644 {
369645 struct tegra_hsp *hsp;
370646 struct resource *res;
647
+ unsigned int i;
371648 u32 value;
372649 int err;
373650
....@@ -375,6 +652,7 @@
375652 if (!hsp)
376653 return -ENOMEM;
377654
655
+ hsp->dev = &pdev->dev;
378656 hsp->soc = of_device_get_match_data(&pdev->dev);
379657 INIT_LIST_HEAD(&hsp->doorbells);
380658 spin_lock_init(&hsp->lock);
....@@ -391,62 +669,146 @@
391669 hsp->num_db = (value >> HSP_nDB_SHIFT) & HSP_nINT_MASK;
392670 hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK;
393671
394
- err = platform_get_irq_byname(pdev, "doorbell");
672
+ err = platform_get_irq_byname_optional(pdev, "doorbell");
673
+ if (err >= 0)
674
+ hsp->doorbell_irq = err;
675
+
676
+ if (hsp->num_si > 0) {
677
+ unsigned int count = 0;
678
+
679
+ hsp->shared_irqs = devm_kcalloc(&pdev->dev, hsp->num_si,
680
+ sizeof(*hsp->shared_irqs),
681
+ GFP_KERNEL);
682
+ if (!hsp->shared_irqs)
683
+ return -ENOMEM;
684
+
685
+ for (i = 0; i < hsp->num_si; i++) {
686
+ char *name;
687
+
688
+ name = kasprintf(GFP_KERNEL, "shared%u", i);
689
+ if (!name)
690
+ return -ENOMEM;
691
+
692
+ err = platform_get_irq_byname_optional(pdev, name);
693
+ if (err >= 0) {
694
+ hsp->shared_irqs[i] = err;
695
+ count++;
696
+ }
697
+
698
+ kfree(name);
699
+ }
700
+
701
+ if (count == 0) {
702
+ devm_kfree(&pdev->dev, hsp->shared_irqs);
703
+ hsp->shared_irqs = NULL;
704
+ }
705
+ }
706
+
707
+ /* setup the doorbell controller */
708
+ hsp->mbox_db.of_xlate = tegra_hsp_db_xlate;
709
+ hsp->mbox_db.num_chans = 32;
710
+ hsp->mbox_db.dev = &pdev->dev;
711
+ hsp->mbox_db.ops = &tegra_hsp_db_ops;
712
+
713
+ hsp->mbox_db.chans = devm_kcalloc(&pdev->dev, hsp->mbox_db.num_chans,
714
+ sizeof(*hsp->mbox_db.chans),
715
+ GFP_KERNEL);
716
+ if (!hsp->mbox_db.chans)
717
+ return -ENOMEM;
718
+
719
+ if (hsp->doorbell_irq) {
720
+ err = tegra_hsp_add_doorbells(hsp);
721
+ if (err < 0) {
722
+ dev_err(&pdev->dev, "failed to add doorbells: %d\n",
723
+ err);
724
+ return err;
725
+ }
726
+ }
727
+
728
+ err = devm_mbox_controller_register(&pdev->dev, &hsp->mbox_db);
395729 if (err < 0) {
396
- dev_err(&pdev->dev, "failed to get doorbell IRQ: %d\n", err);
730
+ dev_err(&pdev->dev, "failed to register doorbell mailbox: %d\n",
731
+ err);
397732 return err;
398733 }
399734
400
- hsp->irq = err;
735
+ /* setup the shared mailbox controller */
736
+ hsp->mbox_sm.of_xlate = tegra_hsp_sm_xlate;
737
+ hsp->mbox_sm.num_chans = hsp->num_sm;
738
+ hsp->mbox_sm.dev = &pdev->dev;
739
+ hsp->mbox_sm.ops = &tegra_hsp_sm_ops;
401740
402
- hsp->mbox.of_xlate = of_tegra_hsp_xlate;
403
- hsp->mbox.num_chans = 32;
404
- hsp->mbox.dev = &pdev->dev;
405
- hsp->mbox.txdone_irq = false;
406
- hsp->mbox.txdone_poll = false;
407
- hsp->mbox.ops = &tegra_hsp_doorbell_ops;
408
-
409
- hsp->mbox.chans = devm_kcalloc(&pdev->dev, hsp->mbox.num_chans,
410
- sizeof(*hsp->mbox.chans),
411
- GFP_KERNEL);
412
- if (!hsp->mbox.chans)
741
+ hsp->mbox_sm.chans = devm_kcalloc(&pdev->dev, hsp->mbox_sm.num_chans,
742
+ sizeof(*hsp->mbox_sm.chans),
743
+ GFP_KERNEL);
744
+ if (!hsp->mbox_sm.chans)
413745 return -ENOMEM;
414746
415
- err = tegra_hsp_add_doorbells(hsp);
747
+ if (hsp->shared_irqs) {
748
+ err = tegra_hsp_add_mailboxes(hsp, &pdev->dev);
749
+ if (err < 0) {
750
+ dev_err(&pdev->dev, "failed to add mailboxes: %d\n",
751
+ err);
752
+ return err;
753
+ }
754
+ }
755
+
756
+ err = devm_mbox_controller_register(&pdev->dev, &hsp->mbox_sm);
416757 if (err < 0) {
417
- dev_err(&pdev->dev, "failed to add doorbells: %d\n", err);
758
+ dev_err(&pdev->dev, "failed to register shared mailbox: %d\n",
759
+ err);
418760 return err;
419761 }
420762
421763 platform_set_drvdata(pdev, hsp);
422764
423
- err = mbox_controller_register(&hsp->mbox);
424
- if (err) {
425
- dev_err(&pdev->dev, "failed to register mailbox: %d\n", err);
426
- tegra_hsp_remove_doorbells(hsp);
427
- return err;
765
+ if (hsp->doorbell_irq) {
766
+ err = devm_request_irq(&pdev->dev, hsp->doorbell_irq,
767
+ tegra_hsp_doorbell_irq, IRQF_NO_SUSPEND,
768
+ dev_name(&pdev->dev), hsp);
769
+ if (err < 0) {
770
+ dev_err(&pdev->dev,
771
+ "failed to request doorbell IRQ#%u: %d\n",
772
+ hsp->doorbell_irq, err);
773
+ return err;
774
+ }
428775 }
429776
430
- err = devm_request_irq(&pdev->dev, hsp->irq, tegra_hsp_doorbell_irq,
431
- IRQF_NO_SUSPEND, dev_name(&pdev->dev), hsp);
432
- if (err < 0) {
433
- dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n",
434
- hsp->irq, err);
435
- return err;
777
+ if (hsp->shared_irqs) {
778
+ err = tegra_hsp_request_shared_irq(hsp);
779
+ if (err < 0)
780
+ return err;
436781 }
437782
438783 return 0;
439784 }
440785
441
-static int tegra_hsp_remove(struct platform_device *pdev)
786
+static int __maybe_unused tegra_hsp_resume(struct device *dev)
442787 {
443
- struct tegra_hsp *hsp = platform_get_drvdata(pdev);
788
+ struct tegra_hsp *hsp = dev_get_drvdata(dev);
789
+ unsigned int i;
790
+ struct tegra_hsp_doorbell *db;
444791
445
- mbox_controller_unregister(&hsp->mbox);
446
- tegra_hsp_remove_doorbells(hsp);
792
+ list_for_each_entry(db, &hsp->doorbells, list) {
793
+ if (db && db->channel.chan)
794
+ tegra_hsp_doorbell_startup(db->channel.chan);
795
+ }
796
+
797
+ if (hsp->mailboxes) {
798
+ for (i = 0; i < hsp->num_sm; i++) {
799
+ struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i];
800
+
801
+ if (mb->channel.chan->cl)
802
+ tegra_hsp_mailbox_startup(mb->channel.chan);
803
+ }
804
+ }
447805
448806 return 0;
449807 }
808
+
809
+static const struct dev_pm_ops tegra_hsp_pm_ops = {
810
+ .resume_noirq = tegra_hsp_resume,
811
+};
450812
451813 static const struct tegra_hsp_db_map tegra186_hsp_db_map[] = {
452814 { "ccplex", TEGRA_HSP_DB_MASTER_CCPLEX, HSP_DB_CCPLEX, },
....@@ -456,10 +818,17 @@
456818
457819 static const struct tegra_hsp_soc tegra186_hsp_soc = {
458820 .map = tegra186_hsp_db_map,
821
+ .has_per_mb_ie = false,
822
+};
823
+
824
+static const struct tegra_hsp_soc tegra194_hsp_soc = {
825
+ .map = tegra186_hsp_db_map,
826
+ .has_per_mb_ie = true,
459827 };
460828
461829 static const struct of_device_id tegra_hsp_match[] = {
462830 { .compatible = "nvidia,tegra186-hsp", .data = &tegra186_hsp_soc },
831
+ { .compatible = "nvidia,tegra194-hsp", .data = &tegra194_hsp_soc },
463832 { }
464833 };
465834
....@@ -467,9 +836,9 @@
467836 .driver = {
468837 .name = "tegra-hsp",
469838 .of_match_table = tegra_hsp_match,
839
+ .pm = &tegra_hsp_pm_ops,
470840 },
471841 .probe = tegra_hsp_probe,
472
- .remove = tegra_hsp_remove,
473842 };
474843
475844 static int __init tegra_hsp_init(void)