[U-Boot] [PATCH v5 4/8] drivers/ddr/fsl: Add calculation of register control words

York Sun york.sun at nxp.com
Mon Jan 29 18:24:08 UTC 2018


DDR4 RDIMM has some information in SPD to be used to calculate the
control words for register chip. The rest can be found from JEDEC
spec DDR4RCD02.

Signed-off-by: York Sun <york.sun at nxp.com>

---

Changes in v5:
Fix compiling warning for unused variable.

Changes in v4:
New patch to add RCW calculation.

Changes in v3: None
Changes in v2: None

 drivers/ddr/fsl/ctrl_regs.c        | 30 +++++++++++++++++++++++-------
 drivers/ddr/fsl/ddr4_dimm_params.c | 20 ++++++++++++++++++++
 drivers/ddr/fsl/options.c          |  4 ++++
 include/ddr_spd.h                  |  8 +++++---
 include/fsl_ddr_dimm_params.h      |  2 +-
 5 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index bcab904..8b87271 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -724,10 +724,14 @@ static void set_timing_cfg_2(const unsigned int ctrl_num,
 }
 
 /* DDR SDRAM Register Control Word */
-static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
-			       const memctl_options_t *popts,
-			       const common_timing_params_t *common_dimm)
+static void set_ddr_sdram_rcw(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 ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
+	unsigned int rc0a, rc0f;
+
 	if (common_dimm->all_dimms_registered &&
 	    !common_dimm->all_dimms_unbuffered)	{
 		if (popts->rcw_override) {
@@ -735,6 +739,16 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
 			ddr->ddr_sdram_rcw_2 = popts->rcw_2;
 			ddr->ddr_sdram_rcw_3 = popts->rcw_3;
 		} else {
+			rc0a = ddr_freq > 3200 ? 0x7 :
+			       (ddr_freq > 2933 ? 0x6 :
+				(ddr_freq > 2666 ? 0x5 :
+				 (ddr_freq > 2400 ? 0x4 :
+				  (ddr_freq > 2133 ? 0x3 :
+				   (ddr_freq > 1866 ? 0x2 :
+				    (ddr_freq > 1600 ? 1 : 0))))));
+			rc0f = ddr_freq > 3200 ? 0x3 :
+			       (ddr_freq > 2400 ? 0x2 :
+				(ddr_freq > 2133 ? 0x1 : 0));
 			ddr->ddr_sdram_rcw_1 =
 				common_dimm->rcw[0] << 28 | \
 				common_dimm->rcw[1] << 24 | \
@@ -747,12 +761,14 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
 			ddr->ddr_sdram_rcw_2 =
 				common_dimm->rcw[8] << 28 | \
 				common_dimm->rcw[9] << 24 | \
-				common_dimm->rcw[10] << 20 | \
+				rc0a << 20 | \
 				common_dimm->rcw[11] << 16 | \
 				common_dimm->rcw[12] << 12 | \
 				common_dimm->rcw[13] << 8 | \
 				common_dimm->rcw[14] << 4 | \
-				common_dimm->rcw[15];
+				rc0f;
+			ddr->ddr_sdram_rcw_3 =
+				((ddr_freq - 1260 + 19) / 20) << 8;
 		}
 		debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n",
 		      ddr->ddr_sdram_rcw_1);
@@ -2561,6 +2577,8 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
 	set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en);
 	set_ddr_sdram_mode_10(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
 #endif
+	set_ddr_sdram_rcw(ctrl_num, ddr, popts, common_dimm);
+
 	set_ddr_sdram_interval(ctrl_num, ddr, popts, common_dimm);
 	set_ddr_data_init(ddr);
 	set_ddr_sdram_clk_cntl(ddr, popts);
@@ -2582,8 +2600,6 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
 
 	set_ddr_sr_cntr(ddr, sr_it);
 
-	set_ddr_sdram_rcw(ddr, popts, common_dimm);
-
 #ifdef CONFIG_SYS_FSL_DDR_EMU
 	/* disble DDR training for emulator */
 	ddr->debug[2] = 0x00000400;
diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c
index 0d3d137..5c8fc88 100644
--- a/drivers/ddr/fsl/ddr4_dimm_params.c
+++ b/drivers/ddr/fsl/ddr4_dimm_params.c
@@ -192,6 +192,26 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num,
 		pdimm->registered_dimm = 1;
 		if (spd->mod_section.registered.reg_map & 0x1)
 			pdimm->mirrored_dimm = 1;
+		val = spd->mod_section.registered.ca_stren;
+		pdimm->rcw[3] = val >> 4;
+		pdimm->rcw[4] = ((val & 0x3) << 2) | ((val & 0xc) >> 2);
+		val = spd->mod_section.registered.clk_stren;
+		pdimm->rcw[5] = ((val & 0x3) << 2) | ((val & 0xc) >> 2);
+		/* Not all in SPD. For convience only. Boards may overwrite. */
+		pdimm->rcw[6] = 0xf;
+		/*
+		 * A17 only used for 16Gb and above devices.
+		 * C[2:0] only used for 3DS.
+		 */
+		pdimm->rcw[8] = pdimm->die_density >= 0x6 ? 0x0 : 0x8 |
+				(pdimm->package_3ds > 0x3 ? 0x0 :
+				 (pdimm->package_3ds > 0x1 ? 0x1 :
+				  (pdimm->package_3ds > 0 ? 0x2 : 0x3)));
+		if (pdimm->package_3ds || pdimm->n_ranks != 4)
+			pdimm->rcw[13] = 0xc;
+		else
+			pdimm->rcw[13] = 0xd;	/* Fix encoded by board */
+
 		break;
 
 	case DDR4_SPD_MODULETYPE_UDIMM:
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index 5158ea2..85ec48c 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -750,7 +750,9 @@ unsigned int populate_memctl_options(const common_timing_params_t *common_dimm,
 	defined(CONFIG_SYS_FSL_DDR4)
 	const struct dynamic_odt *pdodt = odt_unknown;
 #endif
+#if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
 	ulong ddr_freq;
+#endif
 
 	/*
 	 * Extract hwconfig from environment since we have not properly setup
@@ -1295,6 +1297,7 @@ done:
 
 	popts->package_3ds = pdimm->package_3ds;
 
+#if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
 	ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
 	if (popts->registered_dimm_en) {
 		popts->rcw_override = 1;
@@ -1308,6 +1311,7 @@ done:
 		else
 			popts->rcw_2 = 0x00300000;
 	}
+#endif
 
 	fsl_ddr_board_options(popts, pdimm, ctrl_num);
 
diff --git a/include/ddr_spd.h b/include/ddr_spd.h
index d71cd9a..20dc9ea 100644
--- a/include/ddr_spd.h
+++ b/include/ddr_spd.h
@@ -382,9 +382,11 @@ struct ddr4_spd_eeprom_s {
 			/* 135 Register Revision Number */
 			uint8_t reg_rev;
 			/* 136 Address mapping from register to DRAM */
-			uint8_t reg_map;
-			/* 137~253 Reserved */
-			uint8_t res_137[254-137];
+			u8 reg_map;
+			u8 ca_stren;
+			u8 clk_stren;
+			/* 139~253 Reserved */
+			u8 res_137[254 - 139];
 			/* 254~255 CRC */
 			uint8_t crc[2];
 		} registered;
diff --git a/include/fsl_ddr_dimm_params.h b/include/fsl_ddr_dimm_params.h
index c6c819e..1f78ea2 100644
--- a/include/fsl_ddr_dimm_params.h
+++ b/include/fsl_ddr_dimm_params.h
@@ -106,7 +106,7 @@ typedef struct dimm_params_s {
 	int tqhs_ps;	/* byte 45, spd->tqhs */
 #endif
 
-	/* DDR3 RDIMM */
+	/* DDR3 & DDR4 RDIMM */
 	unsigned char rcw[16];	/* Register Control Word 0-15 */
 #ifdef CONFIG_SYS_FSL_DDR4
 	unsigned int dq_mapping[18];
-- 
2.7.4



More information about the U-Boot mailing list