Commit c869c75c16b3d1ffcf64fb2fd63ba0c4a369071c

Authored by Suman Anna
1 parent fe32c1f602

mailbox/omap: move the OMAP mailbox framework to drivers

The mailbox hardware (in OMAP) uses a queued mailbox interrupt
mechanism that provides a communication channel between processors
through a set of registers and their associated interrupt signals
by sending and receiving messages.

The OMAP mailbox framework/driver code is moved to be under
drivers/mailbox, in preparation for adapting to a common mailbox
driver framework. This allows the build for OMAP mailbox to be
enabled (it was disabled during the multi-platform support).

As part of the migration from plat and mach code:
- Kconfig symbols have been renamed to build OMAP1 or OMAP2+ drivers.
- mailbox.h under plat-omap/plat/include has been split into a public
  and private header files. The public header has only the API related
  functions and types.
- The module name mailbox.ko from plat-omap is changed to
  omap-mailbox.ko
- The module name mailbox_mach.ko from mach-omapX is changed as
    mailbox_omap1.ko for OMAP1
    mailbox_omap2.ko for OMAP2+

Cc: Tony Lindgren <tony@atomide.com>
[gregkh@linuxfoundation.org: ack for staging part]
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Omar Ramirez Luna <omar.ramirez@copitl.com>
Signed-off-by: Suman Anna <s-anna@ti.com>

Showing 21 changed files with 1176 additions and 1133 deletions Side-by-side Diff

arch/arm/configs/omap1_defconfig
... ... @@ -26,7 +26,8 @@
26 26 CONFIG_ARCH_OMAP1=y
27 27 CONFIG_OMAP_RESET_CLOCKS=y
28 28 # CONFIG_OMAP_MUX is not set
29   -CONFIG_OMAP_MBOX_FWK=y
  29 +CONFIG_MAILBOX=y
  30 +CONFIG_OMAP1_MBOX=y
30 31 CONFIG_OMAP_32K_TIMER=y
31 32 CONFIG_OMAP_DM_TIMER=y
32 33 CONFIG_ARCH_OMAP730=y
arch/arm/mach-omap1/Makefile
... ... @@ -19,10 +19,6 @@
19 19 # Power Management
20 20 obj-$(CONFIG_PM) += pm.o sleep.o
21 21  
22   -# DSP
23   -obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
24   -mailbox_mach-objs := mailbox.o
25   -
26 22 i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
27 23 obj-y += $(i2c-omap-m) $(i2c-omap-y)
28 24  
arch/arm/mach-omap1/mailbox.c
1   -/*
2   - * Mailbox reservation modules for OMAP1
3   - *
4   - * Copyright (C) 2006-2009 Nokia Corporation
5   - * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
6   - *
7   - * This file is subject to the terms and conditions of the GNU General Public
8   - * License. See the file "COPYING" in the main directory of this archive
9   - * for more details.
10   - */
11   -
12   -#include <linux/module.h>
13   -#include <linux/interrupt.h>
14   -#include <linux/platform_device.h>
15   -#include <linux/io.h>
16   -#include <plat/mailbox.h>
17   -
18   -#define MAILBOX_ARM2DSP1 0x00
19   -#define MAILBOX_ARM2DSP1b 0x04
20   -#define MAILBOX_DSP2ARM1 0x08
21   -#define MAILBOX_DSP2ARM1b 0x0c
22   -#define MAILBOX_DSP2ARM2 0x10
23   -#define MAILBOX_DSP2ARM2b 0x14
24   -#define MAILBOX_ARM2DSP1_Flag 0x18
25   -#define MAILBOX_DSP2ARM1_Flag 0x1c
26   -#define MAILBOX_DSP2ARM2_Flag 0x20
27   -
28   -static void __iomem *mbox_base;
29   -
30   -struct omap_mbox1_fifo {
31   - unsigned long cmd;
32   - unsigned long data;
33   - unsigned long flag;
34   -};
35   -
36   -struct omap_mbox1_priv {
37   - struct omap_mbox1_fifo tx_fifo;
38   - struct omap_mbox1_fifo rx_fifo;
39   -};
40   -
41   -static inline int mbox_read_reg(size_t ofs)
42   -{
43   - return __raw_readw(mbox_base + ofs);
44   -}
45   -
46   -static inline void mbox_write_reg(u32 val, size_t ofs)
47   -{
48   - __raw_writew(val, mbox_base + ofs);
49   -}
50   -
51   -/* msg */
52   -static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
53   -{
54   - struct omap_mbox1_fifo *fifo =
55   - &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
56   - mbox_msg_t msg;
57   -
58   - msg = mbox_read_reg(fifo->data);
59   - msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
60   -
61   - return msg;
62   -}
63   -
64   -static void
65   -omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
66   -{
67   - struct omap_mbox1_fifo *fifo =
68   - &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
69   -
70   - mbox_write_reg(msg & 0xffff, fifo->data);
71   - mbox_write_reg(msg >> 16, fifo->cmd);
72   -}
73   -
74   -static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
75   -{
76   - return 0;
77   -}
78   -
79   -static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
80   -{
81   - struct omap_mbox1_fifo *fifo =
82   - &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
83   -
84   - return mbox_read_reg(fifo->flag);
85   -}
86   -
87   -/* irq */
88   -static void
89   -omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
90   -{
91   - if (irq == IRQ_RX)
92   - enable_irq(mbox->irq);
93   -}
94   -
95   -static void
96   -omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
97   -{
98   - if (irq == IRQ_RX)
99   - disable_irq(mbox->irq);
100   -}
101   -
102   -static int
103   -omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
104   -{
105   - if (irq == IRQ_TX)
106   - return 0;
107   - return 1;
108   -}
109   -
110   -static struct omap_mbox_ops omap1_mbox_ops = {
111   - .type = OMAP_MBOX_TYPE1,
112   - .fifo_read = omap1_mbox_fifo_read,
113   - .fifo_write = omap1_mbox_fifo_write,
114   - .fifo_empty = omap1_mbox_fifo_empty,
115   - .fifo_full = omap1_mbox_fifo_full,
116   - .enable_irq = omap1_mbox_enable_irq,
117   - .disable_irq = omap1_mbox_disable_irq,
118   - .is_irq = omap1_mbox_is_irq,
119   -};
120   -
121   -/* FIXME: the following struct should be created automatically by the user id */
122   -
123   -/* DSP */
124   -static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
125   - .tx_fifo = {
126   - .cmd = MAILBOX_ARM2DSP1b,
127   - .data = MAILBOX_ARM2DSP1,
128   - .flag = MAILBOX_ARM2DSP1_Flag,
129   - },
130   - .rx_fifo = {
131   - .cmd = MAILBOX_DSP2ARM1b,
132   - .data = MAILBOX_DSP2ARM1,
133   - .flag = MAILBOX_DSP2ARM1_Flag,
134   - },
135   -};
136   -
137   -static struct omap_mbox mbox_dsp_info = {
138   - .name = "dsp",
139   - .ops = &omap1_mbox_ops,
140   - .priv = &omap1_mbox_dsp_priv,
141   -};
142   -
143   -static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
144   -
145   -static int omap1_mbox_probe(struct platform_device *pdev)
146   -{
147   - struct resource *mem;
148   - int ret;
149   - struct omap_mbox **list;
150   -
151   - list = omap1_mboxes;
152   - list[0]->irq = platform_get_irq_byname(pdev, "dsp");
153   -
154   - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
155   - if (!mem)
156   - return -ENOENT;
157   -
158   - mbox_base = ioremap(mem->start, resource_size(mem));
159   - if (!mbox_base)
160   - return -ENOMEM;
161   -
162   - ret = omap_mbox_register(&pdev->dev, list);
163   - if (ret) {
164   - iounmap(mbox_base);
165   - return ret;
166   - }
167   -
168   - return 0;
169   -}
170   -
171   -static int omap1_mbox_remove(struct platform_device *pdev)
172   -{
173   - omap_mbox_unregister();
174   - iounmap(mbox_base);
175   - return 0;
176   -}
177   -
178   -static struct platform_driver omap1_mbox_driver = {
179   - .probe = omap1_mbox_probe,
180   - .remove = omap1_mbox_remove,
181   - .driver = {
182   - .name = "omap-mailbox",
183   - },
184   -};
185   -
186   -static int __init omap1_mbox_init(void)
187   -{
188   - return platform_driver_register(&omap1_mbox_driver);
189   -}
190   -
191   -static void __exit omap1_mbox_exit(void)
192   -{
193   - platform_driver_unregister(&omap1_mbox_driver);
194   -}
195   -
196   -module_init(omap1_mbox_init);
197   -module_exit(omap1_mbox_exit);
198   -
199   -MODULE_LICENSE("GPL v2");
200   -MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
201   -MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
202   -MODULE_ALIAS("platform:omap1-mailbox");
arch/arm/mach-omap2/Makefile
... ... @@ -203,9 +203,6 @@
203 203 obj-$(CONFIG_OMAP3_EMU) += emu.o
204 204 obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
205 205  
206   -obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
207   -mailbox_mach-objs := mailbox.o
208   -
209 206 iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o
210 207 obj-y += $(iommu-m) $(iommu-y)
211 208  
arch/arm/mach-omap2/devices.c
... ... @@ -328,7 +328,7 @@
328 328 return 0;
329 329 }
330 330  
331   -#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
  331 +#if defined(CONFIG_OMAP2PLUS_MBOX) || defined(CONFIG_OMAP2PLUS_MBOX_MODULE)
332 332 static inline void __init omap_init_mbox(void)
333 333 {
334 334 struct omap_hwmod *oh;
... ... @@ -352,7 +352,7 @@
352 352 }
353 353 #else
354 354 static inline void omap_init_mbox(void) { }
355   -#endif /* CONFIG_OMAP_MBOX_FWK */
  355 +#endif /* CONFIG_OMAP2PLUS_MBOX */
356 356  
357 357 static inline void omap_init_sti(void) {}
358 358  
arch/arm/mach-omap2/mailbox.c
1   -/*
2   - * Mailbox reservation modules for OMAP2/3
3   - *
4   - * Copyright (C) 2006-2009 Nokia Corporation
5   - * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
6   - * and Paul Mundt
7   - *
8   - * This file is subject to the terms and conditions of the GNU General Public
9   - * License. See the file "COPYING" in the main directory of this archive
10   - * for more details.
11   - */
12   -
13   -#include <linux/module.h>
14   -#include <linux/slab.h>
15   -#include <linux/clk.h>
16   -#include <linux/err.h>
17   -#include <linux/platform_device.h>
18   -#include <linux/io.h>
19   -#include <linux/pm_runtime.h>
20   -#include <linux/platform_data/mailbox-omap.h>
21   -
22   -#include <plat/mailbox.h>
23   -
24   -#define MAILBOX_REVISION 0x000
25   -#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
26   -#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
27   -#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
28   -#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
29   -#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
30   -
31   -#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u))
32   -#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u))
33   -#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u))
34   -
35   -#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
36   -#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
37   -
38   -#define MBOX_REG_SIZE 0x120
39   -
40   -#define OMAP4_MBOX_REG_SIZE 0x130
41   -
42   -#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
43   -#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
44   -
45   -static void __iomem *mbox_base;
46   -
47   -struct omap_mbox2_fifo {
48   - unsigned long msg;
49   - unsigned long fifo_stat;
50   - unsigned long msg_stat;
51   -};
52   -
53   -struct omap_mbox2_priv {
54   - struct omap_mbox2_fifo tx_fifo;
55   - struct omap_mbox2_fifo rx_fifo;
56   - unsigned long irqenable;
57   - unsigned long irqstatus;
58   - u32 newmsg_bit;
59   - u32 notfull_bit;
60   - u32 ctx[OMAP4_MBOX_NR_REGS];
61   - unsigned long irqdisable;
62   - u32 intr_type;
63   -};
64   -
65   -static inline unsigned int mbox_read_reg(size_t ofs)
66   -{
67   - return __raw_readl(mbox_base + ofs);
68   -}
69   -
70   -static inline void mbox_write_reg(u32 val, size_t ofs)
71   -{
72   - __raw_writel(val, mbox_base + ofs);
73   -}
74   -
75   -/* Mailbox H/W preparations */
76   -static int omap2_mbox_startup(struct omap_mbox *mbox)
77   -{
78   - u32 l;
79   -
80   - pm_runtime_enable(mbox->dev->parent);
81   - pm_runtime_get_sync(mbox->dev->parent);
82   -
83   - l = mbox_read_reg(MAILBOX_REVISION);
84   - pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
85   -
86   - return 0;
87   -}
88   -
89   -static void omap2_mbox_shutdown(struct omap_mbox *mbox)
90   -{
91   - pm_runtime_put_sync(mbox->dev->parent);
92   - pm_runtime_disable(mbox->dev->parent);
93   -}
94   -
95   -/* Mailbox FIFO handle functions */
96   -static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
97   -{
98   - struct omap_mbox2_fifo *fifo =
99   - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
100   - return (mbox_msg_t) mbox_read_reg(fifo->msg);
101   -}
102   -
103   -static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
104   -{
105   - struct omap_mbox2_fifo *fifo =
106   - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
107   - mbox_write_reg(msg, fifo->msg);
108   -}
109   -
110   -static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
111   -{
112   - struct omap_mbox2_fifo *fifo =
113   - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
114   - return (mbox_read_reg(fifo->msg_stat) == 0);
115   -}
116   -
117   -static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
118   -{
119   - struct omap_mbox2_fifo *fifo =
120   - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
121   - return mbox_read_reg(fifo->fifo_stat);
122   -}
123   -
124   -/* Mailbox IRQ handle functions */
125   -static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
126   -{
127   - struct omap_mbox2_priv *p = mbox->priv;
128   - u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
129   -
130   - l = mbox_read_reg(p->irqenable);
131   - l |= bit;
132   - mbox_write_reg(l, p->irqenable);
133   -}
134   -
135   -static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
136   -{
137   - struct omap_mbox2_priv *p = mbox->priv;
138   - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
139   -
140   - /*
141   - * Read and update the interrupt configuration register for pre-OMAP4.
142   - * OMAP4 and later SoCs have a dedicated interrupt disabling register.
143   - */
144   - if (!p->intr_type)
145   - bit = mbox_read_reg(p->irqdisable) & ~bit;
146   -
147   - mbox_write_reg(bit, p->irqdisable);
148   -}
149   -
150   -static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
151   -{
152   - struct omap_mbox2_priv *p = mbox->priv;
153   - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
154   -
155   - mbox_write_reg(bit, p->irqstatus);
156   -
157   - /* Flush posted write for irq status to avoid spurious interrupts */
158   - mbox_read_reg(p->irqstatus);
159   -}
160   -
161   -static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
162   -{
163   - struct omap_mbox2_priv *p = mbox->priv;
164   - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
165   - u32 enable = mbox_read_reg(p->irqenable);
166   - u32 status = mbox_read_reg(p->irqstatus);
167   -
168   - return (int)(enable & status & bit);
169   -}
170   -
171   -static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
172   -{
173   - int i;
174   - struct omap_mbox2_priv *p = mbox->priv;
175   - int nr_regs;
176   -
177   - if (p->intr_type)
178   - nr_regs = OMAP4_MBOX_NR_REGS;
179   - else
180   - nr_regs = MBOX_NR_REGS;
181   - for (i = 0; i < nr_regs; i++) {
182   - p->ctx[i] = mbox_read_reg(i * sizeof(u32));
183   -
184   - dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
185   - i, p->ctx[i]);
186   - }
187   -}
188   -
189   -static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
190   -{
191   - int i;
192   - struct omap_mbox2_priv *p = mbox->priv;
193   - int nr_regs;
194   -
195   - if (p->intr_type)
196   - nr_regs = OMAP4_MBOX_NR_REGS;
197   - else
198   - nr_regs = MBOX_NR_REGS;
199   - for (i = 0; i < nr_regs; i++) {
200   - mbox_write_reg(p->ctx[i], i * sizeof(u32));
201   -
202   - dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
203   - i, p->ctx[i]);
204   - }
205   -}
206   -
207   -static struct omap_mbox_ops omap2_mbox_ops = {
208   - .type = OMAP_MBOX_TYPE2,
209   - .startup = omap2_mbox_startup,
210   - .shutdown = omap2_mbox_shutdown,
211   - .fifo_read = omap2_mbox_fifo_read,
212   - .fifo_write = omap2_mbox_fifo_write,
213   - .fifo_empty = omap2_mbox_fifo_empty,
214   - .fifo_full = omap2_mbox_fifo_full,
215   - .enable_irq = omap2_mbox_enable_irq,
216   - .disable_irq = omap2_mbox_disable_irq,
217   - .ack_irq = omap2_mbox_ack_irq,
218   - .is_irq = omap2_mbox_is_irq,
219   - .save_ctx = omap2_mbox_save_ctx,
220   - .restore_ctx = omap2_mbox_restore_ctx,
221   -};
222   -
223   -static int omap2_mbox_probe(struct platform_device *pdev)
224   -{
225   - struct resource *mem;
226   - int ret;
227   - struct omap_mbox **list, *mbox, *mboxblk;
228   - struct omap_mbox2_priv *priv, *privblk;
229   - struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
230   - struct omap_mbox_dev_info *info;
231   - int i;
232   -
233   - if (!pdata || !pdata->info_cnt || !pdata->info) {
234   - pr_err("%s: platform not supported\n", __func__);
235   - return -ENODEV;
236   - }
237   -
238   - /* allocate one extra for marking end of list */
239   - list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
240   - if (!list)
241   - return -ENOMEM;
242   -
243   - mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
244   - if (!mboxblk) {
245   - ret = -ENOMEM;
246   - goto free_list;
247   - }
248   -
249   - privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
250   - if (!privblk) {
251   - ret = -ENOMEM;
252   - goto free_mboxblk;
253   - }
254   -
255   - info = pdata->info;
256   - for (i = 0; i < pdata->info_cnt; i++, info++, priv++) {
257   - priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id);
258   - priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
259   - priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id);
260   - priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id);
261   - priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
262   - priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
263   - if (pdata->intr_type) {
264   - priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id);
265   - priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id);
266   - priv->irqdisable =
267   - OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id);
268   - } else {
269   - priv->irqenable = MAILBOX_IRQENABLE(info->usr_id);
270   - priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id);
271   - priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id);
272   - }
273   - priv->intr_type = pdata->intr_type;
274   -
275   - mbox->priv = priv;
276   - mbox->name = info->name;
277   - mbox->ops = &omap2_mbox_ops;
278   - mbox->irq = platform_get_irq(pdev, info->irq_id);
279   - if (mbox->irq < 0) {
280   - ret = mbox->irq;
281   - goto free_privblk;
282   - }
283   - list[i] = mbox++;
284   - }
285   -
286   - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
287   - if (!mem) {
288   - ret = -ENOENT;
289   - goto free_privblk;
290   - }
291   -
292   - mbox_base = ioremap(mem->start, resource_size(mem));
293   - if (!mbox_base) {
294   - ret = -ENOMEM;
295   - goto free_privblk;
296   - }
297   -
298   - ret = omap_mbox_register(&pdev->dev, list);
299   - if (ret)
300   - goto unmap_mbox;
301   - platform_set_drvdata(pdev, list);
302   -
303   - return 0;
304   -
305   -unmap_mbox:
306   - iounmap(mbox_base);
307   -free_privblk:
308   - kfree(privblk);
309   -free_mboxblk:
310   - kfree(mboxblk);
311   -free_list:
312   - kfree(list);
313   - return ret;
314   -}
315   -
316   -static int omap2_mbox_remove(struct platform_device *pdev)
317   -{
318   - struct omap_mbox2_priv *privblk;
319   - struct omap_mbox **list = platform_get_drvdata(pdev);
320   - struct omap_mbox *mboxblk = list[0];
321   -
322   - privblk = mboxblk->priv;
323   - omap_mbox_unregister();
324   - iounmap(mbox_base);
325   - kfree(privblk);
326   - kfree(mboxblk);
327   - kfree(list);
328   - platform_set_drvdata(pdev, NULL);
329   -
330   - return 0;
331   -}
332   -
333   -static struct platform_driver omap2_mbox_driver = {
334   - .probe = omap2_mbox_probe,
335   - .remove = omap2_mbox_remove,
336   - .driver = {
337   - .name = "omap-mailbox",
338   - },
339   -};
340   -
341   -static int __init omap2_mbox_init(void)
342   -{
343   - return platform_driver_register(&omap2_mbox_driver);
344   -}
345   -
346   -static void __exit omap2_mbox_exit(void)
347   -{
348   - platform_driver_unregister(&omap2_mbox_driver);
349   -}
350   -
351   -module_init(omap2_mbox_init);
352   -module_exit(omap2_mbox_exit);
353   -
354   -MODULE_LICENSE("GPL v2");
355   -MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
356   -MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
357   -MODULE_AUTHOR("Paul Mundt");
358   -MODULE_ALIAS("platform:omap2-mailbox");
arch/arm/plat-omap/Kconfig
... ... @@ -86,22 +86,6 @@
86 86 to change the pin multiplexing setup. When there are no warnings
87 87 printed, it's safe to deselect OMAP_MUX for your product.
88 88  
89   -config OMAP_MBOX_FWK
90   - tristate "Mailbox framework support"
91   - depends on ARCH_OMAP && !ARCH_MULTIPLATFORM
92   - help
93   - Say Y here if you want to use OMAP Mailbox framework support for
94   - DSP, IVA1.0 and IVA2 in OMAP1/2/3.
95   -
96   -config OMAP_MBOX_KFIFO_SIZE
97   - int "Mailbox kfifo default buffer size (bytes)"
98   - depends on OMAP_MBOX_FWK
99   - default 256
100   - help
101   - Specify the default size of mailbox's kfifo buffers (bytes).
102   - This can also be changed at runtime (via the mbox_kfifo_size
103   - module parameter).
104   -
105 89 config OMAP_IOMMU_IVA2
106 90 bool
107 91  
arch/arm/plat-omap/Makefile
... ... @@ -16,7 +16,4 @@
16 16 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
17 17 i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
18 18 obj-y += $(i2c-omap-m) $(i2c-omap-y)
19   -
20   -# OMAP mailbox framework
21   -obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
arch/arm/plat-omap/include/plat/mailbox.h
1   -/* mailbox.h */
2   -
3   -#ifndef MAILBOX_H
4   -#define MAILBOX_H
5   -
6   -#include <linux/spinlock.h>
7   -#include <linux/workqueue.h>
8   -#include <linux/interrupt.h>
9   -#include <linux/device.h>
10   -#include <linux/kfifo.h>
11   -
12   -typedef u32 mbox_msg_t;
13   -struct omap_mbox;
14   -
15   -typedef int __bitwise omap_mbox_irq_t;
16   -#define IRQ_TX ((__force omap_mbox_irq_t) 1)
17   -#define IRQ_RX ((__force omap_mbox_irq_t) 2)
18   -
19   -typedef int __bitwise omap_mbox_type_t;
20   -#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
21   -#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
22   -
23   -struct omap_mbox_ops {
24   - omap_mbox_type_t type;
25   - int (*startup)(struct omap_mbox *mbox);
26   - void (*shutdown)(struct omap_mbox *mbox);
27   - /* fifo */
28   - mbox_msg_t (*fifo_read)(struct omap_mbox *mbox);
29   - void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
30   - int (*fifo_empty)(struct omap_mbox *mbox);
31   - int (*fifo_full)(struct omap_mbox *mbox);
32   - /* irq */
33   - void (*enable_irq)(struct omap_mbox *mbox,
34   - omap_mbox_irq_t irq);
35   - void (*disable_irq)(struct omap_mbox *mbox,
36   - omap_mbox_irq_t irq);
37   - void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
38   - int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
39   - /* ctx */
40   - void (*save_ctx)(struct omap_mbox *mbox);
41   - void (*restore_ctx)(struct omap_mbox *mbox);
42   -};
43   -
44   -struct omap_mbox_queue {
45   - spinlock_t lock;
46   - struct kfifo fifo;
47   - struct work_struct work;
48   - struct tasklet_struct tasklet;
49   - struct omap_mbox *mbox;
50   - bool full;
51   -};
52   -
53   -struct omap_mbox {
54   - const char *name;
55   - unsigned int irq;
56   - struct omap_mbox_queue *txq, *rxq;
57   - struct omap_mbox_ops *ops;
58   - struct device *dev;
59   - void *priv;
60   - int use_count;
61   - struct blocking_notifier_head notifier;
62   -};
63   -
64   -int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
65   -void omap_mbox_init_seq(struct omap_mbox *);
66   -
67   -struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb);
68   -void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb);
69   -
70   -int omap_mbox_register(struct device *parent, struct omap_mbox **);
71   -int omap_mbox_unregister(void);
72   -
73   -static inline void omap_mbox_save_ctx(struct omap_mbox *mbox)
74   -{
75   - if (!mbox->ops->save_ctx) {
76   - dev_err(mbox->dev, "%s:\tno save\n", __func__);
77   - return;
78   - }
79   -
80   - mbox->ops->save_ctx(mbox);
81   -}
82   -
83   -static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox)
84   -{
85   - if (!mbox->ops->restore_ctx) {
86   - dev_err(mbox->dev, "%s:\tno restore\n", __func__);
87   - return;
88   - }
89   -
90   - mbox->ops->restore_ctx(mbox);
91   -}
92   -
93   -static inline void omap_mbox_enable_irq(struct omap_mbox *mbox,
94   - omap_mbox_irq_t irq)
95   -{
96   - mbox->ops->enable_irq(mbox, irq);
97   -}
98   -
99   -static inline void omap_mbox_disable_irq(struct omap_mbox *mbox,
100   - omap_mbox_irq_t irq)
101   -{
102   - mbox->ops->disable_irq(mbox, irq);
103   -}
104   -
105   -#endif /* MAILBOX_H */
arch/arm/plat-omap/mailbox.c
1   -/*
2   - * OMAP mailbox driver
3   - *
4   - * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
5   - *
6   - * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
7   - *
8   - * This program is free software; you can redistribute it and/or
9   - * modify it under the terms of the GNU General Public License
10   - * version 2 as published by the Free Software Foundation.
11   - *
12   - * This program is distributed in the hope that it will be useful, but
13   - * WITHOUT ANY WARRANTY; without even the implied warranty of
14   - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   - * General Public License for more details.
16   - *
17   - * You should have received a copy of the GNU General Public License
18   - * along with this program; if not, write to the Free Software
19   - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   - * 02110-1301 USA
21   - *
22   - */
23   -
24   -#include <linux/interrupt.h>
25   -#include <linux/spinlock.h>
26   -#include <linux/mutex.h>
27   -#include <linux/delay.h>
28   -#include <linux/slab.h>
29   -#include <linux/kfifo.h>
30   -#include <linux/err.h>
31   -#include <linux/notifier.h>
32   -#include <linux/module.h>
33   -
34   -#include <plat/mailbox.h>
35   -
36   -static struct omap_mbox **mboxes;
37   -
38   -static int mbox_configured;
39   -static DEFINE_MUTEX(mbox_configured_lock);
40   -
41   -static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
42   -module_param(mbox_kfifo_size, uint, S_IRUGO);
43   -MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
44   -
45   -/* Mailbox FIFO handle functions */
46   -static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
47   -{
48   - return mbox->ops->fifo_read(mbox);
49   -}
50   -static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
51   -{
52   - mbox->ops->fifo_write(mbox, msg);
53   -}
54   -static inline int mbox_fifo_empty(struct omap_mbox *mbox)
55   -{
56   - return mbox->ops->fifo_empty(mbox);
57   -}
58   -static inline int mbox_fifo_full(struct omap_mbox *mbox)
59   -{
60   - return mbox->ops->fifo_full(mbox);
61   -}
62   -
63   -/* Mailbox IRQ handle functions */
64   -static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
65   -{
66   - if (mbox->ops->ack_irq)
67   - mbox->ops->ack_irq(mbox, irq);
68   -}
69   -static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
70   -{
71   - return mbox->ops->is_irq(mbox, irq);
72   -}
73   -
74   -/*
75   - * message sender
76   - */
77   -static int __mbox_poll_for_space(struct omap_mbox *mbox)
78   -{
79   - int ret = 0, i = 1000;
80   -
81   - while (mbox_fifo_full(mbox)) {
82   - if (mbox->ops->type == OMAP_MBOX_TYPE2)
83   - return -1;
84   - if (--i == 0)
85   - return -1;
86   - udelay(1);
87   - }
88   - return ret;
89   -}
90   -
91   -int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
92   -{
93   - struct omap_mbox_queue *mq = mbox->txq;
94   - int ret = 0, len;
95   -
96   - spin_lock_bh(&mq->lock);
97   -
98   - if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
99   - ret = -ENOMEM;
100   - goto out;
101   - }
102   -
103   - if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
104   - mbox_fifo_write(mbox, msg);
105   - goto out;
106   - }
107   -
108   - len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
109   - WARN_ON(len != sizeof(msg));
110   -
111   - tasklet_schedule(&mbox->txq->tasklet);
112   -
113   -out:
114   - spin_unlock_bh(&mq->lock);
115   - return ret;
116   -}
117   -EXPORT_SYMBOL(omap_mbox_msg_send);
118   -
119   -static void mbox_tx_tasklet(unsigned long tx_data)
120   -{
121   - struct omap_mbox *mbox = (struct omap_mbox *)tx_data;
122   - struct omap_mbox_queue *mq = mbox->txq;
123   - mbox_msg_t msg;
124   - int ret;
125   -
126   - while (kfifo_len(&mq->fifo)) {
127   - if (__mbox_poll_for_space(mbox)) {
128   - omap_mbox_enable_irq(mbox, IRQ_TX);
129   - break;
130   - }
131   -
132   - ret = kfifo_out(&mq->fifo, (unsigned char *)&msg,
133   - sizeof(msg));
134   - WARN_ON(ret != sizeof(msg));
135   -
136   - mbox_fifo_write(mbox, msg);
137   - }
138   -}
139   -
140   -/*
141   - * Message receiver(workqueue)
142   - */
143   -static void mbox_rx_work(struct work_struct *work)
144   -{
145   - struct omap_mbox_queue *mq =
146   - container_of(work, struct omap_mbox_queue, work);
147   - mbox_msg_t msg;
148   - int len;
149   -
150   - while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
151   - len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
152   - WARN_ON(len != sizeof(msg));
153   -
154   - blocking_notifier_call_chain(&mq->mbox->notifier, len,
155   - (void *)msg);
156   - spin_lock_irq(&mq->lock);
157   - if (mq->full) {
158   - mq->full = false;
159   - omap_mbox_enable_irq(mq->mbox, IRQ_RX);
160   - }
161   - spin_unlock_irq(&mq->lock);
162   - }
163   -}
164   -
165   -/*
166   - * Mailbox interrupt handler
167   - */
168   -static void __mbox_tx_interrupt(struct omap_mbox *mbox)
169   -{
170   - omap_mbox_disable_irq(mbox, IRQ_TX);
171   - ack_mbox_irq(mbox, IRQ_TX);
172   - tasklet_schedule(&mbox->txq->tasklet);
173   -}
174   -
175   -static void __mbox_rx_interrupt(struct omap_mbox *mbox)
176   -{
177   - struct omap_mbox_queue *mq = mbox->rxq;
178   - mbox_msg_t msg;
179   - int len;
180   -
181   - while (!mbox_fifo_empty(mbox)) {
182   - if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
183   - omap_mbox_disable_irq(mbox, IRQ_RX);
184   - mq->full = true;
185   - goto nomem;
186   - }
187   -
188   - msg = mbox_fifo_read(mbox);
189   -
190   - len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
191   - WARN_ON(len != sizeof(msg));
192   -
193   - if (mbox->ops->type == OMAP_MBOX_TYPE1)
194   - break;
195   - }
196   -
197   - /* no more messages in the fifo. clear IRQ source. */
198   - ack_mbox_irq(mbox, IRQ_RX);
199   -nomem:
200   - schedule_work(&mbox->rxq->work);
201   -}
202   -
203   -static irqreturn_t mbox_interrupt(int irq, void *p)
204   -{
205   - struct omap_mbox *mbox = p;
206   -
207   - if (is_mbox_irq(mbox, IRQ_TX))
208   - __mbox_tx_interrupt(mbox);
209   -
210   - if (is_mbox_irq(mbox, IRQ_RX))
211   - __mbox_rx_interrupt(mbox);
212   -
213   - return IRQ_HANDLED;
214   -}
215   -
216   -static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
217   - void (*work) (struct work_struct *),
218   - void (*tasklet)(unsigned long))
219   -{
220   - struct omap_mbox_queue *mq;
221   -
222   - mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
223   - if (!mq)
224   - return NULL;
225   -
226   - spin_lock_init(&mq->lock);
227   -
228   - if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
229   - goto error;
230   -
231   - if (work)
232   - INIT_WORK(&mq->work, work);
233   -
234   - if (tasklet)
235   - tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
236   - return mq;
237   -error:
238   - kfree(mq);
239   - return NULL;
240   -}
241   -
242   -static void mbox_queue_free(struct omap_mbox_queue *q)
243   -{
244   - kfifo_free(&q->fifo);
245   - kfree(q);
246   -}
247   -
248   -static int omap_mbox_startup(struct omap_mbox *mbox)
249   -{
250   - int ret = 0;
251   - struct omap_mbox_queue *mq;
252   -
253   - mutex_lock(&mbox_configured_lock);
254   - if (!mbox_configured++) {
255   - if (likely(mbox->ops->startup)) {
256   - ret = mbox->ops->startup(mbox);
257   - if (unlikely(ret))
258   - goto fail_startup;
259   - } else
260   - goto fail_startup;
261   - }
262   -
263   - if (!mbox->use_count++) {
264   - mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
265   - if (!mq) {
266   - ret = -ENOMEM;
267   - goto fail_alloc_txq;
268   - }
269   - mbox->txq = mq;
270   -
271   - mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
272   - if (!mq) {
273   - ret = -ENOMEM;
274   - goto fail_alloc_rxq;
275   - }
276   - mbox->rxq = mq;
277   - mq->mbox = mbox;
278   - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
279   - mbox->name, mbox);
280   - if (unlikely(ret)) {
281   - pr_err("failed to register mailbox interrupt:%d\n",
282   - ret);
283   - goto fail_request_irq;
284   - }
285   -
286   - omap_mbox_enable_irq(mbox, IRQ_RX);
287   - }
288   - mutex_unlock(&mbox_configured_lock);
289   - return 0;
290   -
291   -fail_request_irq:
292   - mbox_queue_free(mbox->rxq);
293   -fail_alloc_rxq:
294   - mbox_queue_free(mbox->txq);
295   -fail_alloc_txq:
296   - if (mbox->ops->shutdown)
297   - mbox->ops->shutdown(mbox);
298   - mbox->use_count--;
299   -fail_startup:
300   - mbox_configured--;
301   - mutex_unlock(&mbox_configured_lock);
302   - return ret;
303   -}
304   -
305   -static void omap_mbox_fini(struct omap_mbox *mbox)
306   -{
307   - mutex_lock(&mbox_configured_lock);
308   -
309   - if (!--mbox->use_count) {
310   - omap_mbox_disable_irq(mbox, IRQ_RX);
311   - free_irq(mbox->irq, mbox);
312   - tasklet_kill(&mbox->txq->tasklet);
313   - flush_work(&mbox->rxq->work);
314   - mbox_queue_free(mbox->txq);
315   - mbox_queue_free(mbox->rxq);
316   - }
317   -
318   - if (likely(mbox->ops->shutdown)) {
319   - if (!--mbox_configured)
320   - mbox->ops->shutdown(mbox);
321   - }
322   -
323   - mutex_unlock(&mbox_configured_lock);
324   -}
325   -
326   -struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
327   -{
328   - struct omap_mbox *_mbox, *mbox = NULL;
329   - int i, ret;
330   -
331   - if (!mboxes)
332   - return ERR_PTR(-EINVAL);
333   -
334   - for (i = 0; (_mbox = mboxes[i]); i++) {
335   - if (!strcmp(_mbox->name, name)) {
336   - mbox = _mbox;
337   - break;
338   - }
339   - }
340   -
341   - if (!mbox)
342   - return ERR_PTR(-ENOENT);
343   -
344   - if (nb)
345   - blocking_notifier_chain_register(&mbox->notifier, nb);
346   -
347   - ret = omap_mbox_startup(mbox);
348   - if (ret) {
349   - blocking_notifier_chain_unregister(&mbox->notifier, nb);
350   - return ERR_PTR(-ENODEV);
351   - }
352   -
353   - return mbox;
354   -}
355   -EXPORT_SYMBOL(omap_mbox_get);
356   -
357   -void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
358   -{
359   - blocking_notifier_chain_unregister(&mbox->notifier, nb);
360   - omap_mbox_fini(mbox);
361   -}
362   -EXPORT_SYMBOL(omap_mbox_put);
363   -
364   -static struct class omap_mbox_class = { .name = "mbox", };
365   -
366   -int omap_mbox_register(struct device *parent, struct omap_mbox **list)
367   -{
368   - int ret;
369   - int i;
370   -
371   - mboxes = list;
372   - if (!mboxes)
373   - return -EINVAL;
374   -
375   - for (i = 0; mboxes[i]; i++) {
376   - struct omap_mbox *mbox = mboxes[i];
377   - mbox->dev = device_create(&omap_mbox_class,
378   - parent, 0, mbox, "%s", mbox->name);
379   - if (IS_ERR(mbox->dev)) {
380   - ret = PTR_ERR(mbox->dev);
381   - goto err_out;
382   - }
383   -
384   - BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
385   - }
386   - return 0;
387   -
388   -err_out:
389   - while (i--)
390   - device_unregister(mboxes[i]->dev);
391   - return ret;
392   -}
393   -EXPORT_SYMBOL(omap_mbox_register);
394   -
395   -int omap_mbox_unregister(void)
396   -{
397   - int i;
398   -
399   - if (!mboxes)
400   - return -EINVAL;
401   -
402   - for (i = 0; mboxes[i]; i++)
403   - device_unregister(mboxes[i]->dev);
404   - mboxes = NULL;
405   - return 0;
406   -}
407   -EXPORT_SYMBOL(omap_mbox_unregister);
408   -
409   -static int __init omap_mbox_init(void)
410   -{
411   - int err;
412   -
413   - err = class_register(&omap_mbox_class);
414   - if (err)
415   - return err;
416   -
417   - /* kfifo size sanity check: alignment and minimal size */
418   - mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
419   - mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
420   - sizeof(mbox_msg_t));
421   -
422   - return 0;
423   -}
424   -subsys_initcall(omap_mbox_init);
425   -
426   -static void __exit omap_mbox_exit(void)
427   -{
428   - class_unregister(&omap_mbox_class);
429   -}
430   -module_exit(omap_mbox_exit);
431   -
432   -MODULE_LICENSE("GPL v2");
433   -MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
434   -MODULE_AUTHOR("Toshihiro Kobayashi");
435   -MODULE_AUTHOR("Hiroshi DOYU");
drivers/mailbox/Kconfig
... ... @@ -16,5 +16,39 @@
16 16 Management Engine, primarily for cpufreq. Say Y here if you want
17 17 to use the PL320 IPCM support.
18 18  
  19 +config OMAP_MBOX
  20 + tristate
  21 + help
  22 + This option is selected by any OMAP architecture specific mailbox
  23 + driver such as CONFIG_OMAP1_MBOX or CONFIG_OMAP2PLUS_MBOX. This
  24 + enables the common OMAP mailbox framework code.
  25 +
  26 +config OMAP1_MBOX
  27 + tristate "OMAP1 Mailbox framework support"
  28 + depends on ARCH_OMAP1
  29 + select OMAP_MBOX
  30 + help
  31 + Mailbox implementation for OMAP chips with hardware for
  32 + interprocessor communication involving DSP in OMAP1. Say Y here
  33 + if you want to use OMAP1 Mailbox framework support.
  34 +
  35 +config OMAP2PLUS_MBOX
  36 + tristate "OMAP2+ Mailbox framework support"
  37 + depends on ARCH_OMAP2PLUS
  38 + select OMAP_MBOX
  39 + help
  40 + Mailbox implementation for OMAP family chips with hardware for
  41 + interprocessor communication involving DSP, IVA1.0 and IVA2 in
  42 + OMAP2/3; or IPU, IVA HD and DSP in OMAP4/5. Say Y here if you
  43 + want to use OMAP2+ Mailbox framework support.
  44 +
  45 +config OMAP_MBOX_KFIFO_SIZE
  46 + int "Mailbox kfifo default buffer size (bytes)"
  47 + depends on OMAP2PLUS_MBOX || OMAP1_MBOX
  48 + default 256
  49 + help
  50 + Specify the default size of mailbox's kfifo buffers (bytes).
  51 + This can also be changed at runtime (via the mbox_kfifo_size
  52 + module parameter).
19 53 endif
drivers/mailbox/Makefile
1 1 obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
  2 +
  3 +obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o
  4 +obj-$(CONFIG_OMAP1_MBOX) += mailbox_omap1.o
  5 +mailbox_omap1-objs := mailbox-omap1.o
  6 +obj-$(CONFIG_OMAP2PLUS_MBOX) += mailbox_omap2.o
  7 +mailbox_omap2-objs := mailbox-omap2.o
drivers/mailbox/mailbox-omap1.c
  1 +/*
  2 + * Mailbox reservation modules for OMAP1
  3 + *
  4 + * Copyright (C) 2006-2009 Nokia Corporation
  5 + * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
  6 + *
  7 + * This file is subject to the terms and conditions of the GNU General Public
  8 + * License. See the file "COPYING" in the main directory of this archive
  9 + * for more details.
  10 + */
  11 +
  12 +#include <linux/module.h>
  13 +#include <linux/interrupt.h>
  14 +#include <linux/platform_device.h>
  15 +#include <linux/io.h>
  16 +
  17 +#include "omap-mbox.h"
  18 +
  19 +#define MAILBOX_ARM2DSP1 0x00
  20 +#define MAILBOX_ARM2DSP1b 0x04
  21 +#define MAILBOX_DSP2ARM1 0x08
  22 +#define MAILBOX_DSP2ARM1b 0x0c
  23 +#define MAILBOX_DSP2ARM2 0x10
  24 +#define MAILBOX_DSP2ARM2b 0x14
  25 +#define MAILBOX_ARM2DSP1_Flag 0x18
  26 +#define MAILBOX_DSP2ARM1_Flag 0x1c
  27 +#define MAILBOX_DSP2ARM2_Flag 0x20
  28 +
  29 +static void __iomem *mbox_base;
  30 +
  31 +struct omap_mbox1_fifo {
  32 + unsigned long cmd;
  33 + unsigned long data;
  34 + unsigned long flag;
  35 +};
  36 +
  37 +struct omap_mbox1_priv {
  38 + struct omap_mbox1_fifo tx_fifo;
  39 + struct omap_mbox1_fifo rx_fifo;
  40 +};
  41 +
  42 +static inline int mbox_read_reg(size_t ofs)
  43 +{
  44 + return __raw_readw(mbox_base + ofs);
  45 +}
  46 +
  47 +static inline void mbox_write_reg(u32 val, size_t ofs)
  48 +{
  49 + __raw_writew(val, mbox_base + ofs);
  50 +}
  51 +
  52 +/* msg */
  53 +static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
  54 +{
  55 + struct omap_mbox1_fifo *fifo =
  56 + &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
  57 + mbox_msg_t msg;
  58 +
  59 + msg = mbox_read_reg(fifo->data);
  60 + msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
  61 +
  62 + return msg;
  63 +}
  64 +
  65 +static void
  66 +omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
  67 +{
  68 + struct omap_mbox1_fifo *fifo =
  69 + &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
  70 +
  71 + mbox_write_reg(msg & 0xffff, fifo->data);
  72 + mbox_write_reg(msg >> 16, fifo->cmd);
  73 +}
  74 +
  75 +static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
  76 +{
  77 + return 0;
  78 +}
  79 +
  80 +static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
  81 +{
  82 + struct omap_mbox1_fifo *fifo =
  83 + &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
  84 +
  85 + return mbox_read_reg(fifo->flag);
  86 +}
  87 +
  88 +/* irq */
  89 +static void
  90 +omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  91 +{
  92 + if (irq == IRQ_RX)
  93 + enable_irq(mbox->irq);
  94 +}
  95 +
  96 +static void
  97 +omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  98 +{
  99 + if (irq == IRQ_RX)
  100 + disable_irq(mbox->irq);
  101 +}
  102 +
  103 +static int
  104 +omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  105 +{
  106 + if (irq == IRQ_TX)
  107 + return 0;
  108 + return 1;
  109 +}
  110 +
  111 +static struct omap_mbox_ops omap1_mbox_ops = {
  112 + .type = OMAP_MBOX_TYPE1,
  113 + .fifo_read = omap1_mbox_fifo_read,
  114 + .fifo_write = omap1_mbox_fifo_write,
  115 + .fifo_empty = omap1_mbox_fifo_empty,
  116 + .fifo_full = omap1_mbox_fifo_full,
  117 + .enable_irq = omap1_mbox_enable_irq,
  118 + .disable_irq = omap1_mbox_disable_irq,
  119 + .is_irq = omap1_mbox_is_irq,
  120 +};
  121 +
  122 +/* FIXME: the following struct should be created automatically by the user id */
  123 +
  124 +/* DSP */
  125 +static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
  126 + .tx_fifo = {
  127 + .cmd = MAILBOX_ARM2DSP1b,
  128 + .data = MAILBOX_ARM2DSP1,
  129 + .flag = MAILBOX_ARM2DSP1_Flag,
  130 + },
  131 + .rx_fifo = {
  132 + .cmd = MAILBOX_DSP2ARM1b,
  133 + .data = MAILBOX_DSP2ARM1,
  134 + .flag = MAILBOX_DSP2ARM1_Flag,
  135 + },
  136 +};
  137 +
  138 +static struct omap_mbox mbox_dsp_info = {
  139 + .name = "dsp",
  140 + .ops = &omap1_mbox_ops,
  141 + .priv = &omap1_mbox_dsp_priv,
  142 +};
  143 +
  144 +static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
  145 +
  146 +static int omap1_mbox_probe(struct platform_device *pdev)
  147 +{
  148 + struct resource *mem;
  149 + int ret;
  150 + struct omap_mbox **list;
  151 +
  152 + list = omap1_mboxes;
  153 + list[0]->irq = platform_get_irq_byname(pdev, "dsp");
  154 +
  155 + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  156 + if (!mem)
  157 + return -ENOENT;
  158 +
  159 + mbox_base = ioremap(mem->start, resource_size(mem));
  160 + if (!mbox_base)
  161 + return -ENOMEM;
  162 +
  163 + ret = omap_mbox_register(&pdev->dev, list);
  164 + if (ret) {
  165 + iounmap(mbox_base);
  166 + return ret;
  167 + }
  168 +
  169 + return 0;
  170 +}
  171 +
  172 +static int omap1_mbox_remove(struct platform_device *pdev)
  173 +{
  174 + omap_mbox_unregister();
  175 + iounmap(mbox_base);
  176 + return 0;
  177 +}
  178 +
  179 +static struct platform_driver omap1_mbox_driver = {
  180 + .probe = omap1_mbox_probe,
  181 + .remove = omap1_mbox_remove,
  182 + .driver = {
  183 + .name = "omap-mailbox",
  184 + },
  185 +};
  186 +
  187 +static int __init omap1_mbox_init(void)
  188 +{
  189 + return platform_driver_register(&omap1_mbox_driver);
  190 +}
  191 +
  192 +static void __exit omap1_mbox_exit(void)
  193 +{
  194 + platform_driver_unregister(&omap1_mbox_driver);
  195 +}
  196 +
  197 +module_init(omap1_mbox_init);
  198 +module_exit(omap1_mbox_exit);
  199 +
  200 +MODULE_LICENSE("GPL v2");
  201 +MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
  202 +MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
  203 +MODULE_ALIAS("platform:omap1-mailbox");
drivers/mailbox/mailbox-omap2.c
  1 +/*
  2 + * Mailbox reservation modules for OMAP2/3
  3 + *
  4 + * Copyright (C) 2006-2009 Nokia Corporation
  5 + * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
  6 + * and Paul Mundt
  7 + *
  8 + * This file is subject to the terms and conditions of the GNU General Public
  9 + * License. See the file "COPYING" in the main directory of this archive
  10 + * for more details.
  11 + */
  12 +
  13 +#include <linux/module.h>
  14 +#include <linux/slab.h>
  15 +#include <linux/clk.h>
  16 +#include <linux/err.h>
  17 +#include <linux/platform_device.h>
  18 +#include <linux/io.h>
  19 +#include <linux/pm_runtime.h>
  20 +#include <linux/platform_data/mailbox-omap.h>
  21 +
  22 +#include "omap-mbox.h"
  23 +
  24 +#define MAILBOX_REVISION 0x000
  25 +#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
  26 +#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
  27 +#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
  28 +#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
  29 +#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
  30 +
  31 +#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u))
  32 +#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u))
  33 +#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u))
  34 +
  35 +#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
  36 +#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
  37 +
  38 +#define MBOX_REG_SIZE 0x120
  39 +
  40 +#define OMAP4_MBOX_REG_SIZE 0x130
  41 +
  42 +#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
  43 +#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
  44 +
  45 +static void __iomem *mbox_base;
  46 +
  47 +struct omap_mbox2_fifo {
  48 + unsigned long msg;
  49 + unsigned long fifo_stat;
  50 + unsigned long msg_stat;
  51 +};
  52 +
  53 +struct omap_mbox2_priv {
  54 + struct omap_mbox2_fifo tx_fifo;
  55 + struct omap_mbox2_fifo rx_fifo;
  56 + unsigned long irqenable;
  57 + unsigned long irqstatus;
  58 + u32 newmsg_bit;
  59 + u32 notfull_bit;
  60 + u32 ctx[OMAP4_MBOX_NR_REGS];
  61 + unsigned long irqdisable;
  62 + u32 intr_type;
  63 +};
  64 +
  65 +static inline unsigned int mbox_read_reg(size_t ofs)
  66 +{
  67 + return __raw_readl(mbox_base + ofs);
  68 +}
  69 +
  70 +static inline void mbox_write_reg(u32 val, size_t ofs)
  71 +{
  72 + __raw_writel(val, mbox_base + ofs);
  73 +}
  74 +
  75 +/* Mailbox H/W preparations */
  76 +static int omap2_mbox_startup(struct omap_mbox *mbox)
  77 +{
  78 + u32 l;
  79 +
  80 + pm_runtime_enable(mbox->dev->parent);
  81 + pm_runtime_get_sync(mbox->dev->parent);
  82 +
  83 + l = mbox_read_reg(MAILBOX_REVISION);
  84 + pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
  85 +
  86 + return 0;
  87 +}
  88 +
  89 +static void omap2_mbox_shutdown(struct omap_mbox *mbox)
  90 +{
  91 + pm_runtime_put_sync(mbox->dev->parent);
  92 + pm_runtime_disable(mbox->dev->parent);
  93 +}
  94 +
  95 +/* Mailbox FIFO handle functions */
  96 +static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
  97 +{
  98 + struct omap_mbox2_fifo *fifo =
  99 + &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
  100 + return (mbox_msg_t) mbox_read_reg(fifo->msg);
  101 +}
  102 +
  103 +static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
  104 +{
  105 + struct omap_mbox2_fifo *fifo =
  106 + &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
  107 + mbox_write_reg(msg, fifo->msg);
  108 +}
  109 +
  110 +static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
  111 +{
  112 + struct omap_mbox2_fifo *fifo =
  113 + &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
  114 + return (mbox_read_reg(fifo->msg_stat) == 0);
  115 +}
  116 +
  117 +static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
  118 +{
  119 + struct omap_mbox2_fifo *fifo =
  120 + &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
  121 + return mbox_read_reg(fifo->fifo_stat);
  122 +}
  123 +
  124 +/* Mailbox IRQ handle functions */
  125 +static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  126 +{
  127 + struct omap_mbox2_priv *p = mbox->priv;
  128 + u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
  129 +
  130 + l = mbox_read_reg(p->irqenable);
  131 + l |= bit;
  132 + mbox_write_reg(l, p->irqenable);
  133 +}
  134 +
  135 +static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  136 +{
  137 + struct omap_mbox2_priv *p = mbox->priv;
  138 + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
  139 +
  140 + /*
  141 + * Read and update the interrupt configuration register for pre-OMAP4.
  142 + * OMAP4 and later SoCs have a dedicated interrupt disabling register.
  143 + */
  144 + if (!p->intr_type)
  145 + bit = mbox_read_reg(p->irqdisable) & ~bit;
  146 +
  147 + mbox_write_reg(bit, p->irqdisable);
  148 +}
  149 +
  150 +static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  151 +{
  152 + struct omap_mbox2_priv *p = mbox->priv;
  153 + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
  154 +
  155 + mbox_write_reg(bit, p->irqstatus);
  156 +
  157 + /* Flush posted write for irq status to avoid spurious interrupts */
  158 + mbox_read_reg(p->irqstatus);
  159 +}
  160 +
  161 +static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  162 +{
  163 + struct omap_mbox2_priv *p = mbox->priv;
  164 + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
  165 + u32 enable = mbox_read_reg(p->irqenable);
  166 + u32 status = mbox_read_reg(p->irqstatus);
  167 +
  168 + return (int)(enable & status & bit);
  169 +}
  170 +
  171 +static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
  172 +{
  173 + int i;
  174 + struct omap_mbox2_priv *p = mbox->priv;
  175 + int nr_regs;
  176 +
  177 + if (p->intr_type)
  178 + nr_regs = OMAP4_MBOX_NR_REGS;
  179 + else
  180 + nr_regs = MBOX_NR_REGS;
  181 + for (i = 0; i < nr_regs; i++) {
  182 + p->ctx[i] = mbox_read_reg(i * sizeof(u32));
  183 +
  184 + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
  185 + i, p->ctx[i]);
  186 + }
  187 +}
  188 +
  189 +static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
  190 +{
  191 + int i;
  192 + struct omap_mbox2_priv *p = mbox->priv;
  193 + int nr_regs;
  194 +
  195 + if (p->intr_type)
  196 + nr_regs = OMAP4_MBOX_NR_REGS;
  197 + else
  198 + nr_regs = MBOX_NR_REGS;
  199 + for (i = 0; i < nr_regs; i++) {
  200 + mbox_write_reg(p->ctx[i], i * sizeof(u32));
  201 +
  202 + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
  203 + i, p->ctx[i]);
  204 + }
  205 +}
  206 +
  207 +static struct omap_mbox_ops omap2_mbox_ops = {
  208 + .type = OMAP_MBOX_TYPE2,
  209 + .startup = omap2_mbox_startup,
  210 + .shutdown = omap2_mbox_shutdown,
  211 + .fifo_read = omap2_mbox_fifo_read,
  212 + .fifo_write = omap2_mbox_fifo_write,
  213 + .fifo_empty = omap2_mbox_fifo_empty,
  214 + .fifo_full = omap2_mbox_fifo_full,
  215 + .enable_irq = omap2_mbox_enable_irq,
  216 + .disable_irq = omap2_mbox_disable_irq,
  217 + .ack_irq = omap2_mbox_ack_irq,
  218 + .is_irq = omap2_mbox_is_irq,
  219 + .save_ctx = omap2_mbox_save_ctx,
  220 + .restore_ctx = omap2_mbox_restore_ctx,
  221 +};
  222 +
  223 +static int omap2_mbox_probe(struct platform_device *pdev)
  224 +{
  225 + struct resource *mem;
  226 + int ret;
  227 + struct omap_mbox **list, *mbox, *mboxblk;
  228 + struct omap_mbox2_priv *priv, *privblk;
  229 + struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
  230 + struct omap_mbox_dev_info *info;
  231 + int i;
  232 +
  233 + if (!pdata || !pdata->info_cnt || !pdata->info) {
  234 + pr_err("%s: platform not supported\n", __func__);
  235 + return -ENODEV;
  236 + }
  237 +
  238 + /* allocate one extra for marking end of list */
  239 + list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
  240 + if (!list)
  241 + return -ENOMEM;
  242 +
  243 + mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
  244 + if (!mboxblk) {
  245 + ret = -ENOMEM;
  246 + goto free_list;
  247 + }
  248 +
  249 + privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
  250 + if (!privblk) {
  251 + ret = -ENOMEM;
  252 + goto free_mboxblk;
  253 + }
  254 +
  255 + info = pdata->info;
  256 + for (i = 0; i < pdata->info_cnt; i++, info++, priv++) {
  257 + priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id);
  258 + priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
  259 + priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id);
  260 + priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id);
  261 + priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
  262 + priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
  263 + if (pdata->intr_type) {
  264 + priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id);
  265 + priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id);
  266 + priv->irqdisable =
  267 + OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id);
  268 + } else {
  269 + priv->irqenable = MAILBOX_IRQENABLE(info->usr_id);
  270 + priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id);
  271 + priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id);
  272 + }
  273 + priv->intr_type = pdata->intr_type;
  274 +
  275 + mbox->priv = priv;
  276 + mbox->name = info->name;
  277 + mbox->ops = &omap2_mbox_ops;
  278 + mbox->irq = platform_get_irq(pdev, info->irq_id);
  279 + if (mbox->irq < 0) {
  280 + ret = mbox->irq;
  281 + goto free_privblk;
  282 + }
  283 + list[i] = mbox++;
  284 + }
  285 +
  286 + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  287 + if (!mem) {
  288 + ret = -ENOENT;
  289 + goto free_privblk;
  290 + }
  291 +
  292 + mbox_base = ioremap(mem->start, resource_size(mem));
  293 + if (!mbox_base) {
  294 + ret = -ENOMEM;
  295 + goto free_privblk;
  296 + }
  297 +
  298 + ret = omap_mbox_register(&pdev->dev, list);
  299 + if (ret)
  300 + goto unmap_mbox;
  301 + platform_set_drvdata(pdev, list);
  302 +
  303 + return 0;
  304 +
  305 +unmap_mbox:
  306 + iounmap(mbox_base);
  307 +free_privblk:
  308 + kfree(privblk);
  309 +free_mboxblk:
  310 + kfree(mboxblk);
  311 +free_list:
  312 + kfree(list);
  313 + return ret;
  314 +}
  315 +
  316 +static int omap2_mbox_remove(struct platform_device *pdev)
  317 +{
  318 + struct omap_mbox2_priv *privblk;
  319 + struct omap_mbox **list = platform_get_drvdata(pdev);
  320 + struct omap_mbox *mboxblk = list[0];
  321 +
  322 + privblk = mboxblk->priv;
  323 + omap_mbox_unregister();
  324 + iounmap(mbox_base);
  325 + kfree(privblk);
  326 + kfree(mboxblk);
  327 + kfree(list);
  328 + platform_set_drvdata(pdev, NULL);
  329 +
  330 + return 0;
  331 +}
  332 +
  333 +static struct platform_driver omap2_mbox_driver = {
  334 + .probe = omap2_mbox_probe,
  335 + .remove = omap2_mbox_remove,
  336 + .driver = {
  337 + .name = "omap-mailbox",
  338 + },
  339 +};
  340 +
  341 +static int __init omap2_mbox_init(void)
  342 +{
  343 + return platform_driver_register(&omap2_mbox_driver);
  344 +}
  345 +
  346 +static void __exit omap2_mbox_exit(void)
  347 +{
  348 + platform_driver_unregister(&omap2_mbox_driver);
  349 +}
  350 +
  351 +module_init(omap2_mbox_init);
  352 +module_exit(omap2_mbox_exit);
  353 +
  354 +MODULE_LICENSE("GPL v2");
  355 +MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
  356 +MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
  357 +MODULE_AUTHOR("Paul Mundt");
  358 +MODULE_ALIAS("platform:omap2-mailbox");
drivers/mailbox/omap-mailbox.c
  1 +/*
  2 + * OMAP mailbox driver
  3 + *
  4 + * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
  5 + *
  6 + * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License
  10 + * version 2 as published by the Free Software Foundation.
  11 + *
  12 + * This program is distributed in the hope that it will be useful, but
  13 + * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20 + * 02110-1301 USA
  21 + *
  22 + */
  23 +
  24 +#include <linux/interrupt.h>
  25 +#include <linux/spinlock.h>
  26 +#include <linux/mutex.h>
  27 +#include <linux/delay.h>
  28 +#include <linux/slab.h>
  29 +#include <linux/kfifo.h>
  30 +#include <linux/err.h>
  31 +#include <linux/notifier.h>
  32 +#include <linux/module.h>
  33 +
  34 +#include "omap-mbox.h"
  35 +
  36 +static struct omap_mbox **mboxes;
  37 +
  38 +static int mbox_configured;
  39 +static DEFINE_MUTEX(mbox_configured_lock);
  40 +
  41 +static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
  42 +module_param(mbox_kfifo_size, uint, S_IRUGO);
  43 +MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
  44 +
  45 +/* Mailbox FIFO handle functions */
  46 +static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
  47 +{
  48 + return mbox->ops->fifo_read(mbox);
  49 +}
  50 +static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
  51 +{
  52 + mbox->ops->fifo_write(mbox, msg);
  53 +}
  54 +static inline int mbox_fifo_empty(struct omap_mbox *mbox)
  55 +{
  56 + return mbox->ops->fifo_empty(mbox);
  57 +}
  58 +static inline int mbox_fifo_full(struct omap_mbox *mbox)
  59 +{
  60 + return mbox->ops->fifo_full(mbox);
  61 +}
  62 +
  63 +/* Mailbox IRQ handle functions */
  64 +static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  65 +{
  66 + if (mbox->ops->ack_irq)
  67 + mbox->ops->ack_irq(mbox, irq);
  68 +}
  69 +static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  70 +{
  71 + return mbox->ops->is_irq(mbox, irq);
  72 +}
  73 +
  74 +/*
  75 + * message sender
  76 + */
  77 +static int __mbox_poll_for_space(struct omap_mbox *mbox)
  78 +{
  79 + int ret = 0, i = 1000;
  80 +
  81 + while (mbox_fifo_full(mbox)) {
  82 + if (mbox->ops->type == OMAP_MBOX_TYPE2)
  83 + return -1;
  84 + if (--i == 0)
  85 + return -1;
  86 + udelay(1);
  87 + }
  88 + return ret;
  89 +}
  90 +
  91 +int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
  92 +{
  93 + struct omap_mbox_queue *mq = mbox->txq;
  94 + int ret = 0, len;
  95 +
  96 + spin_lock_bh(&mq->lock);
  97 +
  98 + if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
  99 + ret = -ENOMEM;
  100 + goto out;
  101 + }
  102 +
  103 + if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
  104 + mbox_fifo_write(mbox, msg);
  105 + goto out;
  106 + }
  107 +
  108 + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
  109 + WARN_ON(len != sizeof(msg));
  110 +
  111 + tasklet_schedule(&mbox->txq->tasklet);
  112 +
  113 +out:
  114 + spin_unlock_bh(&mq->lock);
  115 + return ret;
  116 +}
  117 +EXPORT_SYMBOL(omap_mbox_msg_send);
  118 +
  119 +void omap_mbox_save_ctx(struct omap_mbox *mbox)
  120 +{
  121 + if (!mbox->ops->save_ctx) {
  122 + dev_err(mbox->dev, "%s:\tno save\n", __func__);
  123 + return;
  124 + }
  125 +
  126 + mbox->ops->save_ctx(mbox);
  127 +}
  128 +EXPORT_SYMBOL(omap_mbox_save_ctx);
  129 +
  130 +void omap_mbox_restore_ctx(struct omap_mbox *mbox)
  131 +{
  132 + if (!mbox->ops->restore_ctx) {
  133 + dev_err(mbox->dev, "%s:\tno restore\n", __func__);
  134 + return;
  135 + }
  136 +
  137 + mbox->ops->restore_ctx(mbox);
  138 +}
  139 +EXPORT_SYMBOL(omap_mbox_restore_ctx);
  140 +
  141 +void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  142 +{
  143 + mbox->ops->enable_irq(mbox, irq);
  144 +}
  145 +EXPORT_SYMBOL(omap_mbox_enable_irq);
  146 +
  147 +void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
  148 +{
  149 + mbox->ops->disable_irq(mbox, irq);
  150 +}
  151 +EXPORT_SYMBOL(omap_mbox_disable_irq);
  152 +
  153 +static void mbox_tx_tasklet(unsigned long tx_data)
  154 +{
  155 + struct omap_mbox *mbox = (struct omap_mbox *)tx_data;
  156 + struct omap_mbox_queue *mq = mbox->txq;
  157 + mbox_msg_t msg;
  158 + int ret;
  159 +
  160 + while (kfifo_len(&mq->fifo)) {
  161 + if (__mbox_poll_for_space(mbox)) {
  162 + omap_mbox_enable_irq(mbox, IRQ_TX);
  163 + break;
  164 + }
  165 +
  166 + ret = kfifo_out(&mq->fifo, (unsigned char *)&msg,
  167 + sizeof(msg));
  168 + WARN_ON(ret != sizeof(msg));
  169 +
  170 + mbox_fifo_write(mbox, msg);
  171 + }
  172 +}
  173 +
  174 +/*
  175 + * Message receiver(workqueue)
  176 + */
  177 +static void mbox_rx_work(struct work_struct *work)
  178 +{
  179 + struct omap_mbox_queue *mq =
  180 + container_of(work, struct omap_mbox_queue, work);
  181 + mbox_msg_t msg;
  182 + int len;
  183 +
  184 + while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
  185 + len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
  186 + WARN_ON(len != sizeof(msg));
  187 +
  188 + blocking_notifier_call_chain(&mq->mbox->notifier, len,
  189 + (void *)msg);
  190 + spin_lock_irq(&mq->lock);
  191 + if (mq->full) {
  192 + mq->full = false;
  193 + omap_mbox_enable_irq(mq->mbox, IRQ_RX);
  194 + }
  195 + spin_unlock_irq(&mq->lock);
  196 + }
  197 +}
  198 +
  199 +/*
  200 + * Mailbox interrupt handler
  201 + */
  202 +static void __mbox_tx_interrupt(struct omap_mbox *mbox)
  203 +{
  204 + omap_mbox_disable_irq(mbox, IRQ_TX);
  205 + ack_mbox_irq(mbox, IRQ_TX);
  206 + tasklet_schedule(&mbox->txq->tasklet);
  207 +}
  208 +
  209 +static void __mbox_rx_interrupt(struct omap_mbox *mbox)
  210 +{
  211 + struct omap_mbox_queue *mq = mbox->rxq;
  212 + mbox_msg_t msg;
  213 + int len;
  214 +
  215 + while (!mbox_fifo_empty(mbox)) {
  216 + if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
  217 + omap_mbox_disable_irq(mbox, IRQ_RX);
  218 + mq->full = true;
  219 + goto nomem;
  220 + }
  221 +
  222 + msg = mbox_fifo_read(mbox);
  223 +
  224 + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
  225 + WARN_ON(len != sizeof(msg));
  226 +
  227 + if (mbox->ops->type == OMAP_MBOX_TYPE1)
  228 + break;
  229 + }
  230 +
  231 + /* no more messages in the fifo. clear IRQ source. */
  232 + ack_mbox_irq(mbox, IRQ_RX);
  233 +nomem:
  234 + schedule_work(&mbox->rxq->work);
  235 +}
  236 +
  237 +static irqreturn_t mbox_interrupt(int irq, void *p)
  238 +{
  239 + struct omap_mbox *mbox = p;
  240 +
  241 + if (is_mbox_irq(mbox, IRQ_TX))
  242 + __mbox_tx_interrupt(mbox);
  243 +
  244 + if (is_mbox_irq(mbox, IRQ_RX))
  245 + __mbox_rx_interrupt(mbox);
  246 +
  247 + return IRQ_HANDLED;
  248 +}
  249 +
  250 +static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
  251 + void (*work) (struct work_struct *),
  252 + void (*tasklet)(unsigned long))
  253 +{
  254 + struct omap_mbox_queue *mq;
  255 +
  256 + mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
  257 + if (!mq)
  258 + return NULL;
  259 +
  260 + spin_lock_init(&mq->lock);
  261 +
  262 + if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
  263 + goto error;
  264 +
  265 + if (work)
  266 + INIT_WORK(&mq->work, work);
  267 +
  268 + if (tasklet)
  269 + tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
  270 + return mq;
  271 +error:
  272 + kfree(mq);
  273 + return NULL;
  274 +}
  275 +
  276 +static void mbox_queue_free(struct omap_mbox_queue *q)
  277 +{
  278 + kfifo_free(&q->fifo);
  279 + kfree(q);
  280 +}
  281 +
  282 +static int omap_mbox_startup(struct omap_mbox *mbox)
  283 +{
  284 + int ret = 0;
  285 + struct omap_mbox_queue *mq;
  286 +
  287 + mutex_lock(&mbox_configured_lock);
  288 + if (!mbox_configured++) {
  289 + if (likely(mbox->ops->startup)) {
  290 + ret = mbox->ops->startup(mbox);
  291 + if (unlikely(ret))
  292 + goto fail_startup;
  293 + } else
  294 + goto fail_startup;
  295 + }
  296 +
  297 + if (!mbox->use_count++) {
  298 + mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
  299 + if (!mq) {
  300 + ret = -ENOMEM;
  301 + goto fail_alloc_txq;
  302 + }
  303 + mbox->txq = mq;
  304 +
  305 + mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
  306 + if (!mq) {
  307 + ret = -ENOMEM;
  308 + goto fail_alloc_rxq;
  309 + }
  310 + mbox->rxq = mq;
  311 + mq->mbox = mbox;
  312 + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
  313 + mbox->name, mbox);
  314 + if (unlikely(ret)) {
  315 + pr_err("failed to register mailbox interrupt:%d\n",
  316 + ret);
  317 + goto fail_request_irq;
  318 + }
  319 +
  320 + omap_mbox_enable_irq(mbox, IRQ_RX);
  321 + }
  322 + mutex_unlock(&mbox_configured_lock);
  323 + return 0;
  324 +
  325 +fail_request_irq:
  326 + mbox_queue_free(mbox->rxq);
  327 +fail_alloc_rxq:
  328 + mbox_queue_free(mbox->txq);
  329 +fail_alloc_txq:
  330 + if (mbox->ops->shutdown)
  331 + mbox->ops->shutdown(mbox);
  332 + mbox->use_count--;
  333 +fail_startup:
  334 + mbox_configured--;
  335 + mutex_unlock(&mbox_configured_lock);
  336 + return ret;
  337 +}
  338 +
  339 +static void omap_mbox_fini(struct omap_mbox *mbox)
  340 +{
  341 + mutex_lock(&mbox_configured_lock);
  342 +
  343 + if (!--mbox->use_count) {
  344 + omap_mbox_disable_irq(mbox, IRQ_RX);
  345 + free_irq(mbox->irq, mbox);
  346 + tasklet_kill(&mbox->txq->tasklet);
  347 + flush_work(&mbox->rxq->work);
  348 + mbox_queue_free(mbox->txq);
  349 + mbox_queue_free(mbox->rxq);
  350 + }
  351 +
  352 + if (likely(mbox->ops->shutdown)) {
  353 + if (!--mbox_configured)
  354 + mbox->ops->shutdown(mbox);
  355 + }
  356 +
  357 + mutex_unlock(&mbox_configured_lock);
  358 +}
  359 +
  360 +struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
  361 +{
  362 + struct omap_mbox *_mbox, *mbox = NULL;
  363 + int i, ret;
  364 +
  365 + if (!mboxes)
  366 + return ERR_PTR(-EINVAL);
  367 +
  368 + for (i = 0; (_mbox = mboxes[i]); i++) {
  369 + if (!strcmp(_mbox->name, name)) {
  370 + mbox = _mbox;
  371 + break;
  372 + }
  373 + }
  374 +
  375 + if (!mbox)
  376 + return ERR_PTR(-ENOENT);
  377 +
  378 + if (nb)
  379 + blocking_notifier_chain_register(&mbox->notifier, nb);
  380 +
  381 + ret = omap_mbox_startup(mbox);
  382 + if (ret) {
  383 + blocking_notifier_chain_unregister(&mbox->notifier, nb);
  384 + return ERR_PTR(-ENODEV);
  385 + }
  386 +
  387 + return mbox;
  388 +}
  389 +EXPORT_SYMBOL(omap_mbox_get);
  390 +
  391 +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
  392 +{
  393 + blocking_notifier_chain_unregister(&mbox->notifier, nb);
  394 + omap_mbox_fini(mbox);
  395 +}
  396 +EXPORT_SYMBOL(omap_mbox_put);
  397 +
  398 +static struct class omap_mbox_class = { .name = "mbox", };
  399 +
  400 +int omap_mbox_register(struct device *parent, struct omap_mbox **list)
  401 +{
  402 + int ret;
  403 + int i;
  404 +
  405 + mboxes = list;
  406 + if (!mboxes)
  407 + return -EINVAL;
  408 +
  409 + for (i = 0; mboxes[i]; i++) {
  410 + struct omap_mbox *mbox = mboxes[i];
  411 + mbox->dev = device_create(&omap_mbox_class,
  412 + parent, 0, mbox, "%s", mbox->name);
  413 + if (IS_ERR(mbox->dev)) {
  414 + ret = PTR_ERR(mbox->dev);
  415 + goto err_out;
  416 + }
  417 +
  418 + BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
  419 + }
  420 + return 0;
  421 +
  422 +err_out:
  423 + while (i--)
  424 + device_unregister(mboxes[i]->dev);
  425 + return ret;
  426 +}
  427 +EXPORT_SYMBOL(omap_mbox_register);
  428 +
  429 +int omap_mbox_unregister(void)
  430 +{
  431 + int i;
  432 +
  433 + if (!mboxes)
  434 + return -EINVAL;
  435 +
  436 + for (i = 0; mboxes[i]; i++)
  437 + device_unregister(mboxes[i]->dev);
  438 + mboxes = NULL;
  439 + return 0;
  440 +}
  441 +EXPORT_SYMBOL(omap_mbox_unregister);
  442 +
  443 +static int __init omap_mbox_init(void)
  444 +{
  445 + int err;
  446 +
  447 + err = class_register(&omap_mbox_class);
  448 + if (err)
  449 + return err;
  450 +
  451 + /* kfifo size sanity check: alignment and minimal size */
  452 + mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
  453 + mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
  454 + sizeof(mbox_msg_t));
  455 +
  456 + return 0;
  457 +}
  458 +subsys_initcall(omap_mbox_init);
  459 +
  460 +static void __exit omap_mbox_exit(void)
  461 +{
  462 + class_unregister(&omap_mbox_class);
  463 +}
  464 +module_exit(omap_mbox_exit);
  465 +
  466 +MODULE_LICENSE("GPL v2");
  467 +MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
  468 +MODULE_AUTHOR("Toshihiro Kobayashi");
  469 +MODULE_AUTHOR("Hiroshi DOYU");
drivers/mailbox/omap-mbox.h
  1 +/*
  2 + * omap-mbox.h: OMAP mailbox internal definitions
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License version 2 as
  6 + * published by the Free Software Foundation.
  7 + */
  8 +
  9 +#ifndef OMAP_MBOX_H
  10 +#define OMAP_MBOX_H
  11 +
  12 +#include <linux/device.h>
  13 +#include <linux/interrupt.h>
  14 +#include <linux/kfifo.h>
  15 +#include <linux/spinlock.h>
  16 +#include <linux/workqueue.h>
  17 +#include <linux/omap-mailbox.h>
  18 +
  19 +typedef int __bitwise omap_mbox_type_t;
  20 +#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
  21 +#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
  22 +
  23 +struct omap_mbox_ops {
  24 + omap_mbox_type_t type;
  25 + int (*startup)(struct omap_mbox *mbox);
  26 + void (*shutdown)(struct omap_mbox *mbox);
  27 + /* fifo */
  28 + mbox_msg_t (*fifo_read)(struct omap_mbox *mbox);
  29 + void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
  30 + int (*fifo_empty)(struct omap_mbox *mbox);
  31 + int (*fifo_full)(struct omap_mbox *mbox);
  32 + /* irq */
  33 + void (*enable_irq)(struct omap_mbox *mbox,
  34 + omap_mbox_irq_t irq);
  35 + void (*disable_irq)(struct omap_mbox *mbox,
  36 + omap_mbox_irq_t irq);
  37 + void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
  38 + int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
  39 + /* ctx */
  40 + void (*save_ctx)(struct omap_mbox *mbox);
  41 + void (*restore_ctx)(struct omap_mbox *mbox);
  42 +};
  43 +
  44 +struct omap_mbox_queue {
  45 + spinlock_t lock;
  46 + struct kfifo fifo;
  47 + struct work_struct work;
  48 + struct tasklet_struct tasklet;
  49 + struct omap_mbox *mbox;
  50 + bool full;
  51 +};
  52 +
  53 +struct omap_mbox {
  54 + const char *name;
  55 + unsigned int irq;
  56 + struct omap_mbox_queue *txq, *rxq;
  57 + struct omap_mbox_ops *ops;
  58 + struct device *dev;
  59 + void *priv;
  60 + int use_count;
  61 + struct blocking_notifier_head notifier;
  62 +};
  63 +
  64 +int omap_mbox_register(struct device *parent, struct omap_mbox **);
  65 +int omap_mbox_unregister(void);
  66 +
  67 +#endif /* OMAP_MBOX_H */
drivers/remoteproc/Kconfig
... ... @@ -14,8 +14,9 @@
14 14 depends on HAS_DMA
15 15 depends on ARCH_OMAP4 || SOC_OMAP5
16 16 depends on OMAP_IOMMU
17   - depends on OMAP_MBOX_FWK
18 17 select REMOTEPROC
  18 + select MAILBOX
  19 + select OMAP2PLUS_MBOX
19 20 select RPMSG
20 21 help
21 22 Say y here to support OMAP's remote processors (dual M3
drivers/remoteproc/omap_remoteproc.c
... ... @@ -27,8 +27,8 @@
27 27 #include <linux/platform_device.h>
28 28 #include <linux/dma-mapping.h>
29 29 #include <linux/remoteproc.h>
  30 +#include <linux/omap-mailbox.h>
30 31  
31   -#include <plat/mailbox.h>
32 32 #include <linux/platform_data/remoteproc-omap.h>
33 33  
34 34 #include "omap_remoteproc.h"
drivers/staging/tidspbridge/Kconfig
... ... @@ -5,7 +5,8 @@
5 5 menuconfig TIDSPBRIDGE
6 6 tristate "DSP Bridge driver"
7 7 depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM
8   - select OMAP_MBOX_FWK
  8 + select MAILBOX
  9 + select OMAP2PLUS_MBOX
9 10 help
10 11 DSP/BIOS Bridge is designed for platforms that contain a GPP and
11 12 one or more attached DSPs. The GPP is considered the master or
drivers/staging/tidspbridge/include/dspbridge/host_os.h
... ... @@ -41,7 +41,7 @@
41 41 #include <linux/ioport.h>
42 42 #include <linux/platform_device.h>
43 43 #include <linux/clk.h>
44   -#include <plat/mailbox.h>
  44 +#include <linux/omap-mailbox.h>
45 45 #include <linux/pagemap.h>
46 46 #include <asm/cacheflush.h>
47 47 #include <linux/dma-mapping.h>
include/linux/omap-mailbox.h
  1 +/*
  2 + * omap-mailbox: interprocessor communication module for OMAP
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License version 2 as
  6 + * published by the Free Software Foundation.
  7 + */
  8 +
  9 +#ifndef OMAP_MAILBOX_H
  10 +#define OMAP_MAILBOX_H
  11 +
  12 +typedef u32 mbox_msg_t;
  13 +struct omap_mbox;
  14 +
  15 +typedef int __bitwise omap_mbox_irq_t;
  16 +#define IRQ_TX ((__force omap_mbox_irq_t) 1)
  17 +#define IRQ_RX ((__force omap_mbox_irq_t) 2)
  18 +
  19 +int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
  20 +
  21 +struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb);
  22 +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb);
  23 +
  24 +void omap_mbox_save_ctx(struct omap_mbox *mbox);
  25 +void omap_mbox_restore_ctx(struct omap_mbox *mbox);
  26 +void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq);
  27 +void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq);
  28 +
  29 +#endif /* OMAP_MAILBOX_H */