@@ -84,6 +84,9 @@ 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);
+
struct imx_rproc {
struct device *dev;
struct regmap *regmap;
@@ -355,6 +358,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,
@@ -405,6 +412,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;
}
@@ -584,7 +593,7 @@ static void imx_rproc_kick(struct rproc *rproc, int vqid)
static int imx_rproc_attach(struct rproc *rproc)
{
- return 0;
+ return imx_rproc_xtr_mbox_init(rproc);
}
static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz)
@@ -712,6 +721,9 @@ static int imx_rproc_xtr_mbox_init(struct rproc *rproc)
struct mbox_client *cl;
int ret;
+ if (priv->tx_ch && priv->rx_ch)
+ return 0;
+
if (!of_get_property(dev->of_node, "mbox-names", NULL))
return 0;
@@ -744,8 +756,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 int imx_rproc_partition_notify(struct notifier_block *nb,
@@ -757,6 +776,8 @@ static int imx_rproc_partition_notify(struct notifier_block *nb,
if (!((event & BIT(priv->rproc_pt)) && (*(u8 *)group == IMX_SC_IRQ_GROUP_REBOOTED)))
return 0;
+ imx_rproc_free_mbox(priv->rproc);
+
rproc_report_crash(priv->rproc, RPROC_WATCHDOG);
pr_info("Partition%d reset!\n", priv->rproc_pt);
@@ -1026,7 +1047,6 @@ static int imx_rproc_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clk);
rproc_del(rproc);
- imx_rproc_free_mbox(rproc);
destroy_workqueue(priv->workqueue);
rproc_free(rproc);