
For DDR4, command/address delay in mode registers and parity latency in timing config register are only needed for UDIMMs, but not RDIMMs. Add additional register rcw_3 for DDR4 RDIMM. Fix mirrored bit for dual rank RDIMMs. Set sdram_cfg_3[DIS_MRS_PAR] for RDIMMs. Use hexadecimal format for printing RCW (register control word) registers.
Signed-off-by: York Sun york.sun@nxp.com ---
Changes in v3: None Changes in v2: None
drivers/ddr/fsl/ctrl_regs.c | 32 +++++++++++++++++++++++++------- drivers/ddr/fsl/ddr4_dimm_params.c | 2 ++ drivers/ddr/fsl/interactive.c | 9 +++++++-- include/fsl_ddr_sdram.h | 1 + 4 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index c0ee858..4a1f397 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -732,6 +732,7 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr, if (popts->rcw_override) { ddr->ddr_sdram_rcw_1 = popts->rcw_1; ddr->ddr_sdram_rcw_2 = popts->rcw_2; + ddr->ddr_sdram_rcw_3 = popts->rcw_3; } else { ddr->ddr_sdram_rcw_1 = common_dimm->rcw[0] << 28 | \ @@ -752,8 +753,12 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr, common_dimm->rcw[14] << 4 | \ common_dimm->rcw[15]; } - debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1); - debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2); + debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", + ddr->ddr_sdram_rcw_1); + debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", + ddr->ddr_sdram_rcw_2); + debug("FSLDDR: ddr_sdram_rcw_3 = 0x%08x\n", + ddr->ddr_sdram_rcw_3); } }
@@ -1159,8 +1164,14 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, esdmode5 = 0x00000400; /* Data mask enabled */ }
- /* set command/address parity latency */ - if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { + /* + * For DDR3, set C/A latency if address parity is enabled. + * For DDR4, set C/A latency for UDIMM only. For RDIMM the delay is + * handled by register chip and RCW settings. + */ + if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) && + ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) || + !popts->registered_dimm_en)) { if (mclk_ps >= 935) { /* for DDR4-1600/1866/2133 */ esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; @@ -1193,7 +1204,9 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, esdmode5 = 0x00000400; }
- if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { + if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) && + ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) || + !popts->registered_dimm_en)) { if (mclk_ps >= 935) { /* for DDR4-1600/1866/2133 */ esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; @@ -1965,6 +1978,7 @@ static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
static void set_timing_cfg_7(const unsigned int ctrl_num, fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, const common_timing_params_t *common_dimm) { unsigned int txpr, tcksre, tcksrx; @@ -1975,7 +1989,9 @@ static void set_timing_cfg_7(const unsigned int ctrl_num, tcksre = max(5U, picos_to_mclk(ctrl_num, 10000)); tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000));
- if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { + if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) && + ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) || + !popts->registered_dimm_en)) { if (mclk_ps >= 935) { /* parity latency 4 clocks in case of 1600/1866/2133 */ par_lat = 4; @@ -2130,6 +2146,8 @@ static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr, rd_pre = popts->quad_rank_present ? 1 : 0;
ddr->ddr_sdram_cfg_3 = (rd_pre & 0x1) << 16; + /* Disable MRS on parity error for RDIMMs */ + ddr->ddr_sdram_cfg_3 |= popts->registered_dimm_en ? 1 : 0;
debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3); } @@ -2535,7 +2553,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num, #ifdef CONFIG_SYS_FSL_DDR4 set_ddr_sdram_cfg_3(ddr, popts); set_timing_cfg_6(ddr); - set_timing_cfg_7(ctrl_num, ddr, common_dimm); + set_timing_cfg_7(ctrl_num, ddr, popts, common_dimm); set_timing_cfg_8(ctrl_num, ddr, popts, common_dimm, cas_latency); set_timing_cfg_9(ddr); set_ddr_dq_mapping(ddr, dimm_params); diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 42834ca..6e26ba8 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -179,6 +179,8 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, case DDR4_SPD_MODULETYPE_RDIMM: /* Registered/buffered DIMMs */ pdimm->registered_dimm = 1; + if (spd->mod_section.registered.reg_map & 0x1) + pdimm->mirrored_dimm = 1; break;
case DDR4_SPD_MODULETYPE_UDIMM: diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c index c99bd2f..660060d 100644 --- a/drivers/ddr/fsl/interactive.c +++ b/drivers/ddr/fsl/interactive.c @@ -558,6 +558,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo, */ CTRL_OPTIONS(twot_en), CTRL_OPTIONS(threet_en), + CTRL_OPTIONS(mirrored_dimm), CTRL_OPTIONS(ap_en), CTRL_OPTIONS(x4_en), CTRL_OPTIONS(bstopre), @@ -568,6 +569,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo, CTRL_OPTIONS(rcw_override), CTRL_OPTIONS(rcw_1), CTRL_OPTIONS(rcw_2), + CTRL_OPTIONS(rcw_3), CTRL_OPTIONS(ddr_cdr1), CTRL_OPTIONS(ddr_cdr2), CTRL_OPTIONS(tfaw_window_four_activates_ps), @@ -660,6 +662,7 @@ static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) CFG_REGS(ddr_sr_cntr), CFG_REGS(ddr_sdram_rcw_1), CFG_REGS(ddr_sdram_rcw_2), + CFG_REGS(ddr_sdram_rcw_3), CFG_REGS(ddr_cdr1), CFG_REGS(ddr_cdr2), CFG_REGS(dq_map_0), @@ -750,6 +753,7 @@ static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo, CFG_REGS(ddr_sr_cntr), CFG_REGS(ddr_sdram_rcw_1), CFG_REGS(ddr_sdram_rcw_2), + CFG_REGS(ddr_sdram_rcw_3), CFG_REGS(ddr_cdr1), CFG_REGS(ddr_cdr2), CFG_REGS(dq_map_0), @@ -857,8 +861,9 @@ static void print_memctl_options(const memctl_options_t *popts) CTRL_OPTIONS(wrlvl_start), CTRL_OPTIONS_HEX(cswl_override), CTRL_OPTIONS(rcw_override), - CTRL_OPTIONS(rcw_1), - CTRL_OPTIONS(rcw_2), + CTRL_OPTIONS_HEX(rcw_1), + CTRL_OPTIONS_HEX(rcw_2), + CTRL_OPTIONS_HEX(rcw_3), CTRL_OPTIONS_HEX(ddr_cdr1), CTRL_OPTIONS_HEX(ddr_cdr2), CTRL_OPTIONS(tfaw_window_four_activates_ps), diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index 6a1f04b..de7ef9b 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -408,6 +408,7 @@ typedef struct memctl_options_s { unsigned int rcw_override; unsigned int rcw_1; unsigned int rcw_2; + unsigned int rcw_3; /* control register 1 */ unsigned int ddr_cdr1; unsigned int ddr_cdr2;