aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mailbox
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mailbox')
-rw-r--r--drivers/mailbox/omap-mailbox.c173
1 files changed, 115 insertions, 58 deletions
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index d9a503974d52..a27e00e63a8a 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -84,11 +84,22 @@ struct omap_mbox_queue {
84 bool full; 84 bool full;
85}; 85};
86 86
87struct omap_mbox_device {
88 struct device *dev;
89 struct mutex cfg_lock;
90 void __iomem *mbox_base;
91 u32 num_users;
92 u32 num_fifos;
93 struct omap_mbox **mboxes;
94 struct list_head elem;
95};
96
87struct omap_mbox { 97struct omap_mbox {
88 const char *name; 98 const char *name;
89 int irq; 99 int irq;
90 struct omap_mbox_queue *txq, *rxq; 100 struct omap_mbox_queue *txq, *rxq;
91 struct device *dev; 101 struct device *dev;
102 struct omap_mbox_device *parent;
92 struct omap_mbox_fifo tx_fifo; 103 struct omap_mbox_fifo tx_fifo;
93 struct omap_mbox_fifo rx_fifo; 104 struct omap_mbox_fifo rx_fifo;
94 u32 ctx[OMAP4_MBOX_NR_REGS]; 105 u32 ctx[OMAP4_MBOX_NR_REGS];
@@ -97,48 +108,49 @@ struct omap_mbox {
97 struct blocking_notifier_head notifier; 108 struct blocking_notifier_head notifier;
98}; 109};
99 110
100static void __iomem *mbox_base; 111/* global variables for the mailbox devices */
101static struct omap_mbox **mboxes; 112static DEFINE_MUTEX(omap_mbox_devices_lock);
102 113static LIST_HEAD(omap_mbox_devices);
103static DEFINE_MUTEX(mbox_configured_lock);
104 114
105static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; 115static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
106module_param(mbox_kfifo_size, uint, S_IRUGO); 116module_param(mbox_kfifo_size, uint, S_IRUGO);
107MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); 117MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
108 118
109static inline unsigned int mbox_read_reg(size_t ofs) 119static inline
120unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs)
110{ 121{
111 return __raw_readl(mbox_base + ofs); 122 return __raw_readl(mdev->mbox_base + ofs);
112} 123}
113 124
114static inline void mbox_write_reg(u32 val, size_t ofs) 125static inline
126void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
115{ 127{
116 __raw_writel(val, mbox_base + ofs); 128 __raw_writel(val, mdev->mbox_base + ofs);
117} 129}
118 130
119/* Mailbox FIFO handle functions */ 131/* Mailbox FIFO handle functions */
120static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) 132static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
121{ 133{
122 struct omap_mbox_fifo *fifo = &mbox->rx_fifo; 134 struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
123 return (mbox_msg_t) mbox_read_reg(fifo->msg); 135 return (mbox_msg_t) mbox_read_reg(mbox->parent, fifo->msg);
124} 136}
125 137
126static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) 138static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
127{ 139{
128 struct omap_mbox_fifo *fifo = &mbox->tx_fifo; 140 struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
129 mbox_write_reg(msg, fifo->msg); 141 mbox_write_reg(mbox->parent, msg, fifo->msg);
130} 142}
131 143
132static int mbox_fifo_empty(struct omap_mbox *mbox) 144static int mbox_fifo_empty(struct omap_mbox *mbox)
133{ 145{
134 struct omap_mbox_fifo *fifo = &mbox->rx_fifo; 146 struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
135 return (mbox_read_reg(fifo->msg_stat) == 0); 147 return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0);
136} 148}
137 149
138static int mbox_fifo_full(struct omap_mbox *mbox) 150static int mbox_fifo_full(struct omap_mbox *mbox)
139{ 151{
140 struct omap_mbox_fifo *fifo = &mbox->tx_fifo; 152 struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
141 return mbox_read_reg(fifo->fifo_stat); 153 return mbox_read_reg(mbox->parent, fifo->fifo_stat);
142} 154}
143 155
144/* Mailbox IRQ handle functions */ 156/* Mailbox IRQ handle functions */
@@ -149,10 +161,10 @@ static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
149 u32 bit = fifo->intr_bit; 161 u32 bit = fifo->intr_bit;
150 u32 irqstatus = fifo->irqstatus; 162 u32 irqstatus = fifo->irqstatus;
151 163
152 mbox_write_reg(bit, irqstatus); 164 mbox_write_reg(mbox->parent, bit, irqstatus);
153 165
154 /* Flush posted write for irq status to avoid spurious interrupts */ 166 /* Flush posted write for irq status to avoid spurious interrupts */
155 mbox_read_reg(irqstatus); 167 mbox_read_reg(mbox->parent, irqstatus);
156} 168}
157 169
158static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 170static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
@@ -163,8 +175,8 @@ static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
163 u32 irqenable = fifo->irqenable; 175 u32 irqenable = fifo->irqenable;
164 u32 irqstatus = fifo->irqstatus; 176 u32 irqstatus = fifo->irqstatus;
165 177
166 u32 enable = mbox_read_reg(irqenable); 178 u32 enable = mbox_read_reg(mbox->parent, irqenable);
167 u32 status = mbox_read_reg(irqstatus); 179 u32 status = mbox_read_reg(mbox->parent, irqstatus);
168 180
169 return (int)(enable & status & bit); 181 return (int)(enable & status & bit);
170} 182}
@@ -210,7 +222,7 @@ void omap_mbox_save_ctx(struct omap_mbox *mbox)
210 else 222 else
211 nr_regs = MBOX_NR_REGS; 223 nr_regs = MBOX_NR_REGS;
212 for (i = 0; i < nr_regs; i++) { 224 for (i = 0; i < nr_regs; i++) {
213 mbox->ctx[i] = mbox_read_reg(i * sizeof(u32)); 225 mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32));
214 226
215 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 227 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
216 i, mbox->ctx[i]); 228 i, mbox->ctx[i]);
@@ -228,7 +240,7 @@ void omap_mbox_restore_ctx(struct omap_mbox *mbox)
228 else 240 else
229 nr_regs = MBOX_NR_REGS; 241 nr_regs = MBOX_NR_REGS;
230 for (i = 0; i < nr_regs; i++) { 242 for (i = 0; i < nr_regs; i++) {
231 mbox_write_reg(mbox->ctx[i], i * sizeof(u32)); 243 mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
232 244
233 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 245 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
234 i, mbox->ctx[i]); 246 i, mbox->ctx[i]);
@@ -244,9 +256,9 @@ void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
244 u32 bit = fifo->intr_bit; 256 u32 bit = fifo->intr_bit;
245 u32 irqenable = fifo->irqenable; 257 u32 irqenable = fifo->irqenable;
246 258
247 l = mbox_read_reg(irqenable); 259 l = mbox_read_reg(mbox->parent, irqenable);
248 l |= bit; 260 l |= bit;
249 mbox_write_reg(l, irqenable); 261 mbox_write_reg(mbox->parent, l, irqenable);
250} 262}
251EXPORT_SYMBOL(omap_mbox_enable_irq); 263EXPORT_SYMBOL(omap_mbox_enable_irq);
252 264
@@ -262,9 +274,9 @@ void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
262 * OMAP4 and later SoCs have a dedicated interrupt disabling register. 274 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
263 */ 275 */
264 if (!mbox->intr_type) 276 if (!mbox->intr_type)
265 bit = mbox_read_reg(irqdisable) & ~bit; 277 bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit;
266 278
267 mbox_write_reg(bit, irqdisable); 279 mbox_write_reg(mbox->parent, bit, irqdisable);
268} 280}
269EXPORT_SYMBOL(omap_mbox_disable_irq); 281EXPORT_SYMBOL(omap_mbox_disable_irq);
270 282
@@ -398,9 +410,10 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
398{ 410{
399 int ret = 0; 411 int ret = 0;
400 struct omap_mbox_queue *mq; 412 struct omap_mbox_queue *mq;
413 struct omap_mbox_device *mdev = mbox->parent;
401 414
402 mutex_lock(&mbox_configured_lock); 415 mutex_lock(&mdev->cfg_lock);
403 ret = pm_runtime_get_sync(mbox->dev->parent); 416 ret = pm_runtime_get_sync(mdev->dev);
404 if (unlikely(ret < 0)) 417 if (unlikely(ret < 0))
405 goto fail_startup; 418 goto fail_startup;
406 419
@@ -429,7 +442,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
429 442
430 omap_mbox_enable_irq(mbox, IRQ_RX); 443 omap_mbox_enable_irq(mbox, IRQ_RX);
431 } 444 }
432 mutex_unlock(&mbox_configured_lock); 445 mutex_unlock(&mdev->cfg_lock);
433 return 0; 446 return 0;
434 447
435fail_request_irq: 448fail_request_irq:
@@ -437,16 +450,18 @@ fail_request_irq:
437fail_alloc_rxq: 450fail_alloc_rxq:
438 mbox_queue_free(mbox->txq); 451 mbox_queue_free(mbox->txq);
439fail_alloc_txq: 452fail_alloc_txq:
440 pm_runtime_put_sync(mbox->dev->parent); 453 pm_runtime_put_sync(mdev->dev);
441 mbox->use_count--; 454 mbox->use_count--;
442fail_startup: 455fail_startup:
443 mutex_unlock(&mbox_configured_lock); 456 mutex_unlock(&mdev->cfg_lock);
444 return ret; 457 return ret;
445} 458}
446 459
447static void omap_mbox_fini(struct omap_mbox *mbox) 460static void omap_mbox_fini(struct omap_mbox *mbox)
448{ 461{
449 mutex_lock(&mbox_configured_lock); 462 struct omap_mbox_device *mdev = mbox->parent;
463
464 mutex_lock(&mdev->cfg_lock);
450 465
451 if (!--mbox->use_count) { 466 if (!--mbox->use_count) {
452 omap_mbox_disable_irq(mbox, IRQ_RX); 467 omap_mbox_disable_irq(mbox, IRQ_RX);
@@ -457,25 +472,43 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
457 mbox_queue_free(mbox->rxq); 472 mbox_queue_free(mbox->rxq);
458 } 473 }
459 474
460 pm_runtime_put_sync(mbox->dev->parent); 475 pm_runtime_put_sync(mdev->dev);
461 476
462 mutex_unlock(&mbox_configured_lock); 477 mutex_unlock(&mdev->cfg_lock);
463} 478}
464 479
465struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) 480static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
481 const char *mbox_name)
466{ 482{
467 struct omap_mbox *_mbox, *mbox = NULL; 483 struct omap_mbox *_mbox, *mbox = NULL;
468 int i, ret; 484 struct omap_mbox **mboxes = mdev->mboxes;
485 int i;
469 486
470 if (!mboxes) 487 if (!mboxes)
471 return ERR_PTR(-EINVAL); 488 return NULL;
472 489
473 for (i = 0; (_mbox = mboxes[i]); i++) { 490 for (i = 0; (_mbox = mboxes[i]); i++) {
474 if (!strcmp(_mbox->name, name)) { 491 if (!strcmp(_mbox->name, mbox_name)) {
475 mbox = _mbox; 492 mbox = _mbox;
476 break; 493 break;
477 } 494 }
478 } 495 }
496 return mbox;
497}
498
499struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
500{
501 struct omap_mbox *mbox = NULL;
502 struct omap_mbox_device *mdev;
503 int ret;
504
505 mutex_lock(&omap_mbox_devices_lock);
506 list_for_each_entry(mdev, &omap_mbox_devices, elem) {
507 mbox = omap_mbox_device_find(mdev, name);
508 if (mbox)
509 break;
510 }
511 mutex_unlock(&omap_mbox_devices_lock);
479 512
480 if (!mbox) 513 if (!mbox)
481 return ERR_PTR(-ENOENT); 514 return ERR_PTR(-ENOENT);
@@ -502,19 +535,20 @@ EXPORT_SYMBOL(omap_mbox_put);
502 535
503static struct class omap_mbox_class = { .name = "mbox", }; 536static struct class omap_mbox_class = { .name = "mbox", };
504 537
505static int omap_mbox_register(struct device *parent, struct omap_mbox **list) 538static int omap_mbox_register(struct omap_mbox_device *mdev)
506{ 539{
507 int ret; 540 int ret;
508 int i; 541 int i;
542 struct omap_mbox **mboxes;
509 543
510 mboxes = list; 544 if (!mdev || !mdev->mboxes)
511 if (!mboxes)
512 return -EINVAL; 545 return -EINVAL;
513 546
547 mboxes = mdev->mboxes;
514 for (i = 0; mboxes[i]; i++) { 548 for (i = 0; mboxes[i]; i++) {
515 struct omap_mbox *mbox = mboxes[i]; 549 struct omap_mbox *mbox = mboxes[i];
516 mbox->dev = device_create(&omap_mbox_class, 550 mbox->dev = device_create(&omap_mbox_class,
517 parent, 0, mbox, "%s", mbox->name); 551 mdev->dev, 0, mbox, "%s", mbox->name);
518 if (IS_ERR(mbox->dev)) { 552 if (IS_ERR(mbox->dev)) {
519 ret = PTR_ERR(mbox->dev); 553 ret = PTR_ERR(mbox->dev);
520 goto err_out; 554 goto err_out;
@@ -522,6 +556,11 @@ static int omap_mbox_register(struct device *parent, struct omap_mbox **list)
522 556
523 BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); 557 BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
524 } 558 }
559
560 mutex_lock(&omap_mbox_devices_lock);
561 list_add(&mdev->elem, &omap_mbox_devices);
562 mutex_unlock(&omap_mbox_devices_lock);
563
525 return 0; 564 return 0;
526 565
527err_out: 566err_out:
@@ -530,16 +569,21 @@ err_out:
530 return ret; 569 return ret;
531} 570}
532 571
533static int omap_mbox_unregister(void) 572static int omap_mbox_unregister(struct omap_mbox_device *mdev)
534{ 573{
535 int i; 574 int i;
575 struct omap_mbox **mboxes;
536 576
537 if (!mboxes) 577 if (!mdev || !mdev->mboxes)
538 return -EINVAL; 578 return -EINVAL;
539 579
580 mutex_lock(&omap_mbox_devices_lock);
581 list_del(&mdev->elem);
582 mutex_unlock(&omap_mbox_devices_lock);
583
584 mboxes = mdev->mboxes;
540 for (i = 0; mboxes[i]; i++) 585 for (i = 0; mboxes[i]; i++)
541 device_unregister(mboxes[i]->dev); 586 device_unregister(mboxes[i]->dev);
542 mboxes = NULL;
543 return 0; 587 return 0;
544} 588}
545 589
@@ -550,6 +594,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
550 struct omap_mbox **list, *mbox, *mboxblk; 594 struct omap_mbox **list, *mbox, *mboxblk;
551 struct omap_mbox_pdata *pdata = pdev->dev.platform_data; 595 struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
552 struct omap_mbox_dev_info *info; 596 struct omap_mbox_dev_info *info;
597 struct omap_mbox_device *mdev;
553 struct omap_mbox_fifo *fifo; 598 struct omap_mbox_fifo *fifo;
554 u32 intr_type; 599 u32 intr_type;
555 u32 l; 600 u32 l;
@@ -560,6 +605,15 @@ static int omap_mbox_probe(struct platform_device *pdev)
560 return -ENODEV; 605 return -ENODEV;
561 } 606 }
562 607
608 mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
609 if (!mdev)
610 return -ENOMEM;
611
612 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
613 mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem);
614 if (IS_ERR(mdev->mbox_base))
615 return PTR_ERR(mdev->mbox_base);
616
563 /* allocate one extra for marking end of list */ 617 /* allocate one extra for marking end of list */
564 list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list), 618 list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list),
565 GFP_KERNEL); 619 GFP_KERNEL);
@@ -593,6 +647,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
593 647
594 mbox->intr_type = intr_type; 648 mbox->intr_type = intr_type;
595 649
650 mbox->parent = mdev;
596 mbox->name = info->name; 651 mbox->name = info->name;
597 mbox->irq = platform_get_irq(pdev, info->irq_id); 652 mbox->irq = platform_get_irq(pdev, info->irq_id);
598 if (mbox->irq < 0) 653 if (mbox->irq < 0)
@@ -600,21 +655,21 @@ static int omap_mbox_probe(struct platform_device *pdev)
600 list[i] = mbox++; 655 list[i] = mbox++;
601 } 656 }
602 657
603 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 658 mutex_init(&mdev->cfg_lock);
604 mbox_base = devm_ioremap_resource(&pdev->dev, mem); 659 mdev->dev = &pdev->dev;
605 if (IS_ERR(mbox_base)) 660 mdev->num_users = pdata->num_users;
606 return PTR_ERR(mbox_base); 661 mdev->num_fifos = pdata->num_fifos;
607 662 mdev->mboxes = list;
608 ret = omap_mbox_register(&pdev->dev, list); 663 ret = omap_mbox_register(mdev);
609 if (ret) 664 if (ret)
610 return ret; 665 return ret;
611 666
612 platform_set_drvdata(pdev, list); 667 platform_set_drvdata(pdev, mdev);
613 pm_runtime_enable(&pdev->dev); 668 pm_runtime_enable(mdev->dev);
614 669
615 ret = pm_runtime_get_sync(&pdev->dev); 670 ret = pm_runtime_get_sync(mdev->dev);
616 if (ret < 0) { 671 if (ret < 0) {
617 pm_runtime_put_noidle(&pdev->dev); 672 pm_runtime_put_noidle(mdev->dev);
618 goto unregister; 673 goto unregister;
619 } 674 }
620 675
@@ -622,25 +677,27 @@ static int omap_mbox_probe(struct platform_device *pdev)
622 * just print the raw revision register, the format is not 677 * just print the raw revision register, the format is not
623 * uniform across all SoCs 678 * uniform across all SoCs
624 */ 679 */
625 l = mbox_read_reg(MAILBOX_REVISION); 680 l = mbox_read_reg(mdev, MAILBOX_REVISION);
626 dev_info(&pdev->dev, "omap mailbox rev 0x%x\n", l); 681 dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l);
627 682
628 ret = pm_runtime_put_sync(&pdev->dev); 683 ret = pm_runtime_put_sync(mdev->dev);
629 if (ret < 0) 684 if (ret < 0)
630 goto unregister; 685 goto unregister;
631 686
632 return 0; 687 return 0;
633 688
634unregister: 689unregister:
635 pm_runtime_disable(&pdev->dev); 690 pm_runtime_disable(mdev->dev);
636 omap_mbox_unregister(); 691 omap_mbox_unregister(mdev);
637 return ret; 692 return ret;
638} 693}
639 694
640static int omap_mbox_remove(struct platform_device *pdev) 695static int omap_mbox_remove(struct platform_device *pdev)
641{ 696{
642 pm_runtime_disable(&pdev->dev); 697 struct omap_mbox_device *mdev = platform_get_drvdata(pdev);
643 omap_mbox_unregister(); 698
699 pm_runtime_disable(mdev->dev);
700 omap_mbox_unregister(mdev);
644 701
645 return 0; 702 return 0;
646} 703}