aboutsummaryrefslogtreecommitdiff
path: root/drivers/ddr/imx/imx8ulp/ddr_init.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-02-07 12:13:53 -0500
committerTom Rini <trini@konsulko.com>2022-02-07 12:13:53 -0500
commit8b139f4e1c08c4ffb1a8e739db128ed02cbc637f (patch)
tree0bff6bd0fadc7230538d712b1b1f112e424dbea0 /drivers/ddr/imx/imx8ulp/ddr_init.c
parentb5c5b9a0bee56030f9f05ece52334b5207b72673 (diff)
parent530780a69cb5d32a7794dcc322afaa25cdbdab96 (diff)
Merge tag 'u-boot-imx-20220207' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
u-boot-imx-20211022 ------------------- CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/10887 - imx8 : Toradex Verdin MX8M Plus Kontron pitx-imx8m - imx8ulp: several fixes and improvements - imx6ull fixes - switching to binman
Diffstat (limited to 'drivers/ddr/imx/imx8ulp/ddr_init.c')
-rw-r--r--drivers/ddr/imx/imx8ulp/ddr_init.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/drivers/ddr/imx/imx8ulp/ddr_init.c b/drivers/ddr/imx/imx8ulp/ddr_init.c
index 16aaf56103..a5a9fd8d7c 100644
--- a/drivers/ddr/imx/imx8ulp/ddr_init.c
+++ b/drivers/ddr/imx/imx8ulp/ddr_init.c
@@ -129,8 +129,8 @@ int ddr_calibration(unsigned int fsp_table[3])
* Polling SIM LPDDR_CTRL2 Bit phy_freq_chg_req until be 1'b1
*/
reg_val = readl(AVD_SIM_LPDDR_CTRL2);
- phy_freq_req = (reg_val >> 7) & 0x1;
-
+ /* DFS interrupt is set */
+ phy_freq_req = ((reg_val >> 7) & 0x1) && ((reg_val >> 15) & 0x1);
if (phy_freq_req) {
phy_freq_type = reg_val & 0x1F;
if (phy_freq_type == 0x00) {
@@ -159,7 +159,11 @@ int ddr_calibration(unsigned int fsp_table[3])
if (freq_chg_pt == 2)
freq_chg_cnt--;
}
- reg_val = readl(AVD_SIM_LPDDR_CTRL2);
+
+ /* Hardware clear the ack on falling edge of LPDDR_CTRL2:phy_freq_chg_reg */
+ /* Ensure the ack is clear before starting to poll request again */
+ while ((readl(AVD_SIM_LPDDR_CTRL2) & BIT(6)))
+ ;
}
} while (1);
@@ -178,6 +182,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 +238,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);