diff options
author | Tang Yuantian <yuantian.tang@freescale.com> | 2014-04-17 15:33:46 +0800 |
---|---|---|
committer | York Sun <yorksun@freescale.com> | 2014-04-22 17:58:49 -0700 |
commit | aade20046b7ab5bd9b2afe84ccb31f0adf0c5e1e (patch) | |
tree | 238878efdee4574890334657a984c1c2d564fe91 /drivers | |
parent | 5aef4c86f3629b937cee159c3d44c0d0e9762a42 (diff) |
mpc85xx/t104x: Add deep sleep framework support
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ddr/fsl/mpc85xx_ddr_gen3.c | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c index c805086416..4d5572ef21 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 } |