diff options
-rw-r--r-- | drivers/rpmsg/imx_rpmsg.c | 9 | ||||
-rw-r--r-- | drivers/soc/imx/mu/mx8_mu.c | 31 | ||||
-rw-r--r-- | include/linux/mx8_mu.h | 1 |
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); |