diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index bcab9046ad..8b8727116d 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 1f1d9b897a..5c8fc8804d 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -139,6 +139,7 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, }; int spd_error = 0; u8 *ptr; + u8 val; if (spd->mem_type) { if (spd->mem_type != SPD_MEMTYPE_DDR4) { @@ -191,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 5158ea2089..85ec48c28e 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 d71cd9ab3c..20dc9ea1a6 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 c6c819ea0a..1f78ea2d86 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];