2 * Mailbox reservation modules for OMAP2/3
4 * Copyright (C) 2006-2008 Nokia Corporation
5 * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
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
13 #include <linux/kernel.h>
14 #include <linux/clk.h>
15 #include <linux/err.h>
16 #include <linux/platform_device.h>
18 #include <mach/mailbox.h>
19 #include <mach/irqs.h>
21 #define DRV_NAME "omap2-mailbox"
23 #define MAILBOX_REVISION 0x000
24 #define MAILBOX_SYSCONFIG 0x010
25 #define MAILBOX_SYSSTATUS 0x014
26 #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
27 #define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
28 #define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
29 #define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
30 #define MAILBOX_IRQENABLE(u) (0x108 + 8 * (u))
32 #define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u)))
33 #define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1))
35 #define MBOX_REG_SIZE 0x120
37 static void __iomem
*mbox_base
;
39 struct omap_mbox2_fifo
{
41 unsigned long fifo_stat
;
42 unsigned long msg_stat
;
45 struct omap_mbox2_priv
{
46 struct omap_mbox2_fifo tx_fifo
;
47 struct omap_mbox2_fifo rx_fifo
;
48 unsigned long irqenable
;
49 unsigned long irqstatus
;
52 char ctx
[MBOX_REG_SIZE
];
55 static struct clk
*mbox_ick_handle
;
57 static void omap2_mbox_enable_irq(struct omap_mbox
*mbox
,
58 omap_mbox_type_t irq
);
60 static inline unsigned int mbox_read_reg(size_t ofs
)
62 return __raw_readl(mbox_base
+ ofs
);
65 static inline void mbox_write_reg(u32 val
, size_t ofs
)
67 __raw_writel(val
, mbox_base
+ ofs
);
70 /* Mailbox H/W preparations */
71 static int omap2_mbox_startup(struct omap_mbox
*mbox
)
75 mbox_ick_handle
= clk_get(NULL
, "mailboxes_ick");
76 if (IS_ERR(mbox_ick_handle
)) {
77 printk("Could not get mailboxes_ick\n");
80 clk_enable(mbox_ick_handle
);
82 l
= mbox_read_reg(MAILBOX_REVISION
);
83 pr_info("omap mailbox rev %d.%d\n", (l
& 0xf0) >> 4, (l
& 0x0f));
85 /* set smart-idle & autoidle */
86 l
= mbox_read_reg(MAILBOX_SYSCONFIG
);
88 mbox_write_reg(l
, MAILBOX_SYSCONFIG
);
90 omap2_mbox_enable_irq(mbox
, IRQ_RX
);
95 static void omap2_mbox_shutdown(struct omap_mbox
*mbox
)
97 clk_disable(mbox_ick_handle
);
98 clk_put(mbox_ick_handle
);
101 /* Mailbox FIFO handle functions */
102 static mbox_msg_t
omap2_mbox_fifo_read(struct omap_mbox
*mbox
)
104 struct omap_mbox2_fifo
*fifo
=
105 &((struct omap_mbox2_priv
*)mbox
->priv
)->rx_fifo
;
106 return (mbox_msg_t
) mbox_read_reg(fifo
->msg
);
109 static void omap2_mbox_fifo_write(struct omap_mbox
*mbox
, mbox_msg_t msg
)
111 struct omap_mbox2_fifo
*fifo
=
112 &((struct omap_mbox2_priv
*)mbox
->priv
)->tx_fifo
;
113 mbox_write_reg(msg
, fifo
->msg
);
116 static int omap2_mbox_fifo_empty(struct omap_mbox
*mbox
)
118 struct omap_mbox2_fifo
*fifo
=
119 &((struct omap_mbox2_priv
*)mbox
->priv
)->rx_fifo
;
120 return (mbox_read_reg(fifo
->msg_stat
) == 0);
123 static int omap2_mbox_fifo_full(struct omap_mbox
*mbox
)
125 struct omap_mbox2_fifo
*fifo
=
126 &((struct omap_mbox2_priv
*)mbox
->priv
)->tx_fifo
;
127 return (mbox_read_reg(fifo
->fifo_stat
));
130 /* Mailbox IRQ handle functions */
131 static void omap2_mbox_enable_irq(struct omap_mbox
*mbox
,
132 omap_mbox_type_t irq
)
134 struct omap_mbox2_priv
*p
= (struct omap_mbox2_priv
*)mbox
->priv
;
135 u32 l
, bit
= (irq
== IRQ_TX
) ? p
->notfull_bit
: p
->newmsg_bit
;
137 l
= mbox_read_reg(p
->irqenable
);
139 mbox_write_reg(l
, p
->irqenable
);
142 static void omap2_mbox_disable_irq(struct omap_mbox
*mbox
,
143 omap_mbox_type_t irq
)
145 struct omap_mbox2_priv
*p
= (struct omap_mbox2_priv
*)mbox
->priv
;
146 u32 l
, bit
= (irq
== IRQ_TX
) ? p
->notfull_bit
: p
->newmsg_bit
;
148 l
= mbox_read_reg(p
->irqenable
);
150 mbox_write_reg(l
, p
->irqenable
);
153 static void omap2_mbox_ack_irq(struct omap_mbox
*mbox
,
154 omap_mbox_type_t irq
)
156 struct omap_mbox2_priv
*p
= (struct omap_mbox2_priv
*)mbox
->priv
;
157 u32 bit
= (irq
== IRQ_TX
) ? p
->notfull_bit
: p
->newmsg_bit
;
159 mbox_write_reg(bit
, p
->irqstatus
);
162 static int omap2_mbox_is_irq(struct omap_mbox
*mbox
,
163 omap_mbox_type_t irq
)
165 struct omap_mbox2_priv
*p
= (struct omap_mbox2_priv
*)mbox
->priv
;
166 u32 bit
= (irq
== IRQ_TX
) ? p
->notfull_bit
: p
->newmsg_bit
;
167 u32 enable
= mbox_read_reg(p
->irqenable
);
168 u32 status
= mbox_read_reg(p
->irqstatus
);
170 return (enable
& status
& bit
);
173 static void omap2_mbox_save_ctx(struct omap_mbox
*mbox
)
176 struct omap_mbox2_priv
*p
= mbox
->priv
;
178 for (i
= 0; i
< MBOX_REG_SIZE
; i
+= sizeof(u32
)) {
181 val
= mbox_read_reg(i
);
182 *(u32
*)(p
->ctx
+ i
) = val
;
184 dev_dbg(mbox
->dev
, "%s\t[%02d] %08x\n", __func__
, i
, val
);
188 static void omap2_mbox_restore_ctx(struct omap_mbox
*mbox
)
191 struct omap_mbox2_priv
*p
= mbox
->priv
;
193 for (i
= 0; i
< MBOX_REG_SIZE
; i
+= sizeof(u32
)) {
196 val
= *(u32
*)(p
->ctx
+ i
);
197 mbox_write_reg(val
, i
);
199 dev_dbg(mbox
->dev
, "%s\t[%02d] %08x\n", __func__
, i
, val
);
203 static struct omap_mbox_ops omap2_mbox_ops
= {
204 .type
= OMAP_MBOX_TYPE2
,
205 .startup
= omap2_mbox_startup
,
206 .shutdown
= omap2_mbox_shutdown
,
207 .fifo_read
= omap2_mbox_fifo_read
,
208 .fifo_write
= omap2_mbox_fifo_write
,
209 .fifo_empty
= omap2_mbox_fifo_empty
,
210 .fifo_full
= omap2_mbox_fifo_full
,
211 .enable_irq
= omap2_mbox_enable_irq
,
212 .disable_irq
= omap2_mbox_disable_irq
,
213 .ack_irq
= omap2_mbox_ack_irq
,
214 .is_irq
= omap2_mbox_is_irq
,
215 .save_ctx
= omap2_mbox_save_ctx
,
216 .restore_ctx
= omap2_mbox_restore_ctx
,
220 * MAILBOX 0: ARM -> DSP,
221 * MAILBOX 1: ARM <- DSP.
222 * MAILBOX 2: ARM -> IVA,
223 * MAILBOX 3: ARM <- IVA.
226 /* FIXME: the following structs should be filled automatically by the user id */
229 static struct omap_mbox2_priv omap2_mbox_dsp_priv
= {
231 .msg
= MAILBOX_MESSAGE(0),
232 .fifo_stat
= MAILBOX_FIFOSTATUS(0),
235 .msg
= MAILBOX_MESSAGE(1),
236 .msg_stat
= MAILBOX_MSGSTATUS(1),
238 .irqenable
= MAILBOX_IRQENABLE(0),
239 .irqstatus
= MAILBOX_IRQSTATUS(0),
240 .notfull_bit
= MAILBOX_IRQ_NOTFULL(0),
241 .newmsg_bit
= MAILBOX_IRQ_NEWMSG(1),
244 struct omap_mbox mbox_dsp_info
= {
246 .ops
= &omap2_mbox_ops
,
247 .priv
= &omap2_mbox_dsp_priv
,
249 EXPORT_SYMBOL(mbox_dsp_info
);
251 #if defined(CONFIG_ARCH_OMAP2420) /* IVA */
252 static struct omap_mbox2_priv omap2_mbox_iva_priv
= {
254 .msg
= MAILBOX_MESSAGE(2),
255 .fifo_stat
= MAILBOX_FIFOSTATUS(2),
258 .msg
= MAILBOX_MESSAGE(3),
259 .msg_stat
= MAILBOX_MSGSTATUS(3),
261 .irqenable
= MAILBOX_IRQENABLE(3),
262 .irqstatus
= MAILBOX_IRQSTATUS(3),
263 .notfull_bit
= MAILBOX_IRQ_NOTFULL(2),
264 .newmsg_bit
= MAILBOX_IRQ_NEWMSG(3),
267 static struct omap_mbox mbox_iva_info
= {
269 .ops
= &omap2_mbox_ops
,
270 .priv
= &omap2_mbox_iva_priv
,
274 static int __devinit
omap2_mbox_probe(struct platform_device
*pdev
)
276 struct resource
*res
;
280 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
281 if (unlikely(!res
)) {
282 dev_err(&pdev
->dev
, "invalid mem resource\n");
285 mbox_base
= ioremap(res
->start
, res
->end
- res
->start
);
289 /* DSP or IVA2 IRQ */
290 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
291 if (unlikely(!res
)) {
292 dev_err(&pdev
->dev
, "invalid irq resource\n");
296 mbox_dsp_info
.irq
= res
->start
;
298 ret
= omap_mbox_register(&pdev
->dev
, &mbox_dsp_info
);
302 #if defined(CONFIG_ARCH_OMAP2420) /* IVA */
303 if (cpu_is_omap2420()) {
305 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 1);
306 if (unlikely(!res
)) {
307 dev_err(&pdev
->dev
, "invalid irq resource\n");
311 mbox_iva_info
.irq
= res
->start
;
312 ret
= omap_mbox_register(&pdev
->dev
, &mbox_iva_info
);
320 omap_mbox_unregister(&mbox_dsp_info
);
326 static int __devexit
omap2_mbox_remove(struct platform_device
*pdev
)
328 #if defined(CONFIG_ARCH_OMAP2420)
329 omap_mbox_unregister(&mbox_iva_info
);
331 omap_mbox_unregister(&mbox_dsp_info
);
336 static struct platform_driver omap2_mbox_driver
= {
337 .probe
= omap2_mbox_probe
,
338 .remove
= __devexit_p(omap2_mbox_remove
),
344 static int __init
omap2_mbox_init(void)
346 return platform_driver_register(&omap2_mbox_driver
);
349 static void __exit
omap2_mbox_exit(void)
351 platform_driver_unregister(&omap2_mbox_driver
);
354 module_init(omap2_mbox_init
);
355 module_exit(omap2_mbox_exit
);
357 MODULE_LICENSE("GPL v2");
358 MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions");
359 MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt");
360 MODULE_ALIAS("platform:"DRV_NAME
);