remoteproc: k3-r5: Do not allow core1 to power up before core0 via sysfs
authorBeleswar Padhi <b-padhi@ti.com>
Tue, 30 Apr 2024 10:53:07 +0000 (16:23 +0530)
committerMathieu Poirier <mathieu.poirier@linaro.org>
Tue, 30 Apr 2024 16:51:06 +0000 (10:51 -0600)
PSC controller has a limitation that it can only power-up the second
core when the first core is in ON state. Power-state for core0 should be
equal to or higher than core1.

Therefore, prevent core1 from powering up before core0 during the start
process from sysfs. Similarly, prevent core0 from shutting down before
core1 has been shut down from sysfs.

Fixes: 6dedbd1d5443 ("remoteproc: k3-r5: Add a remoteproc driver for R5F subsystem")
Signed-off-by: Beleswar Padhi <b-padhi@ti.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20240430105307.1190615-3-b-padhi@ti.com
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
drivers/remoteproc/ti_k3_r5_remoteproc.c

index 6d6afd6beb3ab8e67cb7e3f5e017725e0173f43c..1799b4f6d11eea55791f8b8bca1c0a9c45ef7bc3 100644 (file)
@@ -548,7 +548,7 @@ static int k3_r5_rproc_start(struct rproc *rproc)
        struct k3_r5_rproc *kproc = rproc->priv;
        struct k3_r5_cluster *cluster = kproc->cluster;
        struct device *dev = kproc->dev;
-       struct k3_r5_core *core;
+       struct k3_r5_core *core0, *core;
        u32 boot_addr;
        int ret;
 
@@ -574,6 +574,15 @@ static int k3_r5_rproc_start(struct rproc *rproc)
                                goto unroll_core_run;
                }
        } else {
+               /* do not allow core 1 to start before core 0 */
+               core0 = list_first_entry(&cluster->cores, struct k3_r5_core,
+                                        elem);
+               if (core != core0 && core0->rproc->state == RPROC_OFFLINE) {
+                       dev_err(dev, "%s: can not start core 1 before core 0\n",
+                               __func__);
+                       return -EPERM;
+               }
+
                ret = k3_r5_core_run(core);
                if (ret)
                        goto put_mbox;
@@ -619,7 +628,8 @@ static int k3_r5_rproc_stop(struct rproc *rproc)
 {
        struct k3_r5_rproc *kproc = rproc->priv;
        struct k3_r5_cluster *cluster = kproc->cluster;
-       struct k3_r5_core *core = kproc->core;
+       struct device *dev = kproc->dev;
+       struct k3_r5_core *core1, *core = kproc->core;
        int ret;
 
        /* halt all applicable cores */
@@ -632,6 +642,15 @@ static int k3_r5_rproc_stop(struct rproc *rproc)
                        }
                }
        } else {
+               /* do not allow core 0 to stop before core 1 */
+               core1 = list_last_entry(&cluster->cores, struct k3_r5_core,
+                                       elem);
+               if (core != core1 && core1->rproc->state != RPROC_OFFLINE) {
+                       dev_err(dev, "%s: can not stop core 0 before core 1\n",
+                               __func__);
+                       return -EPERM;
+               }
+
                ret = k3_r5_core_halt(core);
                if (ret)
                        goto out;