[U-Boot] [UBOOT PATCH 0/4] Add LS1 PSCI system suspend

From: Hongbo Zhang hongbo.zhang@nxp.com
This patch set is based against latest community uboot tree in which my PSCIv1.0 support was merged. Currently doesn't apply our internal SDK uboot, when these get merged in community we can pull them back into SDK.
We need community kernel to test this PSCI system suspend too, our internal SDK kernel is too old for PSCI. And more codes are needed to be added into kernel to do this test, such as a Flex timer as wake up device, and one peice of code to write IPPDEXPCR registers before SMC call.
All patches have been tested on both LA1021ATWR and LS1021AQDS.
Hongbo Zhang (4): armv7: psci: make v7_flush_dcache_all public for all psci code nxp: ls102xa: add registers definition for system sleep nxp: ls102xa: add EPU Finite State Machine nxp: ls102xa: add LS1 PSCI system suspend
arch/arm/cpu/armv7/ls102xa/Makefile | 2 +- arch/arm/cpu/armv7/ls102xa/fsl_epu.c | 157 ++++++++++++++ arch/arm/cpu/armv7/ls102xa/fsl_epu.h | 8 + arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c | 236 ++++++++++++++++++++++ arch/arm/cpu/armv7/ls102xa/psci.S | 11 + arch/arm/cpu/armv7/psci.S | 6 +- arch/arm/include/asm/arch-ls102xa/config.h | 2 + arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h | 52 ++++- arch/arm/include/asm/psci.h | 2 + board/freescale/common/arm_sleep.c | 35 +++- include/configs/ls1021aqds.h | 8 + include/configs/ls1021atwr.h | 1 + 12 files changed, 514 insertions(+), 6 deletions(-) create mode 100644 arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c

From: Hongbo Zhang hongbo.zhang@nxp.com
The v7_flush_dcache_all function will be called by ls102xa platform system suspend, it is necessary to make it a public call instead of a local one, but changing the LENTRY to ENTRY isn't enough, because there is another one using the same name, so this one gets a psci_ prefix.
Signed-off-by: Hongbo Zhang hongbo.zhang@nxp.com --- arch/arm/cpu/armv7/psci.S | 6 +++--- arch/arm/include/asm/psci.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S index f80f6e2..6a36208 100644 --- a/arch/arm/cpu/armv7/psci.S +++ b/arch/arm/cpu/armv7/psci.S @@ -187,7 +187,7 @@ ENDPROC(psci_get_cpu_id) .weak psci_get_cpu_id
/* Imported from Linux kernel */ -LENTRY(v7_flush_dcache_all) +ENTRY(psci_v7_flush_dcache_all) stmfd sp!, {r4-r5, r7, r9-r11, lr} dmb @ ensure ordering with previous memory accesses mrc p15, 1, r0, c0, c0, 1 @ read clidr @@ -234,7 +234,7 @@ finished: isb ldmfd sp!, {r4-r5, r7, r9-r11, lr} bx lr -ENDPROC(v7_flush_dcache_all) +ENDPROC(psci_v7_flush_dcache_all)
ENTRY(psci_disable_smp) mrc p15, 0, r0, c1, c0, 1 @ ACTLR @@ -264,7 +264,7 @@ ENTRY(psci_cpu_off_common) isb dsb
- bl v7_flush_dcache_all + bl psci_v7_flush_dcache_all
clrex @ Why???
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h index 8aefaa7..9b068f0 100644 --- a/arch/arm/include/asm/psci.h +++ b/arch/arm/include/asm/psci.h @@ -86,6 +86,8 @@ void psci_cpu_off_common(void); int psci_update_dt(void *fdt); void psci_board_init(void); int fdt_psci(void *fdt); + +void psci_v7_flush_dcache_all(void); #endif /* ! __ASSEMBLY__ */
#endif /* __ARM_PSCI_H__ */

On Fri, Aug 19, 2016 at 05:20:30PM +0800, macro.wave.z@gmail.com wrote:
From: Hongbo Zhang hongbo.zhang@nxp.com
The v7_flush_dcache_all function will be called by ls102xa platform system suspend, it is necessary to make it a public call instead of a local one, but changing the LENTRY to ENTRY isn't enough, because there is another one using the same name, so this one gets a psci_ prefix.
Signed-off-by: Hongbo Zhang hongbo.zhang@nxp.com
Reviewed-by: Tom Rini trini@konsulko.com

On 08/19/2016 02:20 AM, macro.wave.z@gmail.com wrote:
From: Hongbo Zhang hongbo.zhang@nxp.com
The v7_flush_dcache_all function will be called by ls102xa platform system suspend, it is necessary to make it a public call instead of a local one, but changing the LENTRY to ENTRY isn't enough, because there is another one using the same name, so this one gets a psci_ prefix.
Signed-off-by: Hongbo Zhang hongbo.zhang@nxp.com
This set has been applied to fsl-qoriq master. Awaiting upstream. Thanks.
York

From: Hongbo Zhang hongbo.zhang@nxp.com
This patch adds definitions of all the regesters necessary for system sleep.
Signed-off-by: Hongbo Zhang hongbo.zhang@nxp.com --- arch/arm/include/asm/arch-ls102xa/config.h | 2 + arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h | 52 ++++++++++++++++++++++- include/configs/ls1021aqds.h | 7 +++ 3 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h index d408fe4..b995a00 100644 --- a/arch/arm/include/asm/arch-ls102xa/config.h +++ b/arch/arm/include/asm/arch-ls102xa/config.h @@ -18,7 +18,9 @@ #define CONFIG_SYS_DCSRBAR 0x20000000
#define CONFIG_SYS_DCSR_DCFG_ADDR (CONFIG_SYS_DCSRBAR + 0x00220000) +#define CONFIG_SYS_DCSR_RCPM_ADDR (CONFIG_SYS_DCSRBAR + 0x00222000)
+#define CONFIG_SYS_GIC_ADDR (CONFIG_SYS_IMMR + 0x00400000) #define CONFIG_SYS_FSL_DDR_ADDR (CONFIG_SYS_IMMR + 0x00080000) #define CONFIG_SYS_CCI400_ADDR (CONFIG_SYS_IMMR + 0x00180000) #define CONFIG_SYS_FSL_CSU_ADDR (CONFIG_SYS_IMMR + 0x00510000) diff --git a/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h b/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h index 0a80772..c34fd63 100644 --- a/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h +++ b/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h @@ -161,6 +161,17 @@ struct ccsr_gur { #define SCFG_SNPCNFGCR_DBG_RD_WR 0x000c0000 #define SCFG_SNPCNFGCR_EDMA_SNP 0x00020000 #define SCFG_ENDIANCR_LE 0x80000000 +#define SCFG_DPSLPCR_WDRR_EN 0x00000001 +#define SCFG_PMCINTECR_LPUART 0x40000000 +#define SCFG_PMCINTECR_FTM 0x20000000 +#define SCFG_PMCINTECR_GPIO 0x10000000 +#define SCFG_PMCINTECR_IRQ0 0x08000000 +#define SCFG_PMCINTECR_IRQ1 0x04000000 +#define SCFG_PMCINTECR_ETSECRXG0 0x00800000 +#define SCFG_PMCINTECR_ETSECRXG1 0x00400000 +#define SCFG_PMCINTECR_ETSECERRG0 0x00080000 +#define SCFG_PMCINTECR_ETSECERRG1 0x00040000 +#define SCFG_CLUSTERPMCR_WFIL2EN 0x80000000
/* Supplemental Configuration Unit */ struct ccsr_scfg { @@ -226,7 +237,7 @@ struct ccsr_scfg { u32 debug_streamid; u32 resv10[5]; u32 snpcnfgcr; - u32 resv11[1]; + u32 hrstcr; u32 intpcr; u32 resv12[20]; u32 scfgrevcr; @@ -243,6 +254,9 @@ struct ccsr_scfg { u32 sdhciovserlcr; u32 resv14[61]; u32 sparecr[8]; + u32 resv15[248]; + u32 core0sftrstsr; + u32 clusterpmcr; };
/* Clocking */ @@ -433,6 +447,42 @@ struct ccsr_ahci { u32 cmds; /* port 0/1 CMD status error */ };
+#define RCPM_POWMGTCSR 0x130 +#define RCPM_POWMGTCSR_SERDES_PW 0x80000000 +#define RCPM_POWMGTCSR_LPM20_REQ 0x00100000 +#define RCPM_POWMGTCSR_LPM20_ST 0x00000200 +#define RCPM_POWMGTCSR_P_LPM20_ST 0x00000100 +#define RCPM_IPPDEXPCR0 0x140 +#define RCPM_IPPDEXPCR0_ETSEC 0x80000000 +#define RCPM_IPPDEXPCR0_GPIO 0x00000040 +#define RCPM_IPPDEXPCR1 0x144 +#define RCPM_IPPDEXPCR1_LPUART 0x40000000 +#define RCPM_IPPDEXPCR1_FLEXTIMER 0x20000000 +#define RCPM_IPPDEXPCR1_OCRAM1 0x10000000 +#define RCPM_NFIQOUTR 0x15c +#define RCPM_NIRQOUTR 0x16c +#define RCPM_DSIMSKR 0x18c +#define RCPM_CLPCL10SETR 0x1c4 +#define RCPM_CLPCL10SETR_C0 0x00000001 + +struct ccsr_rcpm { + u8 rev1[0x4c]; + u32 twaitsr; + u8 rev2[0xe0]; + u32 powmgtcsr; + u8 rev3[0xc]; + u32 ippdexpcr0; + u32 ippdexpcr1; + u8 rev4[0x14]; + u32 nfiqoutr; + u8 rev5[0xc]; + u32 nirqoutr; + u8 rev6[0x1c]; + u32 dsimskr; + u8 rev7[0x34]; + u32 clpcl10setr; +}; + uint get_svr(void);
#endif /* __ASM_ARCH_LS102XA_IMMAP_H_ */ diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h index 47180f9..7c12fc9 100644 --- a/include/configs/ls1021aqds.h +++ b/include/configs/ls1021aqds.h @@ -289,6 +289,13 @@ unsigned long get_board_ddr_clk(void); #define QIXIS_RCFG_CTL_RECONFIG_IDLE 0x20 #define QIXIS_RCFG_CTL_RECONFIG_START 0x21 #define QIXIS_RCFG_CTL_WATCHDOG_ENBLE 0x08 +#define QIXIS_CTL_SYS 0x5 +#define QIXIS_CTL_SYS_EVTSW_MASK 0x0c +#define QIXIS_CTL_SYS_EVTSW_IRQ 0x04 +#define QIXIS_RST_FORCE_3 0x45 +#define QIXIS_RST_FORCE_3_PCIESLOT1 0x80 +#define QIXIS_PWR_CTL2 0x21 +#define QIXIS_PWR_CTL2_PCTL 0x2
#define CONFIG_SYS_FPGA_CSPR_EXT (0x0) #define CONFIG_SYS_FPGA_CSPR (CSPR_PHYS_ADDR(QIXIS_BASE_PHYS) | \

From: Hongbo Zhang hongbo.zhang@nxp.com
The EPU Finite State Machie (FSM) is used in both the last stage of system suspend and the earliest stage of system resume.
Signed-off-by: Hongbo Zhang hongbo.zhang@nxp.com --- arch/arm/cpu/armv7/ls102xa/fsl_epu.c | 157 +++++++++++++++++++++++++++++++++++ arch/arm/cpu/armv7/ls102xa/fsl_epu.h | 8 ++ 2 files changed, 165 insertions(+)
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_epu.c b/arch/arm/cpu/armv7/ls102xa/fsl_epu.c index 6212640..b4de523 100644 --- a/arch/arm/cpu/armv7/ls102xa/fsl_epu.c +++ b/arch/arm/cpu/armv7/ls102xa/fsl_epu.c @@ -9,6 +9,163 @@
#include "fsl_epu.h"
+struct fsm_reg_vals epu_default_val[] = { + /* EPGCR (Event Processor Global Control Register) */ + {EPGCR, 0}, + /* EPECR (Event Processor Event Control Registers) */ + {EPECR0 + EPECR_STRIDE * 0, 0}, + {EPECR0 + EPECR_STRIDE * 1, 0}, + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, + {EPECR0 + EPECR_STRIDE * 3, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 4, 0x20000084}, + {EPECR0 + EPECR_STRIDE * 5, 0x08000004}, + {EPECR0 + EPECR_STRIDE * 6, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 7, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 8, 0x60000084}, + {EPECR0 + EPECR_STRIDE * 9, 0x08000084}, + {EPECR0 + EPECR_STRIDE * 10, 0x42000084}, + {EPECR0 + EPECR_STRIDE * 11, 0x90000084}, + {EPECR0 + EPECR_STRIDE * 12, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 13, 0x08000084}, + {EPECR0 + EPECR_STRIDE * 14, 0x02000084}, + {EPECR0 + EPECR_STRIDE * 15, 0x00000004}, + /* + * EPEVTCR (Event Processor EVT Pin Control Registers) + * SCU8 triger EVT2, and SCU11 triger EVT9 + */ + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x80000001}, + {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB0000001}, + /* EPCMPR (Event Processor Counter Compare Registers) */ + {EPCMPR0 + EPCMPR_STRIDE * 0, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 1, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 2, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 3, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 4, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 5, 0x00000020}, + {EPCMPR0 + EPCMPR_STRIDE * 6, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 7, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 8, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 9, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 10, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 11, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 12, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 13, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 14, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 15, 0x000000FF}, + /* EPCCR (Event Processor Counter Control Registers) */ + {EPCCR0 + EPCCR_STRIDE * 0, 0}, + {EPCCR0 + EPCCR_STRIDE * 1, 0}, + {EPCCR0 + EPCCR_STRIDE * 2, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 3, 0}, + {EPCCR0 + EPCCR_STRIDE * 4, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 5, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 6, 0}, + {EPCCR0 + EPCCR_STRIDE * 7, 0}, + {EPCCR0 + EPCCR_STRIDE * 8, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 9, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 10, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 11, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 12, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 13, 0}, + {EPCCR0 + EPCCR_STRIDE * 14, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 15, 0x92840000}, + /* EPSMCR (Event Processor SCU Mux Control Registers) */ + {EPSMCR0 + EPSMCR_STRIDE * 0, 0}, + {EPSMCR0 + EPSMCR_STRIDE * 1, 0}, + {EPSMCR0 + EPSMCR_STRIDE * 2, 0x6C700000}, + {EPSMCR0 + EPSMCR_STRIDE * 3, 0x2F000000}, + {EPSMCR0 + EPSMCR_STRIDE * 4, 0x002F0000}, + {EPSMCR0 + EPSMCR_STRIDE * 5, 0x00002E00}, + {EPSMCR0 + EPSMCR_STRIDE * 6, 0x7C000000}, + {EPSMCR0 + EPSMCR_STRIDE * 7, 0x30000000}, + {EPSMCR0 + EPSMCR_STRIDE * 8, 0x64300000}, + {EPSMCR0 + EPSMCR_STRIDE * 9, 0x00003000}, + {EPSMCR0 + EPSMCR_STRIDE * 10, 0x65000030}, + {EPSMCR0 + EPSMCR_STRIDE * 11, 0x31740000}, + {EPSMCR0 + EPSMCR_STRIDE * 12, 0x7F000000}, + {EPSMCR0 + EPSMCR_STRIDE * 13, 0x00003100}, + {EPSMCR0 + EPSMCR_STRIDE * 14, 0x00000031}, + {EPSMCR0 + EPSMCR_STRIDE * 15, 0x76000000}, + /* EPACR (Event Processor Action Control Registers) */ + {EPACR0 + EPACR_STRIDE * 0, 0}, + {EPACR0 + EPACR_STRIDE * 1, 0}, + {EPACR0 + EPACR_STRIDE * 2, 0}, + {EPACR0 + EPACR_STRIDE * 3, 0x00000080}, + {EPACR0 + EPACR_STRIDE * 4, 0}, + {EPACR0 + EPACR_STRIDE * 5, 0x00000040}, + {EPACR0 + EPACR_STRIDE * 6, 0}, + {EPACR0 + EPACR_STRIDE * 7, 0}, + {EPACR0 + EPACR_STRIDE * 8, 0}, + {EPACR0 + EPACR_STRIDE * 9, 0x0000001C}, + {EPACR0 + EPACR_STRIDE * 10, 0x00000020}, + {EPACR0 + EPACR_STRIDE * 11, 0}, + {EPACR0 + EPACR_STRIDE * 12, 0x00000003}, + {EPACR0 + EPACR_STRIDE * 13, 0x06000000}, + {EPACR0 + EPACR_STRIDE * 14, 0x04000000}, + {EPACR0 + EPACR_STRIDE * 15, 0x02000000}, + /* EPIMCR (Event Processor Input Mux Control Registers) */ + {EPIMCR0 + EPIMCR_STRIDE * 0, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 1, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 2, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 3, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 4, 0x44000000}, + {EPIMCR0 + EPIMCR_STRIDE * 5, 0x40000000}, + {EPIMCR0 + EPIMCR_STRIDE * 6, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 7, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 8, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 9, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 10, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 11, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 12, 0x44000000}, + {EPIMCR0 + EPIMCR_STRIDE * 13, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 14, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 15, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 16, 0x6A000000}, + {EPIMCR0 + EPIMCR_STRIDE * 17, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 18, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 19, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 20, 0x48000000}, + {EPIMCR0 + EPIMCR_STRIDE * 21, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 22, 0x6C000000}, + {EPIMCR0 + EPIMCR_STRIDE * 23, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 24, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 25, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 26, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 27, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 28, 0x76000000}, + {EPIMCR0 + EPIMCR_STRIDE * 29, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 30, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 31, 0x76000000}, + /* EPXTRIGCR (Event Processor Crosstrigger Control Register) */ + {EPXTRIGCR, 0x0000FFDF}, + /* end */ + {FSM_END_FLAG, 0}, +}; + +/** + * fsl_epu_setup - Setup EPU registers to default values + */ +void fsl_epu_setup(void *epu_base) +{ + struct fsm_reg_vals *data = epu_default_val; + + if (!epu_base || !data) + return; + + while (data->offset != FSM_END_FLAG) { + out_be32(epu_base + data->offset, data->value); + data++; + } +} + /** * fsl_epu_clean - Clear EPU registers */ diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_epu.h b/arch/arm/cpu/armv7/ls102xa/fsl_epu.h index d658aad..d6f7310 100644 --- a/arch/arm/cpu/armv7/ls102xa/fsl_epu.h +++ b/arch/arm/cpu/armv7/ls102xa/fsl_epu.h @@ -63,6 +63,14 @@ #define EPCTR31 0xA7C #define EPCTR_STRIDE FSL_STRIDE_4B
+#define FSM_END_FLAG 0xFFFFFFFFUL + +struct fsm_reg_vals { + u32 offset; + u32 value; +}; + +void fsl_epu_setup(void *epu_base); void fsl_epu_clean(void *epu_base);
#endif

From: Hongbo Zhang hongbo.zhang@nxp.com
The deep sleep function of LS1 platform, is mapped into PSCI system suspend function, this patch adds implementation of it.
Signed-off-by: Hongbo Zhang hongbo.zhang@nxp.com --- arch/arm/cpu/armv7/ls102xa/Makefile | 2 +- arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c | 236 ++++++++++++++++++++++++++++++ arch/arm/cpu/armv7/ls102xa/psci.S | 11 ++ board/freescale/common/arm_sleep.c | 35 ++++- include/configs/ls1021aqds.h | 1 + include/configs/ls1021atwr.h | 1 + 6 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c
diff --git a/arch/arm/cpu/armv7/ls102xa/Makefile b/arch/arm/cpu/armv7/ls102xa/Makefile index 0228300..f8300c7 100644 --- a/arch/arm/cpu/armv7/ls102xa/Makefile +++ b/arch/arm/cpu/armv7/ls102xa/Makefile @@ -16,5 +16,5 @@ obj-$(CONFIG_SYS_HAS_SERDES) += fsl_ls1_serdes.o ls102xa_serdes.o obj-$(CONFIG_SPL) += spl.o
ifdef CONFIG_ARMV7_PSCI -obj-y += psci.o +obj-y += psci.o ls102xa_psci.o endif diff --git a/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c b/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c new file mode 100644 index 0000000..2ac2e6c --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c @@ -0,0 +1,236 @@ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Hongbo Zhang hongbo.zhang@nxp.com + * + * SPDX-License-Identifier: GPL-2.0+ + * This file implements LS102X platform PSCI SYSTEM-SUSPEND function + */ + +#include <config.h> +#include <asm/io.h> +#include <asm/psci.h> +#include <asm/arch/immap_ls102xa.h> +#include <fsl_immap.h> +#include "fsl_epu.h" + +#define __secure __attribute__((section("._secure.text"))) + +#define CCSR_GICD_CTLR 0x1000 +#define CCSR_GICC_CTLR 0x2000 +#define DCSR_RCPM_CG1CR0 0x31c +#define DCSR_RCPM_CSTTACR0 0xb00 +#define DCFG_CRSTSR_WDRFR 0x8 +#define DDR_RESV_LEN 128 + +#ifdef CONFIG_LS1_DEEP_SLEEP +/* + * DDR controller initialization training breaks the first 128 bytes of DDR, + * save them so that the bootloader can restore them while resuming. + */ +static void __secure ls1_save_ddr_head(void) +{ + const char *src = (const char *)CONFIG_SYS_SDRAM_BASE; + char *dest = (char *)(OCRAM_BASE_S_ADDR + OCRAM_S_SIZE - DDR_RESV_LEN); + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + int i; + + out_le32(&scfg->sparecr[2], dest); + + for (i = 0; i < DDR_RESV_LEN; i++) + *dest++ = *src++; +} + +static void __secure ls1_fsm_setup(void) +{ + void *dcsr_epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET); + void *dcsr_rcpm_base = (void *)CONFIG_SYS_DCSR_RCPM_ADDR; + + out_be32(dcsr_rcpm_base + DCSR_RCPM_CSTTACR0, 0x00001001); + out_be32(dcsr_rcpm_base + DCSR_RCPM_CG1CR0, 0x00000001); + + fsl_epu_setup((void *)dcsr_epu_base); + + /* Pull MCKE signal low before enabling deep sleep signal in FPGA */ + out_be32(dcsr_epu_base + EPECR0, 0x5); + out_be32(dcsr_epu_base + EPSMCR15, 0x76300000); +} + +static void __secure ls1_deepsleep_irq_cfg(void) +{ + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR; + u32 ippdexpcr0, ippdexpcr1, pmcintecr = 0; + + /* Mask interrupts from GIC */ + out_be32(&rcpm->nfiqoutr, 0x0ffffffff); + out_be32(&rcpm->nirqoutr, 0x0ffffffff); + /* Mask deep sleep wake-up interrupts while entering deep sleep */ + out_be32(&rcpm->dsimskr, 0x0ffffffff); + + ippdexpcr0 = in_be32(&rcpm->ippdexpcr0); + /* + * Workaround: There is bug of register ippdexpcr1, when read it always + * returns zero, so its value is saved to a scrachpad register to be + * read, that is why we don't read it from register ippdexpcr1 itself. + */ + ippdexpcr1 = in_le32(&scfg->sparecr[7]); + + if (ippdexpcr0 & RCPM_IPPDEXPCR0_ETSEC) + pmcintecr |= SCFG_PMCINTECR_ETSECRXG0 | + SCFG_PMCINTECR_ETSECRXG1 | + SCFG_PMCINTECR_ETSECERRG0 | + SCFG_PMCINTECR_ETSECERRG1; + + if (ippdexpcr0 & RCPM_IPPDEXPCR0_GPIO) + pmcintecr |= SCFG_PMCINTECR_GPIO; + + if (ippdexpcr1 & RCPM_IPPDEXPCR1_LPUART) + pmcintecr |= SCFG_PMCINTECR_LPUART; + + if (ippdexpcr1 & RCPM_IPPDEXPCR1_FLEXTIMER) + pmcintecr |= SCFG_PMCINTECR_FTM; + + /* Always set external IRQ pins as wakeup source */ + pmcintecr |= SCFG_PMCINTECR_IRQ0 | SCFG_PMCINTECR_IRQ1; + + out_be32(&scfg->pmcintlecr, 0); + /* Clear PMC interrupt status */ + out_be32(&scfg->pmcintsr, 0xffffffff); + /* Enable wakeup interrupt during deep sleep */ + out_be32(&scfg->pmcintecr, pmcintecr); +} + +static void __secure ls1_delay(unsigned int loop) +{ + while (loop--) { + int i = 1000; + while (i--) + ; + } +} + +static void __secure ls1_start_fsm(void) +{ + void *dcsr_epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET); + void *ccsr_gic_base = (void *)CONFIG_SYS_GIC_ADDR; + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + + /* Set HRSTCR */ + setbits_be32(&scfg->hrstcr, 0x80000000); + + /* Place DDR controller in self refresh mode */ + setbits_be32(&ddr->sdram_cfg_2, 0x80000000); + + ls1_delay(2000); + + /* Set EVT4_B to lock the signal MCKE down */ + out_be32(dcsr_epu_base + EPECR0, 0x0); + + ls1_delay(2000); + + out_be32(ccsr_gic_base + CCSR_GICD_CTLR, 0x0); + out_be32(ccsr_gic_base + CCSR_GICC_CTLR, 0x0); + + /* Enable all EPU Counters */ + setbits_be32(dcsr_epu_base + EPGCR, 0x80000000); + + /* Enable SCU15 */ + setbits_be32(dcsr_epu_base + EPECR15, 0x90000004); + + /* Enter WFI mode, and EPU FSM will start */ + __asm__ __volatile__ ("wfi" : : : "memory"); + + /* NEVER ENTER HERE */ + while (1) + ; +} + +static void __secure ls1_deep_sleep(u32 entry_point) +{ + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR; +#ifdef QIXIS_BASE + u32 tmp; + void *qixis_base = (void *)QIXIS_BASE; +#endif + + /* Enable cluster to enter the PCL10 state */ + out_be32(&scfg->clusterpmcr, SCFG_CLUSTERPMCR_WFIL2EN); + + /* Save the first 128 bytes of DDR data */ + ls1_save_ddr_head(); + + /* Save the kernel resume entry */ + out_le32(&scfg->sparecr[3], entry_point); + + /* Request to put cluster 0 in PCL10 state */ + setbits_be32(&rcpm->clpcl10setr, RCPM_CLPCL10SETR_C0); + + /* Setup the registers of the EPU FSM for deep sleep */ + ls1_fsm_setup(); + +#ifdef QIXIS_BASE + /* Connect the EVENT button to IRQ in FPGA */ + tmp = in_8(qixis_base + QIXIS_CTL_SYS); + tmp &= ~QIXIS_CTL_SYS_EVTSW_MASK; + tmp |= QIXIS_CTL_SYS_EVTSW_IRQ; + out_8(qixis_base + QIXIS_CTL_SYS, tmp); + + /* Enable deep sleep signals in FPGA */ + tmp = in_8(qixis_base + QIXIS_PWR_CTL2); + tmp |= QIXIS_PWR_CTL2_PCTL; + out_8(qixis_base + QIXIS_PWR_CTL2, tmp); + + /* Pull down PCIe RST# */ + tmp = in_8(qixis_base + QIXIS_RST_FORCE_3); + tmp |= QIXIS_RST_FORCE_3_PCIESLOT1; + out_8(qixis_base + QIXIS_RST_FORCE_3, tmp); +#endif + + /* Enable Warm Device Reset */ + setbits_be32(&scfg->dpslpcr, SCFG_DPSLPCR_WDRR_EN); + setbits_be32(&gur->crstsr, DCFG_CRSTSR_WDRFR); + + ls1_deepsleep_irq_cfg(); + + psci_v7_flush_dcache_all(); + + ls1_start_fsm(); +} + +#else +static void __secure ls1_sleep(void) +{ + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR; + +#ifdef QIXIS_BASE + u32 tmp; + void *qixis_base = (void *)QIXIS_BASE; + + /* Connect the EVENT button to IRQ in FPGA */ + tmp = in_8(qixis_base + QIXIS_CTL_SYS); + tmp &= ~QIXIS_CTL_SYS_EVTSW_MASK; + tmp |= QIXIS_CTL_SYS_EVTSW_IRQ; + out_8(qixis_base + QIXIS_CTL_SYS, tmp); +#endif + + /* Enable cluster to enter the PCL10 state */ + out_be32(&scfg->clusterpmcr, SCFG_CLUSTERPMCR_WFIL2EN); + + setbits_be32(&rcpm->powmgtcsr, RCPM_POWMGTCSR_LPM20_REQ); + + __asm__ __volatile__ ("wfi" : : : "memory"); +} +#endif + +void __secure ls1_system_suspend(u32 fn, u32 entry_point, u32 context_id) +{ +#ifdef CONFIG_LS1_DEEP_SLEEP + ls1_deep_sleep(entry_point); +#else + ls1_sleep(); +#endif +} diff --git a/arch/arm/cpu/armv7/ls102xa/psci.S b/arch/arm/cpu/armv7/ls102xa/psci.S index 8f38680..3d41d37 100644 --- a/arch/arm/cpu/armv7/ls102xa/psci.S +++ b/arch/arm/cpu/armv7/ls102xa/psci.S @@ -29,6 +29,7 @@ #define PSCI_FN_AFFINITY_INFO_FEATURE_MASK 0x0 #define PSCI_FN_SYSTEM_OFF_FEATURE_MASK 0x0 #define PSCI_FN_SYSTEM_RESET_FEATURE_MASK 0x0 +#define PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK 0x0
.pushsection ._secure.text, "ax"
@@ -61,6 +62,8 @@ _ls102x_psci_supported_table: .word PSCI_FN_SYSTEM_OFF_FEATURE_MASK .word ARM_PSCI_0_2_FN_SYSTEM_RESET .word PSCI_FN_SYSTEM_RESET_FEATURE_MASK + .word ARM_PSCI_1_0_FN_SYSTEM_SUSPEND + .word PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK .word 0 .word ARM_PSCI_RET_NI
@@ -243,4 +246,12 @@ psci_system_reset: 1: wfi b 1b
+.globl psci_system_suspend +psci_system_suspend: + push {lr} + + bl ls1_system_suspend + + pop {pc} + .popsection diff --git a/board/freescale/common/arm_sleep.c b/board/freescale/common/arm_sleep.c index 71ed15e..16fd445 100644 --- a/board/freescale/common/arm_sleep.c +++ b/board/freescale/common/arm_sleep.c @@ -66,6 +66,36 @@ static void dp_ddr_restore(void) *dst++ = *src++; }
+#if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_LS102XA) +void ls1_psci_resume_fixup(void) +{ + u32 tmp; + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + +#ifdef QIXIS_BASE + void *qixis_base = (void *)QIXIS_BASE; + + /* Pull on PCIe RST# */ + out_8(qixis_base + QIXIS_RST_FORCE_3, 0); + + /* disable deep sleep signals in FPGA */ + tmp = in_8(qixis_base + QIXIS_PWR_CTL2); + tmp &= ~QIXIS_PWR_CTL2_PCTL; + out_8(qixis_base + QIXIS_PWR_CTL2, tmp); +#endif + + /* Disable wakeup interrupt during deep sleep */ + out_be32(&scfg->pmcintecr, 0); + /* Clear PMC interrupt status */ + out_be32(&scfg->pmcintsr, 0xffffffff); + + /* Disable Warm Device Reset */ + tmp = in_be32(&scfg->dpslpcr); + tmp &= ~SCFG_DPSLPCR_WDRR_EN; + out_be32(&scfg->dpslpcr, tmp); +} +#endif + static void dp_resume_prepare(void) { dp_ddr_restore(); @@ -74,6 +104,9 @@ static void dp_resume_prepare(void) #ifdef CONFIG_U_QE u_qe_resume(); #endif +#if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_LS102XA) + ls1_psci_resume_fixup(); +#endif }
int fsl_dp_resume(void) @@ -88,7 +121,7 @@ int fsl_dp_resume(void) dp_resume_prepare();
/* Get the entry address and jump to kernel */ - start_addr = in_le32(&scfg->sparecr[1]); + start_addr = in_le32(&scfg->sparecr[3]); debug("Entry address is 0x%08x\n", start_addr); kernel_resume = (void (*)(void))start_addr; secure_ram_addr(_do_nonsec_entry)(kernel_resume, 0, 0, 0); diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h index 7c12fc9..8178ece 100644 --- a/include/configs/ls1021aqds.h +++ b/include/configs/ls1021aqds.h @@ -12,6 +12,7 @@ #define CONFIG_ARMV7_PSCI #define CONFIG_ARMV7_PSCI_1_0 #define CONFIG_ARMV7_PSCI_NR_CPUS CONFIG_MAX_CPUS +#define CONFIG_LS1_DEEP_SLEEP
#define CONFIG_ARMV7_SECURE_BASE OCRAM_BASE_S_ADDR
diff --git a/include/configs/ls1021atwr.h b/include/configs/ls1021atwr.h index 2f19950..c740c24 100644 --- a/include/configs/ls1021atwr.h +++ b/include/configs/ls1021atwr.h @@ -12,6 +12,7 @@ #define CONFIG_ARMV7_PSCI #define CONFIG_ARMV7_PSCI_1_0 #define CONFIG_ARMV7_PSCI_NR_CPUS CONFIG_MAX_CPUS +#define CONFIG_LS1_DEEP_SLEEP
#define CONFIG_ARMV7_SECURE_BASE OCRAM_BASE_S_ADDR
participants (3)
-
macro.wave.z@gmail.com
-
Tom Rini
-
york sun