[U-Boot] [PATCH v4] mpc85xx/t104x: Add deep sleep framework support

Tang Yuantian Yuantian.Tang at freescale.com
Thu Apr 17 09:33:46 CEST 2014


From: Tang Yuantian <yuantian.tang at 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.Tang at 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 (sleep_flag)
+		out_be32(&ddr->sdram_cfg_2,
+			 regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+	else
+#endif
+		out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
 	out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
 	out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
 	out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
@@ -132,8 +149,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
 	out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
 	out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
-	out_be32(&ddr->init_addr, regs->ddr_init_addr);
-	out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+#ifdef CONFIG_DEEP_SLEEP
+	if (sleep_flag) {
+		out_be32(&ddr->init_addr, 0);
+		out_be32(&ddr->init_ext_addr, (1 << 31));
+	} else
+#endif
+	{
+		out_be32(&ddr->init_addr, regs->ddr_init_addr);
+		out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+	}
 
 	out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4);
 	out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5);
@@ -374,8 +399,22 @@ step2:
 	udelay(500);
 	asm volatile("sync;isync");
 
+#ifdef CONFIG_DEEP_SLEEP
+	if (sleep_flag) {
+		/* enter self-refresh */
+		setbits_be32(&ddr->sdram_cfg_2, (1 << 31));
+		/* do board specific memory setup */
+		board_mem_sleep_setup();
+	}
+#endif
+
 	/* Let the controller go */
-	temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
+#ifdef CONFIG_DEEP_SLEEP
+	if (sleep_flag)
+		temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) | SDRAM_CFG_BI);
+	else
+#endif
+		temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI);
 	out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
 	asm volatile("sync;isync");
 
@@ -526,4 +565,9 @@ step2:
 		clrbits_be32(&ddr->sdram_cfg, 0x2);
 	}
 #endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */
+#ifdef CONFIG_DEEP_SLEEP
+	if (sleep_flag)
+		/* exit self-refresh */
+		clrbits_be32(&ddr->sdram_cfg_2, (1 << 31));
+#endif
 }
diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h
index e39b716..e8a2db9 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -406,6 +406,10 @@ static int __board_need_mem_reset(void)
 int board_need_mem_reset(void)
 	__attribute__((weak, alias("__board_need_mem_reset")));
 
+void __weak board_mem_sleep_setup(void)
+{
+}
+
 /*
  * The 85xx boards have a common prototype for fixed_sdram so put the
  * declaration here.
-- 
1.8.5




More information about the U-Boot mailing list