Currently the driver could only start cores. Add support for stopping
CR52 and CA720AE cores via SCMI. Note that the SCP core is controlled
via direct register IO.

Signed-off-by: Marek Vasut <[email protected]>
---
Cc: Nobuhiro Iwamatsu <[email protected]>
Cc: Tom Rini <[email protected]>
Cc: [email protected]
---
 drivers/remoteproc/renesas_rsip.c | 67 +++++++++++++++++++++----------
 1 file changed, 46 insertions(+), 21 deletions(-)

diff --git a/drivers/remoteproc/renesas_rsip.c 
b/drivers/remoteproc/renesas_rsip.c
index 96f3bf77eb8..7c2643e9728 100644
--- a/drivers/remoteproc/renesas_rsip.c
+++ b/drivers/remoteproc/renesas_rsip.c
@@ -100,22 +100,53 @@ static void scp_send_interrupt(void)
  * This must be removed when proper upstream SCP port exists
  */
 #define SCMI_PD_POWER_STATE_SET_BOOTADDR       0x4411
+#define SCMI_PD_POWER_STATE_SET_STATE_ON       0
+#define SCMI_PD_POWER_STATE_SET_STATE_OFF      BIT(30)
 
 /**
- * scp_cpu_core_start() - Boot CPU core by invoking SCP via SCMI
+ * scp_cpu_core_id_to_domain() - Convert core ID to SCMI domain ID
+ * @core: CPU core
+ * @domain: SCMI domain
+ */
+static int scp_cpu_core_id_to_domain(const u32 core, u32 *domain)
+{
+       if (core >= RCAR5_SCP_CORES && core < RCAR5_SCP_CORES + 
RCAR5_CR52_CORES) {
+               /* CR52 */
+               *domain = core - RCAR5_SCP_CORES + SCMI_PD_CORE_RT_CORE00;
+               return 0;
+       }
+
+       if (core >= RCAR5_SCP_CORES + RCAR5_CR52_CORES &&
+           core < RCAR5_SCP_CORES + RCAR5_CR52_CORES + RCAR5_CA720_CORES) {
+               /* CA720 */
+               *domain = core - RCAR5_SCP_CORES - RCAR5_CR52_CORES + 
SCMI_PD_CORE_AP_CORE00;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * scp_cpu_core_set() - Start or stop CPU core by invoking SCP via SCMI
  * @core: CPU core to boot
  * @ep: Entry point
+ * @state: Power state, 0: Power on, BIT(30): Power off
  */
-static void scp_cpu_core_start(const u32 core, const u32 ep)
+static int scp_cpu_core_set(const u32 core, const u32 ep, const u32 state)
 {
        struct scp_scmi_shmem *shmem = (struct scp_scmi_shmem 
*)SCP_SCMI_SHMEM_AREA09;
        struct scp_scmi_pd_power_state_set_a2p scmi_parameter = {
                .flags = 1,     /* Asynchronous power transition using APMU */
-               .domain_id = core,
-               .power_state = 0,       /* Power on */
+               .domain_id = 0,         /* Core ID */
+               .power_state = state,   /* 0: Power on, BIT(30): Power off */
                .boot_addr = ep,
        };
        u32 status;
+       int ret;
+
+       ret = scp_cpu_core_id_to_domain(core, &scmi_parameter.domain_id);
+       if (ret)
+               return ret;
 
        /* Wait for SCP to be free, then set it busy */
        scp_wait_fw_free();
@@ -136,7 +167,10 @@ static void scp_cpu_core_start(const u32 core, const u32 
ep)
        if (status) {
                printf("SCP POWER_STATE_SET domain %d failed, status=0x%x 
(%d)\n",
                       scmi_parameter.domain_id, status, status);
+               return -EINVAL;
        }
+
+       return 0;
 }
 
 /**
@@ -214,27 +248,16 @@ static int renesas_rsip_rproc_init(struct udevice *dev)
 static int renesas_rsip_rproc_start(struct udevice *dev)
 {
        struct renesas_rsip_rproc_privdata *priv = dev_get_priv(dev);
-       int scmi_core;
 
        if (priv->core_id == 0) {
                /* SCP */
                clrbits_le32(SCP_CPUWAIT, SCP_CPUWAIT_WAIT);
                return 0;
-       } else if (priv->core_id >= RCAR5_SCP_CORES &&
-                  priv->core_id < RCAR5_SCP_CORES + RCAR5_CR52_CORES) {
-               /* CR52 */
-               scmi_core = priv->core_id - RCAR5_SCP_CORES +
-                           SCMI_PD_CORE_RT_CORE00;
-       } else if (priv->core_id >= RCAR5_SCP_CORES + RCAR5_CR52_CORES &&
-                  priv->core_id < RCAR5_SCP_CORES + RCAR5_CR52_CORES + 
RCAR5_CA720_CORES) {
-               /* CA720 */
-               scmi_core = priv->core_id - RCAR5_SCP_CORES - RCAR5_CR52_CORES +
-                           SCMI_PD_CORE_AP_CORE00;
+       } else {
+               /* CR52 or CA720 */
+               return scp_cpu_core_set(priv->core_id, priv->ep,
+                                       SCMI_PD_POWER_STATE_SET_STATE_ON);
        }
-
-       scp_cpu_core_start(scmi_core, priv->ep);
-
-       return 0;
 }
 
 /**
@@ -250,9 +273,11 @@ static int renesas_rsip_rproc_stop(struct udevice *dev)
        if (priv->core_id == 0) {
                /* SCP */
                return renesas_rsip_rproc_init(dev);
+       } else {
+               /* CR52 or CA720 */
+               return scp_cpu_core_set(priv->core_id, 0,
+                                       SCMI_PD_POWER_STATE_SET_STATE_OFF);
        }
-
-       return 0;
 }
 
 /**
-- 
2.53.0

Reply via email to