summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/rpmsg/imx_rpmsg.c9
-rw-r--r--drivers/soc/imx/mu/mx8_mu.c31
-rw-r--r--include/linux/mx8_mu.h1
3 files changed, 39 insertions, 2 deletions
diff --git a/drivers/rpmsg/imx_rpmsg.c b/drivers/rpmsg/imx_rpmsg.c
index 7b6e772393fe..4fed5b07f2bc 100644
--- a/drivers/rpmsg/imx_rpmsg.c
+++ b/drivers/rpmsg/imx_rpmsg.c
@@ -121,8 +121,13 @@ static bool imx_rpmsg_notify(struct virtqueue *vq)
mu_rpmsg = rpvq->vq_id << 16;
mutex_lock(&rpvq->rpdev->lock);
- /* send the index of the triggered virtqueue as the mu payload */
- MU_SendMessage(rpvq->rpdev->mu_base, 1, mu_rpmsg);
+ /*
+ * Send the index of the triggered virtqueue as the mu payload.
+ * Use the timeout MU send message here.
+ * Since that M4 core may not be loaded, and the first MSG may
+ * not be handled by M4 when multi-vdev is enabled.
+ */
+ MU_SendMessageTimeout(rpvq->rpdev->mu_base, 1, mu_rpmsg, 200);
mutex_unlock(&rpvq->rpdev->lock);
return true;
diff --git a/drivers/soc/imx/mu/mx8_mu.c b/drivers/soc/imx/mu/mx8_mu.c
index 30c7fd888cb4..2cd6dc880bbe 100644
--- a/drivers/soc/imx/mu/mx8_mu.c
+++ b/drivers/soc/imx/mu/mx8_mu.c
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: GPL-2.0+
*/
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/mx8_mu.h>
@@ -103,6 +104,36 @@ void MU_SendMessage(void __iomem *base, uint32_t regIndex, uint32_t msg)
}
}
+/*
+ * Wait and send message to the other core with timeout mechanism.
+ */
+void MU_SendMessageTimeout(void __iomem *base, uint32_t regIndex, uint32_t msg,
+ uint32_t t)
+{
+ uint32_t mask = MU_SR_TE0_MASK1 >> regIndex;
+ uint32_t timeout = t;
+
+ if (unlikely(version == MU_VER_ID_V10)) {
+ /* Wait TX register to be empty. */
+ while (!(readl_relaxed(base + MU_V10_ASR_OFFSET1) & mask)) {
+ udelay(10);
+ if (timeout-- == 0)
+ return;
+ };
+
+ writel_relaxed(msg, base + MU_V10_ATR0_OFFSET1
+ + (regIndex * 4));
+ } else {
+ /* Wait TX register to be empty. */
+ while (!(readl_relaxed(base + MU_ASR_OFFSET1) & mask)) {
+ udelay(10);
+ if (timeout-- == 0)
+ return;
+ };
+
+ writel_relaxed(msg, base + MU_ATR0_OFFSET1 + (regIndex * 4));
+ }
+}
/*
* Wait to receive message from the other core.
diff --git a/include/linux/mx8_mu.h b/include/linux/mx8_mu.h
index a26d2c6f9b17..b31e52693db8 100644
--- a/include/linux/mx8_mu.h
+++ b/include/linux/mx8_mu.h
@@ -39,6 +39,7 @@
void MU_Init(void __iomem *base);
void MU_SendMessage(void __iomem *base, uint32_t regIndex, uint32_t msg);
+void MU_SendMessageTimeout(void __iomem *base, uint32_t regIndex, uint32_t msg, uint32_t t);
void MU_ReceiveMsg(void __iomem *base, uint32_t regIndex, uint32_t *msg);
void MU_EnableGeneralInt(void __iomem *base, uint32_t index);
void MU_EnableRxFullInt(void __iomem *base, uint32_t index);