diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index e913c5efcdbf..8537eccfd73a 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -365,6 +365,76 @@ bool imx_rproc_ready(struct rproc *rproc) return true; } +static int imx_rproc_rebuild_channels(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + struct mbox_client *cl = &priv->cl; + struct device *dev = priv->dev; + int ret = 0; + + if (!priv->tx_ch) { + priv->tx_ch = mbox_request_channel_byname(cl, "tx"); + if (IS_ERR(priv->tx_ch)) { + ret = PTR_ERR(priv->tx_ch); + dev_err(dev, "failed to restart tx chan %d\n", ret); + priv->tx_ch = NULL; + + goto err_exit; + } + } + + if (!priv->rx_ch) { + priv->rx_ch = mbox_request_channel_byname(cl, "rx"); + if (IS_ERR(priv->rx_ch)) { + ret = PTR_ERR(priv->rx_ch); + dev_err(dev, "failed to restart rx chan %d\n", ret); + priv->rx_ch = NULL; + + goto err_exit; + } + } + + if (!priv->rxdb_ch) { + priv->rxdb_ch = mbox_request_channel_byname(cl, "rxdb"); + if (IS_ERR(priv->rxdb_ch)) { + ret = PTR_ERR(priv->rxdb_ch); + dev_err(dev, "failed to restart rxdb chan %d\n", ret); + priv->rxdb_ch = NULL; + + goto err_exit; + } + } + + /* txdb is optional */ + if (!priv->txdb_ch) { + priv->txdb_ch = mbox_request_channel_byname(cl, "txdb"); + if (IS_ERR(priv->txdb_ch)) + priv->txdb_ch = NULL; + } + +err_exit: + return ret; +} + +static void imx_rproc_free_channels(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + __u32 mmsg; + + if (priv->txdb_ch) + mbox_send_message(priv->txdb_ch, (void *)&mmsg); + + mbox_free_channel(priv->tx_ch); + mbox_free_channel(priv->rx_ch); + mbox_free_channel(priv->rxdb_ch); + mbox_free_channel(priv->txdb_ch); + + priv->tx_ch = NULL; + priv->rx_ch = NULL; + priv->rxdb_ch = NULL; + priv->txdb_ch = NULL; +} + static int imx_rproc_start(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; @@ -376,6 +446,10 @@ static int imx_rproc_start(struct rproc *rproc) if (priv->ipc_only) { dev_info(dev, "%s: IPC only\n", __func__); + ret = imx_rproc_rebuild_channels(rproc); + if (ret < 0) + return -EINVAL; + /* To partition M4, we need block userspace stop/start */ if (priv->skip_fw_load_recovery) { priv->skip_fw_load_recovery = false; @@ -451,6 +525,8 @@ static int imx_rproc_stop(struct rproc *rproc) if (priv->ipc_only) { dev_info(dev, "%s: IPC only\n", __func__); + imx_rproc_free_channels(rproc); + /* * TO i.MX8 Paritioned M4, M4 reboot is handled by itself, * so we still keep early boot and skip fw load flag