From: Tang Yuantian yuantian.t...@freescale.com
When T104x soc wakes up from deep sleep, control is passed to the
primary core that starts executing uboot. After re-initialized some
IP blocks, like DDRC, kernel will take responsibility to continue
to restore environment it leaves before.
Signed-off-by: Tang Yuantian yuantian.t...@freescale.com
---
based on: git://git.denx.de/u-boot-mpc85xx.git
branch: next
tested on: t1040qds and t1040rdb platforms.
v4:
- refactor the framework. In the new patch, the entry is placed
just after DDRC's initialization when resume.
v3:
- fix out-of-tree compile warning
v2:
- added explaination for CONFIG_DEEP_SLEEP
- fixed some issues
README | 4 +++
arch/powerpc/cpu/mpc85xx/cpu_init.c | 8 ++
arch/powerpc/lib/board.c| 16
drivers/ddr/fsl/mpc85xx_ddr_gen3.c | 52 ++---
include/fsl_ddr_sdram.h | 4 +++
5 files changed, 80 insertions(+), 4 deletions(-)
diff --git a/README b/README
index 83a1b25..31e37cb 100644
--- a/README
+++ b/README
@@ -431,6 +431,10 @@ The following options need to be configured:
This CONFIG is defined when the CPC is configured as SRAM at the
time of U-boot entry and is required to be re-initialized.
+ CONFIG_DEEP_SLEEP
+ Inidcates this SoC supports deep sleep feature. If deep sleep is
+ supported, core will start to execute uboot when wakes up.
+
- Generic CPU options:
CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c
b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index 941c20e..867abb6 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -350,6 +350,7 @@ void cpu_init_f (void)
extern void m8560_cpm_reset (void);
#ifdef CONFIG_SYS_DCSRBAR_PHYS
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ gd = (gd_t *)(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
#endif
#if defined(CONFIG_SECURE_BOOT)
struct law_entry law;
@@ -414,6 +415,13 @@ void cpu_init_f (void)
in_be32(gur-dcsrcr);
#endif
+#ifdef CONFIG_SYS_DCSRBAR_PHYS
+#ifdef CONFIG_DEEP_SLEEP
+ /* disable the console if boot from deep sleep */
+ if (in_be32(gur-scrtsr[0]) (1 3))
+ gd-flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
+#endif
+#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A007212
fsl_erratum_a007212_workaround();
#endif
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index f86c6f3..8b03d3a 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -343,6 +343,13 @@ void board_init_f(ulong bootflag)
#ifdef CONFIG_PRAM
ulong reg;
#endif
+#ifdef CONFIG_DEEP_SLEEP
+ const ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ struct ccsr_scfg *scfg = (void *)CONFIG_SYS_MPC85xx_SCFG;
+ u32 start_addr;
+ typedef void (*func_t)(void);
+ func_t kernel_resume;
+#endif
/* Pointer is writable since we allocated a register for it */
gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
@@ -360,6 +367,15 @@ void board_init_f(ulong bootflag)
if ((*init_fnc_ptr) () != 0)
hang();
+#ifdef CONFIG_DEEP_SLEEP
+ /* Jump to kernel in deep sleep case */
+ if (in_be32(gur-scrtsr[0]) (1 3)) {
+ start_addr = in_be32(scfg-sparecr[1]);
+ kernel_resume = (func_t)start_addr;
+ kernel_resume();
+ }
+#endif
+
#ifdef CONFIG_POST
post_bootmode_init();
post_run(NULL, POST_ROM | post_bootmode_get(NULL));
diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
index c805086..4d5572e 100644
--- a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
+++ b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
@@ -15,6 +15,7 @@
#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
#endif
+DECLARE_GLOBAL_DATA_PTR;
/*
* regs has the to-be-set values for DDR controller registers
@@ -43,6 +44,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
u32 save1, save2;
#endif
+#ifdef CONFIG_DEEP_SLEEP
+ const ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ bool sleep_flag = 0;
+#endif
+
+#ifdef CONFIG_DEEP_SLEEP
+ if (in_be32(gur-scrtsr[0]) (1 3))
+ sleep_flag = 1;
+#endif
+
switch (ctrl_num) {
case 0:
ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
@@ -119,7 +130,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t
*regs,
out_be32(ddr-timing_cfg_0, regs-timing_cfg_0);
out_be32(ddr-timing_cfg_1, regs-timing_cfg_1);
out_be32(ddr-timing_cfg_2, regs-timing_cfg_2);
- out_be32(ddr-sdram_cfg_2, regs-ddr_sdram_cfg_2);
+#ifdef CONFIG_DEEP_SLEEP
+ if