aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorYork Sun2018-01-29 10:24:08 -0800
committerYork Sun2018-01-30 09:14:07 -0800
commit564e9383e53b567114bd3403246c0759a6d69c50 (patch)
tree2350bb47536eac77f3cd4c9f3f866abc345f5516 /drivers
parentc0c32af0b2f037e3e167c7ac82e7110ebae48fb5 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ddr/fsl/ctrl_regs.c30
-rw-r--r--drivers/ddr/fsl/ddr4_dimm_params.c21
-rw-r--r--drivers/ddr/fsl/options.c4
3 files changed, 48 insertions, 7 deletions
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index bcab9046adc..8b8727116da 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 1f1d9b897a4..5c8fc8804d4 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 5158ea20899..85ec48c28e3 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);