]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/mailbox.c
6a37582141e4b8f8fe0cf1f693866e066ad2dfa0
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / mailbox.c
1 /*
2  * OMAP mailbox driver
3  *
4  * Copyright (C) 2006 Nokia Corporation. All rights reserved.
5  *
6  * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@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/init.h>
25 #include <linux/module.h>
26 #include <linux/sched.h>
27 #include <linux/interrupt.h>
28 #include <linux/err.h>
29 #ifdef CONFIG_ARCH_OMAP2
30 #include <linux/clk.h>
31 #endif
32 #include <asm/io.h>
33 #ifdef CONFIG_ARCH_OMAP1
34 #include <asm/delay.h>
35 #endif
36 #include <asm/arch/mailbox.h>
37 #include "mailbox_hw.h"
38
39 #if defined(CONFIG_ARCH_OMAP1)
40
41 #define read_mbx(m, msgp) \
42                 do { \
43                         *(msgp) = omap_readw((m)->data_r); \
44                         *(msgp) |= ((mbx_msg_t)omap_readw((m)->cmd_r)) << 16; \
45                 } while (0)
46 #define write_mbx(m, msg) \
47                 do { \
48                         omap_writew((msg) & 0xffff, (m)->data_w); \
49                         omap_writew((msg) >> 16, (m)->cmd_w); \
50                 } while (0)
51 #define enable_newmsg_irq(m)    enable_irq((m)->irq)
52 #define disable_newmsg_irq(m)   disable_irq((m)->irq)
53 #define mbx_is_notfull(m)       (omap_readw((m)->flag_w) == 0)
54
55 #elif defined(CONFIG_ARCH_OMAP2)
56
57 #define omap_bit_setl(b,r) \
58                 do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
59 #define omap_bit_clrl(b,r) \
60                 do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
61
62 #define read_mbx(m, msgp) \
63                 do { *(msgp) = omap_readl((m)->message_r); } while (0)
64 #define write_mbx(m, msg)       omap_writel(msg, (m)->message_w)
65 #define enable_newmsg_irq(m)    omap_bit_setl((m)->newmsg_bit, (m)->irqenable)
66 #define disable_newmsg_irq(m)   omap_bit_clrl((m)->newmsg_bit, (m)->irqenable)
67 #define enable_notfull_irq(m)   omap_bit_setl((m)->notfull_bit, (m)->irqenable)
68 #define disable_notfull_irq(m)  omap_bit_clrl((m)->notfull_bit, (m)->irqenable)
69 #define clear_newmsg_irq(m)     omap_writel((m)->newmsg_bit, (m)->irqstatus)
70 #define clear_notfull_irq(m)    omap_writel((m)->notfull_bit, (m)->irqstatus)
71 #define notfull_irq_enabled(m)  (omap_readl((m)->irqenable) & (m)->notfull_bit)
72 #define has_newmsg_irq(m)       (omap_readl((m)->irqstatus) & (m)->newmsg_bit)
73 #define has_notfull_irq(m)      (omap_readl((m)->irqstatus) & (m)->notfull_bit)
74 #define mbx_nomsg(m)            (omap_readl((m)->msgstatus_r) == 0)
75 #define mbx_is_notfull(m)       (omap_readl((m)->fifostatus_w) == 0)
76
77 #endif /* CONFIG_ARCH_OMAP2 */
78
79 static void do_mbx(void *p);
80
81 #define MBQ_DEPTH       16
82 struct mbq {
83         mbx_msg_t msg[MBQ_DEPTH];
84         int rp, wp, full;
85 };
86
87 #define mbq_inc(p)      do { if (++(p) == MBQ_DEPTH) (p) = 0; } while(0)
88
89 #if defined(CONFIG_ARCH_OMAP1)
90 #  define MBX_USE_SEQ_BIT       /* XXX */
91 #elif defined(CONFIG_ARCH_OMAP2)
92 #  undef MBX_USE_SEQ_BIT
93 #endif
94
95 struct mbx {
96         char *name;
97         unsigned int irq;
98         char irq_devid_newmsg;
99 #ifdef CONFIG_ARCH_OMAP2
100         char irq_devid_notfull;
101 #endif
102 #ifdef MBX_USE_SEQ_BIT
103         mbx_msg_t seq_snd;
104         mbx_msg_t seq_rcv;
105                 /* seq_rcv should be initialized with any value other than
106                  * 0 and 1 << 31, to allow either value for the first
107                  * message.  */
108 #endif
109         mbx_receiver_t *receiver_map[MBX_CMD_MAX];
110         struct work_struct work;
111         struct mbq mbq;
112 #ifdef CONFIG_ARCH_OMAP2
113         wait_queue_head_t full_wait_q;
114 #endif
115
116 #if defined(CONFIG_ARCH_OMAP1)
117         void *cmd_w;
118         void *data_w;
119         void *flag_w;
120         void *cmd_r;
121         void *data_r;
122 #elif defined(CONFIG_ARCH_OMAP2)
123         void *irqenable;
124         void *irqstatus;
125         void *message_w;
126         void *message_r;
127         void *fifostatus_w;
128         void *msgstatus_r;
129         u32 notfull_bit;
130         u32 newmsg_bit;
131 #endif
132 };
133
134 #if defined(CONFIG_ARCH_OMAP1)
135
136 #if defined(CONFIG_ARCH_OMAP15XX)
137 #define INT_DSP_MAILBOX1        INT_1510_DSP_MAILBOX1
138 #elif defined(CONFIG_ARCH_OMAP16XX)
139 #define INT_DSP_MAILBOX1        INT_1610_DSP_MAILBOX1
140 #endif
141
142 static struct mbx mbx_dsp = {
143         .name = "DSP",
144         .irq = INT_DSP_MAILBOX1,
145         .work = __WORK_INITIALIZER(mbx_dsp.work, do_mbx, &mbx_dsp),
146
147         .cmd_w  = (void *)MAILBOX_ARM2DSP1b,
148         .data_w = (void *)MAILBOX_ARM2DSP1,
149         .flag_w = (void *)MAILBOX_ARM2DSP1_Flag,
150         .cmd_r  = (void *)MAILBOX_DSP2ARM1b,
151         .data_r = (void *)MAILBOX_DSP2ARM1,
152 };
153
154 #elif defined(CONFIG_ARCH_OMAP2)
155
156 /*
157  * MAILBOX 0: ARM -> DSP,
158  * MAILBOX 1: ARM <- DSP.
159  * MAILBOX 2: ARM -> IVA,
160  * MAILBOX 3: ARM <- IVA.
161  */
162 static struct mbx mbx_dsp = {
163         .name = "DSP",
164         .irq = INT_24XX_MAIL_U0_MPU,
165         .work = __WORK_INITIALIZER(mbx_dsp.work, do_mbx, &mbx_dsp),
166         .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbx_dsp.full_wait_q),
167
168         .irqenable    = (void *)MAILBOX_IRQENABLE_0,
169         .irqstatus    = (void *)MAILBOX_IRQSTATUS_0,
170         .message_w    = (void *)MAILBOX_MESSAGE_0,
171         .message_r    = (void *)MAILBOX_MESSAGE_1,
172         .fifostatus_w = (void *)MAILBOX_FIFOSTATUS_0,
173         .msgstatus_r  = (void *)MAILBOX_MSGSTATUS_1,
174         .notfull_bit  = MAILBOX_IRQ_NOTFULL(0),
175         .newmsg_bit   = MAILBOX_IRQ_NEWMSG(1),
176 };
177 static struct mbx mbx_iva = {
178         .name = "IVA",
179         .irq = INT_24XX_MAIL_U3_MPU,
180         .work = __WORK_INITIALIZER(mbx_iva.work, do_mbx, &mbx_iva),
181         .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbx_iva.full_wait_q),
182
183         .irqenable    = (void *)MAILBOX_IRQENABLE_3,
184         .irqstatus    = (void *)MAILBOX_IRQSTATUS_3,
185         .message_w    = (void *)MAILBOX_MESSAGE_2,
186         .message_r    = (void *)MAILBOX_MESSAGE_3,
187         .fifostatus_w = (void *)MAILBOX_FIFOSTATUS_2,
188         .msgstatus_r  = (void *)MAILBOX_MSGSTATUS_3,
189         .notfull_bit  = MAILBOX_IRQ_NOTFULL(2),
190         .newmsg_bit   = MAILBOX_IRQ_NEWMSG(3),
191 };
192
193 #endif /* CONFIG_ARCH_OMAP2 */
194
195 static struct mbx *mbxes[] = {
196         &mbx_dsp,
197 #ifdef CONFIG_ARCH_OMAP2
198         &mbx_iva,
199 #endif
200 };
201
202 struct mbx *mbx_get(const char *id)
203 {
204         int i;
205
206         for (i = 0; i < ARRAY_SIZE(mbxes); i++) {
207                 if (!strcmp(id, mbxes[i]->name))
208                         return mbxes[i];
209         }
210
211         return ERR_PTR(-ENOENT);
212 }
213
214 #if defined(CONFIG_ARCH_OMAP1)
215 static __inline__ int mbsync_irq_save(struct mbx *mbx, unsigned long *flags,
216                                       int try_cnt)
217 {
218         int cnt;
219
220         local_irq_save(*flags);
221         if (mbx_is_notfull(mbx))
222                 return 0;
223         /*
224          * mailbox is busy. wait for some usecs...
225          */
226         local_irq_restore(*flags);
227         for (cnt = 0; cnt < try_cnt; cnt++) {
228                 udelay(1);
229                 local_irq_save(*flags);
230                 if (mbx_is_notfull(mbx))        /* success! */
231                         return 0;
232                 local_irq_restore(*flags);
233         }
234
235         /* fail! */
236         return -1;
237 }
238 #elif defined(CONFIG_ARCH_OMAP2)
239 static __inline__ int mbsync_irq_save(struct mbx *mbx, unsigned long *flags)
240 {
241         long current_state; 
242         DECLARE_WAITQUEUE(wait, current);
243
244         do {
245                 local_irq_save(*flags);
246                 if (mbx_is_notfull(mbx))
247                         return 0;
248
249                 /*
250                  * mailbox is busy. 
251                  */
252                 local_irq_restore(*flags);
253                 enable_notfull_irq(mbx);
254
255                 /* wait until the FIFO becomes not-full */
256                 add_wait_queue(&mbx->full_wait_q, &wait);
257                 current_state = current->state;
258                 set_current_state(TASK_INTERRUPTIBLE);
259                 if (!mbx_is_notfull(mbx))       /* last check */
260                         schedule();
261                 set_current_state(current_state);
262                 remove_wait_queue(&mbx->full_wait_q, &wait);
263
264                 if (signal_pending(current))
265                         return -1;
266         } while (1);
267 }
268 #endif
269
270 /*
271  * message dispatcher API
272  */
273 int mbx_send(struct mbx *mbx, mbx_msg_t msg)
274 {
275         unsigned long flags;
276
277 #if defined(CONFIG_ARCH_OMAP1)
278         /*
279          * DSP mailbox interrupt latency must be less than 1ms.
280          */
281         if (mbsync_irq_save(mbx, &flags, 1000) < 0) {
282                 printk(KERN_ERR
283                        "mailbox(%s) is busy. message 0x%08x is aborting.\n",
284                        mbx->name, msg);
285                 return -1;
286         }
287 #elif defined(CONFIG_ARCH_OMAP2)
288         if (mbsync_irq_save(mbx, &flags) < 0)
289                 return -1;
290 #endif
291
292 #ifdef MBX_USE_SEQ_BIT
293         /* add seq_snd to msg */
294         msg = (msg & 0x7fffffff) | mbx->seq_snd;
295         /* flip seq_snd */
296         mbx->seq_snd ^= 1 << 31;
297 #endif
298
299         write_mbx(mbx, msg);
300
301         local_irq_restore(flags);
302         return 0;
303 }
304
305 /*
306  * register / unregister API
307  */
308 int register_mbx_receiver(struct mbx *mbx, unsigned char cmd,
309                           mbx_receiver_t *rcv)
310 {
311         if (cmd >= MBX_CMD_MAX) {
312                 printk(KERN_ERR "register_mbx_receiver(): "
313                        "bad cmd (0x%x)\n", cmd);
314                 return -EINVAL;
315         }
316         if (mbx->receiver_map[cmd] != NULL) {
317                 printk(KERN_ERR "register_mbx_receiver(): cmd 0x%x is "
318                        "already reserved.\n", cmd);
319                 return -EINVAL;
320         }
321
322         mbx->receiver_map[cmd] = rcv;
323         return 0;
324 }
325
326 int unregister_mbx_receiver(struct mbx *mbx, unsigned char cmd,
327                             mbx_receiver_t *rcv)
328 {
329         if (cmd >= MBX_CMD_MAX) {
330                 printk(KERN_ERR "unregister_mbx_receiver(): "
331                        "bad cmd (0x%x)\n", cmd);
332                 return -EINVAL;
333         }
334         if (mbx->receiver_map[cmd] != rcv) {
335                 printk(KERN_ERR "unregister_mbx_receiver(): cmd 0x%x and "
336                        "receiver function mismatch!\n", cmd);
337                 return -EINVAL;
338         }
339
340         mbx->receiver_map[cmd] = NULL;
341         return 0;
342 }
343
344 /*
345  * IRQ disable / enable API
346  */
347 void disable_mbx_irq(struct mbx *mbx)
348 {
349         disable_irq(mbx->irq);
350 }
351
352 void enable_mbx_irq(struct mbx *mbx)
353 {
354         enable_irq(mbx->irq);
355 }
356
357 /*
358  * init_seq API
359  */
360 void mbx_init_seq(struct mbx *mbx)
361 {
362 #ifdef MBX_USE_SEQ_BIT
363         /* backward compatibility */
364         mbx->seq_snd = 0x80000000;
365
366         /* any value other than 0 and 1 << 31 */
367         mbx->seq_rcv = 0xffffffff;
368 #endif /* MBX_USE_SEQ_BIT */
369 }
370
371 /*
372  * receiver workqueue
373  */
374 static void do_mbx(void *p)
375 {
376         int empty = 0;
377         struct mbx *mbx = (struct mbx *)p;
378         struct mbq *mbq = &mbx->mbq;
379         mbx_receiver_t *receiver;
380         mbx_msg_t msg;
381 #ifdef MBX_USE_SEQ_BIT
382         mbx_msg_t seq;
383 #endif
384
385         disable_newmsg_irq(mbx);
386         if ((mbq->rp == mbq->wp) && !mbq->full)
387                 empty = 1;
388         enable_newmsg_irq(mbx);
389
390         while (!empty) {
391                 msg = mbq->msg[mbq->rp];
392 #ifdef MBX_USE_SEQ_BIT
393                 seq = msg & (1 << 31);
394
395                 if (seq == mbx->seq_rcv) {
396                         printk(KERN_ERR
397                                "mbx: illegal seq bit! ignoring this command. "
398                                "(%08x)\n", msg);
399                         goto inc;
400                 }
401                 mbx->seq_rcv = seq;
402 #endif
403
404                 /* call receiver function */
405                 if ((receiver = mbx->receiver_map[(msg >> 24) & 0x7f]) == NULL)
406                         printk(KERN_ERR
407                                "mbx: unknown message (%08x) received from "
408                                "%s.\n", msg, mbx->name);
409                 else
410                         receiver(msg);
411
412 #ifdef MBX_USE_SEQ_BIT
413 inc:
414 #endif
415                 disable_newmsg_irq(mbx);
416                 mbq_inc(mbq->rp);
417                 if (mbq->rp == mbq->wp)
418                         empty = 1;
419                 /* if mbq has been full, now we have a room. */
420                 if (mbq->full) {
421                         mbq->full = 0;
422                         enable_newmsg_irq(mbx);
423                 }
424                 enable_newmsg_irq(mbx);
425         }
426 }
427
428 /*
429  * interrupt handler
430  */
431 static irqreturn_t mbx_int_newmsg(int irq, void *p, struct pt_regs *regs)
432 {
433         struct mbx *mbx = container_of(p, struct mbx, irq_devid_newmsg);
434         struct mbq *mbq = &mbx->mbq;
435         mbx_msg_t *msg;
436
437 #ifdef CONFIG_ARCH_OMAP2
438         /*
439          * mailbox IRQ can be muxed.
440          * if it is not a newmsg interrupt, do nothing.
441          */
442         if (!has_newmsg_irq(mbx))
443                 return IRQ_NONE;
444 #endif
445
446         do {
447 #ifdef CONFIG_ARCH_OMAP2
448                 if (mbx_nomsg(mbx)) {
449                         /* no more messages in the fifo. clear IRQ source. */
450                         clear_newmsg_irq(mbx);
451                         break;
452                 }
453 #endif
454
455                 msg = &mbq->msg[mbq->wp];
456                 read_mbx(mbx, msg);
457
458                 mbq_inc(mbq->wp);
459                 if (mbq->wp == mbq->rp) {       /* mbq is full */
460                         mbq->full = 1;
461                         disable_newmsg_irq(mbx);
462                         break;
463                 }
464 #if defined(CONFIG_ARCH_OMAP1)
465         } while (0);    /* do it once */
466 #elif defined(CONFIG_ARCH_OMAP2)
467         } while (1);
468 #endif
469
470         schedule_work(&mbx->work);
471         return IRQ_HANDLED;
472 }
473
474 #ifdef CONFIG_ARCH_OMAP2
475 static irqreturn_t mbx_int_notfull(int irq, void *p, struct pt_regs *regs)
476 {
477         struct mbx *mbx = container_of(p, struct mbx, irq_devid_notfull);
478
479         /*
480          * mailbox IRQ can be muxed.
481          * if it is not a notfull interrupt, we do nothing.
482          */
483 #if 0
484         if (!has_notfull_irq(mbx))
485 #else
486         if (!(has_notfull_irq(mbx) && notfull_irq_enabled(mbx)))
487 #endif
488                 return IRQ_NONE;
489
490         disable_notfull_irq(mbx);
491
492 #if 0   /*
493          * note: this doesn't seeem to work as explained in the manual.
494          * IRQSTATUS:NOTFULL can't be cleared even we write 1 to that bit.
495          * It is always set when it's not full, regardless of IRQENABLE setting.
496          */
497         clear_notfull_irq(mbx);
498 #endif
499
500         wake_up_interruptible_all(&mbx->full_wait_q);
501         return IRQ_HANDLED;
502 }
503 #endif /* CONFIG_ARCH_OMAP2 */
504
505 static int __init mbx_request_irq(struct mbx *mbx, const char *devname)
506 {
507         int ret;
508
509 #ifdef CONFIG_ARCH_OMAP2
510         enable_newmsg_irq(mbx);
511 #endif
512
513         ret = request_irq(mbx->irq, mbx_int_newmsg, SA_INTERRUPT | SA_SHIRQ,
514                           devname, &mbx->irq_devid_newmsg);
515         if (ret) {
516                 printk(KERN_ERR
517                        "failed to register DSP mailbox newmsg interrupt: "
518                        "%d\n", ret);
519                 return ret;
520         }
521
522 #ifdef CONFIG_ARCH_OMAP2
523         ret = request_irq(mbx->irq, mbx_int_notfull, SA_INTERRUPT | SA_SHIRQ,
524                           devname, &mbx->irq_devid_notfull);
525         if (ret) {
526                 printk(KERN_ERR
527                        "failed to register DSP mailbox notfull interrupt: "
528                        "%d\n", ret);
529                 return ret;
530         }
531 #endif
532
533         return 0;
534 }
535
536 static int __init omap_mailbox_init(void)
537 {
538         int ret;
539 #ifdef CONFIG_ARCH_OMAP2
540         struct clk *mbx_ick_handle;
541 #endif
542
543         printk(KERN_INFO "Initializing OMAP Mailboxes\n");
544 #ifdef CONFIG_ARCH_OMAP2
545         /*
546          * FIXME: mbx_ick will never unsed
547          */
548         mbx_ick_handle = clk_get(NULL, "mailboxes_ick");
549         if (IS_ERR(mbx_ick_handle)) {
550                 printk("Could not get mailboxes_ick\n");
551                 return -ENODEV;
552         } else
553                 clk_enable(mbx_ick_handle);
554 #endif
555
556         if ((ret = mbx_request_irq(&mbx_dsp, "mbx_dsp")) != 0)
557                 return ret;
558 #ifdef CONFIG_ARCH_OMAP2
559         if ((ret = mbx_request_irq(&mbx_iva, "mbx_iva")) != 0)
560                 return ret;
561 #endif
562
563         return 0;
564 }
565
566 arch_initcall(omap_mailbox_init);
567
568 EXPORT_SYMBOL(mbx_get);
569 EXPORT_SYMBOL(mbx_send);
570 EXPORT_SYMBOL(register_mbx_receiver);
571 EXPORT_SYMBOL(unregister_mbx_receiver);
572 EXPORT_SYMBOL(disable_mbx_irq);
573 EXPORT_SYMBOL(enable_mbx_irq);
574 EXPORT_SYMBOL(mbx_init_seq);