[U-Boot] [PATCH 0/4] i.MX8M ddr update/fix

This is a split patch from previous i.MX8MM patchset to ease review.
This patchset is to fix build for ddr4, refine ddr driver for lpddr4/ddr4 and bug fix.
Bai Ping (1): imx8mq: Update the ddrc QoS setting for B1 chip
Jacky Bai (2): driver: ddr: Refine the ddr init driver on imx8m ddr: imx8m: Fix the ddr init hang on imx8mq
Ye Li (1): ddr: imx8m: Fix ddr4 driver build issue
board/freescale/imx8mq_evk/lpddr4_timing.c | 16 ++- drivers/ddr/imx/imx8m/Kconfig | 6 + drivers/ddr/imx/imx8m/Makefile | 4 +- drivers/ddr/imx/imx8m/ddr4_init.c | 113 ----------------- drivers/ddr/imx/imx8m/ddr_init.c | 168 ++++++++++++++++++++++++++ drivers/ddr/imx/imx8m/ddrphy_utils.c | 4 + drivers/ddr/imx/imx8m/helper.c | 10 +- drivers/ddr/imx/imx8m/lpddr4_init.c | 188 ----------------------------- 8 files changed, 194 insertions(+), 315 deletions(-) delete mode 100644 drivers/ddr/imx/imx8m/ddr4_init.c create mode 100644 drivers/ddr/imx/imx8m/ddr_init.c delete mode 100644 drivers/ddr/imx/imx8m/lpddr4_init.c

From: Ye Li ye.li@nxp.com
Since the parameter of dram_pll_init is changed, update to use new. Also remove non-existed header file.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/ddr/imx/imx8m/ddr4_init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/ddr/imx/imx8m/ddr4_init.c b/drivers/ddr/imx/imx8m/ddr4_init.c index 031cdc57e1..b8aa104536 100644 --- a/drivers/ddr/imx/imx8m/ddr4_init.c +++ b/drivers/ddr/imx/imx8m/ddr4_init.c @@ -8,7 +8,6 @@ #include <asm/io.h> #include <asm/arch/ddr.h> #include <asm/arch/clock.h> -#include <asm/arch/imx8m_ddr.h> #include <asm/arch/sys_proto.h>
void ddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) @@ -41,7 +40,7 @@ void ddr_init(struct dram_timing_info *dram_timing) CLK_ROOT_SOURCE_SEL(4) | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- dram_pll_init(DRAM_PLL_OUT_600M); + dram_pll_init(MHZ(600));
reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */

From: Bai Ping ping.bai@nxp.com
Update the ddrc Qos setting for B1 to align with B0's setting. Correct the initial clock for dram_pll. This setting will be overwrite before ddr phy training. Although there is no impact on the dram init, we still need to correct it to eliminate confusion.
Signed-off-by: Bai Ping ping.bai@nxp.com Reviewed-by: Ye Li ye.li@nxp.com Tested-by: Robby Cai robby.cai@nxp.com --- board/freescale/imx8mq_evk/lpddr4_timing.c | 16 ++++++++++------ drivers/ddr/imx/imx8m/lpddr4_init.c | 5 ++++- 2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/board/freescale/imx8mq_evk/lpddr4_timing.c b/board/freescale/imx8mq_evk/lpddr4_timing.c index f7ea799343..46bc7f8591 100644 --- a/board/freescale/imx8mq_evk/lpddr4_timing.c +++ b/board/freescale/imx8mq_evk/lpddr4_timing.c @@ -72,8 +72,10 @@ struct dram_cfg_param lpddr4_ddrc_cfg[] = { { DDRC_SCHED(0), 0x29511505 }, { DDRC_SCHED1(0), 0x0000002c }, { DDRC_PERFHPR1(0), 0x5900575b }, - { DDRC_PERFLPR1(0), 0x00000009 }, - { DDRC_PERFWR1(0), 0x02005574 }, + /* 150T starve and 0x90 max tran len */ + { DDRC_PERFLPR1(0), 0x90000096 }, + /* 300T starve and 0x10 max tran len */ + { DDRC_PERFWR1(0), 0x1000012c }, { DDRC_DBG0(0), 0x00000016 }, { DDRC_DBG1(0), 0x00000000 }, { DDRC_DBGCMD(0), 0x00000000 }, @@ -83,10 +85,12 @@ struct dram_cfg_param lpddr4_ddrc_cfg[] = { { DDRC_PCFGR_0(0), 0x000010f3 }, { DDRC_PCFGW_0(0), 0x000072ff }, { DDRC_PCTRL_0(0), 0x00000001 }, - { DDRC_PCFGQOS0_0(0), 0x01110d00 }, - { DDRC_PCFGQOS1_0(0), 0x00620790 }, - { DDRC_PCFGWQOS0_0(0), 0x00100001 }, - { DDRC_PCFGWQOS1_0(0), 0x0000041f }, + /* disable Read Qos*/ + { DDRC_PCFGQOS0_0(0), 0x00000e00 }, + { DDRC_PCFGQOS1_0(0), 0x0062ffff }, + /* disable Write Qos*/ + { DDRC_PCFGWQOS0_0(0), 0x00000e00 }, + { DDRC_PCFGWQOS1_0(0), 0x0000ffff },
/* Frequency 1: 400mbps */ { DDRC_FREQ1_DRAMTMG0(0), 0x0d0b010c }, diff --git a/drivers/ddr/imx/imx8m/lpddr4_init.c b/drivers/ddr/imx/imx8m/lpddr4_init.c index a4bc1de8eb..0f46ca02b6 100644 --- a/drivers/ddr/imx/imx8m/lpddr4_init.c +++ b/drivers/ddr/imx/imx8m/lpddr4_init.c @@ -54,7 +54,10 @@ void ddr_init(struct dram_timing_info *dram_timing) reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
debug("DDRINFO: cfg clk\n"); - dram_pll_init(MHZ(750)); + if (is_imx8mq()) + dram_pll_init(MHZ(800)); + else + dram_pll_init(MHZ(750));
/* * release [0]ddr1_preset_n, [1]ddr1_core_reset_n,

From: Jacky Bai ping.bai@nxp.com
Refine the ddr init driver to make it more reusable for different DDR type(LPDDR4, DDR4 & DDR3L). So we can reduce some redundant code.
Signed-off-by: Jacky Bai ping.bai@nxp.com Reviewed-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/ddr/imx/imx8m/Kconfig | 6 ++ drivers/ddr/imx/imx8m/Makefile | 4 +- drivers/ddr/imx/imx8m/ddr4_init.c | 112 -------------------- drivers/ddr/imx/imx8m/ddr_init.c | 168 ++++++++++++++++++++++++++++++ drivers/ddr/imx/imx8m/ddrphy_utils.c | 4 + drivers/ddr/imx/imx8m/helper.c | 10 +- drivers/ddr/imx/imx8m/lpddr4_init.c | 191 ----------------------------------- 7 files changed, 184 insertions(+), 311 deletions(-) delete mode 100644 drivers/ddr/imx/imx8m/ddr4_init.c create mode 100644 drivers/ddr/imx/imx8m/ddr_init.c delete mode 100644 drivers/ddr/imx/imx8m/lpddr4_init.c
diff --git a/drivers/ddr/imx/imx8m/Kconfig b/drivers/ddr/imx/imx8m/Kconfig index a83b0f43d7..5bf61eb258 100644 --- a/drivers/ddr/imx/imx8m/Kconfig +++ b/drivers/ddr/imx/imx8m/Kconfig @@ -16,6 +16,12 @@ config IMX8M_DDR4 help Select the i.MX8M DDR4 driver support on i.MX8M SOC.
+config IMX8M_DDR3L + bool "imx8m ddr3l" + select IMX8M_DRAM + help + Select the i.MX8M DDR3L driver support on i.MX8M SOC. + config SAVED_DRAM_TIMING_BASE hex "Define the base address for saved dram timing" help diff --git a/drivers/ddr/imx/imx8m/Makefile b/drivers/ddr/imx/imx8m/Makefile index 64f9ab20e6..bd9bcb8d53 100644 --- a/drivers/ddr/imx/imx8m/Makefile +++ b/drivers/ddr/imx/imx8m/Makefile @@ -5,7 +5,5 @@ #
ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o -obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_init.o -obj-$(CONFIG_IMX8M_DDR4) += ddr4_init.o +obj-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o ddr_init.o endif diff --git a/drivers/ddr/imx/imx8m/ddr4_init.c b/drivers/ddr/imx/imx8m/ddr4_init.c deleted file mode 100644 index b8aa104536..0000000000 --- a/drivers/ddr/imx/imx8m/ddr4_init.c +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2018 NXP - */ - -#include <common.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/arch/ddr.h> -#include <asm/arch/clock.h> -#include <asm/arch/sys_proto.h> - -void ddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) -{ - int i = 0; - - for (i = 0; i < num; i++) { - reg32_write(ddrc_cfg->reg, ddrc_cfg->val); - ddrc_cfg++; - } -} - -void ddr_init(struct dram_timing_info *dram_timing) -{ - volatile unsigned int tmp_t; - /* - * assert [0]ddr1_preset_n, [1]ddr1_core_reset_n, - * [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n, - * [4]src_system_rst_b! - */ - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00003F); - /* deassert [4]src_system_rst_b! */ - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); - - /* - * change the clock source of dram_apb_clk_root - * to source 4 --800MHz/4 - */ - clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | - CLK_ROOT_SOURCE_SEL(4) | - CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); - - dram_pll_init(MHZ(600)); - - reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ - reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */ - - /* release [0]ddr1_preset_n, [3]ddr1_phy_pwrokin_n */ - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); - - reg32_write(DDRC_DBG1(0), 0x00000001); - reg32_write(DDRC_PWRCTL(0), 0x00000001); - - while (0 != (0x7 & reg32_read(DDRC_STAT(0)))) - ; - - /* config the uMCTL2's registers */ - ddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num); - - reg32_write(DDRC_RFSHCTL3(0), 0x00000001); - /* RESET: <ctn> DEASSERTED */ - /* RESET: <a Port 0 DEASSERTED(0) */ - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004); - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000); - - reg32_write(DDRC_DBG1(0), 0x00000000); - reg32_write(DDRC_PWRCTL(0), 0x00000aa); - reg32_write(DDRC_SWCTL(0), 0x00000000); - - reg32_write(DDRC_DFIMISC(0), 0x00000000); - - /* config the DDR PHY's registers */ - ddr_cfg_phy(dram_timing); - - do { - tmp_t = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + - 4 * 0x00020097); - } while (tmp_t != 0); - - reg32_write(DDRC_DFIMISC(0), 0x00000020); - - /* wait DFISTAT.dfi_init_complete to 1 */ - while (0 == (0x1 & reg32_read(DDRC_DFISTAT(0)))) - ; - - /* clear DFIMISC.dfi_init_complete_en */ - reg32_write(DDRC_DFIMISC(0), 0x00000000); - /* set DFIMISC.dfi_init_complete_en again */ - reg32_write(DDRC_DFIMISC(0), 0x00000001); - reg32_write(DDRC_PWRCTL(0), 0x0000088); - - /* - * set SWCTL.sw_done to enable quasi-dynamic register - * programming outside reset. - */ - reg32_write(DDRC_SWCTL(0), 0x00000001); - /* wait SWSTAT.sw_done_ack to 1 */ - while (0 == (0x1 & reg32_read(DDRC_SWSTAT(0)))) - ; - - /* wait STAT to normal state */ - while (0x1 != (0x7 & reg32_read(DDRC_STAT(0)))) - ; - - reg32_write(DDRC_PWRCTL(0), 0x0000088); - reg32_write(DDRC_PCTRL_0(0), 0x00000001); - /* dis_auto-refresh is set to 0 */ - reg32_write(DDRC_RFSHCTL3(0), 0x00000000); - - /* save the dram timing config into memory */ - dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); -} diff --git a/drivers/ddr/imx/imx8m/ddr_init.c b/drivers/ddr/imx/imx8m/ddr_init.c new file mode 100644 index 0000000000..12967583ea --- /dev/null +++ b/drivers/ddr/imx/imx8m/ddr_init.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018-2019 NXP + */ + +#include <common.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/ddr.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> + +void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) +{ + int i = 0; + + for (i = 0; i < num; i++) { + reg32_write(ddrc_cfg->reg, ddrc_cfg->val); + ddrc_cfg++; + } +} + +void ddr_init(struct dram_timing_info *dram_timing) +{ + unsigned int tmp, initial_drate, target_freq; + + printf("DDRINFO: start DRAM init\n"); + + /* Step1: Follow the power up procedure */ + if (is_imx8mq()) { + reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F); + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); + reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000); + } else { + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F); + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); + } + + debug("DDRINFO: cfg clk\n"); + /* change the clock source of dram_apb_clk_root: source 4 800MHz /4 = 200MHz */ + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) | + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); + + initial_drate = dram_timing->fsp_msg[0].drate; + /* default to the frequency point 0 clock */ + ddrphy_init_set_dfi_clk(initial_drate); + + /* disable iso */ + reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ + reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */ + + /* D-aasert the presetn */ + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); + + /* Step2: Program the dwc_ddr_umctl2 registers */ + debug("DDRINFO: ddrc config start\n"); + ddr_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num); + debug("DDRINFO: ddrc config done\n"); + + /* Step3: De-assert reset signal(core_ddrc_rstn & aresetn_n) */ + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004); + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000); + + /* + * Step4: Disable auto-refreshes, self-refresh, powerdown, and + * assertion of dfi_dram_clk_disable by setting RFSHCTL3.dis_auto_refresh = 1, + * PWRCTL.powerdown_en = 0, and PWRCTL.selfref_en = 0, PWRCTL.en_dfi_dram_clk_disable = 0 + */ + reg32_write(DDRC_DBG1(0), 0x00000000); + reg32_write(DDRC_RFSHCTL3(0), 0x0000001); + reg32_write(DDRC_PWRCTL(0), 0xa0); + + /* if ddr type is LPDDR4, do it */ + tmp = reg32_read(DDRC_MSTR(0)); + if (tmp & (0x1 << 5)) + reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */ + + /* determine the initial boot frequency */ + target_freq = reg32_read(DDRC_MSTR2(0)) & 0x3; + target_freq = (tmp & (0x1 << 29)) ? target_freq : 0x0; + + /* Step5: Set SWCT.sw_done to 0 */ + reg32_write(DDRC_SWCTL(0), 0x00000000); + + /* Set the default boot frequency point */ + clrsetbits_le32(DDRC_DFIMISC(0), (0x1f << 8), target_freq << 8); + /* Step6: Set DFIMISC.dfi_init_complete_en to 0 */ + clrbits_le32(DDRC_DFIMISC(0), 0x1); + + /* Step7: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */ + reg32_write(DDRC_SWCTL(0), 0x00000001); + do { + tmp = reg32_read(DDRC_SWSTAT(0)); + } while ((tmp & 0x1) == 0x0); + + /* + * Step8 ~ Step13: Start PHY initialization and training by + * accessing relevant PUB registers + */ + debug("DDRINFO:ddrphy config start\n"); + ddr_cfg_phy(dram_timing); + debug("DDRINFO: ddrphy config done\n"); + + /* + * step14 CalBusy.0 =1, indicates the calibrator is actively + * calibrating. Wait Calibrating done. + */ + do { + tmp = reg32_read(DDRPHY_CalBusy(0)); + } while ((tmp & 0x1)); + + printf("DDRINFO:ddrphy calibration done\n"); + + /* Step15: Set SWCTL.sw_done to 0 */ + reg32_write(DDRC_SWCTL(0), 0x00000000); + + /* Step16: Set DFIMISC.dfi_init_start to 1 */ + setbits_le32(DDRC_DFIMISC(0), (0x1 << 5)); + + /* Step17: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */ + reg32_write(DDRC_SWCTL(0), 0x00000001); + do { + tmp = reg32_read(DDRC_SWSTAT(0)); + } while ((tmp & 0x1) == 0x0); + + /* Step18: Polling DFISTAT.dfi_init_complete = 1 */ + do { + tmp = reg32_read(DDRC_DFISTAT(0)); + } while ((tmp & 0x1) == 0x0); + + /* Step19: Set SWCTL.sw_done to 0 */ + reg32_write(DDRC_SWCTL(0), 0x00000000); + + /* Step20: Set DFIMISC.dfi_init_start to 0 */ + clrbits_le32(DDRC_DFIMISC(0), (0x1 << 5)); + + /* Step21: optional */ + + /* Step22: Set DFIMISC.dfi_init_complete_en to 1 */ + setbits_le32(DDRC_DFIMISC(0), 0x1); + + /* Step23: Set PWRCTL.selfref_sw to 0 */ + clrbits_le32(DDRC_PWRCTL(0), (0x1 << 5)); + + /* Step24: Set SWCTL.sw_done to 1; need polling SWSTAT.sw_done_ack */ + reg32_write(DDRC_SWCTL(0), 0x00000001); + do { + tmp = reg32_read(DDRC_SWSTAT(0)); + } while ((tmp & 0x1) == 0x0); + + /* Step25: Wait for dwc_ddr_umctl2 to move to normal operating mode by monitoring + * STAT.operating_mode signal */ + do { + tmp = reg32_read(DDRC_STAT(0)); + } while ((tmp & 0x3) != 0x1); + + /* Step26: Set back register in Step4 to the original values if desired */ + reg32_write(DDRC_RFSHCTL3(0), 0x0000000); + /* enable selfref_en by default */ + setbits_le32(DDRC_PWRCTL(0), 0x1 << 3); + + /* enable port 0 */ + reg32_write(DDRC_PCTRL_0(0), 0x00000001); + printf("DDRINFO: ddrmix config done\n"); + + /* save the dram timing config into memory */ + dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); +} diff --git a/drivers/ddr/imx/imx8m/ddrphy_utils.c b/drivers/ddr/imx/imx8m/ddrphy_utils.c index 4732539764..e60503309e 100644 --- a/drivers/ddr/imx/imx8m/ddrphy_utils.c +++ b/drivers/ddr/imx/imx8m/ddrphy_utils.c @@ -122,6 +122,10 @@ void ddrphy_init_set_dfi_clk(unsigned int drate) dram_pll_init(MHZ(400)); dram_disable_bypass(); break; + case 1066: + dram_pll_init(MHZ(266)); + dram_disable_bypass(); + break; case 667: dram_pll_init(MHZ(167)); dram_disable_bypass(); diff --git a/drivers/ddr/imx/imx8m/helper.c b/drivers/ddr/imx/imx8m/helper.c index 61cd4f6db1..9828b62218 100644 --- a/drivers/ddr/imx/imx8m/helper.c +++ b/drivers/ddr/imx/imx8m/helper.c @@ -57,7 +57,7 @@ void ddr_load_train_firmware(enum fw_type type) i += 4; }
- debug("check ddr4_pmu_train_imem code\n"); + debug("check ddr_pmu_train_imem code\n"); pr_from32 = imem_start; pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * IMEM_OFFSET_ADDR; for (i = 0x0; i < IMEM_LEN; ) { @@ -74,9 +74,9 @@ void ddr_load_train_firmware(enum fw_type type) i += 4; } if (error) - printf("check ddr4_pmu_train_imem code fail=%d\n", error); + printf("check ddr_pmu_train_imem code fail=%d\n", error); else - debug("check ddr4_pmu_train_imem code pass\n"); + debug("check ddr_pmu_train_imem code pass\n");
debug("check ddr4_pmu_train_dmem code\n"); pr_from32 = dmem_start; @@ -95,9 +95,9 @@ void ddr_load_train_firmware(enum fw_type type) }
if (error) - printf("check ddr4_pmu_train_dmem code fail=%d", error); + printf("check ddr_pmu_train_dmem code fail=%d", error); else - debug("check ddr4_pmu_train_dmem code pass\n"); + debug("check ddr_pmu_train_dmem code pass\n"); }
void ddrphy_trained_csr_save(struct dram_cfg_param *ddrphy_csr, diff --git a/drivers/ddr/imx/imx8m/lpddr4_init.c b/drivers/ddr/imx/imx8m/lpddr4_init.c deleted file mode 100644 index 0f46ca02b6..0000000000 --- a/drivers/ddr/imx/imx8m/lpddr4_init.c +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* -* Copyright 2018 NXP -* -*/ - -#include <common.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/arch/ddr.h> -#include <asm/arch/clock.h> -#include <asm/arch/ddr.h> -#include <asm/arch/lpddr4_define.h> -#include <asm/arch/sys_proto.h> - -void lpddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) -{ - int i = 0; - - for (i = 0; i < num; i++) { - reg32_write(ddrc_cfg->reg, ddrc_cfg->val); - ddrc_cfg++; - } -} - -void ddr_init(struct dram_timing_info *dram_timing) -{ - unsigned int tmp; - - debug("DDRINFO: start lpddr4 ddr init\n"); - /* step 1: reset */ - if (is_imx8mq()) { - reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F); - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); - reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000); - } else { - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F); - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); - } - - mdelay(100); - - debug("DDRINFO: reset done\n"); - /* - * change the clock source of dram_apb_clk_root: - * source 4 800MHz /4 = 200MHz - */ - clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | - CLK_ROOT_SOURCE_SEL(4) | - CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); - - /* disable iso */ - reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ - reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */ - - debug("DDRINFO: cfg clk\n"); - if (is_imx8mq()) - dram_pll_init(MHZ(800)); - else - dram_pll_init(MHZ(750)); - - /* - * release [0]ddr1_preset_n, [1]ddr1_core_reset_n, - * [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n - */ - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); - - /*step2 Configure uMCTL2's registers */ - debug("DDRINFO: ddrc config start\n"); - lpddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num); - debug("DDRINFO: ddrc config done\n"); - - /* - * step3 de-assert all reset - * RESET: <core_ddrc_rstn> DEASSERTED - * RESET: <aresetn> for Port 0 DEASSERT(0)ED - */ - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004); - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000); - - reg32_write(DDRC_DBG1(0), 0x00000000); - /* step4 */ - /* [0]dis_auto_refresh=1 */ - reg32_write(DDRC_RFSHCTL3(0), 0x00000011); - - /* [8]--1: lpddr4_sr allowed; [5]--1: software entry to SR */ - reg32_write(DDRC_PWRCTL(0), 0x000000a8); - - do { - tmp = reg32_read(DDRC_STAT(0)); - } while ((tmp & 0x33f) != 0x223); - - reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */ - - /* step5 */ - reg32_write(DDRC_SWCTL(0), 0x00000000); - - /* step6 */ - tmp = reg32_read(DDRC_MSTR2(0)); - if (tmp == 0x2) - reg32_write(DDRC_DFIMISC(0), 0x00000210); - else if (tmp == 0x1) - reg32_write(DDRC_DFIMISC(0), 0x00000110); - else - reg32_write(DDRC_DFIMISC(0), 0x00000010); - - /* step7 [0]--1: disable quasi-dynamic programming */ - reg32_write(DDRC_SWCTL(0), 0x00000001); - - /* step8 Configure LPDDR4 PHY's registers */ - debug("DDRINFO:ddrphy config start\n"); - ddr_cfg_phy(dram_timing); - debug("DDRINFO: ddrphy config done\n"); - - /* - * step14 CalBusy.0 =1, indicates the calibrator is actively - * calibrating. Wait Calibrating done. - */ - do { - tmp = reg32_read(DDRPHY_CalBusy(0)); - } while ((tmp & 0x1)); - - debug("DDRINFO:ddrphy calibration done\n"); - - /* step15 [0]--0: to enable quasi-dynamic programming */ - reg32_write(DDRC_SWCTL(0), 0x00000000); - - /* step16 */ - tmp = reg32_read(DDRC_MSTR2(0)); - if (tmp == 0x2) - reg32_write(DDRC_DFIMISC(0), 0x00000230); - else if (tmp == 0x1) - reg32_write(DDRC_DFIMISC(0), 0x00000130); - else - reg32_write(DDRC_DFIMISC(0), 0x00000030); - - /* step17 [0]--1: disable quasi-dynamic programming */ - reg32_write(DDRC_SWCTL(0), 0x00000001); - /* step18 wait DFISTAT.dfi_init_complete to 1 */ - do { - tmp = reg32_read(DDRC_DFISTAT(0)); - } while ((tmp & 0x1) == 0x0); - - /* step19 */ - reg32_write(DDRC_SWCTL(0), 0x00000000); - - /* step20~22 */ - tmp = reg32_read(DDRC_MSTR2(0)); - if (tmp == 0x2) { - reg32_write(DDRC_DFIMISC(0), 0x00000210); - /* set DFIMISC.dfi_init_complete_en again */ - reg32_write(DDRC_DFIMISC(0), 0x00000211); - } else if (tmp == 0x1) { - reg32_write(DDRC_DFIMISC(0), 0x00000110); - /* set DFIMISC.dfi_init_complete_en again */ - reg32_write(DDRC_DFIMISC(0), 0x00000111); - } else { - /* clear DFIMISC.dfi_init_complete_en */ - reg32_write(DDRC_DFIMISC(0), 0x00000010); - /* set DFIMISC.dfi_init_complete_en again */ - reg32_write(DDRC_DFIMISC(0), 0x00000011); - } - - /* step23 [5]selfref_sw=0; */ - reg32_write(DDRC_PWRCTL(0), 0x00000008); - /* step24 sw_done=1 */ - reg32_write(DDRC_SWCTL(0), 0x00000001); - - /* step25 wait SWSTAT.sw_done_ack to 1 */ - do { - tmp = reg32_read(DDRC_SWSTAT(0)); - } while ((tmp & 0x1) == 0x0); - -#ifdef DFI_BUG_WR - reg32_write(DDRC_DFIPHYMSTR(0), 0x00000001); -#endif - /* wait STAT.operating_mode([1:0] for ddr3) to normal state */ - do { - tmp = reg32_read(DDRC_STAT(0)); - } while ((tmp & 0x3) != 0x1); - - /* step26 */ - reg32_write(DDRC_RFSHCTL3(0), 0x00000010); - - /* enable port 0 */ - reg32_write(DDRC_PCTRL_0(0), 0x00000001); - debug("DDRINFO: ddrmix config done\n"); - - /* save the dram timing config into memory */ - dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); -}

On 8/8/2019 2:59 AM, Peng Fan wrote:
From: Jacky Bai ping.bai@nxp.com
Refine the ddr init driver to make it more reusable for different DDR type(LPDDR4, DDR4 & DDR3L). So we can reduce some redundant code.
Signed-off-by: Jacky Bai ping.bai@nxp.com Reviewed-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/ddr/imx/imx8m/Kconfig | 6 ++ drivers/ddr/imx/imx8m/Makefile | 4 +- drivers/ddr/imx/imx8m/ddr4_init.c | 112 -------------------- drivers/ddr/imx/imx8m/ddr_init.c | 168 ++++++++++++++++++++++++++++++ drivers/ddr/imx/imx8m/ddrphy_utils.c | 4 + drivers/ddr/imx/imx8m/helper.c | 10 +- drivers/ddr/imx/imx8m/lpddr4_init.c | 191 ----------------------------------- 7 files changed, 184 insertions(+), 311 deletions(-) delete mode 100644 drivers/ddr/imx/imx8m/ddr4_init.c create mode 100644 drivers/ddr/imx/imx8m/ddr_init.c delete mode 100644 drivers/ddr/imx/imx8m/lpddr4_init.c
diff --git a/drivers/ddr/imx/imx8m/Kconfig b/drivers/ddr/imx/imx8m/Kconfig index a83b0f43d7..5bf61eb258 100644 --- a/drivers/ddr/imx/imx8m/Kconfig +++ b/drivers/ddr/imx/imx8m/Kconfig @@ -16,6 +16,12 @@ config IMX8M_DDR4 help Select the i.MX8M DDR4 driver support on i.MX8M SOC.
+config IMX8M_DDR3L
- bool "imx8m ddr3l"
- select IMX8M_DRAM
- help
Select the i.MX8M DDR3L driver support on i.MX8M SOC.
config SAVED_DRAM_TIMING_BASE hex "Define the base address for saved dram timing" help diff --git a/drivers/ddr/imx/imx8m/Makefile b/drivers/ddr/imx/imx8m/Makefile index 64f9ab20e6..bd9bcb8d53 100644 --- a/drivers/ddr/imx/imx8m/Makefile +++ b/drivers/ddr/imx/imx8m/Makefile @@ -5,7 +5,5 @@ #
ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o -obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_init.o -obj-$(CONFIG_IMX8M_DDR4) += ddr4_init.o +obj-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o ddr_init.o endif diff --git a/drivers/ddr/imx/imx8m/ddr4_init.c b/drivers/ddr/imx/imx8m/ddr4_init.c deleted file mode 100644 index b8aa104536..0000000000 --- a/drivers/ddr/imx/imx8m/ddr4_init.c +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/*
- Copyright 2018 NXP
- */
-#include <common.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/arch/ddr.h> -#include <asm/arch/clock.h> -#include <asm/arch/sys_proto.h>
-void ddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) -{
- int i = 0;
- for (i = 0; i < num; i++) {
reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
ddrc_cfg++;
- }
-}
-void ddr_init(struct dram_timing_info *dram_timing) -{
- volatile unsigned int tmp_t;
- /*
* assert [0]ddr1_preset_n, [1]ddr1_core_reset_n,
* [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n,
* [4]src_system_rst_b!
*/
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00003F);
- /* deassert [4]src_system_rst_b! */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
- /*
* change the clock source of dram_apb_clk_root
* to source 4 --800MHz/4
*/
- clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
CLK_ROOT_SOURCE_SEL(4) |
CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- dram_pll_init(MHZ(600));
- reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
- reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
- /* release [0]ddr1_preset_n, [3]ddr1_phy_pwrokin_n */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
- reg32_write(DDRC_DBG1(0), 0x00000001);
- reg32_write(DDRC_PWRCTL(0), 0x00000001);
- while (0 != (0x7 & reg32_read(DDRC_STAT(0))))
;
- /* config the uMCTL2's registers */
- ddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
- reg32_write(DDRC_RFSHCTL3(0), 0x00000001);
- /* RESET: <ctn> DEASSERTED */
- /* RESET: <a Port 0 DEASSERTED(0) */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
- reg32_write(DDRC_DBG1(0), 0x00000000);
- reg32_write(DDRC_PWRCTL(0), 0x00000aa);
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- reg32_write(DDRC_DFIMISC(0), 0x00000000);
- /* config the DDR PHY's registers */
- ddr_cfg_phy(dram_timing);
- do {
tmp_t = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) +
4 * 0x00020097);
- } while (tmp_t != 0);
- reg32_write(DDRC_DFIMISC(0), 0x00000020);
- /* wait DFISTAT.dfi_init_complete to 1 */
- while (0 == (0x1 & reg32_read(DDRC_DFISTAT(0))))
;
- /* clear DFIMISC.dfi_init_complete_en */
- reg32_write(DDRC_DFIMISC(0), 0x00000000);
- /* set DFIMISC.dfi_init_complete_en again */
- reg32_write(DDRC_DFIMISC(0), 0x00000001);
- reg32_write(DDRC_PWRCTL(0), 0x0000088);
- /*
* set SWCTL.sw_done to enable quasi-dynamic register
* programming outside reset.
*/
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* wait SWSTAT.sw_done_ack to 1 */
- while (0 == (0x1 & reg32_read(DDRC_SWSTAT(0))))
;
- /* wait STAT to normal state */
- while (0x1 != (0x7 & reg32_read(DDRC_STAT(0))))
;
- reg32_write(DDRC_PWRCTL(0), 0x0000088);
- reg32_write(DDRC_PCTRL_0(0), 0x00000001);
- /* dis_auto-refresh is set to 0 */
- reg32_write(DDRC_RFSHCTL3(0), 0x00000000);
- /* save the dram timing config into memory */
- dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE);
-} diff --git a/drivers/ddr/imx/imx8m/ddr_init.c b/drivers/ddr/imx/imx8m/ddr_init.c new file mode 100644 index 0000000000..12967583ea --- /dev/null +++ b/drivers/ddr/imx/imx8m/ddr_init.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2018-2019 NXP
- */
+#include <common.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/ddr.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h>
+void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) +{
- int i = 0;
- for (i = 0; i < num; i++) {
reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
ddrc_cfg++;
- }
+}
+void ddr_init(struct dram_timing_info *dram_timing) +{
- unsigned int tmp, initial_drate, target_freq;
- printf("DDRINFO: start DRAM init\n");
- /* Step1: Follow the power up procedure */
- if (is_imx8mq()) {
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
- } else {
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
- }
- debug("DDRINFO: cfg clk\n");
- /* change the clock source of dram_apb_clk_root: source 4 800MHz /4 = 200MHz */
- clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) |
CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- initial_drate = dram_timing->fsp_msg[0].drate;
- /* default to the frequency point 0 clock */
- ddrphy_init_set_dfi_clk(initial_drate);
- /* disable iso */
- reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
- reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
- /* D-aasert the presetn */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
- /* Step2: Program the dwc_ddr_umctl2 registers */
- debug("DDRINFO: ddrc config start\n");
- ddr_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
- debug("DDRINFO: ddrc config done\n");
- /* Step3: De-assert reset signal(core_ddrc_rstn & aresetn_n) */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
- /*
* Step4: Disable auto-refreshes, self-refresh, powerdown, and
* assertion of dfi_dram_clk_disable by setting RFSHCTL3.dis_auto_refresh = 1,
* PWRCTL.powerdown_en = 0, and PWRCTL.selfref_en = 0, PWRCTL.en_dfi_dram_clk_disable = 0
*/
- reg32_write(DDRC_DBG1(0), 0x00000000);
- reg32_write(DDRC_RFSHCTL3(0), 0x0000001);
- reg32_write(DDRC_PWRCTL(0), 0xa0);
- /* if ddr type is LPDDR4, do it */
- tmp = reg32_read(DDRC_MSTR(0));
- if (tmp & (0x1 << 5))
reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
- /* determine the initial boot frequency */
- target_freq = reg32_read(DDRC_MSTR2(0)) & 0x3;
- target_freq = (tmp & (0x1 << 29)) ? target_freq : 0x0;
- /* Step5: Set SWCT.sw_done to 0 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* Set the default boot frequency point */
- clrsetbits_le32(DDRC_DFIMISC(0), (0x1f << 8), target_freq << 8);
- /* Step6: Set DFIMISC.dfi_init_complete_en to 0 */
- clrbits_le32(DDRC_DFIMISC(0), 0x1);
- /* Step7: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /*
* Step8 ~ Step13: Start PHY initialization and training by
* accessing relevant PUB registers
*/
- debug("DDRINFO:ddrphy config start\n");
- ddr_cfg_phy(dram_timing);
- debug("DDRINFO: ddrphy config done\n");
- /*
* step14 CalBusy.0 =1, indicates the calibrator is actively
* calibrating. Wait Calibrating done.
*/
- do {
tmp = reg32_read(DDRPHY_CalBusy(0));
- } while ((tmp & 0x1));
- printf("DDRINFO:ddrphy calibration done\n");
- /* Step15: Set SWCTL.sw_done to 0 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* Step16: Set DFIMISC.dfi_init_start to 1 */
- setbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
- /* Step17: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* Step18: Polling DFISTAT.dfi_init_complete = 1 */
- do {
tmp = reg32_read(DDRC_DFISTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* Step19: Set SWCTL.sw_done to 0 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* Step20: Set DFIMISC.dfi_init_start to 0 */
- clrbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
- /* Step21: optional */
- /* Step22: Set DFIMISC.dfi_init_complete_en to 1 */
- setbits_le32(DDRC_DFIMISC(0), 0x1);
- /* Step23: Set PWRCTL.selfref_sw to 0 */
- clrbits_le32(DDRC_PWRCTL(0), (0x1 << 5));
- /* Step24: Set SWCTL.sw_done to 1; need polling SWSTAT.sw_done_ack */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* Step25: Wait for dwc_ddr_umctl2 to move to normal operating mode by monitoring
* STAT.operating_mode signal */
- do {
tmp = reg32_read(DDRC_STAT(0));
- } while ((tmp & 0x3) != 0x1);
- /* Step26: Set back register in Step4 to the original values if desired */
- reg32_write(DDRC_RFSHCTL3(0), 0x0000000);
- /* enable selfref_en by default */
- setbits_le32(DDRC_PWRCTL(0), 0x1 << 3);
- /* enable port 0 */
- reg32_write(DDRC_PCTRL_0(0), 0x00000001);
- printf("DDRINFO: ddrmix config done\n");
- /* save the dram timing config into memory */
- dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE);
+} diff --git a/drivers/ddr/imx/imx8m/ddrphy_utils.c b/drivers/ddr/imx/imx8m/ddrphy_utils.c index 4732539764..e60503309e 100644 --- a/drivers/ddr/imx/imx8m/ddrphy_utils.c +++ b/drivers/ddr/imx/imx8m/ddrphy_utils.c @@ -122,6 +122,10 @@ void ddrphy_init_set_dfi_clk(unsigned int drate) dram_pll_init(MHZ(400)); dram_disable_bypass(); break;
- case 1066:
dram_pll_init(MHZ(266));
dram_disable_bypass();
case 667: dram_pll_init(MHZ(167)); dram_disable_bypass();break;
diff --git a/drivers/ddr/imx/imx8m/helper.c b/drivers/ddr/imx/imx8m/helper.c index 61cd4f6db1..9828b62218 100644 --- a/drivers/ddr/imx/imx8m/helper.c +++ b/drivers/ddr/imx/imx8m/helper.c @@ -57,7 +57,7 @@ void ddr_load_train_firmware(enum fw_type type) i += 4; }
- debug("check ddr4_pmu_train_imem code\n");
- debug("check ddr_pmu_train_imem code\n"); pr_from32 = imem_start; pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * IMEM_OFFSET_ADDR; for (i = 0x0; i < IMEM_LEN; ) {
@@ -74,9 +74,9 @@ void ddr_load_train_firmware(enum fw_type type) i += 4; } if (error)
printf("check ddr4_pmu_train_imem code fail=%d\n", error);
elseprintf("check ddr_pmu_train_imem code fail=%d\n", error);
debug("check ddr4_pmu_train_imem code pass\n");
debug("check ddr_pmu_train_imem code pass\n");
debug("check ddr4_pmu_train_dmem code\n"); pr_from32 = dmem_start;
@@ -95,9 +95,9 @@ void ddr_load_train_firmware(enum fw_type type) }
if (error)
printf("check ddr4_pmu_train_dmem code fail=%d", error);
elseprintf("check ddr_pmu_train_dmem code fail=%d", error);
debug("check ddr4_pmu_train_dmem code pass\n");
debug("check ddr_pmu_train_dmem code pass\n");
}
void ddrphy_trained_csr_save(struct dram_cfg_param *ddrphy_csr, diff --git a/drivers/ddr/imx/imx8m/lpddr4_init.c b/drivers/ddr/imx/imx8m/lpddr4_init.c deleted file mode 100644 index 0f46ca02b6..0000000000 --- a/drivers/ddr/imx/imx8m/lpddr4_init.c +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* -* Copyright 2018 NXP -* -*/
-#include <common.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/arch/ddr.h> -#include <asm/arch/clock.h> -#include <asm/arch/ddr.h> -#include <asm/arch/lpddr4_define.h> -#include <asm/arch/sys_proto.h>
-void lpddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) -{
- int i = 0;
- for (i = 0; i < num; i++) {
reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
ddrc_cfg++;
- }
-}
-void ddr_init(struct dram_timing_info *dram_timing) -{
- unsigned int tmp;
- debug("DDRINFO: start lpddr4 ddr init\n");
- /* step 1: reset */
- if (is_imx8mq()) {
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
- } else {
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
- }
- mdelay(100);
- debug("DDRINFO: reset done\n");
- /*
* change the clock source of dram_apb_clk_root:
* source 4 800MHz /4 = 200MHz
*/
- clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
CLK_ROOT_SOURCE_SEL(4) |
CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- /* disable iso */
- reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
- reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
- debug("DDRINFO: cfg clk\n");
- if (is_imx8mq())
dram_pll_init(MHZ(800));
- else
dram_pll_init(MHZ(750));
- /*
* release [0]ddr1_preset_n, [1]ddr1_core_reset_n,
* [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n
*/
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
- /*step2 Configure uMCTL2's registers */
- debug("DDRINFO: ddrc config start\n");
- lpddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
- debug("DDRINFO: ddrc config done\n");
- /*
* step3 de-assert all reset
* RESET: <core_ddrc_rstn> DEASSERTED
* RESET: <aresetn> for Port 0 DEASSERT(0)ED
*/
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
- reg32_write(DDRC_DBG1(0), 0x00000000);
- /* step4 */
- /* [0]dis_auto_refresh=1 */
- reg32_write(DDRC_RFSHCTL3(0), 0x00000011);
- /* [8]--1: lpddr4_sr allowed; [5]--1: software entry to SR */
- reg32_write(DDRC_PWRCTL(0), 0x000000a8);
- do {
tmp = reg32_read(DDRC_STAT(0));
- } while ((tmp & 0x33f) != 0x223);
- reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
- /* step5 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* step6 */
- tmp = reg32_read(DDRC_MSTR2(0));
- if (tmp == 0x2)
reg32_write(DDRC_DFIMISC(0), 0x00000210);
- else if (tmp == 0x1)
reg32_write(DDRC_DFIMISC(0), 0x00000110);
- else
reg32_write(DDRC_DFIMISC(0), 0x00000010);
- /* step7 [0]--1: disable quasi-dynamic programming */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* step8 Configure LPDDR4 PHY's registers */
- debug("DDRINFO:ddrphy config start\n");
- ddr_cfg_phy(dram_timing);
- debug("DDRINFO: ddrphy config done\n");
- /*
* step14 CalBusy.0 =1, indicates the calibrator is actively
* calibrating. Wait Calibrating done.
*/
- do {
tmp = reg32_read(DDRPHY_CalBusy(0));
- } while ((tmp & 0x1));
- debug("DDRINFO:ddrphy calibration done\n");
- /* step15 [0]--0: to enable quasi-dynamic programming */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* step16 */
- tmp = reg32_read(DDRC_MSTR2(0));
- if (tmp == 0x2)
reg32_write(DDRC_DFIMISC(0), 0x00000230);
- else if (tmp == 0x1)
reg32_write(DDRC_DFIMISC(0), 0x00000130);
- else
reg32_write(DDRC_DFIMISC(0), 0x00000030);
- /* step17 [0]--1: disable quasi-dynamic programming */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* step18 wait DFISTAT.dfi_init_complete to 1 */
- do {
tmp = reg32_read(DDRC_DFISTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* step19 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* step20~22 */
- tmp = reg32_read(DDRC_MSTR2(0));
- if (tmp == 0x2) {
reg32_write(DDRC_DFIMISC(0), 0x00000210);
/* set DFIMISC.dfi_init_complete_en again */
reg32_write(DDRC_DFIMISC(0), 0x00000211);
- } else if (tmp == 0x1) {
reg32_write(DDRC_DFIMISC(0), 0x00000110);
/* set DFIMISC.dfi_init_complete_en again */
reg32_write(DDRC_DFIMISC(0), 0x00000111);
- } else {
/* clear DFIMISC.dfi_init_complete_en */
reg32_write(DDRC_DFIMISC(0), 0x00000010);
/* set DFIMISC.dfi_init_complete_en again */
reg32_write(DDRC_DFIMISC(0), 0x00000011);
- }
- /* step23 [5]selfref_sw=0; */
- reg32_write(DDRC_PWRCTL(0), 0x00000008);
- /* step24 sw_done=1 */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* step25 wait SWSTAT.sw_done_ack to 1 */
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
-#ifdef DFI_BUG_WR
- reg32_write(DDRC_DFIPHYMSTR(0), 0x00000001);
-#endif
reg32_write(DDRC_DFIPHYMSTR(0), is removed but nothing similar is added.
Can you spilt the patch up so that lpddr4_init is more of just a file move so that it is easier to see what changes ?
BR Troy

Hi Troy,
-----Original Message----- From: Troy Kisky troy.kisky@boundarydevices.com Sent: 2019年8月9日 3:52 To: Peng Fan peng.fan@nxp.com; sbabic@denx.de; festevam@gmail.com Cc: u-boot@lists.denx.de; Jacky Bai ping.bai@nxp.com; dl-uboot-imx uboot-imx@nxp.com Subject: Re: [U-Boot] [PATCH 3/4] driver: ddr: Refine the ddr init driver on imx8m
On 8/8/2019 2:59 AM, Peng Fan wrote:
From: Jacky Bai ping.bai@nxp.com
Refine the ddr init driver to make it more reusable for different DDR type(LPDDR4, DDR4 & DDR3L). So we can reduce some redundant code.
Signed-off-by: Jacky Bai ping.bai@nxp.com Reviewed-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
drivers/ddr/imx/imx8m/Kconfig | 6 ++ drivers/ddr/imx/imx8m/Makefile | 4 +- drivers/ddr/imx/imx8m/ddr4_init.c | 112 -------------------- drivers/ddr/imx/imx8m/ddr_init.c | 168
++++++++++++++++++++++++++++++
drivers/ddr/imx/imx8m/ddrphy_utils.c | 4 + drivers/ddr/imx/imx8m/helper.c | 10 +- drivers/ddr/imx/imx8m/lpddr4_init.c | 191
7 files changed, 184 insertions(+), 311 deletions(-) delete mode 100644 drivers/ddr/imx/imx8m/ddr4_init.c create mode 100644 drivers/ddr/imx/imx8m/ddr_init.c delete mode 100644 drivers/ddr/imx/imx8m/lpddr4_init.c
diff --git a/drivers/ddr/imx/imx8m/Kconfig b/drivers/ddr/imx/imx8m/Kconfig index a83b0f43d7..5bf61eb258 100644 --- a/drivers/ddr/imx/imx8m/Kconfig +++ b/drivers/ddr/imx/imx8m/Kconfig @@ -16,6 +16,12 @@ config IMX8M_DDR4 help Select the i.MX8M DDR4 driver support on i.MX8M SOC.
+config IMX8M_DDR3L
- bool "imx8m ddr3l"
- select IMX8M_DRAM
- help
Select the i.MX8M DDR3L driver support on i.MX8M SOC.
config SAVED_DRAM_TIMING_BASE hex "Define the base address for saved dram timing" help diff --git a/drivers/ddr/imx/imx8m/Makefile b/drivers/ddr/imx/imx8m/Makefile index 64f9ab20e6..bd9bcb8d53 100644 --- a/drivers/ddr/imx/imx8m/Makefile +++ b/drivers/ddr/imx/imx8m/Makefile @@ -5,7 +5,5 @@ #
ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o -obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_init.o -obj-$(CONFIG_IMX8M_DDR4) += ddr4_init.o +obj-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o +ddrphy_csr.o ddr_init.o endif diff --git a/drivers/ddr/imx/imx8m/ddr4_init.c b/drivers/ddr/imx/imx8m/ddr4_init.c deleted file mode 100644 index b8aa104536..0000000000 --- a/drivers/ddr/imx/imx8m/ddr4_init.c +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/*
- Copyright 2018 NXP
- */
-#include <common.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/arch/ddr.h> -#include <asm/arch/clock.h> -#include <asm/arch/sys_proto.h>
-void ddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) -{
- int i = 0;
- for (i = 0; i < num; i++) {
reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
ddrc_cfg++;
- }
-}
-void ddr_init(struct dram_timing_info *dram_timing) -{
- volatile unsigned int tmp_t;
- /*
* assert [0]ddr1_preset_n, [1]ddr1_core_reset_n,
* [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n,
* [4]src_system_rst_b!
*/
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00003F);
- /* deassert [4]src_system_rst_b! */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
- /*
* change the clock source of dram_apb_clk_root
* to source 4 --800MHz/4
*/
- clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
CLK_ROOT_SOURCE_SEL(4) |
CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- dram_pll_init(MHZ(600));
- reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
- reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
- /* release [0]ddr1_preset_n, [3]ddr1_phy_pwrokin_n */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
- reg32_write(DDRC_DBG1(0), 0x00000001);
- reg32_write(DDRC_PWRCTL(0), 0x00000001);
- while (0 != (0x7 & reg32_read(DDRC_STAT(0))))
;
- /* config the uMCTL2's registers */
- ddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
- reg32_write(DDRC_RFSHCTL3(0), 0x00000001);
- /* RESET: <ctn> DEASSERTED */
- /* RESET: <a Port 0 DEASSERTED(0) */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
- reg32_write(DDRC_DBG1(0), 0x00000000);
- reg32_write(DDRC_PWRCTL(0), 0x00000aa);
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- reg32_write(DDRC_DFIMISC(0), 0x00000000);
- /* config the DDR PHY's registers */
- ddr_cfg_phy(dram_timing);
- do {
tmp_t = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) +
4 * 0x00020097);
- } while (tmp_t != 0);
- reg32_write(DDRC_DFIMISC(0), 0x00000020);
- /* wait DFISTAT.dfi_init_complete to 1 */
- while (0 == (0x1 & reg32_read(DDRC_DFISTAT(0))))
;
- /* clear DFIMISC.dfi_init_complete_en */
- reg32_write(DDRC_DFIMISC(0), 0x00000000);
- /* set DFIMISC.dfi_init_complete_en again */
- reg32_write(DDRC_DFIMISC(0), 0x00000001);
- reg32_write(DDRC_PWRCTL(0), 0x0000088);
- /*
* set SWCTL.sw_done to enable quasi-dynamic register
* programming outside reset.
*/
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* wait SWSTAT.sw_done_ack to 1 */
- while (0 == (0x1 & reg32_read(DDRC_SWSTAT(0))))
;
- /* wait STAT to normal state */
- while (0x1 != (0x7 & reg32_read(DDRC_STAT(0))))
;
- reg32_write(DDRC_PWRCTL(0), 0x0000088);
- reg32_write(DDRC_PCTRL_0(0), 0x00000001);
- /* dis_auto-refresh is set to 0 */
- reg32_write(DDRC_RFSHCTL3(0), 0x00000000);
- /* save the dram timing config into memory */
- dram_config_save(dram_timing,
CONFIG_SAVED_DRAM_TIMING_BASE);
-} diff --git a/drivers/ddr/imx/imx8m/ddr_init.c b/drivers/ddr/imx/imx8m/ddr_init.c new file mode 100644 index 0000000000..12967583ea --- /dev/null +++ b/drivers/ddr/imx/imx8m/ddr_init.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2018-2019 NXP
- */
+#include <common.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/ddr.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h>
+void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) {
- int i = 0;
- for (i = 0; i < num; i++) {
reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
ddrc_cfg++;
- }
+}
+void ddr_init(struct dram_timing_info *dram_timing) {
- unsigned int tmp, initial_drate, target_freq;
- printf("DDRINFO: start DRAM init\n");
- /* Step1: Follow the power up procedure */
- if (is_imx8mq()) {
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
- } else {
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
- }
- debug("DDRINFO: cfg clk\n");
- /* change the clock source of dram_apb_clk_root: source 4 800MHz /4 =
200MHz */
- clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
CLK_ROOT_SOURCE_SEL(4) |
CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- initial_drate = dram_timing->fsp_msg[0].drate;
- /* default to the frequency point 0 clock */
- ddrphy_init_set_dfi_clk(initial_drate);
- /* disable iso */
- reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
- reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
- /* D-aasert the presetn */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
- /* Step2: Program the dwc_ddr_umctl2 registers */
- debug("DDRINFO: ddrc config start\n");
- ddr_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
- debug("DDRINFO: ddrc config done\n");
- /* Step3: De-assert reset signal(core_ddrc_rstn & aresetn_n) */
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
- /*
* Step4: Disable auto-refreshes, self-refresh, powerdown, and
* assertion of dfi_dram_clk_disable by setting
RFSHCTL3.dis_auto_refresh = 1,
* PWRCTL.powerdown_en = 0, and PWRCTL.selfref_en = 0,
PWRCTL.en_dfi_dram_clk_disable = 0
*/
- reg32_write(DDRC_DBG1(0), 0x00000000);
- reg32_write(DDRC_RFSHCTL3(0), 0x0000001);
- reg32_write(DDRC_PWRCTL(0), 0xa0);
- /* if ddr type is LPDDR4, do it */
- tmp = reg32_read(DDRC_MSTR(0));
- if (tmp & (0x1 << 5))
reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
- /* determine the initial boot frequency */
- target_freq = reg32_read(DDRC_MSTR2(0)) & 0x3;
- target_freq = (tmp & (0x1 << 29)) ? target_freq : 0x0;
- /* Step5: Set SWCT.sw_done to 0 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* Set the default boot frequency point */
- clrsetbits_le32(DDRC_DFIMISC(0), (0x1f << 8), target_freq << 8);
- /* Step6: Set DFIMISC.dfi_init_complete_en to 0 */
- clrbits_le32(DDRC_DFIMISC(0), 0x1);
- /* Step7: Set SWCTL.sw_done to 1; need to polling
SWSTAT.sw_done_ack */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /*
* Step8 ~ Step13: Start PHY initialization and training by
* accessing relevant PUB registers
*/
- debug("DDRINFO:ddrphy config start\n");
- ddr_cfg_phy(dram_timing);
- debug("DDRINFO: ddrphy config done\n");
- /*
* step14 CalBusy.0 =1, indicates the calibrator is actively
* calibrating. Wait Calibrating done.
*/
- do {
tmp = reg32_read(DDRPHY_CalBusy(0));
- } while ((tmp & 0x1));
- printf("DDRINFO:ddrphy calibration done\n");
- /* Step15: Set SWCTL.sw_done to 0 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* Step16: Set DFIMISC.dfi_init_start to 1 */
- setbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
- /* Step17: Set SWCTL.sw_done to 1; need to polling
SWSTAT.sw_done_ack */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* Step18: Polling DFISTAT.dfi_init_complete = 1 */
- do {
tmp = reg32_read(DDRC_DFISTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* Step19: Set SWCTL.sw_done to 0 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* Step20: Set DFIMISC.dfi_init_start to 0 */
- clrbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
- /* Step21: optional */
- /* Step22: Set DFIMISC.dfi_init_complete_en to 1 */
- setbits_le32(DDRC_DFIMISC(0), 0x1);
- /* Step23: Set PWRCTL.selfref_sw to 0 */
- clrbits_le32(DDRC_PWRCTL(0), (0x1 << 5));
- /* Step24: Set SWCTL.sw_done to 1; need polling SWSTAT.sw_done_ack
*/
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* Step25: Wait for dwc_ddr_umctl2 to move to normal operating mode
by monitoring
* STAT.operating_mode signal */
- do {
tmp = reg32_read(DDRC_STAT(0));
- } while ((tmp & 0x3) != 0x1);
- /* Step26: Set back register in Step4 to the original values if desired */
- reg32_write(DDRC_RFSHCTL3(0), 0x0000000);
- /* enable selfref_en by default */
- setbits_le32(DDRC_PWRCTL(0), 0x1 << 3);
- /* enable port 0 */
- reg32_write(DDRC_PCTRL_0(0), 0x00000001);
- printf("DDRINFO: ddrmix config done\n");
- /* save the dram timing config into memory */
- dram_config_save(dram_timing,
CONFIG_SAVED_DRAM_TIMING_BASE); }
diff --git a/drivers/ddr/imx/imx8m/ddrphy_utils.c b/drivers/ddr/imx/imx8m/ddrphy_utils.c index 4732539764..e60503309e 100644 --- a/drivers/ddr/imx/imx8m/ddrphy_utils.c +++ b/drivers/ddr/imx/imx8m/ddrphy_utils.c @@ -122,6 +122,10 @@ void ddrphy_init_set_dfi_clk(unsigned int drate) dram_pll_init(MHZ(400)); dram_disable_bypass(); break;
- case 1066:
dram_pll_init(MHZ(266));
dram_disable_bypass();
case 667: dram_pll_init(MHZ(167)); dram_disable_bypass();break;
diff --git a/drivers/ddr/imx/imx8m/helper.c b/drivers/ddr/imx/imx8m/helper.c index 61cd4f6db1..9828b62218 100644 --- a/drivers/ddr/imx/imx8m/helper.c +++ b/drivers/ddr/imx/imx8m/helper.c @@ -57,7 +57,7 @@ void ddr_load_train_firmware(enum fw_type type) i += 4; }
- debug("check ddr4_pmu_train_imem code\n");
- debug("check ddr_pmu_train_imem code\n"); pr_from32 = imem_start; pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * IMEM_OFFSET_ADDR; for (i = 0x0; i < IMEM_LEN; ) {
@@ -74,9 +74,9 @@ void ddr_load_train_firmware(enum fw_type type) i += 4; } if (error)
printf("check ddr4_pmu_train_imem code fail=%d\n", error);
elseprintf("check ddr_pmu_train_imem code fail=%d\n", error);
debug("check ddr4_pmu_train_imem code pass\n");
debug("check ddr_pmu_train_imem code pass\n");
debug("check ddr4_pmu_train_dmem code\n"); pr_from32 = dmem_start;
@@ -95,9 +95,9 @@ void ddr_load_train_firmware(enum fw_type type) }
if (error)
printf("check ddr4_pmu_train_dmem code fail=%d", error);
elseprintf("check ddr_pmu_train_dmem code fail=%d", error);
debug("check ddr4_pmu_train_dmem code pass\n");
debug("check ddr_pmu_train_dmem code pass\n");
}
void ddrphy_trained_csr_save(struct dram_cfg_param *ddrphy_csr, diff --git a/drivers/ddr/imx/imx8m/lpddr4_init.c b/drivers/ddr/imx/imx8m/lpddr4_init.c deleted file mode 100644 index 0f46ca02b6..0000000000 --- a/drivers/ddr/imx/imx8m/lpddr4_init.c +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* -* Copyright 2018 NXP -* -*/
-#include <common.h> -#include <errno.h> -#include <asm/io.h> -#include <asm/arch/ddr.h> -#include <asm/arch/clock.h> -#include <asm/arch/ddr.h> -#include <asm/arch/lpddr4_define.h> -#include <asm/arch/sys_proto.h>
-void lpddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) -{
- int i = 0;
- for (i = 0; i < num; i++) {
reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
ddrc_cfg++;
- }
-}
-void ddr_init(struct dram_timing_info *dram_timing) -{
- unsigned int tmp;
- debug("DDRINFO: start lpddr4 ddr init\n");
- /* step 1: reset */
- if (is_imx8mq()) {
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
- } else {
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
- }
- mdelay(100);
- debug("DDRINFO: reset done\n");
- /*
* change the clock source of dram_apb_clk_root:
* source 4 800MHz /4 = 200MHz
*/
- clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
CLK_ROOT_SOURCE_SEL(4) |
CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- /* disable iso */
- reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
- reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
- debug("DDRINFO: cfg clk\n");
- if (is_imx8mq())
dram_pll_init(MHZ(800));
- else
dram_pll_init(MHZ(750));
- /*
* release [0]ddr1_preset_n, [1]ddr1_core_reset_n,
* [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n
*/
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
- /*step2 Configure uMCTL2's registers */
- debug("DDRINFO: ddrc config start\n");
- lpddr4_cfg_umctl2(dram_timing->ddrc_cfg,
dram_timing->ddrc_cfg_num);
- debug("DDRINFO: ddrc config done\n");
- /*
* step3 de-assert all reset
* RESET: <core_ddrc_rstn> DEASSERTED
* RESET: <aresetn> for Port 0 DEASSERT(0)ED
*/
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
- reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
- reg32_write(DDRC_DBG1(0), 0x00000000);
- /* step4 */
- /* [0]dis_auto_refresh=1 */
- reg32_write(DDRC_RFSHCTL3(0), 0x00000011);
- /* [8]--1: lpddr4_sr allowed; [5]--1: software entry to SR */
- reg32_write(DDRC_PWRCTL(0), 0x000000a8);
- do {
tmp = reg32_read(DDRC_STAT(0));
- } while ((tmp & 0x33f) != 0x223);
- reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
- /* step5 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* step6 */
- tmp = reg32_read(DDRC_MSTR2(0));
- if (tmp == 0x2)
reg32_write(DDRC_DFIMISC(0), 0x00000210);
- else if (tmp == 0x1)
reg32_write(DDRC_DFIMISC(0), 0x00000110);
- else
reg32_write(DDRC_DFIMISC(0), 0x00000010);
- /* step7 [0]--1: disable quasi-dynamic programming */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* step8 Configure LPDDR4 PHY's registers */
- debug("DDRINFO:ddrphy config start\n");
- ddr_cfg_phy(dram_timing);
- debug("DDRINFO: ddrphy config done\n");
- /*
* step14 CalBusy.0 =1, indicates the calibrator is actively
* calibrating. Wait Calibrating done.
*/
- do {
tmp = reg32_read(DDRPHY_CalBusy(0));
- } while ((tmp & 0x1));
- debug("DDRINFO:ddrphy calibration done\n");
- /* step15 [0]--0: to enable quasi-dynamic programming */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* step16 */
- tmp = reg32_read(DDRC_MSTR2(0));
- if (tmp == 0x2)
reg32_write(DDRC_DFIMISC(0), 0x00000230);
- else if (tmp == 0x1)
reg32_write(DDRC_DFIMISC(0), 0x00000130);
- else
reg32_write(DDRC_DFIMISC(0), 0x00000030);
- /* step17 [0]--1: disable quasi-dynamic programming */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* step18 wait DFISTAT.dfi_init_complete to 1 */
- do {
tmp = reg32_read(DDRC_DFISTAT(0));
- } while ((tmp & 0x1) == 0x0);
- /* step19 */
- reg32_write(DDRC_SWCTL(0), 0x00000000);
- /* step20~22 */
- tmp = reg32_read(DDRC_MSTR2(0));
- if (tmp == 0x2) {
reg32_write(DDRC_DFIMISC(0), 0x00000210);
/* set DFIMISC.dfi_init_complete_en again */
reg32_write(DDRC_DFIMISC(0), 0x00000211);
- } else if (tmp == 0x1) {
reg32_write(DDRC_DFIMISC(0), 0x00000110);
/* set DFIMISC.dfi_init_complete_en again */
reg32_write(DDRC_DFIMISC(0), 0x00000111);
- } else {
/* clear DFIMISC.dfi_init_complete_en */
reg32_write(DDRC_DFIMISC(0), 0x00000010);
/* set DFIMISC.dfi_init_complete_en again */
reg32_write(DDRC_DFIMISC(0), 0x00000011);
- }
- /* step23 [5]selfref_sw=0; */
- reg32_write(DDRC_PWRCTL(0), 0x00000008);
- /* step24 sw_done=1 */
- reg32_write(DDRC_SWCTL(0), 0x00000001);
- /* step25 wait SWSTAT.sw_done_ack to 1 */
- do {
tmp = reg32_read(DDRC_SWSTAT(0));
- } while ((tmp & 0x1) == 0x0);
-#ifdef DFI_BUG_WR
- reg32_write(DDRC_DFIPHYMSTR(0), 0x00000001);
-#endif
reg32_write(DDRC_DFIPHYMSTR(0), is removed but nothing similar is added.
Can you spilt the patch up so that lpddr4_init is more of just a file move so that it is easier to see what changes ?
Ok, will fix that in v2.
Thanks, Peng.
BR Troy

From: Jacky Bai ping.bai@nxp.com
On, i.MX8MQ, the PLL config must be done when ddrmix isolation is released. So move the dram pll init after iso config done. For other i.MX8M SOC, either init pll before or after isolation is ok.
Signed-off-by: Jacky Bai ping.bai@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/ddr/imx/imx8m/ddr_init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/ddr/imx/imx8m/ddr_init.c b/drivers/ddr/imx/imx8m/ddr_init.c index 12967583ea..d6e915c9b9 100644 --- a/drivers/ddr/imx/imx8m/ddr_init.c +++ b/drivers/ddr/imx/imx8m/ddr_init.c @@ -41,14 +41,14 @@ void ddr_init(struct dram_timing_info *dram_timing) clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
- initial_drate = dram_timing->fsp_msg[0].drate; - /* default to the frequency point 0 clock */ - ddrphy_init_set_dfi_clk(initial_drate); - /* disable iso */ reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
+ initial_drate = dram_timing->fsp_msg[0].drate; + /* default to the frequency point 0 clock */ + ddrphy_init_set_dfi_clk(initial_drate); + /* D-aasert the presetn */ reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
participants (2)
-
Peng Fan
-
Troy Kisky