aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/mailbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/mailbox.c')
-rw-r--r--arch/arm/mach-omap2/mailbox.c197
1 files changed, 155 insertions, 42 deletions
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index ef57b38a56a4..318f3638653c 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -15,9 +15,11 @@
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <mach/mailbox.h> 18#include <plat/mailbox.h>
19#include <mach/irqs.h> 19#include <mach/irqs.h>
20 20
21#define DRV_NAME "omap2-mailbox"
22
21#define MAILBOX_REVISION 0x000 23#define MAILBOX_REVISION 0x000
22#define MAILBOX_SYSCONFIG 0x010 24#define MAILBOX_SYSCONFIG 0x010
23#define MAILBOX_SYSSTATUS 0x014 25#define MAILBOX_SYSSTATUS 0x014
@@ -27,19 +29,30 @@
27#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u)) 29#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
28#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u)) 30#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
29 31
30#define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u))) 32#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 10 * (u))
31#define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1)) 33#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 10 * (u))
34#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 10 * (u))
35
36#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
37#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
32 38
33/* SYSCONFIG: register bit definition */ 39/* SYSCONFIG: register bit definition */
34#define AUTOIDLE (1 << 0) 40#define AUTOIDLE (1 << 0)
35#define SOFTRESET (1 << 1) 41#define SOFTRESET (1 << 1)
36#define SMARTIDLE (2 << 3) 42#define SMARTIDLE (2 << 3)
43#define OMAP4_SOFTRESET (1 << 0)
44#define OMAP4_NOIDLE (1 << 2)
45#define OMAP4_SMARTIDLE (2 << 2)
37 46
38/* SYSSTATUS: register bit definition */ 47/* SYSSTATUS: register bit definition */
39#define RESETDONE (1 << 0) 48#define RESETDONE (1 << 0)
40 49
41#define MBOX_REG_SIZE 0x120 50#define MBOX_REG_SIZE 0x120
51
52#define OMAP4_MBOX_REG_SIZE 0x130
53
42#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) 54#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
55#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
43 56
44static void __iomem *mbox_base; 57static void __iomem *mbox_base;
45 58
@@ -56,7 +69,8 @@ struct omap_mbox2_priv {
56 unsigned long irqstatus; 69 unsigned long irqstatus;
57 u32 newmsg_bit; 70 u32 newmsg_bit;
58 u32 notfull_bit; 71 u32 notfull_bit;
59 u32 ctx[MBOX_NR_REGS]; 72 u32 ctx[OMAP4_MBOX_NR_REGS];
73 unsigned long irqdisable;
60}; 74};
61 75
62static struct clk *mbox_ick_handle; 76static struct clk *mbox_ick_handle;
@@ -82,28 +96,47 @@ static int omap2_mbox_startup(struct omap_mbox *mbox)
82 96
83 mbox_ick_handle = clk_get(NULL, "mailboxes_ick"); 97 mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
84 if (IS_ERR(mbox_ick_handle)) { 98 if (IS_ERR(mbox_ick_handle)) {
85 pr_err("Can't get mailboxes_ick\n"); 99 printk(KERN_ERR "Could not get mailboxes_ick: %ld\n",
86 return -ENODEV; 100 PTR_ERR(mbox_ick_handle));
101 return PTR_ERR(mbox_ick_handle);
87 } 102 }
88 clk_enable(mbox_ick_handle); 103 clk_enable(mbox_ick_handle);
89 104
90 mbox_write_reg(SOFTRESET, MAILBOX_SYSCONFIG); 105 if (cpu_is_omap44xx()) {
91 timeout = jiffies + msecs_to_jiffies(20); 106 mbox_write_reg(OMAP4_SOFTRESET, MAILBOX_SYSCONFIG);
92 do { 107 timeout = jiffies + msecs_to_jiffies(20);
93 l = mbox_read_reg(MAILBOX_SYSSTATUS); 108 do {
94 if (l & RESETDONE) 109 l = mbox_read_reg(MAILBOX_SYSCONFIG);
95 break; 110 if (!(l & OMAP4_SOFTRESET))
96 } while (!time_after(jiffies, timeout)); 111 break;
97 112 } while (!time_after(jiffies, timeout));
98 if (!(l & RESETDONE)) { 113
99 pr_err("Can't take mmu out of reset\n"); 114 if (l & OMAP4_SOFTRESET) {
100 return -ENODEV; 115 pr_err("Can't take mailbox out of reset\n");
116 return -ENODEV;
117 }
118 } else {
119 mbox_write_reg(SOFTRESET, MAILBOX_SYSCONFIG);
120 timeout = jiffies + msecs_to_jiffies(20);
121 do {
122 l = mbox_read_reg(MAILBOX_SYSSTATUS);
123 if (l & RESETDONE)
124 break;
125 } while (!time_after(jiffies, timeout));
126
127 if (!(l & RESETDONE)) {
128 pr_err("Can't take mailbox out of reset\n");
129 return -ENODEV;
130 }
101 } 131 }
102 132
103 l = mbox_read_reg(MAILBOX_REVISION); 133 l = mbox_read_reg(MAILBOX_REVISION);
104 pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); 134 pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
105 135
106 l = SMARTIDLE | AUTOIDLE; 136 if (cpu_is_omap44xx())
137 l = OMAP4_SMARTIDLE;
138 else
139 l = SMARTIDLE | AUTOIDLE;
107 mbox_write_reg(l, MAILBOX_SYSCONFIG); 140 mbox_write_reg(l, MAILBOX_SYSCONFIG);
108 141
109 omap2_mbox_enable_irq(mbox, IRQ_RX); 142 omap2_mbox_enable_irq(mbox, IRQ_RX);
@@ -115,6 +148,7 @@ static void omap2_mbox_shutdown(struct omap_mbox *mbox)
115{ 148{
116 clk_disable(mbox_ick_handle); 149 clk_disable(mbox_ick_handle);
117 clk_put(mbox_ick_handle); 150 clk_put(mbox_ick_handle);
151 mbox_ick_handle = NULL;
118} 152}
119 153
120/* Mailbox FIFO handle functions */ 154/* Mailbox FIFO handle functions */
@@ -143,7 +177,7 @@ static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
143{ 177{
144 struct omap_mbox2_fifo *fifo = 178 struct omap_mbox2_fifo *fifo =
145 &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; 179 &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
146 return (mbox_read_reg(fifo->fifo_stat)); 180 return mbox_read_reg(fifo->fifo_stat);
147} 181}
148 182
149/* Mailbox IRQ handle functions */ 183/* Mailbox IRQ handle functions */
@@ -163,10 +197,9 @@ static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
163{ 197{
164 struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; 198 struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
165 u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 199 u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
166 200 l = mbox_read_reg(p->irqdisable);
167 l = mbox_read_reg(p->irqenable);
168 l &= ~bit; 201 l &= ~bit;
169 mbox_write_reg(l, p->irqenable); 202 mbox_write_reg(l, p->irqdisable);
170} 203}
171 204
172static void omap2_mbox_ack_irq(struct omap_mbox *mbox, 205static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
@@ -189,15 +222,19 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox,
189 u32 enable = mbox_read_reg(p->irqenable); 222 u32 enable = mbox_read_reg(p->irqenable);
190 u32 status = mbox_read_reg(p->irqstatus); 223 u32 status = mbox_read_reg(p->irqstatus);
191 224
192 return (enable & status & bit); 225 return (int)(enable & status & bit);
193} 226}
194 227
195static void omap2_mbox_save_ctx(struct omap_mbox *mbox) 228static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
196{ 229{
197 int i; 230 int i;
198 struct omap_mbox2_priv *p = mbox->priv; 231 struct omap_mbox2_priv *p = mbox->priv;
199 232 int nr_regs;
200 for (i = 0; i < MBOX_NR_REGS; i++) { 233 if (cpu_is_omap44xx())
234 nr_regs = OMAP4_MBOX_NR_REGS;
235 else
236 nr_regs = MBOX_NR_REGS;
237 for (i = 0; i < nr_regs; i++) {
201 p->ctx[i] = mbox_read_reg(i * sizeof(u32)); 238 p->ctx[i] = mbox_read_reg(i * sizeof(u32));
202 239
203 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 240 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
@@ -209,8 +246,12 @@ static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
209{ 246{
210 int i; 247 int i;
211 struct omap_mbox2_priv *p = mbox->priv; 248 struct omap_mbox2_priv *p = mbox->priv;
212 249 int nr_regs;
213 for (i = 0; i < MBOX_NR_REGS; i++) { 250 if (cpu_is_omap44xx())
251 nr_regs = OMAP4_MBOX_NR_REGS;
252 else
253 nr_regs = MBOX_NR_REGS;
254 for (i = 0; i < nr_regs; i++) {
214 mbox_write_reg(p->ctx[i], i * sizeof(u32)); 255 mbox_write_reg(p->ctx[i], i * sizeof(u32));
215 256
216 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 257 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
@@ -242,7 +283,6 @@ static struct omap_mbox_ops omap2_mbox_ops = {
242 */ 283 */
243 284
244/* FIXME: the following structs should be filled automatically by the user id */ 285/* FIXME: the following structs should be filled automatically by the user id */
245
246/* DSP */ 286/* DSP */
247static struct omap_mbox2_priv omap2_mbox_dsp_priv = { 287static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
248 .tx_fifo = { 288 .tx_fifo = {
@@ -257,8 +297,36 @@ static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
257 .irqstatus = MAILBOX_IRQSTATUS(0), 297 .irqstatus = MAILBOX_IRQSTATUS(0),
258 .notfull_bit = MAILBOX_IRQ_NOTFULL(0), 298 .notfull_bit = MAILBOX_IRQ_NOTFULL(0),
259 .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), 299 .newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
300 .irqdisable = MAILBOX_IRQENABLE(0),
301};
302
303
304
305/* OMAP4 specific data structure. Use the cpu_is_omap4xxx()
306to use this*/
307static struct omap_mbox2_priv omap2_mbox_1_priv = {
308 .tx_fifo = {
309 .msg = MAILBOX_MESSAGE(0),
310 .fifo_stat = MAILBOX_FIFOSTATUS(0),
311 },
312 .rx_fifo = {
313 .msg = MAILBOX_MESSAGE(1),
314 .msg_stat = MAILBOX_MSGSTATUS(1),
315 },
316 .irqenable = OMAP4_MAILBOX_IRQENABLE(0),
317 .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0),
318 .notfull_bit = MAILBOX_IRQ_NOTFULL(0),
319 .newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
320 .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0),
260}; 321};
261 322
323struct omap_mbox mbox_1_info = {
324 .name = "mailbox-1",
325 .ops = &omap2_mbox_ops,
326 .priv = &omap2_mbox_1_priv,
327};
328EXPORT_SYMBOL(mbox_1_info);
329
262struct omap_mbox mbox_dsp_info = { 330struct omap_mbox mbox_dsp_info = {
263 .name = "dsp", 331 .name = "dsp",
264 .ops = &omap2_mbox_ops, 332 .ops = &omap2_mbox_ops,
@@ -266,6 +334,30 @@ struct omap_mbox mbox_dsp_info = {
266}; 334};
267EXPORT_SYMBOL(mbox_dsp_info); 335EXPORT_SYMBOL(mbox_dsp_info);
268 336
337static struct omap_mbox2_priv omap2_mbox_2_priv = {
338 .tx_fifo = {
339 .msg = MAILBOX_MESSAGE(3),
340 .fifo_stat = MAILBOX_FIFOSTATUS(3),
341 },
342 .rx_fifo = {
343 .msg = MAILBOX_MESSAGE(2),
344 .msg_stat = MAILBOX_MSGSTATUS(2),
345 },
346 .irqenable = OMAP4_MAILBOX_IRQENABLE(0),
347 .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0),
348 .notfull_bit = MAILBOX_IRQ_NOTFULL(3),
349 .newmsg_bit = MAILBOX_IRQ_NEWMSG(2),
350 .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0),
351};
352
353struct omap_mbox mbox_2_info = {
354 .name = "mailbox-2",
355 .ops = &omap2_mbox_ops,
356 .priv = &omap2_mbox_2_priv,
357};
358EXPORT_SYMBOL(mbox_2_info);
359
360
269#if defined(CONFIG_ARCH_OMAP2420) /* IVA */ 361#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
270static struct omap_mbox2_priv omap2_mbox_iva_priv = { 362static struct omap_mbox2_priv omap2_mbox_iva_priv = {
271 .tx_fifo = { 363 .tx_fifo = {
@@ -280,6 +372,7 @@ static struct omap_mbox2_priv omap2_mbox_iva_priv = {
280 .irqstatus = MAILBOX_IRQSTATUS(3), 372 .irqstatus = MAILBOX_IRQSTATUS(3),
281 .notfull_bit = MAILBOX_IRQ_NOTFULL(2), 373 .notfull_bit = MAILBOX_IRQ_NOTFULL(2),
282 .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), 374 .newmsg_bit = MAILBOX_IRQ_NEWMSG(3),
375 .irqdisable = MAILBOX_IRQENABLE(3),
283}; 376};
284 377
285static struct omap_mbox mbox_iva_info = { 378static struct omap_mbox mbox_iva_info = {
@@ -305,17 +398,31 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
305 return -ENOMEM; 398 return -ENOMEM;
306 399
307 /* DSP or IVA2 IRQ */ 400 /* DSP or IVA2 IRQ */
308 ret = platform_get_irq(pdev, 0); 401 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
309 if (ret < 0) { 402
403 if (unlikely(!res)) {
310 dev_err(&pdev->dev, "invalid irq resource\n"); 404 dev_err(&pdev->dev, "invalid irq resource\n");
405 ret = -ENODEV;
311 goto err_dsp; 406 goto err_dsp;
312 } 407 }
313 mbox_dsp_info.irq = ret; 408 if (cpu_is_omap44xx()) {
314 409 mbox_1_info.irq = res->start;
315 ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info); 410 ret = omap_mbox_register(&pdev->dev, &mbox_1_info);
411 } else {
412 mbox_dsp_info.irq = res->start;
413 ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info);
414 }
316 if (ret) 415 if (ret)
317 goto err_dsp; 416 goto err_dsp;
318 417
418 if (cpu_is_omap44xx()) {
419 mbox_2_info.irq = res->start;
420 ret = omap_mbox_register(&pdev->dev, &mbox_2_info);
421 if (ret) {
422 omap_mbox_unregister(&mbox_1_info);
423 goto err_dsp;
424 }
425 }
319#if defined(CONFIG_ARCH_OMAP2420) /* IVA */ 426#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
320 if (cpu_is_omap2420()) { 427 if (cpu_is_omap2420()) {
321 /* IVA IRQ */ 428 /* IVA IRQ */
@@ -323,18 +430,19 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
323 if (unlikely(!res)) { 430 if (unlikely(!res)) {
324 dev_err(&pdev->dev, "invalid irq resource\n"); 431 dev_err(&pdev->dev, "invalid irq resource\n");
325 ret = -ENODEV; 432 ret = -ENODEV;
326 goto err_iva1; 433 omap_mbox_unregister(&mbox_dsp_info);
434 goto err_dsp;
327 } 435 }
328 mbox_iva_info.irq = res->start; 436 mbox_iva_info.irq = res->start;
329 ret = omap_mbox_register(&pdev->dev, &mbox_iva_info); 437 ret = omap_mbox_register(&pdev->dev, &mbox_iva_info);
330 if (ret) 438 if (ret) {
331 goto err_iva1; 439 omap_mbox_unregister(&mbox_dsp_info);
440 goto err_dsp;
441 }
332 } 442 }
333#endif 443#endif
334 return 0; 444 return 0;
335 445
336err_iva1:
337 omap_mbox_unregister(&mbox_dsp_info);
338err_dsp: 446err_dsp:
339 iounmap(mbox_base); 447 iounmap(mbox_base);
340 return ret; 448 return ret;
@@ -345,7 +453,12 @@ static int __devexit omap2_mbox_remove(struct platform_device *pdev)
345#if defined(CONFIG_ARCH_OMAP2420) 453#if defined(CONFIG_ARCH_OMAP2420)
346 omap_mbox_unregister(&mbox_iva_info); 454 omap_mbox_unregister(&mbox_iva_info);
347#endif 455#endif
348 omap_mbox_unregister(&mbox_dsp_info); 456
457 if (cpu_is_omap44xx()) {
458 omap_mbox_unregister(&mbox_2_info);
459 omap_mbox_unregister(&mbox_1_info);
460 } else
461 omap_mbox_unregister(&mbox_dsp_info);
349 iounmap(mbox_base); 462 iounmap(mbox_base);
350 return 0; 463 return 0;
351} 464}
@@ -354,7 +467,7 @@ static struct platform_driver omap2_mbox_driver = {
354 .probe = omap2_mbox_probe, 467 .probe = omap2_mbox_probe,
355 .remove = __devexit_p(omap2_mbox_remove), 468 .remove = __devexit_p(omap2_mbox_remove),
356 .driver = { 469 .driver = {
357 .name = "omap2-mailbox", 470 .name = DRV_NAME,
358 }, 471 },
359}; 472};
360 473
@@ -372,6 +485,6 @@ module_init(omap2_mbox_init);
372module_exit(omap2_mbox_exit); 485module_exit(omap2_mbox_exit);
373 486
374MODULE_LICENSE("GPL v2"); 487MODULE_LICENSE("GPL v2");
375MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions"); 488MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
376MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt"); 489MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt");
377MODULE_ALIAS("platform:omap2-mailbox"); 490MODULE_ALIAS("platform:"DRV_NAME);