diff options
author | Jacky Bai <ping.bai@nxp.com> | 2023-04-28 12:08:44 +0800 |
---|---|---|
committer | Stefano Babic <sbabic@denx.de> | 2023-05-21 16:54:41 +0200 |
commit | 212a4e19615102277718f6adaa0282b2a69d7320 (patch) | |
tree | ea7cba3df91b0f49b9f659b3d297c7f841edd945 /drivers/ddr | |
parent | 8e81e679db3248f2b3c34aee5302cd15a8283293 (diff) | |
download | u-boot-212a4e19615102277718f6adaa0282b2a69d7320.tar.gz u-boot-212a4e19615102277718f6adaa0282b2a69d7320.tar.bz2 u-boot-212a4e19615102277718f6adaa0282b2a69d7320.zip |
ddr: imx9: update the rank setting for multi fsp support
The rank setting flow should be updated to support multi
fsp config.
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>
Diffstat (limited to 'drivers/ddr')
-rw-r--r-- | drivers/ddr/imx/imx9/ddr_init.c | 178 |
1 files changed, 116 insertions, 62 deletions
diff --git a/drivers/ddr/imx/imx9/ddr_init.c b/drivers/ddr/imx/imx9/ddr_init.c index a2158094b2..7a333880e6 100644 --- a/drivers/ddr/imx/imx9/ddr_init.c +++ b/drivers/ddr/imx/imx9/ddr_init.c @@ -145,68 +145,122 @@ void get_trained_CDD(u32 fsp) g_cdd_ww_max[fsp] = cdd_cha_ww_max > cdd_chb_ww_max ? cdd_cha_ww_max : cdd_chb_ww_max; } -void update_umctl2_rank_space_setting(unsigned int pstat_num) +static u32 ddrc_get_fsp_reg_setting(struct dram_cfg_param *ddrc_cfg, unsigned int cfg_num, u32 reg) { - u32 tmp, tmp_t; + unsigned int i; + + for (i = 0; i < cfg_num; i++) { + if (reg == ddrc_cfg[i].reg) + return ddrc_cfg[i].val; + } - int wwt, rrt, wrt, rwt; - int ext_wwt, ext_rrt, ext_wrt, ext_rwt; - int max_wwt, max_rrt, max_wrt, max_rwt; - - /* read wwt, rrt, wrt, rwt fields from timing_cfg_0 */ - tmp = readl(REG_DDR_TIMING_CFG_0); - wwt = (tmp >> 24) & 0x3; - rrt = (tmp >> 26) & 0x3; - wrt = (tmp >> 28) & 0x3; - rwt = (tmp >> 30) & 0x3; - - /* read rxt_wwt, ext_rrt, ext_wrt, ext_rwt fields from timing_cfg_4 */ - tmp_t = readl(REG_DDR_TIMING_CFG_4); - ext_wwt = (tmp >> 8) & 0x1; - ext_rrt = (tmp >> 10) & 0x1; - ext_wrt = (tmp >> 12) & 0x1; - ext_rwt = (tmp >> 14) & 0x3; - - wwt = (ext_wwt << 2) | wwt; - rrt = (ext_rrt << 2) | wwt; - wrt = (ext_wrt << 2) | wrt; - rwt = (ext_rwt << 2) | rwt; - - /* calculate the maximum between controller and cdd values */ - max_wwt = MAX(g_cdd_ww_max[0], wwt); - max_rrt = MAX(g_cdd_rr_max[0], rrt); - max_wrt = MAX(g_cdd_wr_max[0], wrt); - max_rwt = MAX(g_cdd_rw_max[0], rwt); - - /* verify values to see if are bigger then 7 or 15 (3 bits or 4 bits) */ - if (max_wwt > 7) - max_wwt = 7; - if (max_rrt > 7) - max_rrt = 7; - if (max_wrt > 7) - max_wrt = 7; - if (max_rwt > 15) - max_rwt = 15; - - /* recalculate timings for controller registers */ - wwt = max_wwt & 0x3; - rrt = max_rrt & 0x3; - wrt = max_wrt & 0x3; - rwt = max_rwt & 0x3; - - ext_wwt = (max_wwt & 0x4) >> 2; - ext_rrt = (max_rrt & 0x4) >> 2; - ext_wrt = (max_wrt & 0x4) >> 2; - ext_rwt = (max_rwt & 0xC) >> 2; - - /* update timing_cfg_0 and timing_cfg_4 */ - tmp = (tmp & 0x00ffffff) | (rwt << 30) | (wrt << 28) | - (rrt << 26) | (wwt << 24); - writel(tmp, REG_DDR_TIMING_CFG_0); - - tmp_t = (tmp_t & 0xFFFF2AFF) | (ext_rwt << 14) | - (ext_wrt << 12) | (ext_rrt << 10) | (ext_wwt << 8); - writel(tmp_t, REG_DDR_TIMING_CFG_4); + return 0; +} + +static void ddrc_update_fsp_reg_setting(struct dram_cfg_param *ddrc_cfg, int cfg_num, + u32 reg, u32 val) +{ + unsigned int i; + + for (i = 0; i < cfg_num; i++) { + if (reg == ddrc_cfg[i].reg) { + ddrc_cfg[i].val = val; + return; + } + } +} + +void update_umctl2_rank_space_setting(struct dram_timing_info *dram_timing, unsigned int pstat_num) +{ + u32 tmp, tmp_t; + u32 wwt, rrt, wrt, rwt; + u32 ext_wwt, ext_rrt, ext_wrt, ext_rwt; + u32 max_wwt, max_rrt, max_wrt, max_rwt; + u32 i; + + for (i = 0; i < pstat_num; i++) { + /* read wwt, rrt, wrt, rwt fields from timing_cfg_0 */ + if (!dram_timing->fsp_cfg_num) { + tmp = ddrc_get_fsp_reg_setting(dram_timing->ddrc_cfg, + dram_timing->ddrc_cfg_num, + REG_DDR_TIMING_CFG_0); + } else { + tmp = ddrc_get_fsp_reg_setting(dram_timing->fsp_cfg[i].ddrc_cfg, + ARRAY_SIZE(dram_timing->fsp_cfg[i].ddrc_cfg), + REG_DDR_TIMING_CFG_0); + } + wwt = (tmp >> 24) & 0x3; + rrt = (tmp >> 26) & 0x3; + wrt = (tmp >> 28) & 0x3; + rwt = (tmp >> 30) & 0x3; + + /* read rxt_wwt, ext_rrt, ext_wrt, ext_rwt fields from timing_cfg_4 */ + if (!dram_timing->fsp_cfg_num) { + tmp_t = ddrc_get_fsp_reg_setting(dram_timing->ddrc_cfg, + dram_timing->ddrc_cfg_num, + REG_DDR_TIMING_CFG_4); + } else { + tmp_t = ddrc_get_fsp_reg_setting(dram_timing->fsp_cfg[i].ddrc_cfg, + ARRAY_SIZE(dram_timing->fsp_cfg[i].ddrc_cfg), + REG_DDR_TIMING_CFG_4); + } + ext_wwt = (tmp_t >> 8) & 0x3; + ext_rrt = (tmp_t >> 10) & 0x3; + ext_wrt = (tmp_t >> 12) & 0x3; + ext_rwt = (tmp_t >> 14) & 0x3; + + wwt = (ext_wwt << 2) | wwt; + rrt = (ext_rrt << 2) | rrt; + wrt = (ext_wrt << 2) | wrt; + rwt = (ext_rwt << 2) | rwt; + + max_wwt = MAX(g_cdd_ww_max[0], wwt); + max_rrt = MAX(g_cdd_rr_max[0], rrt); + max_wrt = MAX(g_cdd_wr_max[0], wrt); + max_rwt = MAX(g_cdd_rw_max[0], rwt); + /* verify values to see if are bigger then 15 (4 bits) */ + if (max_wwt > 15) + max_wwt = 15; + if (max_rrt > 15) + max_rrt = 15; + if (max_wrt > 15) + max_wrt = 15; + if (max_rwt > 15) + max_rwt = 15; + + /* recalculate timings for controller registers */ + wwt = max_wwt & 0x3; + rrt = max_rrt & 0x3; + wrt = max_wrt & 0x3; + rwt = max_rwt & 0x3; + + ext_wwt = (max_wwt & 0xC) >> 2; + ext_rrt = (max_rrt & 0xC) >> 2; + ext_wrt = (max_wrt & 0xC) >> 2; + ext_rwt = (max_rwt & 0xC) >> 2; + + /* update timing_cfg_0 and timing_cfg_4 */ + tmp = (tmp & 0x00ffffff) | (rwt << 30) | (wrt << 28) | + (rrt << 26) | (wwt << 24); + tmp_t = (tmp_t & 0xFFFF00FF) | (ext_rwt << 14) | + (ext_wrt << 12) | (ext_rrt << 10) | (ext_wwt << 8); + + if (!dram_timing->fsp_cfg_num) { + ddrc_update_fsp_reg_setting(dram_timing->ddrc_cfg, + dram_timing->ddrc_cfg_num, + REG_DDR_TIMING_CFG_0, tmp); + ddrc_update_fsp_reg_setting(dram_timing->ddrc_cfg, + dram_timing->ddrc_cfg_num, + REG_DDR_TIMING_CFG_4, tmp_t); + } else { + ddrc_update_fsp_reg_setting(dram_timing->fsp_cfg[i].ddrc_cfg, + ARRAY_SIZE(dram_timing->fsp_cfg[i].ddrc_cfg), + REG_DDR_TIMING_CFG_0, tmp); + ddrc_update_fsp_reg_setting(dram_timing->fsp_cfg[i].ddrc_cfg, + ARRAY_SIZE(dram_timing->fsp_cfg[i].ddrc_cfg), + REG_DDR_TIMING_CFG_4, tmp_t); + } + } } u32 ddrc_mrr(u32 chip_select, u32 mode_reg_num, u32 *mode_reg_val) @@ -313,13 +367,13 @@ int ddr_init(struct dram_timing_info *dram_timing) debug("DDRINFO: ddrphy config done\n"); + update_umctl2_rank_space_setting(dram_timing, dram_timing->fsp_msg_num - 1); + /* rogram the ddrc registers */ debug("DDRINFO: ddrc config start\n"); ddrc_config(dram_timing); debug("DDRINFO: ddrc config done\n"); - update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1); - #ifdef CONFIG_IMX9_DRAM_PM_COUNTER writel(0x200000, REG_DDR_DEBUG_19); #endif |