diff options
Diffstat (limited to 'drivers/mailbox')
-rw-r--r-- | drivers/mailbox/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mailbox/mailbox-mpfs.c | 55 | ||||
-rw-r--r-- | drivers/mailbox/rockchip-mailbox.c | 1 | ||||
-rw-r--r-- | drivers/mailbox/zynqmp-ipi-mailbox.c | 13 |
4 files changed, 41 insertions, 30 deletions
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 3f97d5535267..bc2e265cb02d 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -259,7 +259,7 @@ config MTK_CMDQ_MBOX during the vblank. config ZYNQMP_IPI_MBOX - bool "Xilinx ZynqMP IPI Mailbox" + tristate "Xilinx ZynqMP IPI Mailbox" depends on ARCH_ZYNQMP && OF help Say yes here to add support for Xilinx IPI mailbox driver. diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c index 853901acaeec..162df49654fb 100644 --- a/drivers/mailbox/mailbox-mpfs.c +++ b/drivers/mailbox/mailbox-mpfs.c @@ -39,7 +39,7 @@ #define SCB_CTRL_NOTIFY_MASK BIT(SCB_CTRL_NOTIFY) #define SCB_CTRL_POS (16) -#define SCB_CTRL_MASK GENMASK_ULL(SCB_CTRL_POS + SCB_MASK_WIDTH, SCB_CTRL_POS) +#define SCB_CTRL_MASK GENMASK(SCB_CTRL_POS + SCB_MASK_WIDTH - 1, SCB_CTRL_POS) /* SCBCTRL service status register */ @@ -79,6 +79,27 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox) return status & SCB_STATUS_BUSY_MASK; } +static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan) +{ + struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; + struct mpfs_mss_response *response = mbox->response; + u32 val; + + if (mpfs_mbox_busy(mbox)) + return false; + + /* + * The service status is stored in bits 31:16 of the SERVICES_SR + * register & is only valid when the system controller is not busy. + * Failed services are intended to generated interrupts, but in reality + * this does not happen, so the status must be checked here. + */ + val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); + response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS; + + return true; +} + static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data) { struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; @@ -118,6 +139,7 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data) } opt_sel = ((msg->mbox_offset << 7u) | (msg->cmd_opcode & 0x7fu)); + tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK; tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK; writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET); @@ -130,7 +152,7 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan) struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; struct mpfs_mss_response *response = mbox->response; u16 num_words = ALIGN((response->resp_size), (4)) / 4U; - u32 i, status; + u32 i; if (!response->resp_msg) { dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM); @@ -138,8 +160,6 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan) } /* - * The status is stored in bits 31:16 of the SERVICES_SR register. - * It is only valid when BUSY == 0. * We should *never* get an interrupt while the controller is * still in the busy state. If we do, something has gone badly * wrong & the content of the mailbox would not be valid. @@ -150,24 +170,10 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan) return; } - status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); - - /* - * If the status of the individual servers is non-zero, the service has - * failed. The contents of the mailbox at this point are not be valid, - * so don't bother reading them. Set the status so that the driver - * implementing the service can handle the result. - */ - response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS; - if (response->resp_status) - return; - - if (!mpfs_mbox_busy(mbox)) { - for (i = 0; i < num_words; i++) { - response->resp_msg[i] = - readl_relaxed(mbox->mbox_base - + mbox->resp_offset + i * 0x4); - } + for (i = 0; i < num_words; i++) { + response->resp_msg[i] = + readl_relaxed(mbox->mbox_base + + mbox->resp_offset + i * 0x4); } mbox_chan_received_data(chan, response); @@ -182,7 +188,6 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data) mpfs_mbox_rx_data(chan); - mbox_chan_txdone(chan, 0); return IRQ_HANDLED; } @@ -212,6 +217,7 @@ static const struct mbox_chan_ops mpfs_mbox_ops = { .send_data = mpfs_mbox_send_data, .startup = mpfs_mbox_startup, .shutdown = mpfs_mbox_shutdown, + .last_tx_done = mpfs_mbox_last_tx_done, }; static int mpfs_mbox_probe(struct platform_device *pdev) @@ -247,7 +253,8 @@ static int mpfs_mbox_probe(struct platform_device *pdev) mbox->controller.num_chans = 1; mbox->controller.chans = mbox->chans; mbox->controller.ops = &mpfs_mbox_ops; - mbox->controller.txdone_irq = true; + mbox->controller.txdone_poll = true; + mbox->controller.txpoll_period = 10u; ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller); if (ret) { diff --git a/drivers/mailbox/rockchip-mailbox.c b/drivers/mailbox/rockchip-mailbox.c index 5a4934d39ad6..116286ecc5a0 100644 --- a/drivers/mailbox/rockchip-mailbox.c +++ b/drivers/mailbox/rockchip-mailbox.c @@ -254,7 +254,6 @@ static struct platform_driver rockchip_mbox_driver = { module_platform_driver(rockchip_mbox_driver); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Rockchip mailbox: communicate between CPU cores and MCU"); MODULE_AUTHOR("Addy Ke <addy.ke@rock-chips.com>"); MODULE_AUTHOR("Caesar Wang <wxt@rock-chips.com>"); diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c index a4c8d23c76e2..d097f45b0e5f 100644 --- a/drivers/mailbox/zynqmp-ipi-mailbox.c +++ b/drivers/mailbox/zynqmp-ipi-mailbox.c @@ -152,7 +152,7 @@ static irqreturn_t zynqmp_ipi_interrupt(int irq, void *data) struct zynqmp_ipi_message *msg; u64 arg0, arg3; struct arm_smccc_res res; - int ret, i; + int ret, i, status = IRQ_NONE; (void)irq; arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY; @@ -170,11 +170,11 @@ static irqreturn_t zynqmp_ipi_interrupt(int irq, void *data) memcpy_fromio(msg->data, mchan->req_buf, msg->len); mbox_chan_received_data(chan, (void *)msg); - return IRQ_HANDLED; + status = IRQ_HANDLED; } } } - return IRQ_NONE; + return status; } /** @@ -634,7 +634,12 @@ static int zynqmp_ipi_probe(struct platform_device *pdev) struct zynqmp_ipi_mbox *mbox; int num_mboxes, ret = -EINVAL; - num_mboxes = of_get_child_count(np); + num_mboxes = of_get_available_child_count(np); + if (num_mboxes == 0) { + dev_err(dev, "mailbox nodes not available\n"); + return -EINVAL; + } + pdata = devm_kzalloc(dev, struct_size(pdata, ipi_mboxes, num_mboxes), GFP_KERNEL); if (!pdata) |