diff options
-rw-r--r-- | drivers/remoteproc/imx_rproc.c | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 917e6db39572..dda4e8a12adf 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -84,6 +84,8 @@ struct imx_rproc_mem { #define ATT_CORE_MASK 0xffff #define ATT_CORE(I) BIT((I)) +static int imx_rproc_xtr_mbox_init(struct rproc *rproc); +static void imx_rproc_free_mbox(struct rproc *rproc); static int imx_rproc_detach_pd(struct rproc *rproc); struct imx_rproc { @@ -357,6 +359,10 @@ static int imx_rproc_start(struct rproc *rproc) struct arm_smccc_res res; int ret; + ret = imx_rproc_xtr_mbox_init(rproc); + if (ret) + return ret; + switch (dcfg->method) { case IMX_RPROC_MMIO: ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, @@ -407,6 +413,8 @@ static int imx_rproc_stop(struct rproc *rproc) if (ret) dev_err(dev, "Failed to stop remote core\n"); + else + imx_rproc_free_mbox(rproc); return ret; } @@ -592,6 +600,22 @@ static void imx_rproc_kick(struct rproc *rproc, int vqid) static int imx_rproc_attach(struct rproc *rproc) { + return imx_rproc_xtr_mbox_init(rproc); +} + +static int imx_rproc_detach(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + if (dcfg->method != IMX_RPROC_SCU_API) + return -EOPNOTSUPP; + + if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) + return -EOPNOTSUPP; + + imx_rproc_free_mbox(rproc); + return 0; } @@ -610,6 +634,7 @@ static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc static const struct rproc_ops imx_rproc_ops = { .prepare = imx_rproc_prepare, .attach = imx_rproc_attach, + .detach = imx_rproc_detach, .start = imx_rproc_start, .stop = imx_rproc_stop, .kick = imx_rproc_kick, @@ -720,6 +745,18 @@ static int imx_rproc_xtr_mbox_init(struct rproc *rproc) struct device *dev = priv->dev; struct mbox_client *cl; + /* + * stop() and detach() will free the mbox channels, so need + * to request mbox channels in start() and attach(). + * + * Because start() and attach() not able to handle mbox defer + * probe, imx_rproc_xtr_mbox_init is also called in probe(). + * The check is to avoid request mbox again when start() or + * attach() after probe() returns success. + */ + if (priv->tx_ch && priv->rx_ch) + return 0; + if (!of_get_property(dev->of_node, "mbox-names", NULL)) return 0; @@ -749,8 +786,15 @@ static void imx_rproc_free_mbox(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; - mbox_free_channel(priv->tx_ch); - mbox_free_channel(priv->rx_ch); + if (priv->tx_ch) { + mbox_free_channel(priv->tx_ch); + priv->tx_ch = NULL; + } + + if (priv->rx_ch) { + mbox_free_channel(priv->rx_ch); + priv->rx_ch = NULL; + } } static void imx_rproc_put_scu(struct rproc *rproc) |