aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-07-29 11:32:40 -0400
committerArnd Bergmann <arnd@arndb.de>2014-07-29 11:32:40 -0400
commitf64a3c895bce1c703e706b8ee0badb39918c7dee (patch)
tree4e00747d92d1f2330808f223ce4d5b081f2159fb
parent537994aa4708d26a577024b355ad1318ad49b552 (diff)
parent72c1c8179cdc5ba7208d375bd3f104659fc50ad0 (diff)
Merge tag 'omap-for-v3.17/mailbox-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers
Merge "late omap mailbox clean-up, driver parts" from Tony Lindgren: Driver specific omap mailbox cleanup. Mostly to remove broken legacy code for omap1 and move things towards device tree. These patches were posted a while back, but I did not realize I was supposed to merge the driver related parts too. So apologies for a late pull request on these changes. * tag 'omap-for-v3.17/mailbox-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: mailbox/omap: add a parent structure for every IP instance mailbox/omap: remove the private mailbox structure mailbox/omap: consolidate OMAP mailbox driver mailbox/omap: simplify the fifo assignment by using macros mailbox/omap: remove omap_mbox_type_t from mailbox ops mailbox/omap: remove OMAP1 mailbox driver mailbox/omap: use devm_* interfaces Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/arm/configs/omap1_defconfig2
-rw-r--r--drivers/mailbox/Kconfig19
-rw-r--r--drivers/mailbox/Makefile6
-rw-r--r--drivers/mailbox/mailbox-omap1.c203
-rw-r--r--drivers/mailbox/mailbox-omap2.c357
-rw-r--r--drivers/mailbox/omap-mailbox.c444
-rw-r--r--drivers/mailbox/omap-mbox.h67
7 files changed, 360 insertions, 738 deletions
diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
index ce541bb3c2de..115cda9f3260 100644
--- a/arch/arm/configs/omap1_defconfig
+++ b/arch/arm/configs/omap1_defconfig
@@ -26,8 +26,6 @@ CONFIG_ARCH_OMAP=y
26CONFIG_ARCH_OMAP1=y 26CONFIG_ARCH_OMAP1=y
27CONFIG_OMAP_RESET_CLOCKS=y 27CONFIG_OMAP_RESET_CLOCKS=y
28# CONFIG_OMAP_MUX is not set 28# CONFIG_OMAP_MUX is not set
29CONFIG_MAILBOX=y
30CONFIG_OMAP1_MBOX=y
31CONFIG_OMAP_32K_TIMER=y 29CONFIG_OMAP_32K_TIMER=y
32CONFIG_OMAP_DM_TIMER=y 30CONFIG_OMAP_DM_TIMER=y
33CONFIG_ARCH_OMAP730=y 31CONFIG_ARCH_OMAP730=y
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index c8b5c13bcd05..9fd9c6717e0c 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -16,26 +16,9 @@ config PL320_MBOX
16 Management Engine, primarily for cpufreq. Say Y here if you want 16 Management Engine, primarily for cpufreq. Say Y here if you want
17 to use the PL320 IPCM support. 17 to use the PL320 IPCM support.
18 18
19config 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
26config 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
35config OMAP2PLUS_MBOX 19config OMAP2PLUS_MBOX
36 tristate "OMAP2+ Mailbox framework support" 20 tristate "OMAP2+ Mailbox framework support"
37 depends on ARCH_OMAP2PLUS 21 depends on ARCH_OMAP2PLUS
38 select OMAP_MBOX
39 help 22 help
40 Mailbox implementation for OMAP family chips with hardware for 23 Mailbox implementation for OMAP family chips with hardware for
41 interprocessor communication involving DSP, IVA1.0 and IVA2 in 24 interprocessor communication involving DSP, IVA1.0 and IVA2 in
@@ -44,7 +27,7 @@ config OMAP2PLUS_MBOX
44 27
45config OMAP_MBOX_KFIFO_SIZE 28config OMAP_MBOX_KFIFO_SIZE
46 int "Mailbox kfifo default buffer size (bytes)" 29 int "Mailbox kfifo default buffer size (bytes)"
47 depends on OMAP2PLUS_MBOX || OMAP1_MBOX 30 depends on OMAP2PLUS_MBOX
48 default 256 31 default 256
49 help 32 help
50 Specify the default size of mailbox's kfifo buffers (bytes). 33 Specify the default size of mailbox's kfifo buffers (bytes).
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index e0facb34084a..6d184dbcaca8 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -1,7 +1,3 @@
1obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o 1obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
2 2
3obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o 3obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o
4obj-$(CONFIG_OMAP1_MBOX) += mailbox_omap1.o
5mailbox_omap1-objs := mailbox-omap1.o
6obj-$(CONFIG_OMAP2PLUS_MBOX) += mailbox_omap2.o
7mailbox_omap2-objs := mailbox-omap2.o
diff --git a/drivers/mailbox/mailbox-omap1.c b/drivers/mailbox/mailbox-omap1.c
deleted file mode 100644
index 9001b7633f10..000000000000
--- a/drivers/mailbox/mailbox-omap1.c
+++ /dev/null
@@ -1,203 +0,0 @@
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
29static void __iomem *mbox_base;
30
31struct omap_mbox1_fifo {
32 unsigned long cmd;
33 unsigned long data;
34 unsigned long flag;
35};
36
37struct omap_mbox1_priv {
38 struct omap_mbox1_fifo tx_fifo;
39 struct omap_mbox1_fifo rx_fifo;
40};
41
42static inline int mbox_read_reg(size_t ofs)
43{
44 return __raw_readw(mbox_base + ofs);
45}
46
47static inline void mbox_write_reg(u32 val, size_t ofs)
48{
49 __raw_writew(val, mbox_base + ofs);
50}
51
52/* msg */
53static 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
65static void
66omap1_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
75static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
76{
77 return 0;
78}
79
80static 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 */
89static void
90omap1_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
96static void
97omap1_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
103static int
104omap1_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
111static 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 */
125static 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
138static struct omap_mbox mbox_dsp_info = {
139 .name = "dsp",
140 .ops = &omap1_mbox_ops,
141 .priv = &omap1_mbox_dsp_priv,
142};
143
144static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
145
146static 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
172static int omap1_mbox_remove(struct platform_device *pdev)
173{
174 omap_mbox_unregister();
175 iounmap(mbox_base);
176 return 0;
177}
178
179static 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
187static int __init omap1_mbox_init(void)
188{
189 return platform_driver_register(&omap1_mbox_driver);
190}
191
192static void __exit omap1_mbox_exit(void)
193{
194 platform_driver_unregister(&omap1_mbox_driver);
195}
196
197module_init(omap1_mbox_init);
198module_exit(omap1_mbox_exit);
199
200MODULE_LICENSE("GPL v2");
201MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
202MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
203MODULE_ALIAS("platform:omap1-mailbox");
diff --git a/drivers/mailbox/mailbox-omap2.c b/drivers/mailbox/mailbox-omap2.c
deleted file mode 100644
index 42d2b893ea67..000000000000
--- a/drivers/mailbox/mailbox-omap2.c
+++ /dev/null
@@ -1,357 +0,0 @@
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
45static void __iomem *mbox_base;
46
47struct omap_mbox2_fifo {
48 unsigned long msg;
49 unsigned long fifo_stat;
50 unsigned long msg_stat;
51};
52
53struct 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
65static inline unsigned int mbox_read_reg(size_t ofs)
66{
67 return __raw_readl(mbox_base + ofs);
68}
69
70static 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 */
76static 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
89static 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 */
96static 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
103static 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
110static 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
117static 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 */
125static 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
135static 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
150static 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
161static 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
171static 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
189static 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
207static 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
223static 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
305unmap_mbox:
306 iounmap(mbox_base);
307free_privblk:
308 kfree(privblk);
309free_mboxblk:
310 kfree(mboxblk);
311free_list:
312 kfree(list);
313 return ret;
314}
315
316static 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
329 return 0;
330}
331
332static struct platform_driver omap2_mbox_driver = {
333 .probe = omap2_mbox_probe,
334 .remove = omap2_mbox_remove,
335 .driver = {
336 .name = "omap-mailbox",
337 },
338};
339
340static int __init omap2_mbox_init(void)
341{
342 return platform_driver_register(&omap2_mbox_driver);
343}
344
345static void __exit omap2_mbox_exit(void)
346{
347 platform_driver_unregister(&omap2_mbox_driver);
348}
349
350module_init(omap2_mbox_init);
351module_exit(omap2_mbox_exit);
352
353MODULE_LICENSE("GPL v2");
354MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
355MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
356MODULE_AUTHOR("Paul Mundt");
357MODULE_ALIAS("platform:omap2-mailbox");
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index d79a646b9042..a27e00e63a8a 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -2,8 +2,10 @@
2 * OMAP mailbox driver 2 * OMAP mailbox driver
3 * 3 *
4 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. 4 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
5 * Copyright (C) 2013-2014 Texas Instruments Inc.
5 * 6 *
6 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> 7 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
8 * Suman Anna <s-anna@ti.com>
7 * 9 *
8 * This program is free software; you can redistribute it and/or 10 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 11 * modify it under the terms of the GNU General Public License
@@ -24,70 +26,164 @@
24#include <linux/interrupt.h> 26#include <linux/interrupt.h>
25#include <linux/spinlock.h> 27#include <linux/spinlock.h>
26#include <linux/mutex.h> 28#include <linux/mutex.h>
27#include <linux/delay.h>
28#include <linux/slab.h> 29#include <linux/slab.h>
29#include <linux/kfifo.h> 30#include <linux/kfifo.h>
30#include <linux/err.h> 31#include <linux/err.h>
31#include <linux/notifier.h> 32#include <linux/notifier.h>
32#include <linux/module.h> 33#include <linux/module.h>
33 34#include <linux/platform_device.h>
34#include "omap-mbox.h" 35#include <linux/pm_runtime.h>
35 36#include <linux/platform_data/mailbox-omap.h>
36static struct omap_mbox **mboxes; 37#include <linux/omap-mailbox.h>
37 38
38static int mbox_configured; 39#define MAILBOX_REVISION 0x000
39static DEFINE_MUTEX(mbox_configured_lock); 40#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
41#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
42#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
43
44#define OMAP2_MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
45#define OMAP2_MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
46
47#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u))
48#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u))
49#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u))
50
51#define MAILBOX_IRQSTATUS(type, u) (type ? OMAP4_MAILBOX_IRQSTATUS(u) : \
52 OMAP2_MAILBOX_IRQSTATUS(u))
53#define MAILBOX_IRQENABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE(u) : \
54 OMAP2_MAILBOX_IRQENABLE(u))
55#define MAILBOX_IRQDISABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \
56 : OMAP2_MAILBOX_IRQENABLE(u))
57
58#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
59#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
60
61#define MBOX_REG_SIZE 0x120
62
63#define OMAP4_MBOX_REG_SIZE 0x130
64
65#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
66#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
67
68struct omap_mbox_fifo {
69 unsigned long msg;
70 unsigned long fifo_stat;
71 unsigned long msg_stat;
72 unsigned long irqenable;
73 unsigned long irqstatus;
74 unsigned long irqdisable;
75 u32 intr_bit;
76};
77
78struct omap_mbox_queue {
79 spinlock_t lock;
80 struct kfifo fifo;
81 struct work_struct work;
82 struct tasklet_struct tasklet;
83 struct omap_mbox *mbox;
84 bool full;
85};
86
87struct omap_mbox_device {
88 struct device *dev;
89 struct mutex cfg_lock;
90 void __iomem *mbox_base;
91 u32 num_users;
92 u32 num_fifos;
93 struct omap_mbox **mboxes;
94 struct list_head elem;
95};
96
97struct omap_mbox {
98 const char *name;
99 int irq;
100 struct omap_mbox_queue *txq, *rxq;
101 struct device *dev;
102 struct omap_mbox_device *parent;
103 struct omap_mbox_fifo tx_fifo;
104 struct omap_mbox_fifo rx_fifo;
105 u32 ctx[OMAP4_MBOX_NR_REGS];
106 u32 intr_type;
107 int use_count;
108 struct blocking_notifier_head notifier;
109};
110
111/* global variables for the mailbox devices */
112static DEFINE_MUTEX(omap_mbox_devices_lock);
113static LIST_HEAD(omap_mbox_devices);
40 114
41static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; 115static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
42module_param(mbox_kfifo_size, uint, S_IRUGO); 116module_param(mbox_kfifo_size, uint, S_IRUGO);
43MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); 117MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
44 118
119static inline
120unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs)
121{
122 return __raw_readl(mdev->mbox_base + ofs);
123}
124
125static inline
126void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
127{
128 __raw_writel(val, mdev->mbox_base + ofs);
129}
130
45/* Mailbox FIFO handle functions */ 131/* Mailbox FIFO handle functions */
46static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) 132static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
47{ 133{
48 return mbox->ops->fifo_read(mbox); 134 struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
135 return (mbox_msg_t) mbox_read_reg(mbox->parent, fifo->msg);
49} 136}
50static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) 137
138static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
51{ 139{
52 mbox->ops->fifo_write(mbox, msg); 140 struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
141 mbox_write_reg(mbox->parent, msg, fifo->msg);
53} 142}
54static inline int mbox_fifo_empty(struct omap_mbox *mbox) 143
144static int mbox_fifo_empty(struct omap_mbox *mbox)
55{ 145{
56 return mbox->ops->fifo_empty(mbox); 146 struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
147 return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0);
57} 148}
58static inline int mbox_fifo_full(struct omap_mbox *mbox) 149
150static int mbox_fifo_full(struct omap_mbox *mbox)
59{ 151{
60 return mbox->ops->fifo_full(mbox); 152 struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
153 return mbox_read_reg(mbox->parent, fifo->fifo_stat);
61} 154}
62 155
63/* Mailbox IRQ handle functions */ 156/* Mailbox IRQ handle functions */
64static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 157static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
65{ 158{
66 if (mbox->ops->ack_irq) 159 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
67 mbox->ops->ack_irq(mbox, irq); 160 &mbox->tx_fifo : &mbox->rx_fifo;
161 u32 bit = fifo->intr_bit;
162 u32 irqstatus = fifo->irqstatus;
163
164 mbox_write_reg(mbox->parent, bit, irqstatus);
165
166 /* Flush posted write for irq status to avoid spurious interrupts */
167 mbox_read_reg(mbox->parent, irqstatus);
68} 168}
69static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 169
170static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
70{ 171{
71 return mbox->ops->is_irq(mbox, irq); 172 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
173 &mbox->tx_fifo : &mbox->rx_fifo;
174 u32 bit = fifo->intr_bit;
175 u32 irqenable = fifo->irqenable;
176 u32 irqstatus = fifo->irqstatus;
177
178 u32 enable = mbox_read_reg(mbox->parent, irqenable);
179 u32 status = mbox_read_reg(mbox->parent, irqstatus);
180
181 return (int)(enable & status & bit);
72} 182}
73 183
74/* 184/*
75 * message sender 185 * message sender
76 */ 186 */
77static 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
91int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) 187int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
92{ 188{
93 struct omap_mbox_queue *mq = mbox->txq; 189 struct omap_mbox_queue *mq = mbox->txq;
@@ -100,7 +196,7 @@ int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
100 goto out; 196 goto out;
101 } 197 }
102 198
103 if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) { 199 if (kfifo_is_empty(&mq->fifo) && !mbox_fifo_full(mbox)) {
104 mbox_fifo_write(mbox, msg); 200 mbox_fifo_write(mbox, msg);
105 goto out; 201 goto out;
106 } 202 }
@@ -118,35 +214,69 @@ EXPORT_SYMBOL(omap_mbox_msg_send);
118 214
119void omap_mbox_save_ctx(struct omap_mbox *mbox) 215void omap_mbox_save_ctx(struct omap_mbox *mbox)
120{ 216{
121 if (!mbox->ops->save_ctx) { 217 int i;
122 dev_err(mbox->dev, "%s:\tno save\n", __func__); 218 int nr_regs;
123 return; 219
124 } 220 if (mbox->intr_type)
221 nr_regs = OMAP4_MBOX_NR_REGS;
222 else
223 nr_regs = MBOX_NR_REGS;
224 for (i = 0; i < nr_regs; i++) {
225 mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32));
125 226
126 mbox->ops->save_ctx(mbox); 227 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
228 i, mbox->ctx[i]);
229 }
127} 230}
128EXPORT_SYMBOL(omap_mbox_save_ctx); 231EXPORT_SYMBOL(omap_mbox_save_ctx);
129 232
130void omap_mbox_restore_ctx(struct omap_mbox *mbox) 233void omap_mbox_restore_ctx(struct omap_mbox *mbox)
131{ 234{
132 if (!mbox->ops->restore_ctx) { 235 int i;
133 dev_err(mbox->dev, "%s:\tno restore\n", __func__); 236 int nr_regs;
134 return;
135 }
136 237
137 mbox->ops->restore_ctx(mbox); 238 if (mbox->intr_type)
239 nr_regs = OMAP4_MBOX_NR_REGS;
240 else
241 nr_regs = MBOX_NR_REGS;
242 for (i = 0; i < nr_regs; i++) {
243 mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
244
245 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
246 i, mbox->ctx[i]);
247 }
138} 248}
139EXPORT_SYMBOL(omap_mbox_restore_ctx); 249EXPORT_SYMBOL(omap_mbox_restore_ctx);
140 250
141void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 251void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
142{ 252{
143 mbox->ops->enable_irq(mbox, irq); 253 u32 l;
254 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
255 &mbox->tx_fifo : &mbox->rx_fifo;
256 u32 bit = fifo->intr_bit;
257 u32 irqenable = fifo->irqenable;
258
259 l = mbox_read_reg(mbox->parent, irqenable);
260 l |= bit;
261 mbox_write_reg(mbox->parent, l, irqenable);
144} 262}
145EXPORT_SYMBOL(omap_mbox_enable_irq); 263EXPORT_SYMBOL(omap_mbox_enable_irq);
146 264
147void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 265void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
148{ 266{
149 mbox->ops->disable_irq(mbox, irq); 267 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
268 &mbox->tx_fifo : &mbox->rx_fifo;
269 u32 bit = fifo->intr_bit;
270 u32 irqdisable = fifo->irqdisable;
271
272 /*
273 * Read and update the interrupt configuration register for pre-OMAP4.
274 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
275 */
276 if (!mbox->intr_type)
277 bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit;
278
279 mbox_write_reg(mbox->parent, bit, irqdisable);
150} 280}
151EXPORT_SYMBOL(omap_mbox_disable_irq); 281EXPORT_SYMBOL(omap_mbox_disable_irq);
152 282
@@ -158,7 +288,7 @@ static void mbox_tx_tasklet(unsigned long tx_data)
158 int ret; 288 int ret;
159 289
160 while (kfifo_len(&mq->fifo)) { 290 while (kfifo_len(&mq->fifo)) {
161 if (__mbox_poll_for_space(mbox)) { 291 if (mbox_fifo_full(mbox)) {
162 omap_mbox_enable_irq(mbox, IRQ_TX); 292 omap_mbox_enable_irq(mbox, IRQ_TX);
163 break; 293 break;
164 } 294 }
@@ -223,9 +353,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
223 353
224 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); 354 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
225 WARN_ON(len != sizeof(msg)); 355 WARN_ON(len != sizeof(msg));
226
227 if (mbox->ops->type == OMAP_MBOX_TYPE1)
228 break;
229 } 356 }
230 357
231 /* no more messages in the fifo. clear IRQ source. */ 358 /* no more messages in the fifo. clear IRQ source. */
@@ -283,16 +410,12 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
283{ 410{
284 int ret = 0; 411 int ret = 0;
285 struct omap_mbox_queue *mq; 412 struct omap_mbox_queue *mq;
413 struct omap_mbox_device *mdev = mbox->parent;
286 414
287 mutex_lock(&mbox_configured_lock); 415 mutex_lock(&mdev->cfg_lock);
288 if (!mbox_configured++) { 416 ret = pm_runtime_get_sync(mdev->dev);
289 if (likely(mbox->ops->startup)) { 417 if (unlikely(ret < 0))
290 ret = mbox->ops->startup(mbox); 418 goto fail_startup;
291 if (unlikely(ret))
292 goto fail_startup;
293 } else
294 goto fail_startup;
295 }
296 419
297 if (!mbox->use_count++) { 420 if (!mbox->use_count++) {
298 mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); 421 mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
@@ -319,7 +442,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
319 442
320 omap_mbox_enable_irq(mbox, IRQ_RX); 443 omap_mbox_enable_irq(mbox, IRQ_RX);
321 } 444 }
322 mutex_unlock(&mbox_configured_lock); 445 mutex_unlock(&mdev->cfg_lock);
323 return 0; 446 return 0;
324 447
325fail_request_irq: 448fail_request_irq:
@@ -327,18 +450,18 @@ fail_request_irq:
327fail_alloc_rxq: 450fail_alloc_rxq:
328 mbox_queue_free(mbox->txq); 451 mbox_queue_free(mbox->txq);
329fail_alloc_txq: 452fail_alloc_txq:
330 if (mbox->ops->shutdown) 453 pm_runtime_put_sync(mdev->dev);
331 mbox->ops->shutdown(mbox);
332 mbox->use_count--; 454 mbox->use_count--;
333fail_startup: 455fail_startup:
334 mbox_configured--; 456 mutex_unlock(&mdev->cfg_lock);
335 mutex_unlock(&mbox_configured_lock);
336 return ret; 457 return ret;
337} 458}
338 459
339static void omap_mbox_fini(struct omap_mbox *mbox) 460static void omap_mbox_fini(struct omap_mbox *mbox)
340{ 461{
341 mutex_lock(&mbox_configured_lock); 462 struct omap_mbox_device *mdev = mbox->parent;
463
464 mutex_lock(&mdev->cfg_lock);
342 465
343 if (!--mbox->use_count) { 466 if (!--mbox->use_count) {
344 omap_mbox_disable_irq(mbox, IRQ_RX); 467 omap_mbox_disable_irq(mbox, IRQ_RX);
@@ -349,28 +472,43 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
349 mbox_queue_free(mbox->rxq); 472 mbox_queue_free(mbox->rxq);
350 } 473 }
351 474
352 if (likely(mbox->ops->shutdown)) { 475 pm_runtime_put_sync(mdev->dev);
353 if (!--mbox_configured)
354 mbox->ops->shutdown(mbox);
355 }
356 476
357 mutex_unlock(&mbox_configured_lock); 477 mutex_unlock(&mdev->cfg_lock);
358} 478}
359 479
360struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) 480static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
481 const char *mbox_name)
361{ 482{
362 struct omap_mbox *_mbox, *mbox = NULL; 483 struct omap_mbox *_mbox, *mbox = NULL;
363 int i, ret; 484 struct omap_mbox **mboxes = mdev->mboxes;
485 int i;
364 486
365 if (!mboxes) 487 if (!mboxes)
366 return ERR_PTR(-EINVAL); 488 return NULL;
367 489
368 for (i = 0; (_mbox = mboxes[i]); i++) { 490 for (i = 0; (_mbox = mboxes[i]); i++) {
369 if (!strcmp(_mbox->name, name)) { 491 if (!strcmp(_mbox->name, mbox_name)) {
370 mbox = _mbox; 492 mbox = _mbox;
371 break; 493 break;
372 } 494 }
373 } 495 }
496 return mbox;
497}
498
499struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
500{
501 struct omap_mbox *mbox = NULL;
502 struct omap_mbox_device *mdev;
503 int ret;
504
505 mutex_lock(&omap_mbox_devices_lock);
506 list_for_each_entry(mdev, &omap_mbox_devices, elem) {
507 mbox = omap_mbox_device_find(mdev, name);
508 if (mbox)
509 break;
510 }
511 mutex_unlock(&omap_mbox_devices_lock);
374 512
375 if (!mbox) 513 if (!mbox)
376 return ERR_PTR(-ENOENT); 514 return ERR_PTR(-ENOENT);
@@ -397,19 +535,20 @@ EXPORT_SYMBOL(omap_mbox_put);
397 535
398static struct class omap_mbox_class = { .name = "mbox", }; 536static struct class omap_mbox_class = { .name = "mbox", };
399 537
400int omap_mbox_register(struct device *parent, struct omap_mbox **list) 538static int omap_mbox_register(struct omap_mbox_device *mdev)
401{ 539{
402 int ret; 540 int ret;
403 int i; 541 int i;
542 struct omap_mbox **mboxes;
404 543
405 mboxes = list; 544 if (!mdev || !mdev->mboxes)
406 if (!mboxes)
407 return -EINVAL; 545 return -EINVAL;
408 546
547 mboxes = mdev->mboxes;
409 for (i = 0; mboxes[i]; i++) { 548 for (i = 0; mboxes[i]; i++) {
410 struct omap_mbox *mbox = mboxes[i]; 549 struct omap_mbox *mbox = mboxes[i];
411 mbox->dev = device_create(&omap_mbox_class, 550 mbox->dev = device_create(&omap_mbox_class,
412 parent, 0, mbox, "%s", mbox->name); 551 mdev->dev, 0, mbox, "%s", mbox->name);
413 if (IS_ERR(mbox->dev)) { 552 if (IS_ERR(mbox->dev)) {
414 ret = PTR_ERR(mbox->dev); 553 ret = PTR_ERR(mbox->dev);
415 goto err_out; 554 goto err_out;
@@ -417,6 +556,11 @@ int omap_mbox_register(struct device *parent, struct omap_mbox **list)
417 556
418 BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); 557 BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
419 } 558 }
559
560 mutex_lock(&omap_mbox_devices_lock);
561 list_add(&mdev->elem, &omap_mbox_devices);
562 mutex_unlock(&omap_mbox_devices_lock);
563
420 return 0; 564 return 0;
421 565
422err_out: 566err_out:
@@ -424,21 +568,148 @@ err_out:
424 device_unregister(mboxes[i]->dev); 568 device_unregister(mboxes[i]->dev);
425 return ret; 569 return ret;
426} 570}
427EXPORT_SYMBOL(omap_mbox_register);
428 571
429int omap_mbox_unregister(void) 572static int omap_mbox_unregister(struct omap_mbox_device *mdev)
430{ 573{
431 int i; 574 int i;
575 struct omap_mbox **mboxes;
432 576
433 if (!mboxes) 577 if (!mdev || !mdev->mboxes)
434 return -EINVAL; 578 return -EINVAL;
435 579
580 mutex_lock(&omap_mbox_devices_lock);
581 list_del(&mdev->elem);
582 mutex_unlock(&omap_mbox_devices_lock);
583
584 mboxes = mdev->mboxes;
436 for (i = 0; mboxes[i]; i++) 585 for (i = 0; mboxes[i]; i++)
437 device_unregister(mboxes[i]->dev); 586 device_unregister(mboxes[i]->dev);
438 mboxes = NULL;
439 return 0; 587 return 0;
440} 588}
441EXPORT_SYMBOL(omap_mbox_unregister); 589
590static int omap_mbox_probe(struct platform_device *pdev)
591{
592 struct resource *mem;
593 int ret;
594 struct omap_mbox **list, *mbox, *mboxblk;
595 struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
596 struct omap_mbox_dev_info *info;
597 struct omap_mbox_device *mdev;
598 struct omap_mbox_fifo *fifo;
599 u32 intr_type;
600 u32 l;
601 int i;
602
603 if (!pdata || !pdata->info_cnt || !pdata->info) {
604 pr_err("%s: platform not supported\n", __func__);
605 return -ENODEV;
606 }
607
608 mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
609 if (!mdev)
610 return -ENOMEM;
611
612 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
613 mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem);
614 if (IS_ERR(mdev->mbox_base))
615 return PTR_ERR(mdev->mbox_base);
616
617 /* allocate one extra for marking end of list */
618 list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list),
619 GFP_KERNEL);
620 if (!list)
621 return -ENOMEM;
622
623 mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox),
624 GFP_KERNEL);
625 if (!mboxblk)
626 return -ENOMEM;
627
628 info = pdata->info;
629 intr_type = pdata->intr_type;
630 mbox = mboxblk;
631 for (i = 0; i < pdata->info_cnt; i++, info++) {
632 fifo = &mbox->tx_fifo;
633 fifo->msg = MAILBOX_MESSAGE(info->tx_id);
634 fifo->fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
635 fifo->intr_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
636 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
637 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
638 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
639
640 fifo = &mbox->rx_fifo;
641 fifo->msg = MAILBOX_MESSAGE(info->rx_id);
642 fifo->msg_stat = MAILBOX_MSGSTATUS(info->rx_id);
643 fifo->intr_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
644 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
645 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
646 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
647
648 mbox->intr_type = intr_type;
649
650 mbox->parent = mdev;
651 mbox->name = info->name;
652 mbox->irq = platform_get_irq(pdev, info->irq_id);
653 if (mbox->irq < 0)
654 return mbox->irq;
655 list[i] = mbox++;
656 }
657
658 mutex_init(&mdev->cfg_lock);
659 mdev->dev = &pdev->dev;
660 mdev->num_users = pdata->num_users;
661 mdev->num_fifos = pdata->num_fifos;
662 mdev->mboxes = list;
663 ret = omap_mbox_register(mdev);
664 if (ret)
665 return ret;
666
667 platform_set_drvdata(pdev, mdev);
668 pm_runtime_enable(mdev->dev);
669
670 ret = pm_runtime_get_sync(mdev->dev);
671 if (ret < 0) {
672 pm_runtime_put_noidle(mdev->dev);
673 goto unregister;
674 }
675
676 /*
677 * just print the raw revision register, the format is not
678 * uniform across all SoCs
679 */
680 l = mbox_read_reg(mdev, MAILBOX_REVISION);
681 dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l);
682
683 ret = pm_runtime_put_sync(mdev->dev);
684 if (ret < 0)
685 goto unregister;
686
687 return 0;
688
689unregister:
690 pm_runtime_disable(mdev->dev);
691 omap_mbox_unregister(mdev);
692 return ret;
693}
694
695static int omap_mbox_remove(struct platform_device *pdev)
696{
697 struct omap_mbox_device *mdev = platform_get_drvdata(pdev);
698
699 pm_runtime_disable(mdev->dev);
700 omap_mbox_unregister(mdev);
701
702 return 0;
703}
704
705static struct platform_driver omap_mbox_driver = {
706 .probe = omap_mbox_probe,
707 .remove = omap_mbox_remove,
708 .driver = {
709 .name = "omap-mailbox",
710 .owner = THIS_MODULE,
711 },
712};
442 713
443static int __init omap_mbox_init(void) 714static int __init omap_mbox_init(void)
444{ 715{
@@ -453,12 +724,13 @@ static int __init omap_mbox_init(void)
453 mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, 724 mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
454 sizeof(mbox_msg_t)); 725 sizeof(mbox_msg_t));
455 726
456 return 0; 727 return platform_driver_register(&omap_mbox_driver);
457} 728}
458subsys_initcall(omap_mbox_init); 729subsys_initcall(omap_mbox_init);
459 730
460static void __exit omap_mbox_exit(void) 731static void __exit omap_mbox_exit(void)
461{ 732{
733 platform_driver_unregister(&omap_mbox_driver);
462 class_unregister(&omap_mbox_class); 734 class_unregister(&omap_mbox_class);
463} 735}
464module_exit(omap_mbox_exit); 736module_exit(omap_mbox_exit);
diff --git a/drivers/mailbox/omap-mbox.h b/drivers/mailbox/omap-mbox.h
deleted file mode 100644
index 86d7518cd13b..000000000000
--- a/drivers/mailbox/omap-mbox.h
+++ /dev/null
@@ -1,67 +0,0 @@
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
19typedef 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
23struct 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
44struct 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
53struct omap_mbox {
54 const char *name;
55 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
64int omap_mbox_register(struct device *parent, struct omap_mbox **);
65int omap_mbox_unregister(void);
66
67#endif /* OMAP_MBOX_H */