[U-Boot] [PATCH v3 1/3] drivers/ddr/fsl: Fix DDR4 RDIMM support

York Sun york.sun at nxp.com
Wed Jan 24 19:04:28 UTC 2018


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 at 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;
-- 
2.7.4



More information about the U-Boot mailing list