]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
remoteproc: imx_rproc: detect and attach to pre-booted remote cores
authorHiago De Franco <hiago.franco@toradex.com>
Wed, 16 Jul 2025 19:46:38 +0000 (16:46 -0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Fri, 18 Jul 2025 10:43:46 +0000 (12:43 +0200)
When the Cortex-M remote core is started and already running before
Linux boots (typically by the Cortex-A bootloader using a command like
bootaux), the current driver is unable to attach to it. This is because
the driver only checks for remote cores running in different SCU
partitions. However in this case, the M-core is in the same partition as
Linux and is already powered up and running by the bootloader.

This patch adds a check using dev_pm_genpd_is_on() to verify whether the
M-core's power domains are already on. If all power domain devices are
on, the driver assumes the M-core is running and proceed to attach to
it.

To accomplish this, we need to avoid passing any attach_data or flags to
dev_pm_domain_attach_list(), allowing the platform device become a
consumer of the power domain provider without changing its current
state.

During probe, also enable and sync the device runtime PM to make sure
the power domains are correctly managed when the core is controlled by
the kernel.

Suggested-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Hiago De Franco <hiago.franco@toradex.com>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: https://lore.kernel.org/r/20250716194638.113115-1-hiagofranco@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/remoteproc/imx_rproc.c

index 627e57a88db218303ebdac327073c8926f319dc4..a6eef0080ca9e46efe60dcb3878b9efdbdc0f08e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
 #include <linux/remoteproc.h>
@@ -890,10 +891,8 @@ static int imx_rproc_partition_notify(struct notifier_block *nb,
 static int imx_rproc_attach_pd(struct imx_rproc *priv)
 {
        struct device *dev = priv->dev;
-       int ret;
-       struct dev_pm_domain_attach_data pd_data = {
-               .pd_flags = PD_FLAG_DEV_LINK_ON,
-       };
+       int ret, i;
+       bool detached = true;
 
        /*
         * If there is only one power-domain entry, the platform driver framework
@@ -902,8 +901,25 @@ static int imx_rproc_attach_pd(struct imx_rproc *priv)
        if (dev->pm_domain)
                return 0;
 
-       ret = dev_pm_domain_attach_list(dev, &pd_data, &priv->pd_list);
-       return ret < 0 ? ret : 0;
+       ret = dev_pm_domain_attach_list(dev, NULL, &priv->pd_list);
+       if (ret < 0)
+               return ret;
+       /*
+        * If all the power domain devices are already turned on, the remote
+        * core is already powered up and running when the kernel booted (e.g.,
+        * started by U-Boot's bootaux command). In this case attach to it.
+        */
+       for (i = 0; i < ret; i++) {
+               if (!dev_pm_genpd_is_on(priv->pd_list->pd_devs[i])) {
+                       detached = false;
+                       break;
+               }
+       }
+
+       if (detached)
+               priv->rproc->state = RPROC_DETACHED;
+
+       return 0;
 }
 
 static int imx_rproc_detect_mode(struct imx_rproc *priv)
@@ -1146,6 +1162,15 @@ static int imx_rproc_probe(struct platform_device *pdev)
                }
        }
 
+       if (dcfg->method == IMX_RPROC_SCU_API) {
+               pm_runtime_enable(dev);
+               ret = pm_runtime_resume_and_get(dev);
+               if (ret) {
+                       dev_err(dev, "pm_runtime get failed: %d\n", ret);
+                       goto err_put_clk;
+               }
+       }
+
        ret = rproc_add(rproc);
        if (ret) {
                dev_err(dev, "rproc_add failed\n");
@@ -1171,6 +1196,10 @@ static void imx_rproc_remove(struct platform_device *pdev)
        struct rproc *rproc = platform_get_drvdata(pdev);
        struct imx_rproc *priv = rproc->priv;
 
+       if (priv->dcfg->method == IMX_RPROC_SCU_API) {
+               pm_runtime_disable(priv->dev);
+               pm_runtime_put(priv->dev);
+       }
        clk_disable_unprepare(priv->clk);
        rproc_del(rproc);
        imx_rproc_put_scu(rproc);