[U-Boot] [PATCH v4 4/8] drivers/ddr/fsl: Add calculation of register control words
York Sun
york.sun at nxp.com
Mon Jan 29 17:44:36 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 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 | 2 ++
include/ddr_spd.h | 8 +++++---
include/fsl_ddr_dimm_params.h | 2 +-
5 files changed, 51 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..536f143 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -1296,6 +1296,7 @@ done:
popts->package_3ds = pdimm->package_3ds;
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
+#if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
if (popts->registered_dimm_en) {
popts->rcw_override = 1;
popts->rcw_1 = 0x000a5a00;
@@ -1308,6 +1309,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