Lines Matching +full:omap +full:- +full:mailbox

1 // SPDX-License-Identifier: GPL-2.0
3 * OMAP mailbox driver
5 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
6 * Copyright (C) 2013-2021 Texas Instruments Incorporated - https://www.ti.com
9 * Suman Anna <s-anna@ti.com>
22 #include <linux/omap-mailbox.h>
26 #include "mailbox.h"
115 /* global variables for the mailbox devices */
121 MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
125 if (!chan || !chan->con_priv) in mbox_chan_to_omap_mbox()
128 return (struct omap_mbox *)chan->con_priv; in mbox_chan_to_omap_mbox()
134 return __raw_readl(mdev->mbox_base + ofs); in mbox_read_reg()
140 __raw_writel(val, mdev->mbox_base + ofs); in mbox_write_reg()
143 /* Mailbox FIFO handle functions */
146 struct omap_mbox_fifo *fifo = &mbox->rx_fifo; in mbox_fifo_read()
148 return mbox_read_reg(mbox->parent, fifo->msg); in mbox_fifo_read()
153 struct omap_mbox_fifo *fifo = &mbox->tx_fifo; in mbox_fifo_write()
155 mbox_write_reg(mbox->parent, msg, fifo->msg); in mbox_fifo_write()
160 struct omap_mbox_fifo *fifo = &mbox->rx_fifo; in mbox_fifo_empty()
162 return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0); in mbox_fifo_empty()
167 struct omap_mbox_fifo *fifo = &mbox->tx_fifo; in mbox_fifo_full()
169 return mbox_read_reg(mbox->parent, fifo->fifo_stat); in mbox_fifo_full()
172 /* Mailbox IRQ handle functions */
176 &mbox->tx_fifo : &mbox->rx_fifo; in ack_mbox_irq()
177 u32 bit = fifo->intr_bit; in ack_mbox_irq()
178 u32 irqstatus = fifo->irqstatus; in ack_mbox_irq()
180 mbox_write_reg(mbox->parent, bit, irqstatus); in ack_mbox_irq()
183 mbox_read_reg(mbox->parent, irqstatus); in ack_mbox_irq()
189 &mbox->tx_fifo : &mbox->rx_fifo; in is_mbox_irq()
190 u32 bit = fifo->intr_bit; in is_mbox_irq()
191 u32 irqenable = fifo->irqenable; in is_mbox_irq()
192 u32 irqstatus = fifo->irqstatus; in is_mbox_irq()
194 u32 enable = mbox_read_reg(mbox->parent, irqenable); in is_mbox_irq()
195 u32 status = mbox_read_reg(mbox->parent, irqstatus); in is_mbox_irq()
204 &mbox->tx_fifo : &mbox->rx_fifo; in _omap_mbox_enable_irq()
205 u32 bit = fifo->intr_bit; in _omap_mbox_enable_irq()
206 u32 irqenable = fifo->irqenable; in _omap_mbox_enable_irq()
208 l = mbox_read_reg(mbox->parent, irqenable); in _omap_mbox_enable_irq()
210 mbox_write_reg(mbox->parent, l, irqenable); in _omap_mbox_enable_irq()
216 &mbox->tx_fifo : &mbox->rx_fifo; in _omap_mbox_disable_irq()
217 u32 bit = fifo->intr_bit; in _omap_mbox_disable_irq()
218 u32 irqdisable = fifo->irqdisable; in _omap_mbox_disable_irq()
221 * Read and update the interrupt configuration register for pre-OMAP4. in _omap_mbox_disable_irq()
224 if (!mbox->intr_type) in _omap_mbox_disable_irq()
225 bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit; in _omap_mbox_disable_irq()
227 mbox_write_reg(mbox->parent, bit, irqdisable); in _omap_mbox_disable_irq()
263 while (kfifo_len(&mq->fifo) >= sizeof(msg)) { in mbox_rx_work()
264 len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); in mbox_rx_work()
268 mbox_chan_received_data(mq->mbox->chan, (void *)data); in mbox_rx_work()
269 spin_lock_irq(&mq->lock); in mbox_rx_work()
270 if (mq->full) { in mbox_rx_work()
271 mq->full = false; in mbox_rx_work()
272 _omap_mbox_enable_irq(mq->mbox, IRQ_RX); in mbox_rx_work()
274 spin_unlock_irq(&mq->lock); in mbox_rx_work()
279 * Mailbox interrupt handler
285 mbox_chan_txdone(mbox->chan, 0); in __mbox_tx_interrupt()
290 struct omap_mbox_queue *mq = mbox->rxq; in __mbox_rx_interrupt()
295 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { in __mbox_rx_interrupt()
297 mq->full = true; in __mbox_rx_interrupt()
303 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); in __mbox_rx_interrupt()
310 schedule_work(&mbox->rxq->work); in __mbox_rx_interrupt()
338 spin_lock_init(&mq->lock); in mbox_queue_alloc()
340 if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) in mbox_queue_alloc()
343 INIT_WORK(&mq->work, work); in mbox_queue_alloc()
353 kfifo_free(&q->fifo); in mbox_queue_free()
364 return -ENOMEM; in omap_mbox_startup()
365 mbox->rxq = mq; in omap_mbox_startup()
366 mq->mbox = mbox; in omap_mbox_startup()
368 ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, in omap_mbox_startup()
369 mbox->name, mbox); in omap_mbox_startup()
371 pr_err("failed to register mailbox interrupt:%d\n", ret); in omap_mbox_startup()
375 if (mbox->send_no_irq) in omap_mbox_startup()
376 mbox->chan->txdone_method = TXDONE_BY_ACK; in omap_mbox_startup()
383 mbox_queue_free(mbox->rxq); in omap_mbox_startup()
390 free_irq(mbox->irq, mbox); in omap_mbox_fini()
391 flush_work(&mbox->rxq->work); in omap_mbox_fini()
392 mbox_queue_free(mbox->rxq); in omap_mbox_fini()
399 struct omap_mbox **mboxes = mdev->mboxes; in omap_mbox_device_find()
406 if (!strcmp(_mbox->name, mbox_name)) { in omap_mbox_device_find()
417 struct device *dev = cl->dev; in omap_mbox_request_channel()
425 return ERR_PTR(-ENODEV); in omap_mbox_request_channel()
427 if (dev->of_node) { in omap_mbox_request_channel()
428 …pr_err("%s: please use mbox_request_channel(), this API is supported only for OMAP non-DT usage\n", in omap_mbox_request_channel()
430 return ERR_PTR(-ENODEV); in omap_mbox_request_channel()
441 if (!mbox || !mbox->chan) in omap_mbox_request_channel()
442 return ERR_PTR(-ENOENT); in omap_mbox_request_channel()
444 chan = mbox->chan; in omap_mbox_request_channel()
445 spin_lock_irqsave(&chan->lock, flags); in omap_mbox_request_channel()
446 chan->msg_free = 0; in omap_mbox_request_channel()
447 chan->msg_count = 0; in omap_mbox_request_channel()
448 chan->active_req = NULL; in omap_mbox_request_channel()
449 chan->cl = cl; in omap_mbox_request_channel()
450 init_completion(&chan->tx_complete); in omap_mbox_request_channel()
451 spin_unlock_irqrestore(&chan->lock, flags); in omap_mbox_request_channel()
453 ret = chan->mbox->ops->startup(chan); in omap_mbox_request_channel()
472 if (!mdev || !mdev->mboxes) in omap_mbox_register()
473 return -EINVAL; in omap_mbox_register()
475 mboxes = mdev->mboxes; in omap_mbox_register()
479 mbox->dev = device_create(&omap_mbox_class, mdev->dev, in omap_mbox_register()
480 0, mbox, "%s", mbox->name); in omap_mbox_register()
481 if (IS_ERR(mbox->dev)) { in omap_mbox_register()
482 ret = PTR_ERR(mbox->dev); in omap_mbox_register()
488 list_add(&mdev->elem, &omap_mbox_devices); in omap_mbox_register()
491 ret = devm_mbox_controller_register(mdev->dev, &mdev->controller); in omap_mbox_register()
495 while (i--) in omap_mbox_register()
496 device_unregister(mboxes[i]->dev); in omap_mbox_register()
506 if (!mdev || !mdev->mboxes) in omap_mbox_unregister()
507 return -EINVAL; in omap_mbox_unregister()
510 list_del(&mdev->elem); in omap_mbox_unregister()
513 mboxes = mdev->mboxes; in omap_mbox_unregister()
515 device_unregister(mboxes[i]->dev); in omap_mbox_unregister()
522 struct omap_mbox_device *mdev = mbox->parent; in omap_mbox_chan_startup()
525 mutex_lock(&mdev->cfg_lock); in omap_mbox_chan_startup()
526 pm_runtime_get_sync(mdev->dev); in omap_mbox_chan_startup()
529 pm_runtime_put_sync(mdev->dev); in omap_mbox_chan_startup()
530 mutex_unlock(&mdev->cfg_lock); in omap_mbox_chan_startup()
537 struct omap_mbox_device *mdev = mbox->parent; in omap_mbox_chan_shutdown()
539 mutex_lock(&mdev->cfg_lock); in omap_mbox_chan_shutdown()
541 pm_runtime_put_sync(mdev->dev); in omap_mbox_chan_shutdown()
542 mutex_unlock(&mdev->cfg_lock); in omap_mbox_chan_shutdown()
547 int ret = -EBUSY; in omap_mbox_chan_send_noirq()
565 int ret = -EBUSY; in omap_mbox_chan_send()
584 return -EINVAL; in omap_mbox_chan_send_data()
586 if (mbox->send_no_irq) in omap_mbox_chan_send_data()
609 for (fifo = 0; fifo < mdev->num_fifos; fifo++) { in omap_mbox_suspend()
611 dev_err(mdev->dev, "fifo %d has unexpected unread messages\n", in omap_mbox_suspend()
613 return -EBUSY; in omap_mbox_suspend()
617 for (usr = 0; usr < mdev->num_users; usr++) { in omap_mbox_suspend()
618 reg = MAILBOX_IRQENABLE(mdev->intr_type, usr); in omap_mbox_suspend()
619 mdev->irq_ctx[usr] = mbox_read_reg(mdev, reg); in omap_mbox_suspend()
633 for (usr = 0; usr < mdev->num_users; usr++) { in omap_mbox_resume()
634 reg = MAILBOX_IRQENABLE(mdev->intr_type, usr); in omap_mbox_resume()
635 mbox_write_reg(mdev, mdev->irq_ctx[usr], reg); in omap_mbox_resume()
651 .compatible = "ti,omap2-mailbox",
655 .compatible = "ti,omap3-mailbox",
659 .compatible = "ti,omap4-mailbox",
663 .compatible = "ti,am654-mailbox",
667 .compatible = "ti,am64-mailbox",
679 phandle phandle = sp->args[0]; in omap_mbox_of_xlate()
686 return ERR_PTR(-EINVAL); in omap_mbox_of_xlate()
692 return ERR_PTR(-ENODEV); in omap_mbox_of_xlate()
695 mbox = omap_mbox_device_find(mdev, node->name); in omap_mbox_of_xlate()
697 return mbox ? mbox->chan : ERR_PTR(-ENOENT); in omap_mbox_of_xlate()
708 struct device_node *node = pdev->dev.of_node; in omap_mbox_probe()
718 pr_err("%s: only DT-based devices are supported\n", __func__); in omap_mbox_probe()
719 return -ENODEV; in omap_mbox_probe()
722 match_data = of_device_get_match_data(&pdev->dev); in omap_mbox_probe()
724 return -ENODEV; in omap_mbox_probe()
725 intr_type = match_data->intr_type; in omap_mbox_probe()
727 if (of_property_read_u32(node, "ti,mbox-num-users", &num_users)) in omap_mbox_probe()
728 return -ENODEV; in omap_mbox_probe()
730 if (of_property_read_u32(node, "ti,mbox-num-fifos", &num_fifos)) in omap_mbox_probe()
731 return -ENODEV; in omap_mbox_probe()
735 dev_err(&pdev->dev, "no available mbox devices found\n"); in omap_mbox_probe()
736 return -ENODEV; in omap_mbox_probe()
739 finfoblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*finfoblk), in omap_mbox_probe()
742 return -ENOMEM; in omap_mbox_probe()
748 ret = of_property_read_u32_array(child, "ti,mbox-tx", tmp, in omap_mbox_probe()
752 finfo->tx_id = tmp[0]; in omap_mbox_probe()
753 finfo->tx_irq = tmp[1]; in omap_mbox_probe()
754 finfo->tx_usr = tmp[2]; in omap_mbox_probe()
756 ret = of_property_read_u32_array(child, "ti,mbox-rx", tmp, in omap_mbox_probe()
760 finfo->rx_id = tmp[0]; in omap_mbox_probe()
761 finfo->rx_irq = tmp[1]; in omap_mbox_probe()
762 finfo->rx_usr = tmp[2]; in omap_mbox_probe()
764 finfo->name = child->name; in omap_mbox_probe()
766 if (of_find_property(child, "ti,mbox-send-noirq", NULL)) in omap_mbox_probe()
767 finfo->send_no_irq = true; in omap_mbox_probe()
769 if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos || in omap_mbox_probe()
770 finfo->tx_usr >= num_users || finfo->rx_usr >= num_users) in omap_mbox_probe()
771 return -EINVAL; in omap_mbox_probe()
774 mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL); in omap_mbox_probe()
776 return -ENOMEM; in omap_mbox_probe()
778 mdev->mbox_base = devm_platform_ioremap_resource(pdev, 0); in omap_mbox_probe()
779 if (IS_ERR(mdev->mbox_base)) in omap_mbox_probe()
780 return PTR_ERR(mdev->mbox_base); in omap_mbox_probe()
782 mdev->irq_ctx = devm_kcalloc(&pdev->dev, num_users, sizeof(u32), in omap_mbox_probe()
784 if (!mdev->irq_ctx) in omap_mbox_probe()
785 return -ENOMEM; in omap_mbox_probe()
788 list = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*list), in omap_mbox_probe()
791 return -ENOMEM; in omap_mbox_probe()
793 chnls = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*chnls), in omap_mbox_probe()
796 return -ENOMEM; in omap_mbox_probe()
798 mboxblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*mbox), in omap_mbox_probe()
801 return -ENOMEM; in omap_mbox_probe()
806 fifo = &mbox->tx_fifo; in omap_mbox_probe()
807 fifo->msg = MAILBOX_MESSAGE(finfo->tx_id); in omap_mbox_probe()
808 fifo->fifo_stat = MAILBOX_FIFOSTATUS(finfo->tx_id); in omap_mbox_probe()
809 fifo->intr_bit = MAILBOX_IRQ_NOTFULL(finfo->tx_id); in omap_mbox_probe()
810 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->tx_usr); in omap_mbox_probe()
811 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->tx_usr); in omap_mbox_probe()
812 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->tx_usr); in omap_mbox_probe()
814 fifo = &mbox->rx_fifo; in omap_mbox_probe()
815 fifo->msg = MAILBOX_MESSAGE(finfo->rx_id); in omap_mbox_probe()
816 fifo->msg_stat = MAILBOX_MSGSTATUS(finfo->rx_id); in omap_mbox_probe()
817 fifo->intr_bit = MAILBOX_IRQ_NEWMSG(finfo->rx_id); in omap_mbox_probe()
818 fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->rx_usr); in omap_mbox_probe()
819 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr); in omap_mbox_probe()
820 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr); in omap_mbox_probe()
822 mbox->send_no_irq = finfo->send_no_irq; in omap_mbox_probe()
823 mbox->intr_type = intr_type; in omap_mbox_probe()
825 mbox->parent = mdev; in omap_mbox_probe()
826 mbox->name = finfo->name; in omap_mbox_probe()
827 mbox->irq = platform_get_irq(pdev, finfo->tx_irq); in omap_mbox_probe()
828 if (mbox->irq < 0) in omap_mbox_probe()
829 return mbox->irq; in omap_mbox_probe()
830 mbox->chan = &chnls[i]; in omap_mbox_probe()
835 mutex_init(&mdev->cfg_lock); in omap_mbox_probe()
836 mdev->dev = &pdev->dev; in omap_mbox_probe()
837 mdev->num_users = num_users; in omap_mbox_probe()
838 mdev->num_fifos = num_fifos; in omap_mbox_probe()
839 mdev->intr_type = intr_type; in omap_mbox_probe()
840 mdev->mboxes = list; in omap_mbox_probe()
843 * OMAP/K3 Mailbox IP does not have a Tx-Done IRQ, but rather a Tx-Ready in omap_mbox_probe()
846 mdev->controller.txdone_irq = true; in omap_mbox_probe()
847 mdev->controller.dev = mdev->dev; in omap_mbox_probe()
848 mdev->controller.ops = &omap_mbox_chan_ops; in omap_mbox_probe()
849 mdev->controller.chans = chnls; in omap_mbox_probe()
850 mdev->controller.num_chans = info_count; in omap_mbox_probe()
851 mdev->controller.of_xlate = omap_mbox_of_xlate; in omap_mbox_probe()
857 pm_runtime_enable(mdev->dev); in omap_mbox_probe()
859 ret = pm_runtime_resume_and_get(mdev->dev); in omap_mbox_probe()
868 dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l); in omap_mbox_probe()
870 ret = pm_runtime_put_sync(mdev->dev); in omap_mbox_probe()
871 if (ret < 0 && ret != -ENOSYS) in omap_mbox_probe()
874 devm_kfree(&pdev->dev, finfoblk); in omap_mbox_probe()
878 pm_runtime_disable(mdev->dev); in omap_mbox_probe()
887 pm_runtime_disable(mdev->dev); in omap_mbox_remove()
897 .name = "omap-mailbox",
931 MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");