/*
- * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008, 2010-2014 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
unsigned int odt_rtt_wr;
};
-#ifdef CONFIG_SYS_FSL_DDR3
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
static const struct dynamic_odt single_Q[4] = {
{ /* cs0 */
FSL_DDR_ODT_NEVER,
DDR3_RTT_OFF
}
};
-#else /* CONFIG_SYS_FSL_DDR3 */
+#else /* CONFIG_SYS_FSL_DDR3 || CONFIG_SYS_FSL_DDR4 */
static const struct dynamic_odt single_Q[4] = {
{0, 0, 0, 0},
{0, 0, 0, 0},
unsigned int i;
char buffer[HWCONFIG_BUFFER_SIZE];
char *buf = NULL;
-#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2)
+#if defined(CONFIG_SYS_FSL_DDR3) || \
+ defined(CONFIG_SYS_FSL_DDR2) || \
+ defined(CONFIG_SYS_FSL_DDR4)
const struct dynamic_odt *pdodt = odt_unknown;
#endif
ulong ddr_freq;
if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
buf = buffer;
-#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2)
+#if defined(CONFIG_SYS_FSL_DDR3) || \
+ defined(CONFIG_SYS_FSL_DDR2) || \
+ defined(CONFIG_SYS_FSL_DDR4)
/* Chip select options. */
- if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
- switch (pdimm[0].n_ranks) {
- case 1:
- pdodt = single_S;
- break;
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+ switch (pdimm[0].n_ranks) {
+ case 1:
+ pdodt = single_S;
+ break;
+ case 2:
+ pdodt = single_D;
+ break;
+ case 4:
+ pdodt = single_Q;
+ break;
+ }
+#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+ switch (pdimm[0].n_ranks) {
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ case 4:
+ pdodt = single_Q;
+ if (pdimm[1].n_ranks)
+ printf("Error: Quad- and Dual-rank DIMMs cannot be used together\n");
+ break;
+#endif
+ case 2:
+ switch (pdimm[1].n_ranks) {
case 2:
- pdodt = single_D;
+ pdodt = dual_DD;
break;
- case 4:
- pdodt = single_Q;
+ case 1:
+ pdodt = dual_DS;
break;
- }
- } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
- switch (pdimm[0].n_ranks) {
-#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
- case 4:
- pdodt = single_Q;
- if (pdimm[1].n_ranks)
- printf("Error: Quad- and Dual-rank DIMMs "
- "cannot be used together\n");
+ case 0:
+ pdodt = dual_D0;
break;
-#endif
+ }
+ break;
+ case 1:
+ switch (pdimm[1].n_ranks) {
case 2:
- switch (pdimm[1].n_ranks) {
- case 2:
- pdodt = dual_DD;
- break;
- case 1:
- pdodt = dual_DS;
- break;
- case 0:
- pdodt = dual_D0;
- break;
- }
+ pdodt = dual_SD;
break;
case 1:
- switch (pdimm[1].n_ranks) {
- case 2:
- pdodt = dual_SD;
- break;
- case 1:
- pdodt = dual_SS;
- break;
- case 0:
- pdodt = dual_S0;
- break;
- }
+ pdodt = dual_SS;
break;
case 0:
- switch (pdimm[1].n_ranks) {
- case 2:
- pdodt = dual_0D;
- break;
- case 1:
- pdodt = dual_0S;
- break;
- }
+ pdodt = dual_S0;
break;
}
+ break;
+ case 0:
+ switch (pdimm[1].n_ranks) {
+ case 2:
+ pdodt = dual_0D;
+ break;
+ case 1:
+ pdodt = dual_0S;
+ break;
+ }
+ break;
}
-#endif
+#endif /* CONFIG_DIMM_SLOTS_PER_CTLR */
+#endif /* CONFIG_SYS_FSL_DDR2, 3, 4 */
/* Pick chip-select local options. */
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2)
+#if defined(CONFIG_SYS_FSL_DDR3) || \
+ defined(CONFIG_SYS_FSL_DDR2) || \
+ defined(CONFIG_SYS_FSL_DDR4)
popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0;
/* Choose burst length. */
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
#if defined(CONFIG_E500MC)
popts->otf_burst_chop_en = 0; /* on-the-fly burst chop disable */
popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */
#endif
/* Choose ddr controller address mirror mode */
-#if defined(CONFIG_SYS_FSL_DDR3)
- popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+ for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+ if (pdimm[i].n_ranks) {
+ popts->mirrored_dimm = pdimm[i].mirrored_dimm;
+ break;
+ }
+ }
#endif
/* Global Timing Parameters. */
- debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
+ debug("mclk_ps = %u ps\n", get_memory_clk_period_ps(ctrl_num));
/* Pick a caslat override. */
popts->cas_latency_override = 0;
* BSTTOPRE precharge interval
*
* Set this to 0 for global auto precharge
- *
- * FIXME: Should this be configured in picoseconds?
- * Why it should be in ps: better understanding of this
- * relative to actual DRAM timing parameters such as tRAS.
- * e.g. tRAS(min) = 40 ns
+ * The value of 0x100 has been used for DDR1, DDR2, DDR3.
+ * It is not wrong. Any value should be OK. The performance depends on
+ * applications. There is no one good value for all.
*/
popts->bstopre = 0x100;
- /* Minimum CKE pulse width -- tCKE(MIN) */
- popts->tcke_clock_pulse_width_ps
- = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
-
/*
* Window for four activates -- tFAW
*
* FIXME: width, was considering looking at pdimm->primary_sdram_width
*/
#if defined(CONFIG_SYS_FSL_DDR1)
- popts->tfaw_window_four_activates_ps = mclk_to_picos(1);
+ popts->tfaw_window_four_activates_ps = mclk_to_picos(ctrl_num, 1);
#elif defined(CONFIG_SYS_FSL_DDR2)
/*
*/
popts->tfaw_window_four_activates_ps = 37500;
-#elif defined(CONFIG_SYS_FSL_DDR3)
+#else
popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps;
#endif
popts->zq_en = 0;
popts->wrlvl_en = 0;
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
/*
* due to ddr3 dimm is fly-by topology
* we suggest to enable write leveling to
popts->memctl_interleaving_mode = FSL_DDR_256B_INTERLEAVING;
popts->memctl_interleaving = 1;
debug("256 Byte interleaving\n");
- goto done;
-#endif
+#else
/*
* test null first. if CONFIG_HWCONFIG is not defined
* hwconfig_arg_cmp returns non-zero
popts->memctl_interleaving = 0;
printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
}
+#endif /* CONFIG_SYS_FSL_DDR_INTLV_256B */
done:
-#endif
+#endif /* CONFIG_NUM_DDR_CONTROLLERS > 1 */
if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
/* test null first. if CONFIG_HWCONFIG is not defined,
if (pdimm[0].n_ranks == 4)
popts->quad_rank_present = 1;
- ddr_freq = get_ddr_freq(0) / 1000000;
+ ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
if (popts->registered_dimm_en) {
popts->rcw_override = 1;
popts->rcw_1 = 0x000a5a00;
unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
unsigned long long check_rank_density;
struct dimm_params_s *dimm;
+ int first_ctrl = pinfo->first_ctrl;
+ int last_ctrl = first_ctrl + pinfo->num_ctrls - 1;
+
/*
* Check if all controllers are configured for memory
* controller interleaving. Identical dimms are recommended. At least
* the size, row and col address should be checked.
*/
j = 0;
- check_n_ranks = pinfo->dimm_params[0][0].n_ranks;
- check_rank_density = pinfo->dimm_params[0][0].rank_density;
- check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr;
- check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr;
- check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode;
- for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ check_n_ranks = pinfo->dimm_params[first_ctrl][0].n_ranks;
+ check_rank_density = pinfo->dimm_params[first_ctrl][0].rank_density;
+ check_n_row_addr = pinfo->dimm_params[first_ctrl][0].n_row_addr;
+ check_n_col_addr = pinfo->dimm_params[first_ctrl][0].n_col_addr;
+ check_intlv = pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode;
+ for (i = first_ctrl; i <= last_ctrl; i++) {
dimm = &pinfo->dimm_params[i][0];
if (!pinfo->memctl_opts[i].memctl_interleaving) {
continue;
}
if (intlv_invalid) {
- for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
+ for (i = first_ctrl; i <= last_ctrl; i++)
pinfo->memctl_opts[i].memctl_interleaving = 0;
printf("Not all DIMMs are identical. "
"Memory controller interleaving disabled.\n");
case FSL_DDR_PAGE_INTERLEAVING:
case FSL_DDR_BANK_INTERLEAVING:
case FSL_DDR_SUPERBANK_INTERLEAVING:
- if (3 == CONFIG_NUM_DDR_CONTROLLERS)
+#if (3 == CONFIG_NUM_DDR_CONTROLLERS)
k = 2;
- else
+#else
k = CONFIG_NUM_DDR_CONTROLLERS;
+#endif
break;
case FSL_DDR_3WAY_1KB_INTERLEAVING:
case FSL_DDR_3WAY_4KB_INTERLEAVING:
}
debug("%d of %d controllers are interleaving.\n", j, k);
if (j && (j != k)) {
- for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
+ for (i = first_ctrl; i <= last_ctrl; i++)
pinfo->memctl_opts[i].memctl_interleaving = 0;
- printf("Not all controllers have compatible "
- "interleaving mode. All disabled.\n");
+ if ((last_ctrl - first_ctrl) > 1)
+ puts("Not all controllers have compatible interleaving mode. All disabled.\n");
}
}
debug("Checking interleaving options completed\n");