mpc85xx/t104x: Add deep sleep framework support
authorTang Yuantian <yuantian.tang@freescale.com>
Thu, 17 Apr 2014 07:33:46 +0000 (15:33 +0800)
committerYork Sun <yorksun@freescale.com>
Wed, 23 Apr 2014 00:58:49 +0000 (17:58 -0700)
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@freescale.com>
Reviewed-by: York Sun <yorksun@freescale.com>
README
arch/powerpc/cpu/mpc85xx/cpu_init.c
arch/powerpc/lib/board.c
drivers/ddr/fsl/mpc85xx_ddr_gen3.c
include/fsl_ddr_sdram.h

diff --git a/README b/README
index bbd7399..017a13d 100644 (file)
--- 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
 
index 941c20e..867abb6 100644 (file)
@@ -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
index f86c6f3..8b03d3a 100644 (file)
@@ -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));
index c805086..4d5572e 100644 (file)
@@ -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
 }
index e39b716..e8a2db9 100644 (file)
@@ -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.