aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2014-09-24 01:10:18 -0400
committerOlof Johansson <olof@lixom.net>2014-09-24 01:10:27 -0400
commit791cc88c57b524b4267a9ea550b5306749fc7479 (patch)
treec7cd6c33f5c6a97e326e49fe1653df4774e23696
parent9cdf6bd51030e8b80b752adc016719a5b5d75d50 (diff)
parent75288cc66dc478b32e43970dd6913396526504ae (diff)
Merge tag 'mailbox-for-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers
Mailbox related changes for omaps to get it to work with device tree. * tag 'mailbox-for-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: mailbox/omap: add support for parsing dt devices Documentation: dt: add omap mailbox bindings Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/mailbox/omap-mailbox.txt108
-rw-r--r--drivers/mailbox/omap-mailbox.c156
2 files changed, 240 insertions, 24 deletions
diff --git a/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt b/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt
new file mode 100644
index 000000000000..48edc4b92afb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt
@@ -0,0 +1,108 @@
1OMAP2+ Mailbox Driver
2=====================
3
4The OMAP mailbox hardware facilitates communication between different processors
5using a queued mailbox interrupt mechanism. The IP block is external to the
6various processor subsystems and is connected on an interconnect bus. The
7communication is achieved through a set of registers for message storage and
8interrupt configuration registers.
9
10Each mailbox IP block has a certain number of h/w fifo queues and output
11interrupt lines. An output interrupt line is routed to an interrupt controller
12within a processor subsystem, and there can be more than one line going to a
13specific processor's interrupt controller. The interrupt line connections are
14fixed for an instance and are dictated by the IP integration into the SoC
15(excluding the SoCs that have a Interrupt Crossbar IP). Each interrupt line is
16programmable through a set of interrupt configuration registers, and have a rx
17and tx interrupt source per h/w fifo. Communication between different processors
18is achieved through the appropriate programming of the rx and tx interrupt
19sources on the appropriate interrupt lines.
20
21The number of h/w fifo queues and interrupt lines dictate the usable registers.
22All the current OMAP SoCs except for the newest DRA7xx SoC has a single IP
23instance. DRA7xx has multiple instances with different number of h/w fifo queues
24and interrupt lines between different instances. The interrupt lines can also be
25routed to different processor sub-systems on DRA7xx as they are routed through
26the Crossbar, a kind of interrupt router/multiplexer.
27
28Mailbox Device Node:
29====================
30A Mailbox device node is used to represent a Mailbox IP instance within a SoC.
31The sub-mailboxes are represented as child nodes of this parent node.
32
33Required properties:
34--------------------
35- compatible: Should be one of the following,
36 "ti,omap2-mailbox" for OMAP2420, OMAP2430 SoCs
37 "ti,omap3-mailbox" for OMAP3430, OMAP3630 SoCs
38 "ti,omap4-mailbox" for OMAP44xx, OMAP54xx, AM33xx,
39 AM43xx and DRA7xx SoCs
40- reg: Contains the mailbox register address range (base
41 address and length)
42- interrupts: Contains the interrupt information for the mailbox
43 device. The format is dependent on which interrupt
44 controller the OMAP device uses
45- ti,hwmods: Name of the hwmod associated with the mailbox
46- ti,mbox-num-users: Number of targets (processor devices) that the mailbox
47 device can interrupt
48- ti,mbox-num-fifos: Number of h/w fifo queues within the mailbox IP block
49
50Child Nodes:
51============
52A child node is used for representing the actual sub-mailbox device that is
53used for the communication between the host processor and a remote processor.
54Each child node should have a unique node name across all the different
55mailbox device nodes.
56
57Required properties:
58--------------------
59- ti,mbox-tx: sub-mailbox descriptor property defining a Tx fifo
60- ti,mbox-rx: sub-mailbox descriptor property defining a Rx fifo
61
62Sub-mailbox Descriptor Data
63---------------------------
64Each of the above ti,mbox-tx and ti,mbox-rx properties should have 3 cells of
65data that represent the following:
66 Cell #1 (fifo_id) - mailbox fifo id used either for transmitting
67 (ti,mbox-tx) or for receiving (ti,mbox-rx)
68 Cell #2 (irq_id) - irq identifier index number to use from the parent's
69 interrupts data. Should be 0 for most of the cases, a
70 positive index value is seen only on mailboxes that have
71 multiple interrupt lines connected to the MPU processor.
72 Cell #3 (usr_id) - mailbox user id for identifying the interrupt line
73 associated with generating a tx/rx fifo interrupt.
74
75Example:
76--------
77
78/* OMAP4 */
79mailbox: mailbox@4a0f4000 {
80 compatible = "ti,omap4-mailbox";
81 reg = <0x4a0f4000 0x200>;
82 interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
83 ti,hwmods = "mailbox";
84 ti,mbox-num-users = <3>;
85 ti,mbox-num-fifos = <8>;
86 mbox_ipu: mbox_ipu {
87 ti,mbox-tx = <0 0 0>;
88 ti,mbox-rx = <1 0 0>;
89 };
90 mbox_dsp: mbox_dsp {
91 ti,mbox-tx = <3 0 0>;
92 ti,mbox-rx = <2 0 0>;
93 };
94};
95
96/* AM33xx */
97mailbox: mailbox@480C8000 {
98 compatible = "ti,omap4-mailbox";
99 reg = <0x480C8000 0x200>;
100 interrupts = <77>;
101 ti,hwmods = "mailbox";
102 ti,mbox-num-users = <4>;
103 ti,mbox-num-fifos = <8>;
104 mbox_wkupm3: wkup_m3 {
105 ti,mbox-tx = <0 0 0>;
106 ti,mbox-rx = <0 0 3>;
107 };
108};
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index a27e00e63a8a..bcc7ee129276 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -31,6 +31,7 @@
31#include <linux/err.h> 31#include <linux/err.h>
32#include <linux/notifier.h> 32#include <linux/notifier.h>
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/of_device.h>
34#include <linux/platform_device.h> 35#include <linux/platform_device.h>
35#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
36#include <linux/platform_data/mailbox-omap.h> 37#include <linux/platform_data/mailbox-omap.h>
@@ -94,6 +95,18 @@ struct omap_mbox_device {
94 struct list_head elem; 95 struct list_head elem;
95}; 96};
96 97
98struct omap_mbox_fifo_info {
99 int tx_id;
100 int tx_usr;
101 int tx_irq;
102
103 int rx_id;
104 int rx_usr;
105 int rx_irq;
106
107 const char *name;
108};
109
97struct omap_mbox { 110struct omap_mbox {
98 const char *name; 111 const char *name;
99 int irq; 112 int irq;
@@ -587,24 +600,118 @@ static int omap_mbox_unregister(struct omap_mbox_device *mdev)
587 return 0; 600 return 0;
588} 601}
589 602
603static const struct of_device_id omap_mailbox_of_match[] = {
604 {
605 .compatible = "ti,omap2-mailbox",
606 .data = (void *)MBOX_INTR_CFG_TYPE1,
607 },
608 {
609 .compatible = "ti,omap3-mailbox",
610 .data = (void *)MBOX_INTR_CFG_TYPE1,
611 },
612 {
613 .compatible = "ti,omap4-mailbox",
614 .data = (void *)MBOX_INTR_CFG_TYPE2,
615 },
616 {
617 /* end */
618 },
619};
620MODULE_DEVICE_TABLE(of, omap_mailbox_of_match);
621
590static int omap_mbox_probe(struct platform_device *pdev) 622static int omap_mbox_probe(struct platform_device *pdev)
591{ 623{
592 struct resource *mem; 624 struct resource *mem;
593 int ret; 625 int ret;
594 struct omap_mbox **list, *mbox, *mboxblk; 626 struct omap_mbox **list, *mbox, *mboxblk;
595 struct omap_mbox_pdata *pdata = pdev->dev.platform_data; 627 struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
596 struct omap_mbox_dev_info *info; 628 struct omap_mbox_dev_info *info = NULL;
629 struct omap_mbox_fifo_info *finfo, *finfoblk;
597 struct omap_mbox_device *mdev; 630 struct omap_mbox_device *mdev;
598 struct omap_mbox_fifo *fifo; 631 struct omap_mbox_fifo *fifo;
599 u32 intr_type; 632 struct device_node *node = pdev->dev.of_node;
633 struct device_node *child;
634 const struct of_device_id *match;
635 u32 intr_type, info_count;
636 u32 num_users, num_fifos;
637 u32 tmp[3];
600 u32 l; 638 u32 l;
601 int i; 639 int i;
602 640
603 if (!pdata || !pdata->info_cnt || !pdata->info) { 641 if (!node && (!pdata || !pdata->info_cnt || !pdata->info)) {
604 pr_err("%s: platform not supported\n", __func__); 642 pr_err("%s: platform not supported\n", __func__);
605 return -ENODEV; 643 return -ENODEV;
606 } 644 }
607 645
646 if (node) {
647 match = of_match_device(omap_mailbox_of_match, &pdev->dev);
648 if (!match)
649 return -ENODEV;
650 intr_type = (u32)match->data;
651
652 if (of_property_read_u32(node, "ti,mbox-num-users",
653 &num_users))
654 return -ENODEV;
655
656 if (of_property_read_u32(node, "ti,mbox-num-fifos",
657 &num_fifos))
658 return -ENODEV;
659
660 info_count = of_get_available_child_count(node);
661 if (!info_count) {
662 dev_err(&pdev->dev, "no available mbox devices found\n");
663 return -ENODEV;
664 }
665 } else { /* non-DT device creation */
666 info_count = pdata->info_cnt;
667 info = pdata->info;
668 intr_type = pdata->intr_type;
669 num_users = pdata->num_users;
670 num_fifos = pdata->num_fifos;
671 }
672
673 finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk),
674 GFP_KERNEL);
675 if (!finfoblk)
676 return -ENOMEM;
677
678 finfo = finfoblk;
679 child = NULL;
680 for (i = 0; i < info_count; i++, finfo++) {
681 if (node) {
682 child = of_get_next_available_child(node, child);
683 ret = of_property_read_u32_array(child, "ti,mbox-tx",
684 tmp, ARRAY_SIZE(tmp));
685 if (ret)
686 return ret;
687 finfo->tx_id = tmp[0];
688 finfo->tx_irq = tmp[1];
689 finfo->tx_usr = tmp[2];
690
691 ret = of_property_read_u32_array(child, "ti,mbox-rx",
692 tmp, ARRAY_SIZE(tmp));
693 if (ret)
694 return ret;
695 finfo->rx_id = tmp[0];
696 finfo->rx_irq = tmp[1];
697 finfo->rx_usr = tmp[2];
698
699 finfo->name = child->name;
700 } else {
701 finfo->tx_id = info->tx_id;
702 finfo->rx_id = info->rx_id;
703 finfo->tx_usr = info->usr_id;
704 finfo->tx_irq = info->irq_id;
705 finfo->rx_usr = info->usr_id;
706 finfo->rx_irq = info->irq_id;
707 finfo->name = info->name;
708 info++;
709 }
710 if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos ||
711 finfo->tx_usr >= num_users || finfo->rx_usr >= num_users)
712 return -EINVAL;
713 }
714
608 mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL); 715 mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
609 if (!mdev) 716 if (!mdev)
610 return -ENOMEM; 717 return -ENOMEM;
@@ -615,41 +722,40 @@ static int omap_mbox_probe(struct platform_device *pdev)
615 return PTR_ERR(mdev->mbox_base); 722 return PTR_ERR(mdev->mbox_base);
616 723
617 /* allocate one extra for marking end of list */ 724 /* allocate one extra for marking end of list */
618 list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list), 725 list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list),
619 GFP_KERNEL); 726 GFP_KERNEL);
620 if (!list) 727 if (!list)
621 return -ENOMEM; 728 return -ENOMEM;
622 729
623 mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox), 730 mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox),
624 GFP_KERNEL); 731 GFP_KERNEL);
625 if (!mboxblk) 732 if (!mboxblk)
626 return -ENOMEM; 733 return -ENOMEM;
627 734
628 info = pdata->info;
629 intr_type = pdata->intr_type;
630 mbox = mboxblk; 735 mbox = mboxblk;
631 for (i = 0; i < pdata->info_cnt; i++, info++) { 736 finfo = finfoblk;
737 for (i = 0; i < info_count; i++, finfo++) {
632 fifo = &mbox->tx_fifo; 738 fifo = &mbox->tx_fifo;
633 fifo->msg = MAILBOX_MESSAGE(info->tx_id); 739 fifo->msg = MAILBOX_MESSAGE(finfo->tx_id);
634 fifo->fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id); 740 fifo->fifo_stat = MAILBOX_FIFOSTATUS(finfo->tx_id);
635 fifo->intr_bit = MAILBOX_IRQ_NOTFULL(info->tx_id); 741 fifo->intr_bit = MAILBOX_IRQ_NOTFULL(finfo->tx_id);
636 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id); 742 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->tx_usr);
637 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id); 743 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->tx_usr);
638 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id); 744 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->tx_usr);
639 745
640 fifo = &mbox->rx_fifo; 746 fifo = &mbox->rx_fifo;
641 fifo->msg = MAILBOX_MESSAGE(info->rx_id); 747 fifo->msg = MAILBOX_MESSAGE(finfo->rx_id);
642 fifo->msg_stat = MAILBOX_MSGSTATUS(info->rx_id); 748 fifo->msg_stat = MAILBOX_MSGSTATUS(finfo->rx_id);
643 fifo->intr_bit = MAILBOX_IRQ_NEWMSG(info->rx_id); 749 fifo->intr_bit = MAILBOX_IRQ_NEWMSG(finfo->rx_id);
644 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id); 750 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->rx_usr);
645 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id); 751 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr);
646 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id); 752 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr);
647 753
648 mbox->intr_type = intr_type; 754 mbox->intr_type = intr_type;
649 755
650 mbox->parent = mdev; 756 mbox->parent = mdev;
651 mbox->name = info->name; 757 mbox->name = finfo->name;
652 mbox->irq = platform_get_irq(pdev, info->irq_id); 758 mbox->irq = platform_get_irq(pdev, finfo->tx_irq);
653 if (mbox->irq < 0) 759 if (mbox->irq < 0)
654 return mbox->irq; 760 return mbox->irq;
655 list[i] = mbox++; 761 list[i] = mbox++;
@@ -657,8 +763,8 @@ static int omap_mbox_probe(struct platform_device *pdev)
657 763
658 mutex_init(&mdev->cfg_lock); 764 mutex_init(&mdev->cfg_lock);
659 mdev->dev = &pdev->dev; 765 mdev->dev = &pdev->dev;
660 mdev->num_users = pdata->num_users; 766 mdev->num_users = num_users;
661 mdev->num_fifos = pdata->num_fifos; 767 mdev->num_fifos = num_fifos;
662 mdev->mboxes = list; 768 mdev->mboxes = list;
663 ret = omap_mbox_register(mdev); 769 ret = omap_mbox_register(mdev);
664 if (ret) 770 if (ret)
@@ -684,6 +790,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
684 if (ret < 0) 790 if (ret < 0)
685 goto unregister; 791 goto unregister;
686 792
793 devm_kfree(&pdev->dev, finfoblk);
687 return 0; 794 return 0;
688 795
689unregister: 796unregister:
@@ -708,6 +815,7 @@ static struct platform_driver omap_mbox_driver = {
708 .driver = { 815 .driver = {
709 .name = "omap-mailbox", 816 .name = "omap-mailbox",
710 .owner = THIS_MODULE, 817 .owner = THIS_MODULE,
818 .of_match_table = of_match_ptr(omap_mailbox_of_match),
711 }, 819 },
712}; 820};
713 821