
From: Jacky Bai ping.bai@nxp.com
On i.MX8ULP, The dram config timing need to be saved into sram for ddr retention when APD enter PD mode, so add this support on i.MX8ULP.
Reviewed-by: Ye Li ye.li@nxp.com Signed-off-by: Jacky Bai ping.bai@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/ddr/imx/imx8ulp/Kconfig | 7 +++++ drivers/ddr/imx/imx8ulp/ddr_init.c | 45 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+)
diff --git a/drivers/ddr/imx/imx8ulp/Kconfig b/drivers/ddr/imx/imx8ulp/Kconfig index e56062a1d0..42848863aa 100644 --- a/drivers/ddr/imx/imx8ulp/Kconfig +++ b/drivers/ddr/imx/imx8ulp/Kconfig @@ -8,4 +8,11 @@ config IMX8ULP_DRAM_PHY_PLL_BYPASS bool "Enable the DDR PHY PLL bypass mode, so PHY clock is from DDR_CLK " depends on IMX8ULP_DRAM
+config SAVED_DRAM_TIMING_BASE + hex "Define the base address for saved dram timing" + help + The DRAM config timing data need to be saved into sram + for low power use. + default 0x2006c000 + endmenu diff --git a/drivers/ddr/imx/imx8ulp/ddr_init.c b/drivers/ddr/imx/imx8ulp/ddr_init.c index 16aaf56103..9730dd6450 100644 --- a/drivers/ddr/imx/imx8ulp/ddr_init.c +++ b/drivers/ddr/imx/imx8ulp/ddr_init.c @@ -178,6 +178,48 @@ int ddr_calibration(unsigned int fsp_table[3]) return 0; }
+static void save_dram_config(struct dram_timing_info2 *timing_info, unsigned long saved_timing_base) +{ + int i = 0; + struct dram_timing_info2 *saved_timing = (struct dram_timing_info2 *)saved_timing_base; + struct dram_cfg_param *cfg; + + saved_timing->ctl_cfg_num = timing_info->ctl_cfg_num; + saved_timing->phy_f1_cfg_num = timing_info->phy_f1_cfg_num; + saved_timing->phy_f2_cfg_num = timing_info->phy_f2_cfg_num; + + /* save the fsp table */ + for (i = 0; i < 3; i++) + saved_timing->fsp_table[i] = timing_info->fsp_table[i]; + + cfg = (struct dram_cfg_param *)(saved_timing_base + + sizeof(*timing_info)); + + /* save ctl config */ + saved_timing->ctl_cfg = cfg; + for (i = 0; i < timing_info->ctl_cfg_num; i++) { + cfg->reg = timing_info->ctl_cfg[i].reg; + cfg->val = timing_info->ctl_cfg[i].val; + cfg++; + } + + /* save phy f1 config */ + saved_timing->phy_f1_cfg = cfg; + for (i = 0; i < timing_info->phy_f1_cfg_num; i++) { + cfg->reg = timing_info->phy_f1_cfg[i].reg; + cfg->val = timing_info->phy_f1_cfg[i].val; + cfg++; + } + + /* save phy f2 config */ + saved_timing->phy_f2_cfg = cfg; + for (i = 0; i < timing_info->phy_f2_cfg_num; i++) { + cfg->reg = timing_info->phy_f2_cfg[i].reg; + cfg->val = timing_info->phy_f2_cfg[i].val; + cfg++; + } +} + int ddr_init(struct dram_timing_info2 *dram_timing) { int i; @@ -192,6 +234,9 @@ int ddr_init(struct dram_timing_info2 *dram_timing) clrbits_le32(AVD_SIM_BASE_ADDR, 0x1); /* SIM_DDR_CTRL_DIV2_EN */ }
+ /* save the dram config into sram for low power mode */ + save_dram_config(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); + /* Initialize CTL registers */ for (i = 0; i < dram_timing->ctl_cfg_num; i++) writel(dram_timing->ctl_cfg[i].val, (ulong)dram_timing->ctl_cfg[i].reg);