Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Suman Anna and committed by
Tony Lindgren
72c1c817 be3322eb

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