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

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@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];
participants (1)
-
York Sun