summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeng Fan <peng.fan@nxp.com>2020-04-01 17:22:36 +0800
committerPeng Fan <peng.fan@nxp.com>2020-04-07 15:52:10 +0800
commitbfbf223ed855d31085d0a6469aa94357ae0c3674 (patch)
tree9647c324db3a967fddf7f26637ad417561329f8d
parent3511e46772a04136bbec67267360304c701edc6a (diff)
MLK-23727 imx8mp/n: support stop M7
Support stop M7 with SIP call. Per IC team, to rekick M7 need follow steps. If M7 already in WFI, perform below steps. a) Set [0x303A_002C].0=0 [ request SLEEPHOLDREQn ] b) Wait [0x303A_00EC].1 = 0 [ wait SLEEPHOLDACKn ] c) Set GPR.CPUWAIT=1 d) Set [0x303A_002C].0=1 [ de-assert SLEEPHOLDREQn ] e) Set SRC_M7_RCR[3:0] = 0xE0 [ reset M7 core/plat ] f) Wait SRC_M7_RCR[3:0] = 0x8 g) Init TCM or DDR h) Set GPR.INITVTOR i) Set GPR.CPUWAIT=0, M7 starting running Add a timeout check, if timeout, still perform force reset, in this way no need to rely on M7 team's image wfi support ready. Return a1,a2 to caller to check timeout or reset fail. Reviewed-by: Jacky Bai <ping.bai@nxp.com> Signed-off-by: Peng Fan <peng.fan@nxp.com>
-rw-r--r--plat/imx/common/imx_sip_svc.c4
-rw-r--r--plat/imx/common/include/imx_sip_svc.h5
-rw-r--r--plat/imx/imx8m/gpc_common.c50
-rw-r--r--plat/imx/imx8m/imx8mm/gpc.c2
-rw-r--r--plat/imx/imx8m/imx8mm/include/gpc_reg.h1
-rw-r--r--plat/imx/imx8m/imx8mn/include/gpc_reg.h1
-rw-r--r--plat/imx/imx8m/imx8mp/include/gpc_reg.h1
-rw-r--r--plat/imx/imx8m/imx8mq/imx8mq_misc.c2
-rw-r--r--plat/imx/imx8m/imx8mq/include/gpc_reg.h1
9 files changed, 60 insertions, 7 deletions
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index 74b59e83..2fad4740 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -34,7 +34,7 @@ static uintptr_t imx_sip_handler(unsigned int smc_fid,
SMC_RET1(handle, imx_gpc_handler(smc_fid, x1, x2, x3));
break;
case IMX_SIP_SRC:
- SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3));
+ SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3, handle));
break;
case IMX_SIP_DDR_DVFS:
return dram_dvfs_handler(smc_fid, handle, x1, x2, x3);
@@ -52,7 +52,7 @@ static uintptr_t imx_sip_handler(unsigned int smc_fid,
SMC_RET1(handle, imx_gpc_handler(smc_fid, x1, x2, x3));
break;
case IMX_SIP_SRC:
- SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3));
+ SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3, handle));
break;
case IMX_SIP_HAB:
SMC_RET1(handle, imx_hab_handler(smc_fid, x1, x2, x3, x4));
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index 64a01c14..92bde837 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -29,6 +29,7 @@
#define IMX_SIP_SRC 0xc2000005
#define IMX_SIP_SRC_M4_START 0x00
#define IMX_SIP_SRC_M4_STARTED 0x01
+#define IMX_SIP_SRC_M4_STOP 0x02
#define IMX_SIP_GET_SOC_INFO 0xC2000006
@@ -66,7 +67,7 @@ int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
int imx_gpc_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3);
int imx_src_handler(uint32_t smc_fid, u_register_t x1,
- u_register_t x2, u_register_t x3);
+ u_register_t x2, u_register_t x3, void *handle);
int dram_dvfs_handler(uint32_t smc_fid, void *handle,
u_register_t x1, u_register_t x2, u_register_t x3);
@@ -82,7 +83,7 @@ int dram_dvfs_handler(uint32_t smc_fid, void *handle,
int imx_gpc_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3);
int imx_src_handler(uint32_t smc_fid, u_register_t x1,
- u_register_t x2, u_register_t x3);
+ u_register_t x2, u_register_t x3, void *handle);
int imx_hab_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3, u_register_t x4);
#endif
diff --git a/plat/imx/imx8m/gpc_common.c b/plat/imx/imx8m/gpc_common.c
index af1e33b3..5c996e20 100644
--- a/plat/imx/imx8m/gpc_common.c
+++ b/plat/imx/imx8m/gpc_common.c
@@ -12,6 +12,8 @@
#include <common/runtime_svc.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
+#include <drivers/delay_timer.h>
+#include <lib/libc/errno.h>
#include <gpc.h>
#include <imx8m_psci.h>
@@ -334,9 +336,12 @@ int imx_gpc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_regist
#pragma weak imx_src_handler
/* imx8mq/imx8mm need to verrride below function */
int imx_src_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
- u_register_t x3)
+ u_register_t x3, void *handle)
{
uint32_t val;
+ uint64_t timeout;
+ int ret1 = 0, ret2 = 0;
+ uint32_t offset;
switch(x1) {
case IMX_SIP_SRC_M4_START:
@@ -345,6 +350,49 @@ int imx_src_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
case IMX_SIP_SRC_M4_STARTED:
val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x58);
return !(val & 0x1);
+ case IMX_SIP_SRC_M4_STOP:
+ /*
+ * Safe stop
+ * If M4 already in WFI, perform below steps.
+ * a) Set [0x303A_002C].0=0 [ request SLEEPHOLDREQn ]
+ * b) Wait [0x303A_00EC].1 = 0 [ wait SLEEPHOLDACKn ]
+ * c) Set GPR.CPUWAIT=1
+ * d) Set [0x303A_002C].0=1 [ de-assert SLEEPHOLDREQn ]
+ * e) Set SRC_M7_RCR[3:0] = 0xE0 [ reset M7 core/plat ]
+ * f) Wait SRC_M7_RCR[3:0] = 0x8
+ * The following steps move to start part.
+ * g/h is actually no needed here.
+ * g) Init TCM or DDR
+ * h) Set GPR.INITVTOR
+ * i) Set GPR.CPUWAIT=0, M7 starting running
+ */
+ offset = LPS_CPU1;
+ val = mmio_read_32(IMX_GPC_BASE + offset);
+ /* Not in stop/wait mode */
+ if (!(val & (0x3 << 24))) {
+ mmio_clrbits_32(IMX_GPC_BASE + 0x2C, 0x1);
+
+ timeout = timeout_init_us(10000);
+ while((mmio_read_32(IMX_GPC_BASE + offset) & 0x2)) {
+ if (timeout_elapsed(timeout)) {
+ ret1 = -ETIMEDOUT;
+ break;
+ }
+ }
+ }
+ mmio_setbits_32(IMX_IOMUX_GPR_BASE + 0x58, 0x1);
+ mmio_setbits_32(IMX_GPC_BASE + 0x2C, 0x1);
+ mmio_setbits_32(IMX_SRC_BASE + 0xC, 0xE);
+ timeout = timeout_init_us(10000);
+ while ((mmio_read_32(IMX_SRC_BASE + 0xC) & 0xF) != 8) {
+ if (timeout_elapsed(timeout)) {
+ ret2 = -ETIMEDOUT;
+ break;
+ }
+ }
+ SMC_SET_GP(handle, CTX_GPREG_X1, ret1);
+ SMC_SET_GP(handle, CTX_GPREG_X2, ret2);
+ break;
default:
return SMC_UNK;
diff --git a/plat/imx/imx8m/imx8mm/gpc.c b/plat/imx/imx8m/imx8mm/gpc.c
index 33a83613..4df1b9a4 100644
--- a/plat/imx/imx8m/imx8mm/gpc.c
+++ b/plat/imx/imx8m/imx8mm/gpc.c
@@ -422,7 +422,7 @@ void imx_gpc_init(void)
}
int imx_src_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
- u_register_t x3)
+ u_register_t x3, void *handle)
{
uint32_t val;
diff --git a/plat/imx/imx8m/imx8mm/include/gpc_reg.h b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
index 8e213169..ab6dbf43 100644
--- a/plat/imx/imx8m/imx8mm/include/gpc_reg.h
+++ b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
@@ -27,6 +27,7 @@
#define PU_PGC_UP_TRG 0xF8
#define CPU_PGC_DN_TRG 0xFC
#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
#define A53_CORE0_PGC 0x800
#define A53_PLAT_PGC 0x900
#define PLAT_PGC_PCR 0x900
diff --git a/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
index 51a4b103..592c5ccc 100644
--- a/plat/imx/imx8m/imx8mn/include/gpc_reg.h
+++ b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
@@ -27,6 +27,7 @@
#define PU_PGC_UP_TRG 0xF8
#define CPU_PGC_DN_TRG 0xFC
#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
#define A53_CORE0_PGC 0x800
#define A53_PLAT_PGC 0x900
#define PLAT_PGC_PCR 0x900
diff --git a/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
index ff92c242..4786d9eb 100644
--- a/plat/imx/imx8m/imx8mp/include/gpc_reg.h
+++ b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
@@ -28,6 +28,7 @@
#define PU_PGC_UP_TRG 0xD8
#define CPU_PGC_DN_TRG 0xDC
#define PU_PGC_DN_TRG 0xE4
+#define LPS_CPU1 0xEC
#define A53_CORE0_PGC 0x800
#define A53_PLAT_PGC 0x900
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_misc.c b/plat/imx/imx8m/imx8mq/imx8mq_misc.c
index 9ee3b2ad..dd18b35a 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_misc.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_misc.c
@@ -10,7 +10,7 @@
#include <imx_sip_svc.h>
int imx_src_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
- u_register_t x3)
+ u_register_t x3, void *handle)
{
uint32_t val;
diff --git a/plat/imx/imx8m/imx8mq/include/gpc_reg.h b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
index 65992696..4b099387 100644
--- a/plat/imx/imx8m/imx8mq/include/gpc_reg.h
+++ b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
@@ -27,6 +27,7 @@
#define PU_PGC_UP_TRG 0xF8
#define CPU_PGC_DN_TRG 0xFC
#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
#define A53_CORE0_PGC 0x800
#define A53_PLAT_PGC 0x900
#define PLAT_PGC_PCR 0x900