4 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
5 * Copyright (C) 2013-2014 Texas Instruments Inc.
7 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
8 * Suman Anna <s-anna@ti.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 #include <linux/interrupt.h>
27 #include <linux/spinlock.h>
28 #include <linux/mutex.h>
29 #include <linux/slab.h>
30 #include <linux/kfifo.h>
31 #include <linux/err.h>
32 #include <linux/notifier.h>
33 #include <linux/module.h>
34 #include <linux/platform_device.h>
35 #include <linux/pm_runtime.h>
36 #include <linux/platform_data/mailbox-omap.h>
37 #include <linux/omap-mailbox.h>
39 #define MAILBOX_REVISION 0x000
40 #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
41 #define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
42 #define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
44 #define OMAP2_MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
45 #define OMAP2_MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
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))
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))
58 #define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
59 #define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
61 #define MBOX_REG_SIZE 0x120
63 #define OMAP4_MBOX_REG_SIZE 0x130
65 #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
66 #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
68 struct omap_mbox_fifo
{
70 unsigned long fifo_stat
;
71 unsigned long msg_stat
;
72 unsigned long irqenable
;
73 unsigned long irqstatus
;
74 unsigned long irqdisable
;
78 struct omap_mbox_queue
{
81 struct work_struct work
;
82 struct tasklet_struct tasklet
;
83 struct omap_mbox
*mbox
;
87 struct omap_mbox_device
{
89 struct mutex cfg_lock
;
90 void __iomem
*mbox_base
;
93 struct omap_mbox
**mboxes
;
94 struct list_head elem
;
100 struct omap_mbox_queue
*txq
, *rxq
;
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
];
108 struct blocking_notifier_head notifier
;
111 /* global variables for the mailbox devices */
112 static DEFINE_MUTEX(omap_mbox_devices_lock
);
113 static LIST_HEAD(omap_mbox_devices
);
115 static unsigned int mbox_kfifo_size
= CONFIG_OMAP_MBOX_KFIFO_SIZE
;
116 module_param(mbox_kfifo_size
, uint
, S_IRUGO
);
117 MODULE_PARM_DESC(mbox_kfifo_size
, "Size of omap's mailbox kfifo (bytes)");
120 unsigned int mbox_read_reg(struct omap_mbox_device
*mdev
, size_t ofs
)
122 return __raw_readl(mdev
->mbox_base
+ ofs
);
126 void mbox_write_reg(struct omap_mbox_device
*mdev
, u32 val
, size_t ofs
)
128 __raw_writel(val
, mdev
->mbox_base
+ ofs
);
131 /* Mailbox FIFO handle functions */
132 static mbox_msg_t
mbox_fifo_read(struct omap_mbox
*mbox
)
134 struct omap_mbox_fifo
*fifo
= &mbox
->rx_fifo
;
135 return (mbox_msg_t
) mbox_read_reg(mbox
->parent
, fifo
->msg
);
138 static void mbox_fifo_write(struct omap_mbox
*mbox
, mbox_msg_t msg
)
140 struct omap_mbox_fifo
*fifo
= &mbox
->tx_fifo
;
141 mbox_write_reg(mbox
->parent
, msg
, fifo
->msg
);
144 static int mbox_fifo_empty(struct omap_mbox
*mbox
)
146 struct omap_mbox_fifo
*fifo
= &mbox
->rx_fifo
;
147 return (mbox_read_reg(mbox
->parent
, fifo
->msg_stat
) == 0);
150 static int mbox_fifo_full(struct omap_mbox
*mbox
)
152 struct omap_mbox_fifo
*fifo
= &mbox
->tx_fifo
;
153 return mbox_read_reg(mbox
->parent
, fifo
->fifo_stat
);
156 /* Mailbox IRQ handle functions */
157 static void ack_mbox_irq(struct omap_mbox
*mbox
, omap_mbox_irq_t irq
)
159 struct omap_mbox_fifo
*fifo
= (irq
== IRQ_TX
) ?
160 &mbox
->tx_fifo
: &mbox
->rx_fifo
;
161 u32 bit
= fifo
->intr_bit
;
162 u32 irqstatus
= fifo
->irqstatus
;
164 mbox_write_reg(mbox
->parent
, bit
, irqstatus
);
166 /* Flush posted write for irq status to avoid spurious interrupts */
167 mbox_read_reg(mbox
->parent
, irqstatus
);
170 static int is_mbox_irq(struct omap_mbox
*mbox
, omap_mbox_irq_t 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
;
178 u32 enable
= mbox_read_reg(mbox
->parent
, irqenable
);
179 u32 status
= mbox_read_reg(mbox
->parent
, irqstatus
);
181 return (int)(enable
& status
& bit
);
187 int omap_mbox_msg_send(struct omap_mbox
*mbox
, mbox_msg_t msg
)
189 struct omap_mbox_queue
*mq
= mbox
->txq
;
192 spin_lock_bh(&mq
->lock
);
194 if (kfifo_avail(&mq
->fifo
) < sizeof(msg
)) {
199 if (kfifo_is_empty(&mq
->fifo
) && !mbox_fifo_full(mbox
)) {
200 mbox_fifo_write(mbox
, msg
);
204 len
= kfifo_in(&mq
->fifo
, (unsigned char *)&msg
, sizeof(msg
));
205 WARN_ON(len
!= sizeof(msg
));
207 tasklet_schedule(&mbox
->txq
->tasklet
);
210 spin_unlock_bh(&mq
->lock
);
213 EXPORT_SYMBOL(omap_mbox_msg_send
);
215 void omap_mbox_save_ctx(struct omap_mbox
*mbox
)
221 nr_regs
= OMAP4_MBOX_NR_REGS
;
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
));
227 dev_dbg(mbox
->dev
, "%s: [%02x] %08x\n", __func__
,
231 EXPORT_SYMBOL(omap_mbox_save_ctx
);
233 void omap_mbox_restore_ctx(struct omap_mbox
*mbox
)
239 nr_regs
= OMAP4_MBOX_NR_REGS
;
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
));
245 dev_dbg(mbox
->dev
, "%s: [%02x] %08x\n", __func__
,
249 EXPORT_SYMBOL(omap_mbox_restore_ctx
);
251 void omap_mbox_enable_irq(struct omap_mbox
*mbox
, omap_mbox_irq_t irq
)
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
;
259 l
= mbox_read_reg(mbox
->parent
, irqenable
);
261 mbox_write_reg(mbox
->parent
, l
, irqenable
);
263 EXPORT_SYMBOL(omap_mbox_enable_irq
);
265 void omap_mbox_disable_irq(struct omap_mbox
*mbox
, omap_mbox_irq_t 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
;
273 * Read and update the interrupt configuration register for pre-OMAP4.
274 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
276 if (!mbox
->intr_type
)
277 bit
= mbox_read_reg(mbox
->parent
, irqdisable
) & ~bit
;
279 mbox_write_reg(mbox
->parent
, bit
, irqdisable
);
281 EXPORT_SYMBOL(omap_mbox_disable_irq
);
283 static void mbox_tx_tasklet(unsigned long tx_data
)
285 struct omap_mbox
*mbox
= (struct omap_mbox
*)tx_data
;
286 struct omap_mbox_queue
*mq
= mbox
->txq
;
290 while (kfifo_len(&mq
->fifo
)) {
291 if (mbox_fifo_full(mbox
)) {
292 omap_mbox_enable_irq(mbox
, IRQ_TX
);
296 ret
= kfifo_out(&mq
->fifo
, (unsigned char *)&msg
,
298 WARN_ON(ret
!= sizeof(msg
));
300 mbox_fifo_write(mbox
, msg
);
305 * Message receiver(workqueue)
307 static void mbox_rx_work(struct work_struct
*work
)
309 struct omap_mbox_queue
*mq
=
310 container_of(work
, struct omap_mbox_queue
, work
);
314 while (kfifo_len(&mq
->fifo
) >= sizeof(msg
)) {
315 len
= kfifo_out(&mq
->fifo
, (unsigned char *)&msg
, sizeof(msg
));
316 WARN_ON(len
!= sizeof(msg
));
318 blocking_notifier_call_chain(&mq
->mbox
->notifier
, len
,
320 spin_lock_irq(&mq
->lock
);
323 omap_mbox_enable_irq(mq
->mbox
, IRQ_RX
);
325 spin_unlock_irq(&mq
->lock
);
330 * Mailbox interrupt handler
332 static void __mbox_tx_interrupt(struct omap_mbox
*mbox
)
334 omap_mbox_disable_irq(mbox
, IRQ_TX
);
335 ack_mbox_irq(mbox
, IRQ_TX
);
336 tasklet_schedule(&mbox
->txq
->tasklet
);
339 static void __mbox_rx_interrupt(struct omap_mbox
*mbox
)
341 struct omap_mbox_queue
*mq
= mbox
->rxq
;
345 while (!mbox_fifo_empty(mbox
)) {
346 if (unlikely(kfifo_avail(&mq
->fifo
) < sizeof(msg
))) {
347 omap_mbox_disable_irq(mbox
, IRQ_RX
);
352 msg
= mbox_fifo_read(mbox
);
354 len
= kfifo_in(&mq
->fifo
, (unsigned char *)&msg
, sizeof(msg
));
355 WARN_ON(len
!= sizeof(msg
));
358 /* no more messages in the fifo. clear IRQ source. */
359 ack_mbox_irq(mbox
, IRQ_RX
);
361 schedule_work(&mbox
->rxq
->work
);
364 static irqreturn_t
mbox_interrupt(int irq
, void *p
)
366 struct omap_mbox
*mbox
= p
;
368 if (is_mbox_irq(mbox
, IRQ_TX
))
369 __mbox_tx_interrupt(mbox
);
371 if (is_mbox_irq(mbox
, IRQ_RX
))
372 __mbox_rx_interrupt(mbox
);
377 static struct omap_mbox_queue
*mbox_queue_alloc(struct omap_mbox
*mbox
,
378 void (*work
) (struct work_struct
*),
379 void (*tasklet
)(unsigned long))
381 struct omap_mbox_queue
*mq
;
383 mq
= kzalloc(sizeof(struct omap_mbox_queue
), GFP_KERNEL
);
387 spin_lock_init(&mq
->lock
);
389 if (kfifo_alloc(&mq
->fifo
, mbox_kfifo_size
, GFP_KERNEL
))
393 INIT_WORK(&mq
->work
, work
);
396 tasklet_init(&mq
->tasklet
, tasklet
, (unsigned long)mbox
);
403 static void mbox_queue_free(struct omap_mbox_queue
*q
)
405 kfifo_free(&q
->fifo
);
409 static int omap_mbox_startup(struct omap_mbox
*mbox
)
412 struct omap_mbox_queue
*mq
;
413 struct omap_mbox_device
*mdev
= mbox
->parent
;
415 mutex_lock(&mdev
->cfg_lock
);
416 ret
= pm_runtime_get_sync(mdev
->dev
);
417 if (unlikely(ret
< 0))
420 if (!mbox
->use_count
++) {
421 mq
= mbox_queue_alloc(mbox
, NULL
, mbox_tx_tasklet
);
428 mq
= mbox_queue_alloc(mbox
, mbox_rx_work
, NULL
);
435 ret
= request_irq(mbox
->irq
, mbox_interrupt
, IRQF_SHARED
,
438 pr_err("failed to register mailbox interrupt:%d\n",
440 goto fail_request_irq
;
443 omap_mbox_enable_irq(mbox
, IRQ_RX
);
445 mutex_unlock(&mdev
->cfg_lock
);
449 mbox_queue_free(mbox
->rxq
);
451 mbox_queue_free(mbox
->txq
);
453 pm_runtime_put_sync(mdev
->dev
);
456 mutex_unlock(&mdev
->cfg_lock
);
460 static void omap_mbox_fini(struct omap_mbox
*mbox
)
462 struct omap_mbox_device
*mdev
= mbox
->parent
;
464 mutex_lock(&mdev
->cfg_lock
);
466 if (!--mbox
->use_count
) {
467 omap_mbox_disable_irq(mbox
, IRQ_RX
);
468 free_irq(mbox
->irq
, mbox
);
469 tasklet_kill(&mbox
->txq
->tasklet
);
470 flush_work(&mbox
->rxq
->work
);
471 mbox_queue_free(mbox
->txq
);
472 mbox_queue_free(mbox
->rxq
);
475 pm_runtime_put_sync(mdev
->dev
);
477 mutex_unlock(&mdev
->cfg_lock
);
480 static struct omap_mbox
*omap_mbox_device_find(struct omap_mbox_device
*mdev
,
481 const char *mbox_name
)
483 struct omap_mbox
*_mbox
, *mbox
= NULL
;
484 struct omap_mbox
**mboxes
= mdev
->mboxes
;
490 for (i
= 0; (_mbox
= mboxes
[i
]); i
++) {
491 if (!strcmp(_mbox
->name
, mbox_name
)) {
499 struct omap_mbox
*omap_mbox_get(const char *name
, struct notifier_block
*nb
)
501 struct omap_mbox
*mbox
= NULL
;
502 struct omap_mbox_device
*mdev
;
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
);
511 mutex_unlock(&omap_mbox_devices_lock
);
514 return ERR_PTR(-ENOENT
);
517 blocking_notifier_chain_register(&mbox
->notifier
, nb
);
519 ret
= omap_mbox_startup(mbox
);
521 blocking_notifier_chain_unregister(&mbox
->notifier
, nb
);
522 return ERR_PTR(-ENODEV
);
527 EXPORT_SYMBOL(omap_mbox_get
);
529 void omap_mbox_put(struct omap_mbox
*mbox
, struct notifier_block
*nb
)
531 blocking_notifier_chain_unregister(&mbox
->notifier
, nb
);
532 omap_mbox_fini(mbox
);
534 EXPORT_SYMBOL(omap_mbox_put
);
536 static struct class omap_mbox_class
= { .name
= "mbox", };
538 static int omap_mbox_register(struct omap_mbox_device
*mdev
)
542 struct omap_mbox
**mboxes
;
544 if (!mdev
|| !mdev
->mboxes
)
547 mboxes
= mdev
->mboxes
;
548 for (i
= 0; mboxes
[i
]; i
++) {
549 struct omap_mbox
*mbox
= mboxes
[i
];
550 mbox
->dev
= device_create(&omap_mbox_class
,
551 mdev
->dev
, 0, mbox
, "%s", mbox
->name
);
552 if (IS_ERR(mbox
->dev
)) {
553 ret
= PTR_ERR(mbox
->dev
);
557 BLOCKING_INIT_NOTIFIER_HEAD(&mbox
->notifier
);
560 mutex_lock(&omap_mbox_devices_lock
);
561 list_add(&mdev
->elem
, &omap_mbox_devices
);
562 mutex_unlock(&omap_mbox_devices_lock
);
568 device_unregister(mboxes
[i
]->dev
);
572 static int omap_mbox_unregister(struct omap_mbox_device
*mdev
)
575 struct omap_mbox
**mboxes
;
577 if (!mdev
|| !mdev
->mboxes
)
580 mutex_lock(&omap_mbox_devices_lock
);
581 list_del(&mdev
->elem
);
582 mutex_unlock(&omap_mbox_devices_lock
);
584 mboxes
= mdev
->mboxes
;
585 for (i
= 0; mboxes
[i
]; i
++)
586 device_unregister(mboxes
[i
]->dev
);
590 static int omap_mbox_probe(struct platform_device
*pdev
)
592 struct resource
*mem
;
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
;
603 if (!pdata
|| !pdata
->info_cnt
|| !pdata
->info
) {
604 pr_err("%s: platform not supported\n", __func__
);
608 mdev
= devm_kzalloc(&pdev
->dev
, sizeof(*mdev
), GFP_KERNEL
);
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
);
617 /* allocate one extra for marking end of list */
618 list
= devm_kzalloc(&pdev
->dev
, (pdata
->info_cnt
+ 1) * sizeof(*list
),
623 mboxblk
= devm_kzalloc(&pdev
->dev
, pdata
->info_cnt
* sizeof(*mbox
),
629 intr_type
= pdata
->intr_type
;
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
);
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
);
648 mbox
->intr_type
= intr_type
;
651 mbox
->name
= info
->name
;
652 mbox
->irq
= platform_get_irq(pdev
, info
->irq_id
);
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
;
663 ret
= omap_mbox_register(mdev
);
667 platform_set_drvdata(pdev
, mdev
);
668 pm_runtime_enable(mdev
->dev
);
670 ret
= pm_runtime_get_sync(mdev
->dev
);
672 pm_runtime_put_noidle(mdev
->dev
);
677 * just print the raw revision register, the format is not
678 * uniform across all SoCs
680 l
= mbox_read_reg(mdev
, MAILBOX_REVISION
);
681 dev_info(mdev
->dev
, "omap mailbox rev 0x%x\n", l
);
683 ret
= pm_runtime_put_sync(mdev
->dev
);
690 pm_runtime_disable(mdev
->dev
);
691 omap_mbox_unregister(mdev
);
695 static int omap_mbox_remove(struct platform_device
*pdev
)
697 struct omap_mbox_device
*mdev
= platform_get_drvdata(pdev
);
699 pm_runtime_disable(mdev
->dev
);
700 omap_mbox_unregister(mdev
);
705 static struct platform_driver omap_mbox_driver
= {
706 .probe
= omap_mbox_probe
,
707 .remove
= omap_mbox_remove
,
709 .name
= "omap-mailbox",
710 .owner
= THIS_MODULE
,
714 static int __init
omap_mbox_init(void)
718 err
= class_register(&omap_mbox_class
);
722 /* kfifo size sanity check: alignment and minimal size */
723 mbox_kfifo_size
= ALIGN(mbox_kfifo_size
, sizeof(mbox_msg_t
));
724 mbox_kfifo_size
= max_t(unsigned int, mbox_kfifo_size
,
727 return platform_driver_register(&omap_mbox_driver
);
729 subsys_initcall(omap_mbox_init
);
731 static void __exit
omap_mbox_exit(void)
733 platform_driver_unregister(&omap_mbox_driver
);
734 class_unregister(&omap_mbox_class
);
736 module_exit(omap_mbox_exit
);
738 MODULE_LICENSE("GPL v2");
739 MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
740 MODULE_AUTHOR("Toshihiro Kobayashi");
741 MODULE_AUTHOR("Hiroshi DOYU");