aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mailbox
diff options
context:
space:
mode:
authorSuman Anna <s-anna@ti.com>2014-06-24 20:43:43 -0400
committerTony Lindgren <tony@atomide.com>2014-07-29 04:57:25 -0400
commit72c1c8179cdc5ba7208d375bd3f104659fc50ad0 (patch)
tree6be3154385d5a638ad214313d1a7d6f4a656ad55 /drivers/mailbox
parentbe3322eb7038926ecd5fbd37b3aaa4aee76b78e0 (diff)
mailbox/omap: add a parent structure for every IP instance
A new structure, omap_mbox_device, is added to contain the global variables pertinent to a mailbox h/w IP block. This enables the support for having multiple instances of the same h/w IP block in the SoC. This is in preparation to support the DRA7 SoC, which is the first SoC in the OMAP family to have multiple mailbox IP instances. The changes include enhancements to the sub-mailbox registration logic and mbox startup sequencing, removing the usage of single global configuration variables for all h/w instances, and storing the registered sub-mailboxes with the parent mailbox device structure. Signed-off-by: Suman Anna <s-anna@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
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}