]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/mailbox.c
ARM: OMAP: DSPGW: rename mbx -> mbox
[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_mbox(m, msgp) \
42                 do { \
43                         *(msgp) = omap_readw((m)->data_r); \
44                         *(msgp) |= ((mbox_msg_t)omap_readw((m)->cmd_r)) << 16; \
45                 } while (0)
46 #define write_mbox(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 mbox_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_mbox(m, msgp) \
63                 do { *(msgp) = omap_readl((m)->message_r); } while (0)
64 #define write_mbox(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 mbox_nomsg(m)           (omap_readl((m)->msgstatus_r) == 0)
75 #define mbox_is_notfull(m)      (omap_readl((m)->fifostatus_w) == 0)
76
77 #endif /* CONFIG_ARCH_OMAP2 */
78
79 static void do_mbox(void *p);
80
81 #define MBQ_DEPTH       16
82 struct mbq {
83         mbox_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 MBOX_USE_SEQ_BIT      /* XXX */
91 #elif defined(CONFIG_ARCH_OMAP2)
92 #  undef MBOX_USE_SEQ_BIT
93 #endif
94
95 struct mbox {
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 MBOX_USE_SEQ_BIT
103         mbox_msg_t seq_snd;
104         mbox_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         mbox_receiver_t *receiver_map[MBOX_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 mbox mbox_dsp = {
143         .name = "DSP",
144         .irq = INT_DSP_MAILBOX1,
145         .work = __WORK_INITIALIZER(mbox_dsp.work, do_mbox, &mbox_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 mbox mbox_dsp = {
163         .name = "DSP",
164         .irq = INT_24XX_MAIL_U0_MPU,
165         .work = __WORK_INITIALIZER(mbox_dsp.work, do_mbox, &mbox_dsp),
166         .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbox_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 mbox mbox_iva = {
178         .name = "IVA",
179         .irq = INT_24XX_MAIL_U3_MPU,
180         .work = __WORK_INITIALIZER(mbox_iva.work, do_mbox, &mbox_iva),
181         .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbox_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 mbox *mboxes[] = {
196         &mbox_dsp,
197 #ifdef CONFIG_ARCH_OMAP2
198         &mbox_iva,
199 #endif
200 };
201
202 struct mbox *mbox_get(const char *id)
203 {
204         int i;
205
206         for (i = 0; i < ARRAY_SIZE(mboxes); i++) {
207                 if (!strcmp(id, mboxes[i]->name))
208                         return mboxes[i];
209         }
210
211         return ERR_PTR(-ENOENT);
212 }
213
214 #if defined(CONFIG_ARCH_OMAP1)
215 static __inline__ int mbsync_irq_save(struct mbox *mbox, unsigned long *flags,
216                                       int try_cnt)
217 {
218         int cnt;
219
220         local_irq_save(*flags);
221         if (mbox_is_notfull(mbox))
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 (mbox_is_notfull(mbox))      /* 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 mbox *mbox, unsigned long *flags)
240 {
241         long current_state;
242         DECLARE_WAITQUEUE(wait, current);
243
244         do {
245                 local_irq_save(*flags);
246                 if (mbox_is_notfull(mbox))
247                         return 0;
248
249                 /*
250                  * mailbox is busy.
251                  */
252                 local_irq_restore(*flags);
253                 enable_notfull_irq(mbox);
254
255                 /* wait until the FIFO becomes not-full */
256                 add_wait_queue(&mbox->full_wait_q, &wait);
257                 current_state = current->state;
258                 set_current_state(TASK_INTERRUPTIBLE);
259                 if (!mbox_is_notfull(mbox))     /* last check */
260                         schedule();
261                 set_current_state(current_state);
262                 remove_wait_queue(&mbox->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 mbox_send(struct mbox *mbox, mbox_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(mbox, &flags, 1000) < 0) {
282                 printk(KERN_ERR
283                        "mailbox(%s) is busy. message 0x%08x is aborting.\n",
284                        mbox->name, msg);
285                 return -1;
286         }
287 #elif defined(CONFIG_ARCH_OMAP2)
288         if (mbsync_irq_save(mbox, &flags) < 0)
289                 return -1;
290 #endif
291
292 #ifdef MBOX_USE_SEQ_BIT
293         /* add seq_snd to msg */
294         msg = (msg & 0x7fffffff) | mbox->seq_snd;
295         /* flip seq_snd */
296         mbox->seq_snd ^= 1 << 31;
297 #endif
298
299         write_mbox(mbox, msg);
300
301         local_irq_restore(flags);
302         return 0;
303 }
304
305 /*
306  * register / unregister API
307  */
308 int register_mbox_receiver(struct mbox *mbox, unsigned char cmd,
309                           mbox_receiver_t *rcv)
310 {
311         if (cmd >= MBOX_CMD_MAX) {
312                 printk(KERN_ERR "register_mbox_receiver(): "
313                        "bad cmd (0x%x)\n", cmd);
314                 return -EINVAL;
315         }
316         if (mbox->receiver_map[cmd] != NULL) {
317                 printk(KERN_ERR "register_mbox_receiver(): cmd 0x%x is "
318                        "already reserved.\n", cmd);
319                 return -EINVAL;
320         }
321
322         mbox->receiver_map[cmd] = rcv;
323         return 0;
324 }
325
326 int unregister_mbox_receiver(struct mbox *mbox, unsigned char cmd,
327                             mbox_receiver_t *rcv)
328 {
329         if (cmd >= MBOX_CMD_MAX) {
330                 printk(KERN_ERR "unregister_mbox_receiver(): "
331                        "bad cmd (0x%x)\n", cmd);
332                 return -EINVAL;
333         }
334         if (mbox->receiver_map[cmd] != rcv) {
335                 printk(KERN_ERR "unregister_mbox_receiver(): cmd 0x%x and "
336                        "receiver function mismatch!\n", cmd);
337                 return -EINVAL;
338         }
339
340         mbox->receiver_map[cmd] = NULL;
341         return 0;
342 }
343
344 /*
345  * IRQ disable / enable API
346  */
347 void disable_mbox_irq(struct mbox *mbox)
348 {
349         disable_irq(mbox->irq);
350 }
351
352 void enable_mbox_irq(struct mbox *mbox)
353 {
354         enable_irq(mbox->irq);
355 }
356
357 /*
358  * init_seq API
359  */
360 void mbox_init_seq(struct mbox *mbox)
361 {
362 #ifdef MBOX_USE_SEQ_BIT
363         /* backward compatibility */
364         mbox->seq_snd = 0x80000000;
365
366         /* any value other than 0 and 1 << 31 */
367         mbox->seq_rcv = 0xffffffff;
368 #endif /* MBOX_USE_SEQ_BIT */
369 }
370
371 /*
372  * receiver workqueue
373  */
374 static void do_mbox(void *p)
375 {
376         int empty = 0;
377         struct mbox *mbox = (struct mbox *)p;
378         struct mbq *mbq = &mbox->mbq;
379         mbox_receiver_t *receiver;
380         mbox_msg_t msg;
381 #ifdef MBOX_USE_SEQ_BIT
382         mbox_msg_t seq;
383 #endif
384
385         disable_newmsg_irq(mbox);
386         if ((mbq->rp == mbq->wp) && !mbq->full)
387                 empty = 1;
388         enable_newmsg_irq(mbox);
389
390         while (!empty) {
391                 msg = mbq->msg[mbq->rp];
392 #ifdef MBOX_USE_SEQ_BIT
393                 seq = msg & (1 << 31);
394
395                 if (seq == mbox->seq_rcv) {
396                         printk(KERN_ERR
397                                "mbox: illegal seq bit! ignoring this command. "
398                                "(%08x)\n", msg);
399                         goto inc;
400                 }
401                 mbox->seq_rcv = seq;
402 #endif
403
404                 /* call receiver function */
405                 if ((receiver = mbox->receiver_map[(msg >> 24) & 0x7f]) == NULL)
406                         printk(KERN_ERR
407                                "mbox: unknown message (%08x) received from "
408                                "%s.\n", msg, mbox->name);
409                 else
410                         receiver(msg);
411
412 #ifdef MBOX_USE_SEQ_BIT
413 inc:
414 #endif
415                 disable_newmsg_irq(mbox);
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(mbox);
423                 }
424                 enable_newmsg_irq(mbox);
425         }
426 }
427
428 /*
429  * interrupt handler
430  */
431 static irqreturn_t mbox_int_newmsg(int irq, void *p, struct pt_regs *regs)
432 {
433         struct mbox *mbox = container_of(p, struct mbox, irq_devid_newmsg);
434         struct mbq *mbq = &mbox->mbq;
435         mbox_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(mbox))
443                 return IRQ_NONE;
444 #endif
445
446         do {
447 #ifdef CONFIG_ARCH_OMAP2
448                 if (mbox_nomsg(mbox)) {
449                         /* no more messages in the fifo. clear IRQ source. */
450                         clear_newmsg_irq(mbox);
451                         break;
452                 }
453 #endif
454
455                 msg = &mbq->msg[mbq->wp];
456                 read_mbox(mbox, msg);
457
458                 mbq_inc(mbq->wp);
459                 if (mbq->wp == mbq->rp) {       /* mbq is full */
460                         mbq->full = 1;
461                         disable_newmsg_irq(mbox);
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(&mbox->work);
471         return IRQ_HANDLED;
472 }
473
474 #ifdef CONFIG_ARCH_OMAP2
475 static irqreturn_t mbox_int_notfull(int irq, void *p, struct pt_regs *regs)
476 {
477         struct mbox *mbox = container_of(p, struct mbox, 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(mbox))
485 #else
486         if (!(has_notfull_irq(mbox) && notfull_irq_enabled(mbox)))
487 #endif
488                 return IRQ_NONE;
489
490         disable_notfull_irq(mbox);
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(mbox);
498 #endif
499
500         wake_up_interruptible_all(&mbox->full_wait_q);
501         return IRQ_HANDLED;
502 }
503 #endif /* CONFIG_ARCH_OMAP2 */
504
505 static int __init mbox_request_irq(struct mbox *mbox, const char *devname)
506 {
507         int ret;
508
509 #ifdef CONFIG_ARCH_OMAP2
510         enable_newmsg_irq(mbox);
511 #endif
512
513         ret = request_irq(mbox->irq, mbox_int_newmsg, SA_INTERRUPT | SA_SHIRQ,
514                           devname, &mbox->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(mbox->irq, mbox_int_notfull, SA_INTERRUPT | SA_SHIRQ,
524                           devname, &mbox->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 *mbox_ick_handle;
541 #endif
542
543         printk(KERN_INFO "Initializing OMAP Mailboxes\n");
544 #ifdef CONFIG_ARCH_OMAP2
545         /*
546          * FIXME: mbox_ick will never unsed
547          */
548         mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
549         if (IS_ERR(mbox_ick_handle)) {
550                 printk("Could not get mailboxes_ick\n");
551                 return -ENODEV;
552         } else
553                 clk_enable(mbox_ick_handle);
554 #endif
555
556         if ((ret = mbox_request_irq(&mbox_dsp, "mbox_dsp")) != 0)
557                 return ret;
558 #ifdef CONFIG_ARCH_OMAP2
559         if ((ret = mbox_request_irq(&mbox_iva, "mbox_iva")) != 0)
560                 return ret;
561 #endif
562
563         return 0;
564 }
565
566 arch_initcall(omap_mailbox_init);
567
568 EXPORT_SYMBOL(mbox_get);
569 EXPORT_SYMBOL(mbox_send);
570 EXPORT_SYMBOL(register_mbox_receiver);
571 EXPORT_SYMBOL(unregister_mbox_receiver);
572 EXPORT_SYMBOL(disable_mbox_irq);
573 EXPORT_SYMBOL(enable_mbox_irq);
574 EXPORT_SYMBOL(mbox_init_seq);