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)  | 
