Introduce the required mechanic to set the state of the M4 in order to properly deal with scenarios where the co-processor has been started by another entity. Mainly based on the work published by Arnaud Pouliquen [1]. [1]. https://patchwork.kernel.org/project/linux-remoteproc/list/?series=239877 Signed-off-by: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx> Reviewed-by: Bjorn Andersson <bjorn.andersson@xxxxxxxxxx> --- drivers/remoteproc/stm32_rproc.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 961a53f67ec5..cbeb5ceb15c5 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -39,6 +39,13 @@ #define STM32_MBX_VQ1_ID 1 #define STM32_MBX_SHUTDOWN "shutdown" +#define M4_STATE_OFF 0 +#define M4_STATE_INI 1 +#define M4_STATE_CRUN 2 +#define M4_STATE_CSTOP 3 +#define M4_STATE_STANDBY 4 +#define M4_STATE_CRASH 5 + struct stm32_syscon { struct regmap *map; u32 reg; @@ -636,12 +643,30 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev, return 0; } +static int stm32_rproc_get_m4_status(struct stm32_rproc *ddata, + unsigned int *state) +{ + /* See stm32_rproc_parse_dt() */ + if (!ddata->m4_state.map) { + /* + * We couldn't get the coprocessor's state, assume + * it is not running. + */ + state = M4_STATE_OFF; + return 0; + } + + return regmap_read(ddata->m4_state.map, ddata->m4_state.reg, state); +} + + static int stm32_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct stm32_rproc *ddata; struct device_node *np = dev->of_node; struct rproc *rproc; + unsigned int state; int ret; ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); @@ -664,6 +689,13 @@ static int stm32_rproc_probe(struct platform_device *pdev) if (ret) goto free_rproc; + ret = stm32_rproc_get_m4_status(ddata, &state); + if (ret) + goto free_rproc; + + if (state == M4_STATE_CRUN) + rproc->state = RPROC_DETACHED; + rproc->has_iommu = false; ddata->workqueue = create_workqueue(dev_name(dev)); if (!ddata->workqueue) { -- 2.25.1