imx8ulp:ddr: saving the dram config timing data into sram
authorJacky Bai <ping.bai@nxp.com>
Fri, 29 Oct 2021 01:46:33 +0000 (09:46 +0800)
committerStefano Babic <sbabic@denx.de>
Sat, 5 Feb 2022 12:38:39 +0000 (13:38 +0100)
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
drivers/ddr/imx/imx8ulp/ddr_init.c

index e56062a..4284886 100644 (file)
@@ -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
index 16aaf56..9730dd6 100644 (file)
@@ -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);