summaryrefslogtreecommitdiff
path: root/drivers/ddr
diff options
context:
space:
mode:
authorYork Sun <yorksun@freescale.com>2014-03-27 17:54:47 -0700
committerYork Sun <yorksun@freescale.com>2014-04-22 17:58:48 -0700
commit34e026f9b1eb3bcffb38e7787c2e6eac0e88ba85 (patch)
treef155ebdbac95a5ef637e7796ad22935029a56ce6 /drivers/ddr
parent8d451a7129ee6820cc126c77f0f0a175a2cb2e8d (diff)
downloadu-boot-imx-34e026f9b1eb3bcffb38e7787c2e6eac0e88ba85.zip
u-boot-imx-34e026f9b1eb3bcffb38e7787c2e6eac0e88ba85.tar.gz
u-boot-imx-34e026f9b1eb3bcffb38e7787c2e6eac0e88ba85.tar.bz2
driver/ddr/fsl: Add DDR4 support to Freescale DDR driver
Mostly reusing DDR3 driver, this patch adds DDR4 SPD handling, register calculation and programming. Signed-off-by: York Sun <yorksun@freescale.com>
Diffstat (limited to 'drivers/ddr')
-rw-r--r--drivers/ddr/fsl/Makefile19
-rw-r--r--drivers/ddr/fsl/ctrl_regs.c739
-rw-r--r--drivers/ddr/fsl/ddr4_dimm_params.c300
-rw-r--r--drivers/ddr/fsl/fsl_ddr_gen4.c234
-rw-r--r--drivers/ddr/fsl/interactive.c391
-rw-r--r--drivers/ddr/fsl/lc_common_dimm_params.c407
-rw-r--r--drivers/ddr/fsl/main.c25
-rw-r--r--drivers/ddr/fsl/options.c34
-rw-r--r--drivers/ddr/fsl/util.c26
9 files changed, 1906 insertions, 269 deletions
diff --git a/drivers/ddr/fsl/Makefile b/drivers/ddr/fsl/Makefile
index 265204f..df66c07 100644
--- a/drivers/ddr/fsl/Makefile
+++ b/drivers/ddr/fsl/Makefile
@@ -1,19 +1,20 @@
#
-# Copyright 2008-2011 Freescale Semiconductor, Inc.
+# Copyright 2008-2014 Freescale Semiconductor, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# Version 2 as published by the Free Software Foundation.
#
-obj-$(CONFIG_SYS_FSL_DDR1) += main.o util.o ctrl_regs.o options.o \
- lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR1) += main.o util.o ctrl_regs.o options.o \
+ lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR2) += main.o util.o ctrl_regs.o options.o \
+ lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR3) += main.o util.o ctrl_regs.o options.o \
+ lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR4) += main.o util.o ctrl_regs.o options.o \
+ lc_common_dimm_params.o
-obj-$(CONFIG_SYS_FSL_DDR2) += main.o util.o ctrl_regs.o options.o \
- lc_common_dimm_params.o
-
-obj-$(CONFIG_SYS_FSL_DDR3) += main.o util.o ctrl_regs.o options.o \
- lc_common_dimm_params.o
ifdef CONFIG_DDR_SPD
SPD := y
endif
@@ -24,6 +25,7 @@ ifdef SPD
obj-$(CONFIG_SYS_FSL_DDR1) += ddr1_dimm_params.o
obj-$(CONFIG_SYS_FSL_DDR2) += ddr2_dimm_params.o
obj-$(CONFIG_SYS_FSL_DDR3) += ddr3_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR4) += ddr4_dimm_params.o
endif
obj-$(CONFIG_FSL_DDR_INTERACTIVE) += interactive.o
@@ -32,3 +34,4 @@ obj-$(CONFIG_SYS_FSL_DDRC_GEN2) += mpc85xx_ddr_gen2.o
obj-$(CONFIG_SYS_FSL_DDRC_GEN3) += mpc85xx_ddr_gen3.o
obj-$(CONFIG_SYS_FSL_DDR_86XX) += mpc86xx_ddr.o
obj-$(CONFIG_SYS_FSL_DDRC_ARM_GEN3) += arm_ddr_gen3.o
+obj-$(CONFIG_SYS_FSL_DDRC_GEN4) += fsl_ddr_gen4.o
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 0882932..d01eea0 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -17,20 +17,6 @@
#include <fsl_immap.h>
#include <asm/io.h>
-#define _DDR_ADDR CONFIG_SYS_FSL_DDR_ADDR
-
-static u32 fsl_ddr_get_version(void)
-{
- struct ccsr_ddr __iomem *ddr;
- u32 ver_major_minor_errata;
-
- ddr = (void *)_DDR_ADDR;
- ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
- ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
-
- return ver_major_minor_errata;
-}
-
unsigned int picos_to_mclk(unsigned int picos);
/*
@@ -81,6 +67,39 @@ static inline int fsl_ddr_get_rtt(void)
return rtt;
}
+#ifdef CONFIG_SYS_FSL_DDR4
+/*
+ * compute CAS write latency according to DDR4 spec
+ * CWL = 9 for <= 1600MT/s
+ * 10 for <= 1866MT/s
+ * 11 for <= 2133MT/s
+ * 12 for <= 2400MT/s
+ * 14 for <= 2667MT/s
+ * 16 for <= 2933MT/s
+ * 18 for higher
+ */
+static inline unsigned int compute_cas_write_latency(void)
+{
+ unsigned int cwl;
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+ if (mclk_ps >= 1250)
+ cwl = 9;
+ else if (mclk_ps >= 1070)
+ cwl = 10;
+ else if (mclk_ps >= 935)
+ cwl = 11;
+ else if (mclk_ps >= 833)
+ cwl = 12;
+ else if (mclk_ps >= 750)
+ cwl = 14;
+ else if (mclk_ps >= 681)
+ cwl = 16;
+ else
+ cwl = 18;
+
+ return cwl;
+}
+#else
/*
* compute the CAS write latency according to DDR3 spec
* CWL = 5 if tCK >= 2.5ns
@@ -119,6 +138,7 @@ static inline unsigned int compute_cas_write_latency(void)
}
return cwl;
}
+#endif
/* Chip Select Configuration (CSn_CONFIG) */
static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
@@ -135,6 +155,11 @@ static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
int go_config = 0;
+#ifdef CONFIG_SYS_FSL_DDR4
+ unsigned int bg_bits_cs_n = 0; /* Num of bank group bits */
+#else
+ unsigned int n_banks_per_sdram_device;
+#endif
/* Compute CS_CONFIG only for existing ranks of each DIMM. */
switch (i) {
@@ -178,14 +203,18 @@ static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
break;
}
if (go_config) {
- unsigned int n_banks_per_sdram_device;
cs_n_en = 1;
ap_n_en = popts->cs_local_opts[i].auto_precharge;
odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
+#ifdef CONFIG_SYS_FSL_DDR4
+ ba_bits_cs_n = dimm_params[dimm_number].bank_addr_bits;
+ bg_bits_cs_n = dimm_params[dimm_number].bank_group_bits;
+#else
n_banks_per_sdram_device
= dimm_params[dimm_number].n_banks_per_sdram_device;
ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
+#endif
row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12;
col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8;
}
@@ -203,6 +232,9 @@ static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
| ((ba_bits_cs_n & 0x3) << 14)
| ((row_bits_cs_n & 0x7) << 8)
+#ifdef CONFIG_SYS_FSL_DDR4
+ | ((bg_bits_cs_n & 0x3) << 4)
+#endif
| ((col_bits_cs_n & 0x7) << 0)
);
debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
@@ -262,11 +294,23 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
/* Precharge powerdown exit timing (tXP). */
unsigned char pre_pd_exit_mclk;
/* ODT powerdown exit timing (tAXPD). */
- unsigned char taxpd_mclk;
+ unsigned char taxpd_mclk = 0;
/* Mode register set cycle time (tMRD). */
unsigned char tmrd_mclk;
-#ifdef CONFIG_SYS_FSL_DDR3
+#ifdef CONFIG_SYS_FSL_DDR4
+ /* tXP=max(4nCK, 6ns) */
+ int txp = max((get_memory_clk_period_ps() * 4), 6000); /* unit=ps */
+ trwt_mclk = 2;
+ twrt_mclk = 1;
+ act_pd_exit_mclk = picos_to_mclk(txp);
+ pre_pd_exit_mclk = act_pd_exit_mclk;
+ /*
+ * MRS_CYC = max(tMRD, tMOD)
+ * tMRD = 8nCK, tMOD = max(24nCK, 15ns)
+ */
+ tmrd_mclk = max(24, picos_to_mclk(15000));
+#elif defined(CONFIG_SYS_FSL_DDR3)
/*
* (tXARD and tXARDS). Empirical?
* The DDR3 spec has not tXARD,
@@ -275,7 +319,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
* spec has not the tAXPD, we use
* tAXPD=1, need design to confirm.
*/
- int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */
+ int txp = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */
unsigned int data_rate = get_ddr_freq(0);
tmrd_mclk = 4;
/* set the turnaround time */
@@ -300,7 +344,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
taxpd_mclk = 1;
} else {
/* act_pd_exit_mclk = tXARD, see above */
- act_pd_exit_mclk = picos_to_mclk(tXP);
+ act_pd_exit_mclk = picos_to_mclk(txp);
/* Mode register MR0[A12] is '1' - fast exit */
pre_pd_exit_mclk = act_pd_exit_mclk;
taxpd_mclk = 1;
@@ -364,8 +408,12 @@ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr,
ext_acttorw = picos_to_mclk(common_dimm->trcd_ps) >> 4;
ext_caslat = (2 * cas_latency - 1) >> 4;
ext_add_lat = additive_latency >> 4;
+#ifdef CONFIG_SYS_FSL_DDR4
+ ext_refrec = (picos_to_mclk(common_dimm->trfc1_ps) - 8) >> 4;
+#else
ext_refrec = (picos_to_mclk(common_dimm->trfc_ps) - 8) >> 4;
/* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
+#endif
ext_wrrec = (picos_to_mclk(common_dimm->twr_ps) +
(popts->otf_burst_chop_en ? 2 : 0)) >> 4;
@@ -404,9 +452,19 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
unsigned char acttoact_mclk;
/* Last write data pair to read command issue interval (tWTR) */
unsigned char wrtord_mclk;
+#ifdef CONFIG_SYS_FSL_DDR4
+ /* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */
+ static const u8 wrrec_table[] = {
+ 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10,
+ 12, 12, 14, 14, 16,
+ 16, 18, 18, 20, 20,
+ 24, 24, 24, 24};
+#else
/* DDR_SDRAM_MODE doesn't support 9,11,13,15 */
static const u8 wrrec_table[] = {
1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0};
+#endif
pretoact_mclk = picos_to_mclk(common_dimm->trp_ps);
acttopre_mclk = picos_to_mclk(common_dimm->tras_ps);
@@ -438,20 +496,34 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
* we need set extend bit for it at
* TIMING_CFG_3[EXT_CASLAT]
*/
- caslat_ctrl = 2 * cas_latency - 1;
+ if (fsl_ddr_get_version() <= 0x40400)
+ caslat_ctrl = 2 * cas_latency - 1;
+ else
+ caslat_ctrl = (cas_latency - 1) << 1;
#endif
+#ifdef CONFIG_SYS_FSL_DDR4
+ refrec_ctrl = picos_to_mclk(common_dimm->trfc1_ps) - 8;
+ wrrec_mclk = picos_to_mclk(common_dimm->twr_ps);
+ acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4);
+ wrtord_mclk = max(2, picos_to_mclk(2500));
+ if (wrrec_mclk > 24)
+ printf("Error: WRREC doesn't support more than 24 clocks\n");
+ else
+ wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+#else
refrec_ctrl = picos_to_mclk(common_dimm->trfc_ps) - 8;
wrrec_mclk = picos_to_mclk(common_dimm->twr_ps);
-
+ acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps);
+ wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps);
if (wrrec_mclk > 16)
printf("Error: WRREC doesn't support more than 16 clocks\n");
else
wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+#endif
if (popts->otf_burst_chop_en)
wrrec_mclk += 2;
- acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps);
/*
* JEDEC has min requirement for tRRD
*/
@@ -459,7 +531,6 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
if (acttoact_mclk < 4)
acttoact_mclk = 4;
#endif
- wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps);
/*
* JEDEC has some min requirements for tWTR
*/
@@ -526,14 +597,18 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
wr_lat = compute_cas_write_latency();
#endif
+#ifdef CONFIG_SYS_FSL_DDR4
+ rd_to_pre = picos_to_mclk(7500);
+#else
rd_to_pre = picos_to_mclk(common_dimm->trtp_ps);
+#endif
/*
* JEDEC has some min requirements for tRTP
*/
#if defined(CONFIG_SYS_FSL_DDR2)
if (rd_to_pre < 2)
rd_to_pre = 2;
-#elif defined(CONFIG_SYS_FSL_DDR3)
+#elif defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
if (rd_to_pre < 4)
rd_to_pre = 4;
#endif
@@ -541,13 +616,20 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
rd_to_pre += 2; /* according to UM */
wr_data_delay = popts->write_data_delay;
+#ifdef CONFIG_SYS_FSL_DDR4
+ cpo = 0;
+ cke_pls = max(3, picos_to_mclk(5000));
+#else
cke_pls = picos_to_mclk(popts->tcke_clock_pulse_width_ps);
+#endif
+
four_act = picos_to_mclk(popts->tfaw_window_four_activates_ps);
ddr->timing_cfg_2 = (0
| ((add_lat_mclk & 0xf) << 28)
| ((cpo & 0x1f) << 23)
| ((wr_lat & 0xf) << 19)
+ | ((wr_lat & 0x10) << 14)
| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
| ((cke_pls & 0x7) << 6)
@@ -640,7 +722,8 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
* we must clear it when use the on-the-fly mode,
* must set it when use the 32-bits bus mode.
*/
- if (sdram_type == SDRAM_TYPE_DDR3) {
+ if ((sdram_type == SDRAM_TYPE_DDR3) ||
+ (sdram_type == SDRAM_TYPE_DDR4)) {
if (popts->burst_length == DDR_BL8)
eight_be = 1;
if (popts->burst_length == DDR_OTF)
@@ -682,8 +765,6 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
{
unsigned int frc_sr = 0; /* Force self refresh */
unsigned int sr_ie = 0; /* Self-refresh interrupt enable */
- unsigned int dll_rst_dis; /* DLL reset disable */
- unsigned int dqs_cfg; /* DQS configuration */
unsigned int odt_cfg = 0; /* ODT configuration */
unsigned int num_pr; /* Number of posted refreshes */
unsigned int slow = 0; /* DDR will be run less than 1250 */
@@ -695,9 +776,12 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
unsigned int md_en = 0; /* Mirrored DIMM Enable */
unsigned int qd_en = 0; /* quad-rank DIMM Enable */
int i;
+#ifndef CONFIG_SYS_FSL_DDR4
+ unsigned int dll_rst_dis = 1; /* DLL reset disable */
+ unsigned int dqs_cfg; /* DQS configuration */
- dll_rst_dis = 1; /* Make this configurable */
dqs_cfg = popts->dqs_config;
+#endif
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
if (popts->cs_local_opts[i].odt_rd_cfg
|| popts->cs_local_opts[i].odt_wr_cfg) {
@@ -715,7 +799,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
* * ({EXT_REFREC || REFREC} + 8 + 2)]}
* << DDR_SDRAM_INTERVAL[REFINT]
*/
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
obc_cfg = popts->otf_burst_chop_en;
#else
obc_cfg = 0;
@@ -744,15 +828,17 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
d_init = 0;
#endif
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
md_en = popts->mirrored_dimm;
#endif
qd_en = popts->quad_rank_present ? 1 : 0;
ddr->ddr_sdram_cfg_2 = (0
| ((frc_sr & 0x1) << 31)
| ((sr_ie & 0x1) << 30)
+#ifndef CONFIG_SYS_FSL_DDR4
| ((dll_rst_dis & 0x1) << 29)
| ((dqs_cfg & 0x3) << 26)
+#endif
| ((odt_cfg & 0x3) << 21)
| ((num_pr & 0xf) << 12)
| ((slow & 1) << 11)
@@ -768,6 +854,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);
}
+#ifdef CONFIG_SYS_FSL_DDR4
/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
const memctl_options_t *popts,
@@ -776,8 +863,93 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
{
unsigned short esdmode2 = 0; /* Extended SDRAM mode 2 */
unsigned short esdmode3 = 0; /* Extended SDRAM mode 3 */
+ int i;
+ unsigned int wr_crc = 0; /* Disable */
+ unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */
+ unsigned int srt = 0; /* self-refresh temerature, normal range */
+ unsigned int cwl = compute_cas_write_latency() - 9;
+ unsigned int mpr = 0; /* serial */
+ unsigned int wc_lat;
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
-#if defined(CONFIG_SYS_FSL_DDR3)
+ if (popts->rtt_override)
+ rtt_wr = popts->rtt_wr_override_value;
+ else
+ rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
+
+ if (common_dimm->extended_op_srt)
+ srt = common_dimm->extended_op_srt;
+
+ esdmode2 = (0
+ | ((wr_crc & 0x1) << 12)
+ | ((rtt_wr & 0x3) << 9)
+ | ((srt & 0x3) << 6)
+ | ((cwl & 0x7) << 3));
+
+ if (mclk_ps >= 1250)
+ wc_lat = 0;
+ else if (mclk_ps >= 833)
+ wc_lat = 1;
+ else
+ wc_lat = 2;
+
+ esdmode3 = (0
+ | ((mpr & 0x3) << 11)
+ | ((wc_lat & 0x3) << 9));
+
+ ddr->ddr_sdram_mode_2 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
+
+ if (unq_mrs_en) { /* unique mode registers are supported */
+ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (popts->rtt_override)
+ rtt_wr = popts->rtt_wr_override_value;
+ else
+ rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
+
+ esdmode2 &= 0xF9FF; /* clear bit 10, 9 */
+ esdmode2 |= (rtt_wr & 0x3) << 9;
+ switch (i) {
+ case 1:
+ ddr->ddr_sdram_mode_4 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ break;
+ case 2:
+ ddr->ddr_sdram_mode_6 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ break;
+ case 3:
+ ddr->ddr_sdram_mode_8 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ break;
+ }
+ }
+ debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
+ ddr->ddr_sdram_mode_4);
+ debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
+ ddr->ddr_sdram_mode_6);
+ debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
+ ddr->ddr_sdram_mode_8);
+ }
+}
+#elif defined(CONFIG_SYS_FSL_DDR3)
+/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
+static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ const unsigned int unq_mrs_en)
+{
+ unsigned short esdmode2 = 0; /* Extended SDRAM mode 2 */
+ unsigned short esdmode3 = 0; /* Extended SDRAM mode 3 */
int i;
unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */
unsigned int srt = 0; /* self-refresh temerature, normal range */
@@ -799,14 +971,12 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
| ((asr & 0x1) << 6)
| ((cwl & 0x7) << 3)
| ((pasr & 0x7) << 0));
-#endif
ddr->ddr_sdram_mode_2 = (0
| ((esdmode2 & 0xFFFF) << 16)
| ((esdmode3 & 0xFFFF) << 0)
);
debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
-#ifdef CONFIG_SYS_FSL_DDR3
if (unq_mrs_en) { /* unique mode registers are supported */
for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
if (popts->rtt_override)
@@ -844,9 +1014,128 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
ddr->ddr_sdram_mode_8);
}
+}
+
+#else /* for DDR2 and DDR1 */
+/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
+static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ const unsigned int unq_mrs_en)
+{
+ unsigned short esdmode2 = 0; /* Extended SDRAM mode 2 */
+ unsigned short esdmode3 = 0; /* Extended SDRAM mode 3 */
+
+ ddr->ddr_sdram_mode_2 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
+}
#endif
+
+#ifdef CONFIG_SYS_FSL_DDR4
+/* DDR SDRAM Mode configuration 9 (DDR_SDRAM_MODE_9) */
+static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ const unsigned int unq_mrs_en)
+{
+ int i;
+ unsigned short esdmode4 = 0; /* Extended SDRAM mode 4 */
+ unsigned short esdmode5; /* Extended SDRAM mode 5 */
+
+ esdmode5 = 0x00000400; /* Data mask enabled */
+
+ ddr->ddr_sdram_mode_9 = (0
+ | ((esdmode4 & 0xffff) << 16)
+ | ((esdmode5 & 0xffff) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9);
+ if (unq_mrs_en) { /* unique mode registers are supported */
+ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ switch (i) {
+ case 1:
+ ddr->ddr_sdram_mode_11 = (0
+ | ((esdmode4 & 0xFFFF) << 16)
+ | ((esdmode5 & 0xFFFF) << 0)
+ );
+ break;
+ case 2:
+ ddr->ddr_sdram_mode_13 = (0
+ | ((esdmode4 & 0xFFFF) << 16)
+ | ((esdmode5 & 0xFFFF) << 0)
+ );
+ break;
+ case 3:
+ ddr->ddr_sdram_mode_15 = (0
+ | ((esdmode4 & 0xFFFF) << 16)
+ | ((esdmode5 & 0xFFFF) << 0)
+ );
+ break;
+ }
+ }
+ debug("FSLDDR: ddr_sdram_mode_11 = 0x%08x\n",
+ ddr->ddr_sdram_mode_11);
+ debug("FSLDDR: ddr_sdram_mode_13 = 0x%08x\n",
+ ddr->ddr_sdram_mode_13);
+ debug("FSLDDR: ddr_sdram_mode_15 = 0x%08x\n",
+ ddr->ddr_sdram_mode_15);
+ }
+}
+
+/* DDR SDRAM Mode configuration 10 (DDR_SDRAM_MODE_10) */
+static void set_ddr_sdram_mode_10(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ const unsigned int unq_mrs_en)
+{
+ int i;
+ unsigned short esdmode6 = 0; /* Extended SDRAM mode 6 */
+ unsigned short esdmode7 = 0; /* Extended SDRAM mode 7 */
+ unsigned int tccdl_min = picos_to_mclk(common_dimm->tccdl_ps);
+
+ esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
+
+ ddr->ddr_sdram_mode_10 = (0
+ | ((esdmode6 & 0xffff) << 16)
+ | ((esdmode7 & 0xffff) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_mode_10) = 0x%08x\n", ddr->ddr_sdram_mode_10);
+ if (unq_mrs_en) { /* unique mode registers are supported */
+ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ switch (i) {
+ case 1:
+ ddr->ddr_sdram_mode_12 = (0
+ | ((esdmode6 & 0xFFFF) << 16)
+ | ((esdmode7 & 0xFFFF) << 0)
+ );
+ break;
+ case 2:
+ ddr->ddr_sdram_mode_14 = (0
+ | ((esdmode6 & 0xFFFF) << 16)
+ | ((esdmode7 & 0xFFFF) << 0)
+ );
+ break;
+ case 3:
+ ddr->ddr_sdram_mode_16 = (0
+ | ((esdmode6 & 0xFFFF) << 16)
+ | ((esdmode7 & 0xFFFF) << 0)
+ );
+ break;
+ }
+ }
+ debug("FSLDDR: ddr_sdram_mode_12 = 0x%08x\n",
+ ddr->ddr_sdram_mode_12);
+ debug("FSLDDR: ddr_sdram_mode_14 = 0x%08x\n",
+ ddr->ddr_sdram_mode_14);
+ debug("FSLDDR: ddr_sdram_mode_16 = 0x%08x\n",
+ ddr->ddr_sdram_mode_16);
+ }
}
+#endif
+
/* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
const memctl_options_t *popts,
@@ -867,7 +1156,7 @@ static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
}
-#if defined(CONFIG_SYS_FSL_DDR3)
+#ifdef CONFIG_SYS_FSL_DDR4
/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
const memctl_options_t *popts,
@@ -876,6 +1165,177 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
unsigned int additive_latency,
const unsigned int unq_mrs_en)
{
+ int i;
+ unsigned short esdmode; /* Extended SDRAM mode */
+ unsigned short sdmode; /* SDRAM mode */
+
+ /* Mode Register - MR1 */
+ unsigned int qoff = 0; /* Output buffer enable 0=yes, 1=no */
+ unsigned int tdqs_en = 0; /* TDQS Enable: 0=no, 1=yes */
+ unsigned int rtt;
+ unsigned int wrlvl_en = 0; /* Write level enable: 0=no, 1=yes */
+ unsigned int al = 0; /* Posted CAS# additive latency (AL) */
+ unsigned int dic = 0; /* Output driver impedance, 40ohm */
+ unsigned int dll_en = 1; /* DLL Enable 1=Enable (Normal),
+ 0=Disable (Test/Debug) */
+
+ /* Mode Register - MR0 */
+ unsigned int wr = 0; /* Write Recovery */
+ unsigned int dll_rst; /* DLL Reset */
+ unsigned int mode; /* Normal=0 or Test=1 */
+ unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
+ /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+ unsigned int bt;
+ unsigned int bl; /* BL: Burst Length */
+
+ unsigned int wr_mclk;
+ /* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
+ static const u8 wr_table[] = {
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6};
+ /* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
+ static const u8 cas_latency_table[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
+ 9, 9, 10, 10, 11, 11};
+
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[0].odt_rtt_norm;
+
+ if (additive_latency == (cas_latency - 1))
+ al = 1;
+ if (additive_latency == (cas_latency - 2))
+ al = 2;
+
+ if (popts->quad_rank_present)
+ dic = 1; /* output driver impedance 240/7 ohm */
+
+ /*
+ * The esdmode value will also be used for writing
+ * MR1 during write leveling for DDR3, although the
+ * bits specifically related to the write leveling
+ * scheme will be handled automatically by the DDR
+ * controller. so we set the wrlvl_en = 0 here.
+ */
+ esdmode = (0
+ | ((qoff & 0x1) << 12)
+ | ((tdqs_en & 0x1) << 11)
+ | ((rtt & 0x7) << 8)
+ | ((wrlvl_en & 0x1) << 7)
+ | ((al & 0x3) << 3)
+ | ((dic & 0x3) << 1) /* DIC field is split */
+ | ((dll_en & 0x1) << 0)
+ );
+
+ /*
+ * DLL control for precharge PD
+ * 0=slow exit DLL off (tXPDLL)
+ * 1=fast exit DLL on (tXP)
+ */
+
+ wr_mclk = picos_to_mclk(common_dimm->twr_ps);
+ if (wr_mclk <= 24) {
+ wr = wr_table[wr_mclk - 10];
+ } else {
+ printf("Error: unsupported write recovery for mode register wr_mclk = %d\n",
+ wr_mclk);
+ }
+
+ dll_rst = 0; /* dll no reset */
+ mode = 0; /* normal mode */
+
+ /* look up table to get the cas latency bits */
+ if (cas_latency >= 9 && cas_latency <= 24)
+ caslat = cas_latency_table[cas_latency - 9];
+ else
+ printf("Error: unsupported cas latency for mode register\n");
+
+ bt = 0; /* Nibble sequential */
+
+ switch (popts->burst_length) {
+ case DDR_BL8:
+ bl = 0;
+ break;
+ case DDR_OTF:
+ bl = 1;
+ break;
+ case DDR_BC4:
+ bl = 2;
+ break;
+ default:
+ printf("Error: invalid burst length of %u specified. ",
+ popts->burst_length);
+ puts("Defaulting to on-the-fly BC4 or BL8 beats.\n");
+ bl = 1;
+ break;
+ }
+
+ sdmode = (0
+ | ((wr & 0x7) << 9)
+ | ((dll_rst & 0x1) << 8)
+ | ((mode & 0x1) << 7)
+ | (((caslat >> 1) & 0x7) << 4)
+ | ((bt & 0x1) << 3)
+ | ((caslat & 1) << 2)
+ | ((bl & 0x3) << 0)
+ );
+
+ ddr->ddr_sdram_mode = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+
+ debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+
+ if (unq_mrs_en) { /* unique mode registers are supported */
+ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[i].odt_rtt_norm;
+
+ esdmode &= 0xF8FF; /* clear bit 10,9,8 for rtt */
+ esdmode |= (rtt & 0x7) << 8;
+ switch (i) {
+ case 1:
+ ddr->ddr_sdram_mode_3 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ case 2:
+ ddr->ddr_sdram_mode_5 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ case 3:
+ ddr->ddr_sdram_mode_7 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ }
+ }
+ debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
+ ddr->ddr_sdram_mode_3);
+ debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+ ddr->ddr_sdram_mode_5);
+ debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+ ddr->ddr_sdram_mode_5);
+ }
+}
+
+#elif defined(CONFIG_SYS_FSL_DDR3)
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency,
+ unsigned int additive_latency,
+ const unsigned int unq_mrs_en)
+{
+ int i;
unsigned short esdmode; /* Extended SDRAM mode */
unsigned short sdmode; /* SDRAM mode */
@@ -907,9 +1367,6 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
*/
static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
- const unsigned int mclk_ps = get_memory_clk_period_ps();
- int i;
-
if (popts->rtt_override)
rtt = popts->rtt_override_value;
else
@@ -950,7 +1407,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
*/
dll_on = 1;
- wr_mclk = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps;
+ wr_mclk = picos_to_mclk(common_dimm->twr_ps);
if (wr_mclk <= 16) {
wr = wr_table[wr_mclk - 5];
} else {
@@ -1109,9 +1566,6 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
unsigned int bt;
unsigned int bl; /* BL: Burst Length */
-#if defined(CONFIG_SYS_FSL_DDR2)
- const unsigned int mclk_ps = get_memory_clk_period_ps();
-#endif
dqs_en = !popts->dqs_config;
rtt = fsl_ddr_get_rtt();
@@ -1141,7 +1595,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
#if defined(CONFIG_SYS_FSL_DDR1)
wr = 0; /* Historical */
#elif defined(CONFIG_SYS_FSL_DDR2)
- wr = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps - 1;
+ wr = picos_to_mclk(common_dimm->twr_ps);
#endif
dll_res = 0;
mode = 0;
@@ -1255,7 +1709,7 @@ static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
if (popts->burst_length == DDR_BL8) {
/* We set BL/2 for fixed BL8 */
rrt = 0; /* BL/2 clocks */
@@ -1265,6 +1719,11 @@ static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
rrt = 2; /* BL/2 + 2 clocks */
wwt = 2; /* BL/2 + 2 clocks */
}
+#endif
+
+#ifdef CONFIG_SYS_FSL_DDR4
+ dll_lock = 2; /* tDLLK = 1024 clocks */
+#elif defined(CONFIG_SYS_FSL_DDR3)
dll_lock = 1; /* tDLLK = 512 clocks from spec */
#endif
ddr->timing_cfg_4 = (0
@@ -1285,9 +1744,12 @@ static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
unsigned int wodt_on = 0; /* Write to ODT on */
unsigned int wodt_off = 0; /* Write to ODT off */
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+ unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
+ ((ddr->timing_cfg_2 & 0x00040000) >> 14);
/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
- rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1;
+ if (cas_latency >= wr_lat)
+ rodt_on = cas_latency - wr_lat + 1;
rodt_off = 4; /* 4 clocks */
wodt_on = 1; /* 1 clocks */
wodt_off = 4; /* 4 clocks */
@@ -1302,6 +1764,164 @@ static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
}
+#ifdef CONFIG_SYS_FSL_DDR4
+static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
+{
+ unsigned int hs_caslat = 0;
+ unsigned int hs_wrlat = 0;
+ unsigned int hs_wrrec = 0;
+ unsigned int hs_clkadj = 0;
+ unsigned int hs_wrlvl_start = 0;
+
+ ddr->timing_cfg_6 = (0
+ | ((hs_caslat & 0x1f) << 24)
+ | ((hs_wrlat & 0x1f) << 19)
+ | ((hs_wrrec & 0x1f) << 12)
+ | ((hs_clkadj & 0x1f) << 6)
+ | ((hs_wrlvl_start & 0x1f) << 0)
+ );
+ debug("FSLDDR: timing_cfg_6 = 0x%08x\n", ddr->timing_cfg_6);
+}
+
+static void set_timing_cfg_7(fsl_ddr_cfg_regs_t *ddr,
+ const common_timing_params_t *common_dimm)
+{
+ unsigned int txpr, tcksre, tcksrx;
+ unsigned int cke_rst, cksre, cksrx, par_lat, cs_to_cmd;
+
+ txpr = max(5, picos_to_mclk(common_dimm->trfc1_ps + 10000));
+ tcksre = max(5, picos_to_mclk(10000));
+ tcksrx = max(5, picos_to_mclk(10000));
+ par_lat = 0;
+ cs_to_cmd = 0;
+
+ if (txpr <= 200)
+ cke_rst = 0;
+ else if (txpr <= 256)
+ cke_rst = 1;
+ else if (txpr <= 512)
+ cke_rst = 2;
+ else
+ cke_rst = 3;
+
+ if (tcksre <= 19)
+ cksre = tcksre - 5;
+ else
+ cksre = 15;
+
+ if (tcksrx <= 19)
+ cksrx = tcksrx - 5;
+ else
+ cksrx = 15;
+
+ ddr->timing_cfg_7 = (0
+ | ((cke_rst & 0x3) << 28)
+ | ((cksre & 0xf) << 24)
+ | ((cksrx & 0xf) << 20)
+ | ((par_lat & 0xf) << 16)
+ | ((cs_to_cmd & 0xf) << 4)
+ );
+ debug("FSLDDR: timing_cfg_7 = 0x%08x\n", ddr->timing_cfg_7);
+}
+
+static void set_timing_cfg_8(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency)
+{
+ unsigned int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
+ unsigned int acttoact_bg, wrtord_bg, pre_all_rec;
+ unsigned int tccdl = picos_to_mclk(common_dimm->tccdl_ps);
+ unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
+ ((ddr->timing_cfg_2 & 0x00040000) >> 14);
+
+ rwt_bg = cas_latency + 2 + 4 - wr_lat;
+ if (rwt_bg < tccdl)
+ rwt_bg = tccdl - rwt_bg;
+ else
+ rwt_bg = 0;
+
+ wrt_bg = wr_lat + 4 + 1 - cas_latency;
+ if (wrt_bg < tccdl)
+ wrt_bg = tccdl - wrt_bg;
+ else
+ wrt_bg = 0;
+
+ if (popts->burst_length == DDR_BL8) {
+ rrt_bg = tccdl - 4;
+ wwt_bg = tccdl - 4;
+ } else {
+ rrt_bg = tccdl - 2;
+ wwt_bg = tccdl - 4;
+ }
+
+ acttoact_bg = picos_to_mclk(common_dimm->trrdl_ps);
+ wrtord_bg = max(4, picos_to_mclk(7500));
+ pre_all_rec = 0;
+
+ ddr->timing_cfg_8 = (0
+ | ((rwt_bg & 0xf) << 28)
+ | ((wrt_bg & 0xf) << 24)
+ | ((rrt_bg & 0xf) << 20)
+ | ((wwt_bg & 0xf) << 16)
+ | ((acttoact_bg & 0xf) << 12)
+ | ((wrtord_bg & 0xf) << 8)
+ | ((pre_all_rec & 0x1f) << 0)
+ );
+
+ debug("FSLDDR: timing_cfg_8 = 0x%08x\n", ddr->timing_cfg_8);
+}
+
+static void set_timing_cfg_9(fsl_ddr_cfg_regs_t *ddr)
+{
+ ddr->timing_cfg_9 = 0;
+ debug("FSLDDR: timing_cfg_9 = 0x%08x\n", ddr->timing_cfg_9);
+}
+
+static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
+ const dimm_params_t *dimm_params)
+{
+ ddr->dq_map_0 = ((dimm_params->dq_mapping[0] & 0x3F) << 26) |
+ ((dimm_params->dq_mapping[1] & 0x3F) << 20) |
+ ((dimm_params->dq_mapping[2] & 0x3F) << 14) |
+ ((dimm_params->dq_mapping[3] & 0x3F) << 8) |
+ ((dimm_params->dq_mapping[4] & 0x3F) << 2);
+
+ ddr->dq_map_1 = ((dimm_params->dq_mapping[5] & 0x3F) << 26) |
+ ((dimm_params->dq_mapping[6] & 0x3F) << 20) |
+ ((dimm_params->dq_mapping[7] & 0x3F) << 14) |
+ ((dimm_params->dq_mapping[10] & 0x3F) << 8) |
+ ((dimm_params->dq_mapping[11] & 0x3F) << 2);
+
+ ddr->dq_map_2 = ((dimm_params->dq_mapping[12] & 0x3F) << 26) |
+ ((dimm_params->dq_mapping[13] & 0x3F) << 20) |
+ ((dimm_params->dq_mapping[14] & 0x3F) << 14) |
+ ((dimm_params->dq_mapping[15] & 0x3F) << 8) |
+ ((dimm_params->dq_mapping[16] & 0x3F) << 2);
+
+ ddr->dq_map_3 = ((dimm_params->dq_mapping[17] & 0x3F) << 26) |
+ ((dimm_params->dq_mapping[8] & 0x3F) << 20) |
+ ((dimm_params->dq_mapping[9] & 0x3F) << 14) |
+ dimm_params->dq_mapping_ors;
+
+ debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0);
+ debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1);
+ debug("FSLDDR: dq_map_2 = 0x%08x\n", ddr->dq_map_2);
+ debug("FSLDDR: dq_map_3 = 0x%08x\n", ddr->dq_map_3);
+}
+static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts)
+{
+ int rd_pre;
+
+ rd_pre = popts->quad_rank_present ? 1 : 0;
+
+ ddr->ddr_sdram_cfg_3 = (rd_pre & 0x1) << 16;
+
+ debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3);
+}
+#endif /* CONFIG_SYS_FSL_DDR4 */
+
/* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
{
@@ -1310,11 +1930,21 @@ static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
unsigned int zqoper = 0;
/* Normal Operation Short Calibration Time (tZQCS) */
unsigned int zqcs = 0;
+#ifdef CONFIG_SYS_FSL_DDR4
+ unsigned int zqcs_init;
+#endif
if (zq_en) {
+#ifdef CONFIG_SYS_FSL_DDR4
+ zqinit = 10; /* 1024 clocks */
+ zqoper = 9; /* 512 clocks */
+ zqcs = 7; /* 128 clocks */
+ zqcs_init = 5; /* 1024 refresh sequences */
+#else
zqinit = 9; /* 512 clocks */
zqoper = 8; /* 256 clocks */
zqcs = 6; /* 64 clocks */
+#endif
}
ddr->ddr_zq_cntl = (0
@@ -1322,6 +1952,9 @@ static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
| ((zqinit & 0xF) << 24)
| ((zqoper & 0xF) << 16)
| ((zqcs & 0xF) << 8)
+#ifdef CONFIG_SYS_FSL_DDR4
+ | ((zqcs_init & 0xF) << 0)
+#endif
);
debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl);
}
@@ -1478,7 +2111,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
*/
cas_latency = (popts->cas_latency_override)
? popts->cas_latency_override_value
- : common_dimm->lowest_common_SPD_caslat;
+ : common_dimm->lowest_common_spd_caslat;
additive_latency = (popts->additive_latency_override)
? popts->additive_latency_override_value
@@ -1639,6 +2272,10 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
set_ddr_sdram_mode(ddr, popts, common_dimm,
cas_latency, additive_latency, unq_mrs_en);
set_ddr_sdram_mode_2(ddr, popts, common_dimm, unq_mrs_en);
+#ifdef CONFIG_SYS_FSL_DDR4
+ set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en);
+ set_ddr_sdram_mode_10(ddr, popts, common_dimm, unq_mrs_en);
+#endif
set_ddr_sdram_interval(ddr, popts, common_dimm);
set_ddr_data_init(ddr);
set_ddr_sdram_clk_cntl(ddr, popts);
@@ -1646,6 +2283,14 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
set_ddr_init_ext_addr(ddr);
set_timing_cfg_4(ddr, popts);
set_timing_cfg_5(ddr, cas_latency);
+#ifdef CONFIG_SYS_FSL_DDR4
+ set_ddr_sdram_cfg_3(ddr, popts);
+ set_timing_cfg_6(ddr);
+ set_timing_cfg_7(ddr, common_dimm);
+ set_timing_cfg_8(ddr, popts, common_dimm, cas_latency);
+ set_timing_cfg_9(ddr);
+ set_ddr_dq_mapping(ddr, dimm_params);
+#endif
set_ddr_zq_cntl(ddr, zq_en);
set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c
new file mode 100644
index 0000000..4745b7f
--- /dev/null
+++ b/drivers/ddr/fsl/ddr4_dimm_params.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * calculate the organization and timing parameter
+ * from ddr3 spd, please refer to the spec
+ * JEDEC standard No.21-C 4_01_02_12R23A.pdf
+ *
+ *
+ */
+
+#include <common.h>
+#include <fsl_ddr_sdram.h>
+
+#include <fsl_ddr.h>
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Total DIMM size =
+ * sdram capacity(bit) / 8 * primary bus width / sdram width
+ * * Logical Ranks per DIMM
+ *
+ * where: sdram capacity = spd byte4[3:0]
+ * primary bus width = spd byte13[2:0]
+ * sdram width = spd byte12[2:0]
+ * Logical Ranks per DIMM = spd byte12[5:3] for SDP, DDP, QDP
+ * spd byte12{5:3] * spd byte6[6:4] for 3DS
+ *
+ * To simplify each rank size = total DIMM size / Number of Package Ranks
+ * where Number of Package Ranks = spd byte12[5:3]
+ *
+ * SPD byte4 - sdram density and banks
+ * bit[3:0] size(bit) size(byte)
+ * 0000 256Mb 32MB
+ * 0001 512Mb 64MB
+ * 0010 1Gb 128MB
+ * 0011 2Gb 256MB
+ * 0100 4Gb 512MB
+ * 0101 8Gb 1GB
+ * 0110 16Gb 2GB
+ * 0111 32Gb 4GB
+ *
+ * SPD byte13 - module memory bus width
+ * bit[2:0] primary bus width
+ * 000 8bits
+ * 001 16bits
+ * 010 32bits
+ * 011 64bits
+ *
+ * SPD byte12 - module organization
+ * bit[2:0] sdram device width
+ * 000 4bits
+ * 001 8bits
+ * 010 16bits
+ * 011 32bits
+ *
+ * SPD byte12 - module organization
+ * bit[5:3] number of package ranks per DIMM
+ * 000 1
+ * 001 2
+ * 010 3
+ * 011 4
+ *
+ * SPD byte6 - SDRAM package type
+ * bit[6:4] Die count
+ * 000 1
+ * 001 2
+ * 010 3
+ * 011 4
+ * 100 5
+ * 101 6
+ * 110 7
+ * 111 8
+ *
+ * SPD byte6 - SRAM package type
+ * bit[1:0] Signal loading
+ * 00 Not specified
+ * 01 Multi load stack
+ * 10 Sigle load stack (3DS)
+ * 11 Reserved
+ */
+static unsigned long long
+compute_ranksize(const struct ddr4_spd_eeprom_s *spd)
+{
+ unsigned long long bsize;
+
+ int nbit_sdram_cap_bsize = 0;
+ int nbit_primary_bus_width = 0;
+ int nbit_sdram_width = 0;
+ int die_count = 0;
+ bool package_3ds;
+
+ if ((spd->density_banks & 0xf) <= 7)
+ nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+ if ((spd->bus_width & 0x7) < 4)
+ nbit_primary_bus_width = (spd->bus_width & 0x7) + 3;
+ if ((spd->organization & 0x7) < 4)
+ nbit_sdram_width = (spd->organization & 0x7) + 2;
+ package_3ds = (spd->package_type & 0x3) == 0x2;
+ if (package_3ds)
+ die_count = (spd->package_type >> 4) & 0x7;
+
+ bsize = 1ULL << (nbit_sdram_cap_bsize - 3 +
+ nbit_primary_bus_width - nbit_sdram_width +
+ die_count);
+
+ debug("DDR: DDR III rank density = 0x%16llx\n", bsize);
+
+ return bsize;
+}
+
+#define spd_to_ps(mtb, ftb) \
+ (mtb * pdimm->mtb_ps + (ftb * pdimm->ftb_10th_ps) / 10)
+/*
+ * ddr_compute_dimm_parameters for DDR3 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ */
+unsigned int
+ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd,
+ dimm_params_t *pdimm,
+ unsigned int dimm_number)
+{
+ unsigned int retval;
+ int i;
+
+ if (spd->mem_type) {
+ if (spd->mem_type != SPD_MEMTYPE_DDR4) {
+ printf("DIMM %u: is not a DDR4 SPD.\n", dimm_number);
+ return 1;
+ }
+ } else {
+ memset(pdimm, 0, sizeof(dimm_params_t));
+ return 1;
+ }
+
+ retval = ddr4_spd_check(spd);
+ if (retval) {
+ printf("DIMM %u: failed checksum\n", dimm_number);
+ return 2;
+ }
+
+ /*
+ * The part name in ASCII in the SPD EEPROM is not null terminated.
+ * Guarantee null termination here by presetting all bytes to 0
+ * and copying the part name in ASCII from the SPD onto it
+ */
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ if ((spd->info_size_crc & 0xF) > 2)
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+ pdimm->rank_density = compute_ranksize(spd);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+ if ((spd->bus_width >> 3) & 0x3)
+ pdimm->ec_sdram_width = 8;
+ else
+ pdimm->ec_sdram_width = 0;
+ pdimm->data_width = pdimm->primary_sdram_width
+ + pdimm->ec_sdram_width;
+ pdimm->device_width = 1 << ((spd->organization & 0x7) + 2);
+
+ /* These are the types defined by the JEDEC DDR3 SPD spec */
+ pdimm->mirrored_dimm = 0;
+ pdimm->registered_dimm = 0;
+ switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) {
+ case DDR3_SPD_MODULETYPE_RDIMM:
+ /* Registered/buffered DIMMs */
+ pdimm->registered_dimm = 1;
+ break;
+
+ case DDR3_SPD_MODULETYPE_UDIMM:
+ case DDR3_SPD_MODULETYPE_SO_DIMM:
+ /* Unbuffered DIMMs */
+ if (spd->mod_section.unbuffered.addr_mapping & 0x1)
+ pdimm->mirrored_dimm = 1;
+ break;
+
+ default:
+ printf("unknown module_type 0x%02X\n", spd->module_type);
+ return 1;
+ }
+
+ /* SDRAM device parameters */
+ pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+ pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+ pdimm->bank_addr_bits = (spd->density_banks >> 4) & 0x3;
+ pdimm->bank_group_bits = (spd->density_banks >> 6) & 0x3;
+
+ /*
+ * The SPD spec has not the ECC bit,
+ * We consider the DIMM as ECC capability
+ * when the extension bus exist
+ */
+ if (pdimm->ec_sdram_width)
+ pdimm->edc_config = 0x02;
+ else
+ pdimm->edc_config = 0x00;
+
+ /*
+ * The SPD spec has not the burst length byte
+ * but DDR4 spec has nature BL8 and BC4,
+ * BL8 -bit3, BC4 -bit2
+ */
+ pdimm->burst_lengths_bitmask = 0x0c;
+ pdimm->row_density = __ilog2(pdimm->rank_density);
+
+ /* MTB - medium timebase
+ * The MTB in the SPD spec is 125ps,
+ *
+ * FTB - fine timebase
+ * use 1/10th of ps as our unit to avoid floating point
+ * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps
+ */
+ if ((spd->timebases & 0xf) == 0x0) {
+ pdimm->mtb_ps = 125;
+ pdimm->ftb_10th_ps = 10;
+
+ } else {
+ printf("Unknown Timebases\n");
+ }
+
+ /* sdram minimum cycle time */
+ pdimm->tckmin_x_ps = spd_to_ps(spd->tck_min, spd->fine_tck_min);
+
+ /* sdram max cycle time */
+ pdimm->tckmax_ps = spd_to_ps(spd->tck_max, spd->fine_tck_max);
+
+ /*
+ * CAS latency supported
+ * bit0 - CL7
+ * bit4 - CL11
+ * bit8 - CL15
+ * bit12- CL19
+ * bit16- CL23
+ */
+ pdimm->caslat_x = (spd->caslat_b1 << 7) |
+ (spd->caslat_b2 << 15) |
+ (spd->caslat_b3 << 23);
+
+ BUG_ON(spd->caslat_b4 != 0);
+
+ /*
+ * min CAS latency time
+ */
+ pdimm->taa_ps = spd_to_ps(spd->taa_min, spd->fine_taa_min);
+
+ /*
+ * min RAS to CAS delay time
+ */
+ pdimm->trcd_ps = spd_to_ps(spd->trcd_min, spd->fine_trcd_min);
+
+ /*
+ * Min Row Precharge Delay Time
+ */
+ pdimm->trp_ps = spd_to_ps(spd->trp_min, spd->fine_trp_min);
+
+ /* min active to precharge delay time */
+ pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) +
+ spd->tras_min_lsb) * pdimm->mtb_ps;
+
+ /* min active to actice/refresh delay time */
+ pdimm->trc_ps = spd_to_ps((((spd->tras_trc_ext & 0xf0) << 4) +
+ spd->trc_min_lsb), spd->fine_trc_min);
+ /* Min Refresh Recovery Delay Time */
+ pdimm->trfc1_ps = ((spd->trfc1_min_msb << 8) | (spd->trfc1_min_lsb)) *
+ pdimm->mtb_ps;
+ pdimm->trfc2_ps = ((spd->trfc2_min_msb << 8) | (spd->trfc2_min_lsb)) *
+ pdimm->mtb_ps;
+ pdimm->trfc4_ps = ((spd->trfc4_min_msb << 8) | (spd->trfc4_min_lsb)) *
+ pdimm->mtb_ps;
+ /* min four active window delay time */
+ pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) *
+ pdimm->mtb_ps;
+
+ /* min row active to row active delay time, different bank group */
+ pdimm->trrds_ps = spd_to_ps(spd->trrds_min, spd->fine_trrds_min);
+ /* min row active to row active delay time, same bank group */
+ pdimm->trrdl_ps = spd_to_ps(spd->trrdl_min, spd->fine_trrdl_min);
+ /* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */
+ pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min);
+
+ /*
+ * Average periodic refresh interval
+ * tREFI = 7.8 us at normal temperature range
+ */
+ pdimm->refresh_rate_ps = 7800000;
+
+ for (i = 0; i < 18; i++)
+ pdimm->dq_mapping[i] = spd->mapping[i];
+
+ pdimm->dq_mapping_ors = ((spd->mapping[0] >> 6) & 0x3) == 0 ? 1 : 0;
+
+ return 0;
+}
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
new file mode 100644
index 0000000..7cd878a
--- /dev/null
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <fsl_ddr_sdram.h>
+#include <asm/processor.h>
+#include <fsl_ddr.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+/*
+ * regs has the to-be-set values for DDR controller registers
+ * ctrl_num is the DDR controller number
+ * step: 0 goes through the initialization in one pass
+ * 1 sets registers and returns before enabling controller
+ * 2 resumes from step 1 and continues to initialize
+ * Dividing the initialization to two steps to deassert DDR reset signal
+ * to comply with JEDEC specs for RDIMMs.
+ */
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num, int step)
+{
+ unsigned int i, bus_width;
+ struct ccsr_ddr __iomem *ddr;
+ u32 temp_sdram_cfg;
+ u32 total_gb_size_per_controller;
+ int timeout;
+
+ switch (ctrl_num) {
+ case 0:
+ ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
+ break;
+#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
+ case 1:
+ ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+ case 2:
+ ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+ case 3:
+ ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR;
+ break;
+#endif
+ default:
+ printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num);
+ return;
+ }
+
+ if (step == 2)
+ goto step2;
+
+ if (regs->ddr_eor)
+ ddr_out32(&ddr->eor, regs->ddr_eor);
+
+ ddr_out32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ ddr_out32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ ddr_out32(&ddr->cs0_config, regs->cs[i].config);
+ ddr_out32(&ddr->cs0_config_2, regs->cs[i].config_2);
+
+ } else if (i == 1) {
+ ddr_out32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ ddr_out32(&ddr->cs1_config, regs->cs[i].config);
+ ddr_out32(&ddr->cs1_config_2, regs->cs[i].config_2);
+
+ } else if (i == 2) {
+ ddr_out32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ ddr_out32(&ddr->cs2_config, regs->cs[i].config);
+ ddr_out32(&ddr->cs2_config_2, regs->cs[i].config_2);
+
+ } else if (i == 3) {
+ ddr_out32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ ddr_out32(&ddr->cs3_config, regs->cs[i].config);
+ ddr_out32(&ddr->cs3_config_2, regs->cs[i].config_2);
+ }
+ }
+
+ ddr_out32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+ ddr_out32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+ ddr_out32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ ddr_out32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg_4);
+ ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg_5);
+ ddr_out32(&ddr->timing_cfg_6, regs->timing_cfg_6);
+ ddr_out32(&ddr->timing_cfg_7, regs->timing_cfg_7);
+ ddr_out32(&ddr->timing_cfg_8, regs->timing_cfg_8);
+ ddr_out32(&ddr->timing_cfg_9, regs->timing_cfg_9);
+ ddr_out32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
+ ddr_out32(&ddr->dq_map_0, regs->dq_map_0);
+ ddr_out32(&ddr->dq_map_1, regs->dq_map_1);
+ ddr_out32(&ddr->dq_map_2, regs->dq_map_2);
+ ddr_out32(&ddr->dq_map_3, regs->dq_map_3);
+ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ ddr_out32(&ddr->sdram_cfg_3, regs->ddr_sdram_cfg_3);
+ ddr_out32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ ddr_out32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+ ddr_out32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
+ ddr_out32(&ddr->sdram_mode_4, regs->ddr_sdram_mode_4);
+ ddr_out32(&ddr->sdram_mode_5, regs->ddr_sdram_mode_5);
+ ddr_out32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6);
+ ddr_out32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7);
+ ddr_out32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8);
+ ddr_out32(&ddr->sdram_mode_9, regs->ddr_sdram_mode_9);
+ ddr_out32(&ddr->sdram_mode_10, regs->ddr_sdram_mode_10);
+ ddr_out32(&ddr->sdram_mode_11, regs->ddr_sdram_mode_11);
+ ddr_out32(&ddr->sdram_mode_12, regs->ddr_sdram_mode_12);
+ ddr_out32(&ddr->sdram_mode_13, regs->ddr_sdram_mode_13);
+ ddr_out32(&ddr->sdram_mode_14, regs->ddr_sdram_mode_14);
+ ddr_out32(&ddr->sdram_mode_15, regs->ddr_sdram_mode_15);
+ ddr_out32(&ddr->sdram_mode_16, regs->ddr_sdram_mode_16);
+ ddr_out32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
+ ddr_out32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+ ddr_out32(&ddr->sdram_data_init, regs->ddr_data_init);
+ ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
+ ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+ ddr_out32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
+#ifndef CONFIG_SYS_FSL_DDR_EMU
+ /*
+ * Skip these two registers if running on emulator
+ * because emulator doesn't have skew between bytes.
+ */
+
+ if (regs->ddr_wrlvl_cntl_2)
+ ddr_out32(&ddr->ddr_wrlvl_cntl_2, regs->ddr_wrlvl_cntl_2);
+ if (regs->ddr_wrlvl_cntl_3)
+ ddr_out32(&ddr->ddr_wrlvl_cntl_3, regs->ddr_wrlvl_cntl_3);
+#endif
+
+ ddr_out32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr);
+ ddr_out32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
+ ddr_out32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
+ ddr_out32(&ddr->ddr_sdram_rcw_3, regs->ddr_sdram_rcw_3);
+ ddr_out32(&ddr->ddr_sdram_rcw_4, regs->ddr_sdram_rcw_4);
+ ddr_out32(&ddr->ddr_sdram_rcw_5, regs->ddr_sdram_rcw_5);
+ ddr_out32(&ddr->ddr_sdram_rcw_6, regs->ddr_sdram_rcw_6);
+ ddr_out32(&ddr->ddr_cdr1, regs->ddr_cdr1);
+ ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+ ddr_out32(&ddr->err_disable, regs->err_disable);
+ ddr_out32(&ddr->err_int_en, regs->err_int_en);
+ for (i = 0; i < 32; i++) {
+ if (regs->debug[i]) {
+ debug("Write to debug_%d as %08x\n",
+ i+1, regs->debug[i]);
+ ddr_out32(&ddr->debug[i], regs->debug[i]);
+ }
+ }
+
+ /*
+ * For RDIMMs, JEDEC spec requires clocks to be stable before reset is
+ * deasserted. Clocks start when any chip select is enabled and clock
+ * control register is set. Because all DDR components are connected to
+ * one reset signal, this needs to be done in two steps. Step 1 is to
+ * get the clocks started. Step 2 resumes after reset signal is
+ * deasserted.
+ */
+ if (step == 1) {
+ udelay(200);
+ return;
+ }
+
+step2:
+ /* Set, but do not enable the memory */
+ temp_sdram_cfg = regs->ddr_sdram_cfg;
+ temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
+ ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg);
+
+ /*
+ * 500 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ * DDR2 need 200 us, and DDR3 need 500 us from spec,
+ * we choose the max, that is 500 us for all of case.
+ */
+ udelay(500);
+ asm volatile("sync;isync");
+
+ /* Let the controller go */
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
+ ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+ asm volatile("sync;isync");
+
+ total_gb_size_per_controller = 0;
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (!(regs->cs[i].config & 0x80000000))
+ continue;
+ total_gb_size_per_controller += 1 << (
+ ((regs->cs[i].config >> 14) & 0x3) + 2 +
+ ((regs->cs[i].config >> 8) & 0x7) + 12 +
+ ((regs->cs[i].config >> 4) & 0x3) + 0 +
+ ((regs->cs[i].config >> 0) & 0x7) + 8 +
+ 3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) -
+ 26); /* minus 26 (count of 64M) */
+ }
+ if (fsl_ddr_get_intl3r() & 0x80000000) /* 3-way interleaving */
+ total_gb_size_per_controller *= 3;
+ else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */
+ total_gb_size_per_controller <<= 1;
+ /*
+ * total memory / bus width = transactions needed
+ * transactions needed / data rate = seconds
+ * to add plenty of buffer, double the time
+ * For example, 2GB on 666MT/s 64-bit bus takes about 402ms
+ * Let's wait for 800ms
+ */
+ bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK)
+ >> SDRAM_CFG_DBW_SHIFT);
+ timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 /
+ (get_ddr_freq(0) >> 20)) << 2;
+ total_gb_size_per_controller >>= 4; /* shift down to gb size */
+ debug("total %d GB\n", total_gb_size_per_controller);
+ debug("Need to wait up to %d * 10ms\n", timeout);
+
+ /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
+ while ((ddr_in32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) &&
+ (timeout >= 0)) {
+ udelay(10000); /* throttle polling rate */
+ timeout--;
+ }
+
+ if (timeout <= 0)
+ printf("Waiting for D_INIT timeout. Memory may not work.\n");
+
+}
diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c
index ebf3ed6..cfe1e1f 100644
--- a/drivers/ddr/fsl/interactive.c
+++ b/drivers/ddr/fsl/interactive.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2012 Freescale Semiconductor, Inc.
+ * Copyright 2010-2014 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -153,25 +153,38 @@ static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
static const struct options_string options[] = {
COMMON_TIMING(tckmin_x_ps),
COMMON_TIMING(tckmax_ps),
- COMMON_TIMING(tckmax_max_ps),
+ COMMON_TIMING(taamin_ps),
COMMON_TIMING(trcd_ps),
COMMON_TIMING(trp_ps),
COMMON_TIMING(tras_ps),
- COMMON_TIMING(twr_ps),
+
+#ifdef CONFIG_SYS_FSL_DDR4
+ COMMON_TIMING(trfc1_ps),
+ COMMON_TIMING(trfc2_ps),
+ COMMON_TIMING(trfc4_ps),
+ COMMON_TIMING(trrds_ps),
+ COMMON_TIMING(trrdl_ps),
+ COMMON_TIMING(tccdl_ps),
+#else
COMMON_TIMING(twtr_ps),
COMMON_TIMING(trfc_ps),
COMMON_TIMING(trrd_ps),
+ COMMON_TIMING(trtp_ps),
+#endif
+ COMMON_TIMING(twr_ps),
COMMON_TIMING(trc_ps),
COMMON_TIMING(refresh_rate_ps),
+ COMMON_TIMING(extended_op_srt),
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
COMMON_TIMING(tis_ps),
COMMON_TIMING(tih_ps),
COMMON_TIMING(tds_ps),
COMMON_TIMING(tdh_ps),
- COMMON_TIMING(trtp_ps),
COMMON_TIMING(tdqsq_max_ps),
COMMON_TIMING(tqhs_ps),
+#endif
COMMON_TIMING(ndimms_present),
- COMMON_TIMING(lowest_common_SPD_caslat),
+ COMMON_TIMING(lowest_common_spd_caslat),
COMMON_TIMING(highest_common_derated_caslat),
COMMON_TIMING(additive_latency),
COMMON_TIMING(all_dimms_burst_lengths_bitmask),
@@ -211,7 +224,12 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
DIMM_PARM(n_row_addr),
DIMM_PARM(n_col_addr),
DIMM_PARM(edc_config),
+#ifdef CONFIG_SYS_FSL_DDR4
+ DIMM_PARM(bank_addr_bits),
+ DIMM_PARM(bank_group_bits),
+#else
DIMM_PARM(n_banks_per_sdram_device),
+#endif
DIMM_PARM(burst_lengths_bitmask),
DIMM_PARM(row_density),
@@ -229,20 +247,32 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
DIMM_PARM(trcd_ps),
DIMM_PARM(trp_ps),
DIMM_PARM(tras_ps),
+#ifdef CONFIG_SYS_FSL_DDR4
+ DIMM_PARM(trfc1_ps),
+ DIMM_PARM(trfc2_ps),
+ DIMM_PARM(trfc4_ps),
+ DIMM_PARM(trrds_ps),
+ DIMM_PARM(trrdl_ps),
+ DIMM_PARM(tccdl_ps),
+#else
DIMM_PARM(twr_ps),
DIMM_PARM(twtr_ps),
DIMM_PARM(trfc_ps),
DIMM_PARM(trrd_ps),
+ DIMM_PARM(trtp_ps),
+#endif
DIMM_PARM(trc_ps),
DIMM_PARM(refresh_rate_ps),
+ DIMM_PARM(extended_op_srt),
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
DIMM_PARM(tis_ps),
DIMM_PARM(tih_ps),
DIMM_PARM(tds_ps),
DIMM_PARM(tdh_ps),
- DIMM_PARM(trtp_ps),
DIMM_PARM(tdqsq_max_ps),
DIMM_PARM(tqhs_ps),
+#endif
DIMM_PARM(rank_density),
DIMM_PARM(capacity),
@@ -270,7 +300,12 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
DIMM_PARM(n_row_addr),
DIMM_PARM(n_col_addr),
DIMM_PARM(edc_config),
+#ifdef CONFIG_SYS_FSL_DDR4
+ DIMM_PARM(bank_addr_bits),
+ DIMM_PARM(bank_group_bits),
+#else
DIMM_PARM(n_banks_per_sdram_device),
+#endif
DIMM_PARM(tckmin_x_ps),
DIMM_PARM(tckmin_x_minus_1_ps),
@@ -286,20 +321,31 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
DIMM_PARM(trcd_ps),
DIMM_PARM(trp_ps),
DIMM_PARM(tras_ps),
+#ifdef CONFIG_SYS_FSL_DDR4
+ DIMM_PARM(trfc1_ps),
+ DIMM_PARM(trfc2_ps),
+ DIMM_PARM(trfc4_ps),
+ DIMM_PARM(trrds_ps),
+ DIMM_PARM(trrdl_ps),
+ DIMM_PARM(tccdl_ps),
+#else
DIMM_PARM(twr_ps),
DIMM_PARM(twtr_ps),
DIMM_PARM(trfc_ps),
DIMM_PARM(trrd_ps),
+ DIMM_PARM(trtp_ps),
+#endif
DIMM_PARM(trc_ps),
DIMM_PARM(refresh_rate_ps),
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
DIMM_PARM(tis_ps),
DIMM_PARM(tih_ps),
DIMM_PARM(tds_ps),
DIMM_PARM(tdh_ps),
- DIMM_PARM(trtp_ps),
DIMM_PARM(tdqsq_max_ps),
DIMM_PARM(tqhs_ps),
+#endif
};
static const unsigned int n_opts = ARRAY_SIZE(options);
@@ -326,23 +372,36 @@ static void print_lowest_common_dimm_parameters(
const common_timing_params_t *plcd_dimm_params)
{
static const struct options_string options[] = {
- COMMON_TIMING(tckmax_max_ps),
+ COMMON_TIMING(taamin_ps),
COMMON_TIMING(trcd_ps),
COMMON_TIMING(trp_ps),
COMMON_TIMING(tras_ps),
- COMMON_TIMING(twr_ps),
+#ifdef CONFIG_SYS_FSL_DDR4
+ COMMON_TIMING(trfc1_ps),
+ COMMON_TIMING(trfc2_ps),
+ COMMON_TIMING(trfc4_ps),
+ COMMON_TIMING(trrds_ps),
+ COMMON_TIMING(trrdl_ps),
+ COMMON_TIMING(tccdl_ps),
+#else
COMMON_TIMING(twtr_ps),
COMMON_TIMING(trfc_ps),
COMMON_TIMING(trrd_ps),
+ COMMON_TIMING(trtp_ps),
+#endif
+ COMMON_TIMING(twr_ps),
COMMON_TIMING(trc_ps),
COMMON_TIMING(refresh_rate_ps),
+ COMMON_TIMING(extended_op_srt),
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
COMMON_TIMING(tis_ps),
+ COMMON_TIMING(tih_ps),
COMMON_TIMING(tds_ps),
COMMON_TIMING(tdh_ps),
- COMMON_TIMING(trtp_ps),
COMMON_TIMING(tdqsq_max_ps),
COMMON_TIMING(tqhs_ps),
- COMMON_TIMING(lowest_common_SPD_caslat),
+#endif
+ COMMON_TIMING(lowest_common_spd_caslat),
COMMON_TIMING(highest_common_derated_caslat),
COMMON_TIMING(additive_latency),
COMMON_TIMING(ndimms_present),
@@ -460,6 +519,9 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
CTRL_OPTIONS(tfaw_window_four_activates_ps),
CTRL_OPTIONS(trwt_override),
CTRL_OPTIONS(trwt),
+ CTRL_OPTIONS(rtt_override),
+ CTRL_OPTIONS(rtt_override_value),
+ CTRL_OPTIONS(rtt_wr_override_value),
};
static const unsigned int n_opts = ARRAY_SIZE(options);
@@ -505,6 +567,7 @@ static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
CFG_REGS(timing_cfg_2),
CFG_REGS(ddr_sdram_cfg),
CFG_REGS(ddr_sdram_cfg_2),
+ CFG_REGS(ddr_sdram_cfg_3),
CFG_REGS(ddr_sdram_mode),
CFG_REGS(ddr_sdram_mode_2),
CFG_REGS(ddr_sdram_mode_3),
@@ -513,6 +576,16 @@ static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
CFG_REGS(ddr_sdram_mode_6),
CFG_REGS(ddr_sdram_mode_7),
CFG_REGS(ddr_sdram_mode_8),
+#ifdef CONFIG_SYS_FSL_DDR4
+ CFG_REGS(ddr_sdram_mode_9),
+ CFG_REGS(ddr_sdram_mode_10),
+ CFG_REGS(ddr_sdram_mode_11),
+ CFG_REGS(ddr_sdram_mode_12),
+ CFG_REGS(ddr_sdram_mode_13),
+ CFG_REGS(ddr_sdram_mode_14),
+ CFG_REGS(ddr_sdram_mode_15),
+ CFG_REGS(ddr_sdram_mode_16),
+#endif
CFG_REGS(ddr_sdram_interval),
CFG_REGS(ddr_data_init),
CFG_REGS(ddr_sdram_clk_cntl),
@@ -520,6 +593,12 @@ static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
CFG_REGS(ddr_init_ext_addr),
CFG_REGS(timing_cfg_4),
CFG_REGS(timing_cfg_5),
+#ifdef CONFIG_SYS_FSL_DDR4
+ CFG_REGS(timing_cfg_6),
+ CFG_REGS(timing_cfg_7),
+ CFG_REGS(timing_cfg_8),
+ CFG_REGS(timing_cfg_9),
+#endif
CFG_REGS(ddr_zq_cntl),
CFG_REGS(ddr_wrlvl_cntl),
CFG_REGS(ddr_wrlvl_cntl_2),
@@ -529,6 +608,10 @@ static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
CFG_REGS(ddr_sdram_rcw_2),
CFG_REGS(ddr_cdr1),
CFG_REGS(ddr_cdr2),
+ CFG_REGS(dq_map_0),
+ CFG_REGS(dq_map_1),
+ CFG_REGS(dq_map_2),
+ CFG_REGS(dq_map_3),
CFG_REGS(err_disable),
CFG_REGS(err_int_en),
CFG_REGS(ddr_eor),
@@ -574,6 +657,7 @@ static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
CFG_REGS(timing_cfg_2),
CFG_REGS(ddr_sdram_cfg),
CFG_REGS(ddr_sdram_cfg_2),
+ CFG_REGS(ddr_sdram_cfg_3),
CFG_REGS(ddr_sdram_mode),
CFG_REGS(ddr_sdram_mode_2),
CFG_REGS(ddr_sdram_mode_3),
@@ -582,6 +666,16 @@ static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
CFG_REGS(ddr_sdram_mode_6),
CFG_REGS(ddr_sdram_mode_7),
CFG_REGS(ddr_sdram_mode_8),
+#ifdef CONFIG_SYS_FSL_DDR4
+ CFG_REGS(ddr_sdram_mode_9),
+ CFG_REGS(ddr_sdram_mode_10),
+ CFG_REGS(ddr_sdram_mode_11),
+ CFG_REGS(ddr_sdram_mode_12),
+ CFG_REGS(ddr_sdram_mode_13),
+ CFG_REGS(ddr_sdram_mode_14),
+ CFG_REGS(ddr_sdram_mode_15),
+ CFG_REGS(ddr_sdram_mode_16),
+#endif
CFG_REGS(ddr_sdram_interval),
CFG_REGS(ddr_data_init),
CFG_REGS(ddr_sdram_clk_cntl),
@@ -589,6 +683,12 @@ static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
CFG_REGS(ddr_init_ext_addr),
CFG_REGS(timing_cfg_4),
CFG_REGS(timing_cfg_5),
+#ifdef CONFIG_SYS_FSL_DDR4
+ CFG_REGS(timing_cfg_6),
+ CFG_REGS(timing_cfg_7),
+ CFG_REGS(timing_cfg_8),
+ CFG_REGS(timing_cfg_9),
+#endif
CFG_REGS(ddr_zq_cntl),
CFG_REGS(ddr_wrlvl_cntl),
CFG_REGS(ddr_wrlvl_cntl_2),
@@ -598,6 +698,10 @@ static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
CFG_REGS(ddr_sdram_rcw_2),
CFG_REGS(ddr_cdr1),
CFG_REGS(ddr_cdr2),
+ CFG_REGS(dq_map_0),
+ CFG_REGS(dq_map_1),
+ CFG_REGS(dq_map_2),
+ CFG_REGS(dq_map_3),
CFG_REGS(err_disable),
CFG_REGS(err_int_en),
CFG_REGS(ddr_sdram_rcw_2),
@@ -705,6 +809,9 @@ static void print_memctl_options(const memctl_options_t *popts)
CTRL_OPTIONS(tfaw_window_four_activates_ps),
CTRL_OPTIONS(trwt_override),
CTRL_OPTIONS(trwt),
+ CTRL_OPTIONS(rtt_override),
+ CTRL_OPTIONS(rtt_override_value),
+ CTRL_OPTIONS(rtt_wr_override_value),
};
static const unsigned int n_opts = ARRAY_SIZE(options);
@@ -1245,6 +1352,266 @@ void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd)
}
#endif
+#ifdef CONFIG_SYS_FSL_DDR4
+void ddr4_spd_dump(const struct ddr4_spd_eeprom_s *spd)
+{
+ unsigned int i;
+
+ /* General Section: Bytes 0-127 */
+
+#define PRINT_NXS(x, y, z...) printf("%-3d : %02x " z "\n", x, (u8)y);
+#define PRINT_NNXXS(n0, n1, x0, x1, s) \
+ printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1);
+
+ PRINT_NXS(0, spd->info_size_crc,
+ "info_size_crc bytes written into serial memory, CRC coverage");
+ PRINT_NXS(1, spd->spd_rev,
+ "spd_rev SPD Revision");
+ PRINT_NXS(2, spd->mem_type,
+ "mem_type Key Byte / DRAM Device Type");
+ PRINT_NXS(3, spd->module_type,
+ "module_type Key Byte / Module Type");
+ PRINT_NXS(4, spd->density_banks,
+ "density_banks SDRAM Density and Banks");
+ PRINT_NXS(5, spd->addressing,
+ "addressing SDRAM Addressing");
+ PRINT_NXS(6, spd->package_type,
+ "package_type Package type");
+ PRINT_NXS(7, spd->opt_feature,
+ "opt_feature Optional features");
+ PRINT_NXS(8, spd->thermal_ref,
+ "thermal_ref Thermal and Refresh options");
+ PRINT_NXS(9, spd->oth_opt_features,
+ "oth_opt_features Other SDRAM optional features");
+ PRINT_NXS(10, spd->res_10,
+ "res_10 Reserved");
+ PRINT_NXS(11, spd->module_vdd,
+ "module_vdd Module Nominal Voltage, VDD");
+ PRINT_NXS(12, spd->organization,
+ "organization Module Organization");
+ PRINT_NXS(13, spd->bus_width,
+ "bus_width Module Memory Bus Width");
+ PRINT_NXS(14, spd->therm_sensor,
+ "therm_sensor Module Thermal Sensor");
+ PRINT_NXS(15, spd->ext_type,
+ "ext_type Extended module type");
+ PRINT_NXS(16, spd->res_16,
+ "res_16 Reserved");
+ PRINT_NXS(17, spd->timebases,
+ "timebases MTb and FTB");
+ PRINT_NXS(18, spd->tck_min,
+ "tck_min tCKAVGmin");
+ PRINT_NXS(19, spd->tck_max,
+ "tck_max TCKAVGmax");
+ PRINT_NXS(20, spd->caslat_b1,
+ "caslat_b1 CAS latencies, 1st byte");
+ PRINT_NXS(21, spd->caslat_b2,
+ "caslat_b2 CAS latencies, 2nd byte");
+ PRINT_NXS(22, spd->caslat_b3,
+ "caslat_b3 CAS latencies, 3rd byte ");
+ PRINT_NXS(23, spd->caslat_b4,
+ "caslat_b4 CAS latencies, 4th byte");
+ PRINT_NXS(24, spd->taa_min,
+ "taa_min Min CAS Latency Time");
+ PRINT_NXS(25, spd->trcd_min,
+ "trcd_min Min RAS# to CAS# Delay Time");
+ PRINT_NXS(26, spd->trp_min,
+ "trp_min Min Row Precharge Delay Time");
+ PRINT_NXS(27, spd->tras_trc_ext,
+ "tras_trc_ext Upper Nibbles for tRAS and tRC");
+ PRINT_NXS(28, spd->tras_min_lsb,
+ "tras_min_lsb tRASmin, lsb");
+ PRINT_NXS(29, spd->trc_min_lsb,
+ "trc_min_lsb tRCmin, lsb");
+ PRINT_NXS(30, spd->trfc1_min_lsb,
+ "trfc1_min_lsb Min Refresh Recovery Delay Time, LSB");
+ PRINT_NXS(31, spd->trfc1_min_msb,
+ "trfc1_min_msb Min Refresh Recovery Delay Time, MSB ");
+ PRINT_NXS(32, spd->trfc2_min_lsb,
+ "trfc2_min_lsb Min Refresh Recovery Delay Time, LSB");
+ PRINT_NXS(33, spd->trfc2_min_msb,
+ "trfc2_min_msb Min Refresh Recovery Delay Time, MSB");
+ PRINT_NXS(34, spd->trfc4_min_lsb,
+ "trfc4_min_lsb Min Refresh Recovery Delay Time, LSB");
+ PRINT_NXS(35, spd->trfc4_min_msb,
+ "trfc4_min_msb Min Refresh Recovery Delay Time, MSB");
+ PRINT_NXS(36, spd->tfaw_msb,
+ "tfaw_msb Upper Nibble for tFAW");
+ PRINT_NXS(37, spd->tfaw_min,
+ "tfaw_min tFAW, lsb");
+ PRINT_NXS(38, spd->trrds_min,
+ "trrds_min tRRD_Smin, MTB");
+ PRINT_NXS(39, spd->trrdl_min,
+ "trrdl_min tRRD_Lmin, MTB");
+ PRINT_NXS(40, spd->tccdl_min,
+ "tccdl_min tCCS_Lmin, MTB");
+
+ printf("%-3d-%3d: ", 41, 59); /* Reserved, General Section */
+ for (i = 41; i <= 59; i++)
+ printf("%02x ", spd->res_41[i - 41]);
+
+ puts("\n");
+ printf("%-3d-%3d: ", 60, 77);
+ for (i = 60; i <= 77; i++)
+ printf("%02x ", spd->mapping[i - 60]);
+ puts(" mapping[] Connector to SDRAM bit map\n");
+
+ PRINT_NXS(117, spd->fine_tccdl_min,
+ "fine_tccdl_min Fine offset for tCCD_Lmin");
+ PRINT_NXS(118, spd->fine_trrdl_min,
+ "fine_trrdl_min Fine offset for tRRD_Lmin");
+ PRINT_NXS(119, spd->fine_trrds_min,
+ "fine_trrds_min Fine offset for tRRD_Smin");
+ PRINT_NXS(120, spd->fine_trc_min,
+ "fine_trc_min Fine offset for tRCmin");
+ PRINT_NXS(121, spd->fine_trp_min,
+ "fine_trp_min Fine offset for tRPmin");
+ PRINT_NXS(122, spd->fine_trcd_min,
+ "fine_trcd_min Fine offset for tRCDmin");
+ PRINT_NXS(123, spd->fine_taa_min,
+ "fine_taa_min Fine offset for tAAmin");
+ PRINT_NXS(124, spd->fine_tck_max,
+ "fine_tck_max Fine offset for tCKAVGmax");
+ PRINT_NXS(125, spd->fine_tck_min,
+ "fine_tck_min Fine offset for tCKAVGmin");
+
+ /* CRC: Bytes 126-127 */
+ PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], " SPD CRC");
+
+ switch (spd->module_type) {
+ case 0x02: /* UDIMM */
+ case 0x03: /* SO-DIMM */
+ PRINT_NXS(128, spd->mod_section.unbuffered.mod_height,
+ "mod_height (Unbuffered) Module Nominal Height");
+ PRINT_NXS(129, spd->mod_section.unbuffered.mod_thickness,
+ "mod_thickness (Unbuffered) Module Maximum Thickness");
+ PRINT_NXS(130, spd->mod_section.unbuffered.ref_raw_card,
+ "ref_raw_card (Unbuffered) Reference Raw Card Used");
+ PRINT_NXS(131, spd->mod_section.unbuffered.addr_mapping,
+ "addr_mapping (Unbuffered) Address mapping from Edge Connector to DRAM");
+ PRINT_NNXXS(254, 255, spd->mod_section.unbuffered.crc[0],
+ spd->mod_section.unbuffered.crc[1], " Module CRC");
+ break;
+ case 0x01: /* RDIMM */
+ PRINT_NXS(128, spd->mod_section.registered.mod_height,
+ "mod_height (Registered) Module Nominal Height");
+ PRINT_NXS(129, spd->mod_section.registered.mod_thickness,
+ "mod_thickness (Registered) Module Maximum Thickness");
+ PRINT_NXS(130, spd->mod_section.registered.ref_raw_card,
+ "ref_raw_card (Registered) Reference Raw Card Used");
+ PRINT_NXS(131, spd->mod_section.registered.modu_attr,
+ "modu_attr (Registered) DIMM Module Attributes");
+ PRINT_NXS(132, spd->mod_section.registered.thermal,
+ "thermal (Registered) Thermal Heat Spreader Solution");
+ PRINT_NXS(133, spd->mod_section.registered.reg_id_lo,
+ "reg_id_lo (Registered) Register Manufacturer ID Code, LSB");
+ PRINT_NXS(134, spd->mod_section.registered.reg_id_hi,
+ "reg_id_hi (Registered) Register Manufacturer ID Code, MSB");
+ PRINT_NXS(135, spd->mod_section.registered.reg_rev,
+ "reg_rev (Registered) Register Revision Number");
+ PRINT_NXS(136, spd->mod_section.registered.reg_map,
+ "reg_map (Registered) Address mapping");
+ PRINT_NNXXS(254, 255, spd->mod_section.registered.crc[0],
+ spd->mod_section.registered.crc[1], " Module CRC");
+ break;
+ case 0x04: /* LRDIMM */
+ PRINT_NXS(128, spd->mod_section.loadreduced.mod_height,
+ "mod_height (Loadreduced) Module Nominal Height");
+ PRINT_NXS(129, spd->mod_section.loadreduced.mod_thickness,
+ "mod_thickness (Loadreduced) Module Maximum Thickness");
+ PRINT_NXS(130, spd->mod_section.loadreduced.ref_raw_card,
+ "ref_raw_card (Loadreduced) Reference Raw Card Used");
+ PRINT_NXS(131, spd->mod_section.loadreduced.modu_attr,
+ "modu_attr (Loadreduced) DIMM Module Attributes");
+ PRINT_NXS(132, spd->mod_section.loadreduced.thermal,
+ "thermal (Loadreduced) Thermal Heat Spreader Solution");
+ PRINT_NXS(133, spd->mod_section.loadreduced.reg_id_lo,
+ "reg_id_lo (Loadreduced) Register Manufacturer ID Code, LSB");
+ PRINT_NXS(134, spd->mod_section.loadreduced.reg_id_hi,
+ "reg_id_hi (Loadreduced) Register Manufacturer ID Code, MSB");
+ PRINT_NXS(135, spd->mod_section.loadreduced.reg_rev,
+ "reg_rev (Loadreduced) Register Revision Number");
+ PRINT_NXS(136, spd->mod_section.loadreduced.reg_map,
+ "reg_map (Loadreduced) Address mapping");
+ PRINT_NXS(137, spd->mod_section.loadreduced.reg_drv,
+ "reg_drv (Loadreduced) Reg output drive strength");
+ PRINT_NXS(138, spd->mod_section.loadreduced.reg_drv_ck,
+ "reg_drv_ck (Loadreduced) Reg output drive strength for CK");
+ PRINT_NXS(139, spd->mod_section.loadreduced.data_buf_rev,
+ "data_buf_rev (Loadreduced) Data Buffer Revision Numbe");
+ PRINT_NXS(140, spd->mod_section.loadreduced.vrefqe_r0,
+ "vrefqe_r0 (Loadreduced) DRAM VrefDQ for Package Rank 0");
+ PRINT_NXS(141, spd->mod_section.loadreduced.vrefqe_r1,
+ "vrefqe_r1 (Loadreduced) DRAM VrefDQ for Package Rank 1");
+ PRINT_NXS(142, spd->mod_section.loadreduced.vrefqe_r2,
+ "vrefqe_r2 (Loadreduced) DRAM VrefDQ for Package Rank 2");
+ PRINT_NXS(143, spd->mod_section.loadreduced.vrefqe_r3,
+ "vrefqe_r3 (Loadreduced) DRAM VrefDQ for Package Rank 3");
+ PRINT_NXS(144, spd->mod_section.loadreduced.data_intf,
+ "data_intf (Loadreduced) Data Buffer VrefDQ for DRAM Interface");
+ PRINT_NXS(145, spd->mod_section.loadreduced.data_drv_1866,
+ "data_drv_1866 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
+ PRINT_NXS(146, spd->mod_section.loadreduced.data_drv_2400,
+ "data_drv_2400 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
+ PRINT_NXS(147, spd->mod_section.loadreduced.data_drv_3200,
+ "data_drv_3200 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
+ PRINT_NXS(148, spd->mod_section.loadreduced.dram_drv,
+ "dram_drv (Loadreduced) DRAM Drive Strength");
+ PRINT_NXS(149, spd->mod_section.loadreduced.dram_odt_1866,
+ "dram_odt_1866 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
+ PRINT_NXS(150, spd->mod_section.loadreduced.dram_odt_2400,
+ "dram_odt_2400 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
+ PRINT_NXS(151, spd->mod_section.loadreduced.dram_odt_3200,
+ "dram_odt_3200 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
+ PRINT_NXS(152, spd->mod_section.loadreduced.dram_odt_park_1866,
+ "dram_odt_park_1866 (Loadreduced) DRAM ODT (RTT_PARK)");
+ PRINT_NXS(153, spd->mod_section.loadreduced.dram_odt_park_2400,
+ "dram_odt_park_2400 (Loadreduced) DRAM ODT (RTT_PARK)");
+ PRINT_NXS(154, spd->mod_section.loadreduced.dram_odt_park_3200,
+ "dram_odt_park_3200 (Loadreduced) DRAM ODT (RTT_PARK)");
+ PRINT_NNXXS(254, 255, spd->mod_section.loadreduced.crc[0],
+ spd->mod_section.loadreduced.crc[1],
+ " Module CRC");
+ break;
+ default:
+ /* Module-specific Section, Unsupported Module Type */
+ printf("%-3d-%3d: ", 128, 255);
+
+ for (i = 128; i <= 255; i++)
+ printf("%02x", spd->mod_section.uc[i - 60]);
+
+ break;
+ }
+
+ /* Unique Module ID: Bytes 320-383 */
+ PRINT_NXS(320, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106");
+ PRINT_NXS(321, spd->mmid_msb, "Module MfgID Code MSB - JEP-106");
+ PRINT_NXS(322, spd->mloc, "Mfg Location");
+ PRINT_NNXXS(323, 324, spd->mdate[0], spd->mdate[1], "Mfg Date");
+
+ printf("%-3d-%3d: ", 325, 328);
+
+ for (i = 325; i <= 328; i++)
+ printf("%02x ", spd->sernum[i - 325]);
+ printf(" Module Serial Number\n");
+
+ printf("%-3d-%3d: ", 329, 348);
+ for (i = 329; i <= 348; i++)
+ printf("%02x ", spd->mpart[i - 329]);
+ printf(" Mfg's Module Part Number\n");
+
+ PRINT_NXS(349, spd->mrev, "Module Revision code");
+ PRINT_NXS(350, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106");
+ PRINT_NXS(351, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106");
+ PRINT_NXS(352, spd->stepping, "DRAM stepping");
+
+ printf("%-3d-%3d: ", 353, 381);
+ for (i = 353; i <= 381; i++)
+ printf("%02x ", spd->msd[i - 353]);
+ printf(" Mfg's Specific Data\n");
+}
+#endif
+
static inline void generic_spd_dump(const generic_spd_eeprom_t *spd)
{
#if defined(CONFIG_SYS_FSL_DDR1)
@@ -1253,6 +1620,8 @@ static inline void generic_spd_dump(const generic_spd_eeprom_t *spd)
ddr2_spd_dump(spd);
#elif defined(CONFIG_SYS_FSL_DDR3)
ddr3_spd_dump(spd);
+#elif defined(CONFIG_SYS_FSL_DDR4)
+ ddr4_spd_dump(spd);
#endif
}
diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c
index 610318a..05a24dd 100644
--- a/drivers/ddr/fsl/lc_common_dimm_params.c
+++ b/drivers/ddr/fsl/lc_common_dimm_params.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -11,20 +11,23 @@
#include <fsl_ddr.h>
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
static unsigned int
-compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
- common_timing_params_t *outpdimm,
- unsigned int number_of_dimms)
+compute_cas_latency(const dimm_params_t *dimm_params,
+ common_timing_params_t *outpdimm,
+ unsigned int number_of_dimms)
{
unsigned int i;
- unsigned int taamin_ps = 0;
- unsigned int tckmin_x_ps = 0;
unsigned int common_caslat;
unsigned int caslat_actual;
unsigned int retry = 16;
unsigned int tmp;
const unsigned int mclk_ps = get_memory_clk_period_ps();
+#ifdef CONFIG_SYS_FSL_DDR3
+ const unsigned int taamax = 20000;
+#else
+ const unsigned int taamax = 18000;
+#endif
/* compute the common CAS latency supported between slots */
tmp = dimm_params[0].caslat_x;
@@ -34,19 +37,20 @@ compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
}
common_caslat = tmp;
- /* compute the max tAAmin tCKmin between slots */
- for (i = 0; i < number_of_dimms; i++) {
- taamin_ps = max(taamin_ps, dimm_params[i].taa_ps);
- tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps);
- }
/* validate if the memory clk is in the range of dimms */
- if (mclk_ps < tckmin_x_ps) {
+ if (mclk_ps < outpdimm->tckmin_x_ps) {
printf("DDR clock (MCLK cycle %u ps) is faster than "
"the slowest DIMM(s) (tCKmin %u ps) can support.\n",
- mclk_ps, tckmin_x_ps);
+ mclk_ps, outpdimm->tckmin_x_ps);
+ }
+#ifdef CONFIG_SYS_FSL_DDR4
+ if (mclk_ps > outpdimm->tckmax_ps) {
+ printf("DDR clock (MCLK cycle %u ps) is slower than DIMM(s) (tCKmax %u ps) can support.\n",
+ mclk_ps, outpdimm->tckmax_ps);
}
+#endif
/* determine the acutal cas latency */
- caslat_actual = (taamin_ps + mclk_ps - 1) / mclk_ps;
+ caslat_actual = (outpdimm->taamin_ps + mclk_ps - 1) / mclk_ps;
/* check if the dimms support the CAS latency */
while (!(common_caslat & (1 << caslat_actual)) && retry > 0) {
caslat_actual++;
@@ -54,13 +58,147 @@ compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
}
/* once the caculation of caslat_actual is completed
* we must verify that this CAS latency value does not
- * exceed tAAmax, which is 20 ns for all DDR3 speed grades
+ * exceed tAAmax, which is 20 ns for all DDR3 speed grades,
+ * 18ns for all DDR4 speed grades.
*/
- if (caslat_actual * mclk_ps > 20000) {
+ if (caslat_actual * mclk_ps > taamax) {
printf("The choosen cas latency %d is too large\n",
caslat_actual);
}
- outpdimm->lowest_common_SPD_caslat = caslat_actual;
+ outpdimm->lowest_common_spd_caslat = caslat_actual;
+ debug("lowest_common_spd_caslat is 0x%x\n", caslat_actual);
+
+ return 0;
+}
+#else /* for DDR1 and DDR2 */
+static unsigned int
+compute_cas_latency(const dimm_params_t *dimm_params,
+ common_timing_params_t *outpdimm,
+ unsigned int number_of_dimms)
+{
+ int i;
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+ unsigned int lowest_good_caslat;
+ unsigned int not_ok;
+ unsigned int temp1, temp2;
+
+ debug("using mclk_ps = %u\n", mclk_ps);
+ if (mclk_ps > outpdimm->tckmax_ps) {
+ printf("Warning: DDR clock (%u ps) is slower than DIMM(s) (tCKmax %u ps)\n",
+ mclk_ps, outpdimm->tckmax_ps);
+ }
+
+ /*
+ * Compute a CAS latency suitable for all DIMMs
+ *
+ * Strategy for SPD-defined latencies: compute only
+ * CAS latency defined by all DIMMs.
+ */
+
+ /*
+ * Step 1: find CAS latency common to all DIMMs using bitwise
+ * operation.
+ */
+ temp1 = 0xFF;
+ for (i = 0; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks) {
+ temp2 = 0;
+ temp2 |= 1 << dimm_params[i].caslat_x;
+ temp2 |= 1 << dimm_params[i].caslat_x_minus_1;
+ temp2 |= 1 << dimm_params[i].caslat_x_minus_2;
+ /*
+ * If there was no entry for X-2 (X-1) in
+ * the SPD, then caslat_x_minus_2
+ * (caslat_x_minus_1) contains either 255 or
+ * 0xFFFFFFFF because that's what the glorious
+ * __ilog2 function returns for an input of 0.
+ * On 32-bit PowerPC, left shift counts with bit
+ * 26 set (that the value of 255 or 0xFFFFFFFF
+ * will have), cause the destination register to
+ * be 0. That is why this works.
+ */
+ temp1 &= temp2;
+ }
+ }
+
+ /*
+ * Step 2: check each common CAS latency against tCK of each
+ * DIMM's SPD.
+ */
+ lowest_good_caslat = 0;
+ temp2 = 0;
+ while (temp1) {
+ not_ok = 0;
+ temp2 = __ilog2(temp1);
+ debug("checking common caslat = %u\n", temp2);
+
+ /* Check if this CAS latency will work on all DIMMs at tCK. */
+ for (i = 0; i < number_of_dimms; i++) {
+ if (!dimm_params[i].n_ranks)
+ continue;
+
+ if (dimm_params[i].caslat_x == temp2) {
+ if (mclk_ps >= dimm_params[i].tckmin_x_ps) {
+ debug("CL = %u ok on DIMM %u at tCK=%u ps with tCKmin_X_ps of %u\n",
+ temp2, i, mclk_ps,
+ dimm_params[i].tckmin_x_ps);
+ continue;
+ } else {
+ not_ok++;
+ }
+ }
+
+ if (dimm_params[i].caslat_x_minus_1 == temp2) {
+ unsigned int tckmin_x_minus_1_ps
+ = dimm_params[i].tckmin_x_minus_1_ps;
+ if (mclk_ps >= tckmin_x_minus_1_ps) {
+ debug("CL = %u ok on DIMM %u at tCK=%u ps with tckmin_x_minus_1_ps of %u\n",
+ temp2, i, mclk_ps,
+ tckmin_x_minus_1_ps);
+ continue;
+ } else {
+ not_ok++;
+ }
+ }
+
+ if (dimm_params[i].caslat_x_minus_2 == temp2) {
+ unsigned int tckmin_x_minus_2_ps
+ = dimm_params[i].tckmin_x_minus_2_ps;
+ if (mclk_ps >= tckmin_x_minus_2_ps) {
+ debug("CL = %u ok on DIMM %u at tCK=%u ps with tckmin_x_minus_2_ps of %u\n",
+ temp2, i, mclk_ps,
+ tckmin_x_minus_2_ps);
+ continue;
+ } else {
+ not_ok++;
+ }
+ }
+ }
+
+ if (!not_ok)
+ lowest_good_caslat = temp2;
+
+ temp1 &= ~(1 << temp2);
+ }
+
+ debug("lowest common SPD-defined CAS latency = %u\n",
+ lowest_good_caslat);
+ outpdimm->lowest_common_spd_caslat = lowest_good_caslat;
+
+
+ /*
+ * Compute a common 'de-rated' CAS latency.
+ *
+ * The strategy here is to find the *highest* dereated cas latency
+ * with the assumption that all of the DIMMs will support a dereated
+ * CAS latency higher than or equal to their lowest dereated value.
+ */
+ temp1 = 0;
+ for (i = 0; i < number_of_dimms; i++)
+ temp1 = max(temp1, dimm_params[i].caslat_lowest_derated);
+
+ outpdimm->highest_common_derated_caslat = temp1;
+ debug("highest common dereated CAS latency = %u\n", temp1);
return 0;
}
@@ -82,34 +220,40 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
unsigned int tckmin_x_ps = 0;
unsigned int tckmax_ps = 0xFFFFFFFF;
- unsigned int tckmax_max_ps = 0;
unsigned int trcd_ps = 0;
unsigned int trp_ps = 0;
unsigned int tras_ps = 0;
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+ unsigned int taamin_ps = 0;
+#endif
+#ifdef CONFIG_SYS_FSL_DDR4
+ unsigned int twr_ps = 15000;
+ unsigned int trfc1_ps = 0;
+ unsigned int trfc2_ps = 0;
+ unsigned int trfc4_ps = 0;
+ unsigned int trrds_ps = 0;
+ unsigned int trrdl_ps = 0;
+ unsigned int tccdl_ps = 0;
+#else
unsigned int twr_ps = 0;
unsigned int twtr_ps = 0;
unsigned int trfc_ps = 0;
unsigned int trrd_ps = 0;
+ unsigned int trtp_ps = 0;
+#endif
unsigned int trc_ps = 0;
unsigned int refresh_rate_ps = 0;
unsigned int extended_op_srt = 1;
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
unsigned int tis_ps = 0;
unsigned int tih_ps = 0;
unsigned int tds_ps = 0;
unsigned int tdh_ps = 0;
- unsigned int trtp_ps = 0;
unsigned int tdqsq_max_ps = 0;
unsigned int tqhs_ps = 0;
-
+#endif
unsigned int temp1, temp2;
unsigned int additive_latency = 0;
-#if !defined(CONFIG_SYS_FSL_DDR3)
- const unsigned int mclk_ps = get_memory_clk_period_ps();
- unsigned int lowest_good_caslat;
- unsigned int not_ok;
-
- debug("using mclk_ps = %u\n", mclk_ps);
-#endif
temp1 = 0;
for (i = 0; i < number_of_dimms; i++) {
@@ -146,31 +290,34 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
* i.e., this is the slowest the whole system can go.
*/
tckmax_ps = min(tckmax_ps, dimm_params[i].tckmax_ps);
-
- /* Either find maximum value to determine slowest
- * speed, delay, time, period, etc */
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+ taamin_ps = max(taamin_ps, dimm_params[i].taa_ps);
+#endif
tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps);
- tckmax_max_ps = max(tckmax_max_ps, dimm_params[i].tckmax_ps);
trcd_ps = max(trcd_ps, dimm_params[i].trcd_ps);
trp_ps = max(trp_ps, dimm_params[i].trp_ps);
tras_ps = max(tras_ps, dimm_params[i].tras_ps);
+#ifdef CONFIG_SYS_FSL_DDR4
+ trfc1_ps = max(trfc1_ps, dimm_params[i].trfc1_ps);
+ trfc2_ps = max(trfc2_ps, dimm_params[i].trfc2_ps);
+ trfc4_ps = max(trfc4_ps, dimm_params[i].trfc4_ps);
+ trrds_ps = max(trrds_ps, dimm_params[i].trrds_ps);
+ trrdl_ps = max(trrdl_ps, dimm_params[i].trrdl_ps);
+ tccdl_ps = max(tccdl_ps, dimm_params[i].tccdl_ps);
+#else
twr_ps = max(twr_ps, dimm_params[i].twr_ps);
twtr_ps = max(twtr_ps, dimm_params[i].twtr_ps);
trfc_ps = max(trfc_ps, dimm_params[i].trfc_ps);
trrd_ps = max(trrd_ps, dimm_params[i].trrd_ps);
+ trtp_ps = max(trtp_ps, dimm_params[i].trtp_ps);
+#endif
trc_ps = max(trc_ps, dimm_params[i].trc_ps);
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
tis_ps = max(tis_ps, dimm_params[i].tis_ps);
tih_ps = max(tih_ps, dimm_params[i].tih_ps);
tds_ps = max(tds_ps, dimm_params[i].tds_ps);
tdh_ps = max(tdh_ps, dimm_params[i].tdh_ps);
- trtp_ps = max(trtp_ps, dimm_params[i].trtp_ps);
tqhs_ps = max(tqhs_ps, dimm_params[i].tqhs_ps);
- refresh_rate_ps = max(refresh_rate_ps,
- dimm_params[i].refresh_rate_ps);
- /* extended_op_srt is either 0 or 1, 0 having priority */
- extended_op_srt = min(extended_op_srt,
- dimm_params[i].extended_op_srt);
-
/*
* Find maximum tdqsq_max_ps to find slowest.
*
@@ -178,6 +325,12 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
* strategy for this parameter?
*/
tdqsq_max_ps = max(tdqsq_max_ps, dimm_params[i].tdqsq_max_ps);
+#endif
+ refresh_rate_ps = max(refresh_rate_ps,
+ dimm_params[i].refresh_rate_ps);
+ /* extended_op_srt is either 0 or 1, 0 having priority */
+ extended_op_srt = min(extended_op_srt,
+ dimm_params[i].extended_op_srt);
}
outpdimm->ndimms_present = number_of_dimms - temp1;
@@ -189,24 +342,37 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
outpdimm->tckmin_x_ps = tckmin_x_ps;
outpdimm->tckmax_ps = tckmax_ps;
- outpdimm->tckmax_max_ps = tckmax_max_ps;
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+ outpdimm->taamin_ps = taamin_ps;
+#endif
outpdimm->trcd_ps = trcd_ps;
outpdimm->trp_ps = trp_ps;
outpdimm->tras_ps = tras_ps;
- outpdimm->twr_ps = twr_ps;
+#ifdef CONFIG_SYS_FSL_DDR4
+ outpdimm->trfc1_ps = trfc1_ps;
+ outpdimm->trfc2_ps = trfc2_ps;
+ outpdimm->trfc4_ps = trfc4_ps;
+ outpdimm->trrds_ps = trrds_ps;
+ outpdimm->trrdl_ps = trrdl_ps;
+ outpdimm->tccdl_ps = tccdl_ps;
+#else
outpdimm->twtr_ps = twtr_ps;
outpdimm->trfc_ps = trfc_ps;
outpdimm->trrd_ps = trrd_ps;
+ outpdimm->trtp_ps = trtp_ps;
+#endif
+ outpdimm->twr_ps = twr_ps;
outpdimm->trc_ps = trc_ps;
outpdimm->refresh_rate_ps = refresh_rate_ps;
outpdimm->extended_op_srt = extended_op_srt;
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
outpdimm->tis_ps = tis_ps;
outpdimm->tih_ps = tih_ps;
outpdimm->tds_ps = tds_ps;
outpdimm->tdh_ps = tdh_ps;
- outpdimm->trtp_ps = trtp_ps;
outpdimm->tdqsq_max_ps = tdqsq_max_ps;
outpdimm->tqhs_ps = tqhs_ps;
+#endif
/* Determine common burst length for all DIMMs. */
temp1 = 0xff;
@@ -265,128 +431,9 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
if (temp1 != 0)
printf("ERROR: Mix different RDIMM detected!\n");
-#if defined(CONFIG_SYS_FSL_DDR3)
- if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms))
+ /* calculate cas latency for all DDR types */
+ if (compute_cas_latency(dimm_params, outpdimm, number_of_dimms))
return 1;
-#else
- /*
- * Compute a CAS latency suitable for all DIMMs
- *
- * Strategy for SPD-defined latencies: compute only
- * CAS latency defined by all DIMMs.
- */
-
- /*
- * Step 1: find CAS latency common to all DIMMs using bitwise
- * operation.
- */
- temp1 = 0xFF;
- for (i = 0; i < number_of_dimms; i++) {
- if (dimm_params[i].n_ranks) {
- temp2 = 0;
- temp2 |= 1 << dimm_params[i].caslat_x;
- temp2 |= 1 << dimm_params[i].caslat_x_minus_1;
- temp2 |= 1 << dimm_params[i].caslat_x_minus_2;
- /*
- * FIXME: If there was no entry for X-2 (X-1) in
- * the SPD, then caslat_x_minus_2
- * (caslat_x_minus_1) contains either 255 or
- * 0xFFFFFFFF because that's what the glorious
- * __ilog2 function returns for an input of 0.
- * On 32-bit PowerPC, left shift counts with bit
- * 26 set (that the value of 255 or 0xFFFFFFFF
- * will have), cause the destination register to
- * be 0. That is why this works.
- */
- temp1 &= temp2;
- }
- }
-
- /*
- * Step 2: check each common CAS latency against tCK of each
- * DIMM's SPD.
- */
- lowest_good_caslat = 0;
- temp2 = 0;
- while (temp1) {
- not_ok = 0;
- temp2 = __ilog2(temp1);
- debug("checking common caslat = %u\n", temp2);
-
- /* Check if this CAS latency will work on all DIMMs at tCK. */
- for (i = 0; i < number_of_dimms; i++) {
- if (!dimm_params[i].n_ranks) {
- continue;
- }
- if (dimm_params[i].caslat_x == temp2) {
- if (mclk_ps >= dimm_params[i].tckmin_x_ps) {
- debug("CL = %u ok on DIMM %u at tCK=%u"
- " ps with its tCKmin_X_ps of %u\n",
- temp2, i, mclk_ps,
- dimm_params[i].tckmin_x_ps);
- continue;
- } else {
- not_ok++;
- }
- }
-
- if (dimm_params[i].caslat_x_minus_1 == temp2) {
- unsigned int tckmin_x_minus_1_ps
- = dimm_params[i].tckmin_x_minus_1_ps;
- if (mclk_ps >= tckmin_x_minus_1_ps) {
- debug("CL = %u ok on DIMM %u at "
- "tCK=%u ps with its "
- "tckmin_x_minus_1_ps of %u\n",
- temp2, i, mclk_ps,
- tckmin_x_minus_1_ps);
- continue;
- } else {
- not_ok++;
- }
- }
-
- if (dimm_params[i].caslat_x_minus_2 == temp2) {
- unsigned int tckmin_x_minus_2_ps
- = dimm_params[i].tckmin_x_minus_2_ps;
- if (mclk_ps >= tckmin_x_minus_2_ps) {
- debug("CL = %u ok on DIMM %u at "
- "tCK=%u ps with its "
- "tckmin_x_minus_2_ps of %u\n",
- temp2, i, mclk_ps,
- tckmin_x_minus_2_ps);
- continue;
- } else {
- not_ok++;
- }
- }
- }
-
- if (!not_ok) {
- lowest_good_caslat = temp2;
- }
-
- temp1 &= ~(1 << temp2);
- }
-
- debug("lowest common SPD-defined CAS latency = %u\n",
- lowest_good_caslat);
- outpdimm->lowest_common_SPD_caslat = lowest_good_caslat;
-
-
- /*
- * Compute a common 'de-rated' CAS latency.
- *
- * The strategy here is to find the *highest* dereated cas latency
- * with the assumption that all of the DIMMs will support a dereated
- * CAS latency higher than or equal to their lowest dereated value.
- */
- temp1 = 0;
- for (i = 0; i < number_of_dimms; i++) {
- temp1 = max(temp1, dimm_params[i].caslat_lowest_derated);
- }
- outpdimm->highest_common_derated_caslat = temp1;
- debug("highest common dereated CAS latency = %u\n", temp1);
-#endif /* #if defined(CONFIG_SYS_FSL_DDR3) */
/* Determine if all DIMMs ECC capable. */
temp1 = 1;
@@ -404,14 +451,6 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
}
outpdimm->all_dimms_ecc_capable = temp1;
-#ifndef CONFIG_SYS_FSL_DDR3
- /* FIXME: move to somewhere else to validate. */
- if (mclk_ps > tckmax_max_ps) {
- printf("Warning: some of the installed DIMMs "
- "can not operate this slowly.\n");
- return 1;
- }
-#endif
/*
* Compute additive latency.
*
@@ -468,27 +507,20 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
additive_latency = 0;
#if defined(CONFIG_SYS_FSL_DDR2)
- if (lowest_good_caslat < 4) {
- additive_latency = (picos_to_mclk(trcd_ps) > lowest_good_caslat)
- ? picos_to_mclk(trcd_ps) - lowest_good_caslat : 0;
+ if ((outpdimm->lowest_common_spd_caslat < 4) &&
+ (picos_to_mclk(trcd_ps) > outpdimm->lowest_common_spd_caslat)) {
+ additive_latency = picos_to_mclk(trcd_ps) -
+ outpdimm->lowest_common_spd_caslat;
if (mclk_to_picos(additive_latency) > trcd_ps) {
additive_latency = picos_to_mclk(trcd_ps);
debug("setting additive_latency to %u because it was "
" greater than tRCD_ps\n", additive_latency);
}
}
-
-#elif defined(CONFIG_SYS_FSL_DDR3)
- /*
- * The system will not use the global auto-precharge mode.
- * However, it uses the page mode, so we set AL=0
- */
- additive_latency = 0;
#endif
/*
* Validate additive latency
- * FIXME: move to somewhere else to validate
*
* AL <= tRCD(min)
*/
@@ -516,10 +548,19 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
debug("trcd_ps = %u\n", outpdimm->trcd_ps);
debug("trp_ps = %u\n", outpdimm->trp_ps);
debug("tras_ps = %u\n", outpdimm->tras_ps);
- debug("twr_ps = %u\n", outpdimm->twr_ps);
+#ifdef CONFIG_SYS_FSL_DDR4
+ debug("trfc1_ps = %u\n", trfc1_ps);
+ debug("trfc2_ps = %u\n", trfc2_ps);
+ debug("trfc4_ps = %u\n", trfc4_ps);
+ debug("trrds_ps = %u\n", trrds_ps);
+ debug("trrdl_ps = %u\n", trrdl_ps);
+ debug("tccdl_ps = %u\n", tccdl_ps);
+#else
debug("twtr_ps = %u\n", outpdimm->twtr_ps);
debug("trfc_ps = %u\n", outpdimm->trfc_ps);
debug("trrd_ps = %u\n", outpdimm->trrd_ps);
+#endif
+ debug("twr_ps = %u\n", outpdimm->twr_ps);
debug("trc_ps = %u\n", outpdimm->trc_ps);
return 0;
diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c
index d62ca63..f95704f 100644
--- a/drivers/ddr/fsl/main.c
+++ b/drivers/ddr/fsl/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -81,14 +81,37 @@ u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
#endif
+#define SPD_SPA0_ADDRESS 0x36
+#define SPD_SPA1_ADDRESS 0x37
+
static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
{
int ret;
+#ifdef CONFIG_SYS_FSL_DDR4
+ uint8_t dummy = 0;
+#endif
i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM);
+#ifdef CONFIG_SYS_FSL_DDR4
+ /*
+ * DDR4 SPD has 384 to 512 bytes
+ * To access the lower 256 bytes, we need to set EE page address to 0
+ * To access the upper 256 bytes, we need to set EE page address to 1
+ * See Jedec standar No. 21-C for detail
+ */
+ i2c_write(SPD_SPA0_ADDRESS, 0, 1, &dummy, 1);
+ ret = i2c_read(i2c_address, 0, 1, (uchar *)spd, 256);
+ if (!ret) {
+ i2c_write(SPD_SPA1_ADDRESS, 0, 1, &dummy, 1);
+ ret = i2c_read(i2c_address, 0, 1,
+ (uchar *)((ulong)spd + 256),
+ min(256, sizeof(generic_spd_eeprom_t) - 256));
+ }
+#else
ret = i2c_read(i2c_address, 0, 1, (uchar *)spd,
sizeof(generic_spd_eeprom_t));
+#endif
if (ret) {
if (i2c_address ==
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index b0cf046..bf0d1da 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008, 2010-2014 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -29,7 +29,7 @@ struct dynamic_odt {
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,
@@ -259,7 +259,7 @@ static const struct dynamic_odt odt_unknown[4] = {
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},
@@ -507,7 +507,9 @@ unsigned int populate_memctl_options(int all_dimms_registered,
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;
@@ -519,7 +521,9 @@ unsigned int populate_memctl_options(int all_dimms_registered,
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) {
@@ -585,7 +589,9 @@ unsigned int populate_memctl_options(int all_dimms_registered,
/* 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;
@@ -703,7 +709,7 @@ unsigned int populate_memctl_options(int all_dimms_registered,
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 */
@@ -722,7 +728,7 @@ unsigned int populate_memctl_options(int all_dimms_registered,
#endif
/* Choose ddr controller address mirror mode */
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
popts->mirrored_dimm = pdimm[0].mirrored_dimm;
#endif
@@ -766,11 +772,9 @@ unsigned int populate_memctl_options(int all_dimms_registered,
* 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;
@@ -795,12 +799,12 @@ unsigned int populate_memctl_options(int all_dimms_registered,
*/
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
diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c
index ad53658..7a22aa3 100644
--- a/drivers/ddr/fsl/util.c
+++ b/drivers/ddr/fsl/util.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -23,6 +23,18 @@
#define ULL_8FS 0xFFFFFFFFULL
+u32 fsl_ddr_get_version(void)
+{
+ struct ccsr_ddr __iomem *ddr;
+ u32 ver_major_minor_errata;
+
+ ddr = (void *)_DDR_ADDR;
+ ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
+ ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
+
+ return ver_major_minor_errata;
+}
+
/*
* Round up mclk_ps to nearest 1 ps in memory controller code
* if the error is 0.5ps or more.
@@ -175,6 +187,9 @@ void board_add_ram_info(int use_default)
case SDRAM_TYPE_DDR3:
puts("3");
break;
+ case SDRAM_TYPE_DDR4:
+ puts("4");
+ break;
default:
puts("?");
break;
@@ -188,9 +203,12 @@ void board_add_ram_info(int use_default)
puts(", 64-bit");
/* Calculate CAS latency based on timing cfg values */
- cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1;
- if ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 1)
- cas_lat += (8 << 1);
+ cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
+ if (fsl_ddr_get_version() <= 0x40400)
+ cas_lat += 1;
+ else
+ cas_lat += 2;
+ cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4;
printf(", CL=%d", cas_lat >> 1);
if (cas_lat & 0x1)
puts(".5");