public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4
@ 2015-03-19 16:30 York Sun
  2015-03-19 16:30 ` [U-Boot] [PATCH 2/4] driver/ddr/fsl: Fix driver to support empty first slot York Sun
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: York Sun @ 2015-03-19 16:30 UTC (permalink / raw)
  To: u-boot

Add/update registers for DDR4, including DQ mappings. Allow raw timing
method used for all controllers. Update mode_9 register to 0x500 for
improved stability. Check DDR controller version number individually
in case a SoC has multiple DDR controllers of different versions.
Increase read-write turnaround for DDR4 high speeds.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 drivers/ddr/fsl/ctrl_regs.c   |   17 ++++++++++----
 drivers/ddr/fsl/interactive.c |   51 ++++++++++++++++++++++++++++++++++++++++-
 drivers/ddr/fsl/main.c        |    2 +-
 drivers/ddr/fsl/util.c        |   28 +++++++++++++++++++---
 include/fsl_ddr.h             |    4 +---
 5 files changed, 89 insertions(+), 13 deletions(-)

diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 690e73d..9ccddef 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -313,7 +313,10 @@ static void set_timing_cfg_0(const unsigned int ctrl_num,
 #ifdef CONFIG_SYS_FSL_DDR4
 	/* tXP=max(4nCK, 6ns) */
 	int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
-	trwt_mclk = 2;
+	unsigned int data_rate = get_ddr_freq(ctrl_num);
+
+	/* for faster clock, need more time for data setup */
+	trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2;
 	twrt_mclk = 1;
 	act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
 	pre_pd_exit_mclk = act_pd_exit_mclk;
@@ -338,7 +341,7 @@ static void set_timing_cfg_0(const unsigned int ctrl_num,
 	 */
 	txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
 
-	ip_rev = fsl_ddr_get_version();
+	ip_rev = fsl_ddr_get_version(ctrl_num);
 	if (ip_rev >= 0x40700) {
 		/*
 		 * MRS_CYC = max(tMRD, tMOD)
@@ -544,7 +547,7 @@ static void set_timing_cfg_1(const unsigned int ctrl_num,
 	 * we need set extend bit for it at
 	 * TIMING_CFG_3[EXT_CASLAT]
 	 */
-	if (fsl_ddr_get_version() <= 0x40400)
+	if (fsl_ddr_get_version(ctrl_num) <= 0x40400)
 		caslat_ctrl = 2 * cas_latency - 1;
 	else
 		caslat_ctrl = (cas_latency - 1) << 1;
@@ -1114,12 +1117,16 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
 	unsigned short esdmode4 = 0;	/* Extended SDRAM mode 4 */
 	unsigned short esdmode5;	/* Extended SDRAM mode 5 */
 
-	esdmode5 = 0x00000400;		/* Data mask enabled */
+	esdmode5 = 0x00000500;		/* Data mask enabled */
 
 	ddr->ddr_sdram_mode_9 = (0
 				 | ((esdmode4 & 0xffff) << 16)
 				 | ((esdmode5 & 0xffff) << 0)
 				);
+
+	/* only mode_9 use 0x500, others use 0x400 */
+	esdmode5 = 0x00000400;		/* Data mask enabled */
+
 	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++) {
@@ -2349,7 +2356,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
 	set_ddr_cdr1(ddr, popts);
 	set_ddr_cdr2(ddr, popts);
 	set_ddr_sdram_cfg(ddr, popts, common_dimm);
-	ip_rev = fsl_ddr_get_version();
+	ip_rev = fsl_ddr_get_version(ctrl_num);
 	if (ip_rev > 0x40400)
 		unq_mrs_en = 1;
 
diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c
index 32ba6d8..57d14e8 100644
--- a/drivers/ddr/fsl/interactive.c
+++ b/drivers/ddr/fsl/interactive.c
@@ -205,6 +205,8 @@ static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
 
 #define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \
 	sizeof((dimm_params_t *)0)->x, 0}
+#define DIMM_PARM_HEX(x) {#x, offsetof(dimm_params_t, x), \
+	sizeof((dimm_params_t *)0)->x, 1}
 
 static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
 				   unsigned int ctrl_num,
@@ -220,6 +222,7 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
 		DIMM_PARM(primary_sdram_width),
 		DIMM_PARM(ec_sdram_width),
 		DIMM_PARM(registered_dimm),
+		DIMM_PARM(mirrored_dimm),
 		DIMM_PARM(device_width),
 
 		DIMM_PARM(n_row_addr),
@@ -274,7 +277,27 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
 		DIMM_PARM(tdqsq_max_ps),
 		DIMM_PARM(tqhs_ps),
 #endif
-
+#ifdef CONFIG_SYS_FSL_DDR4
+		DIMM_PARM_HEX(dq_mapping[0]),
+		DIMM_PARM_HEX(dq_mapping[1]),
+		DIMM_PARM_HEX(dq_mapping[2]),
+		DIMM_PARM_HEX(dq_mapping[3]),
+		DIMM_PARM_HEX(dq_mapping[4]),
+		DIMM_PARM_HEX(dq_mapping[5]),
+		DIMM_PARM_HEX(dq_mapping[6]),
+		DIMM_PARM_HEX(dq_mapping[7]),
+		DIMM_PARM_HEX(dq_mapping[8]),
+		DIMM_PARM_HEX(dq_mapping[9]),
+		DIMM_PARM_HEX(dq_mapping[10]),
+		DIMM_PARM_HEX(dq_mapping[11]),
+		DIMM_PARM_HEX(dq_mapping[12]),
+		DIMM_PARM_HEX(dq_mapping[13]),
+		DIMM_PARM_HEX(dq_mapping[14]),
+		DIMM_PARM_HEX(dq_mapping[15]),
+		DIMM_PARM_HEX(dq_mapping[16]),
+		DIMM_PARM_HEX(dq_mapping[17]),
+		DIMM_PARM(dq_mapping_ors),
+#endif
 		DIMM_PARM(rank_density),
 		DIMM_PARM(capacity),
 		DIMM_PARM(base_address),
@@ -296,6 +319,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
 		DIMM_PARM(primary_sdram_width),
 		DIMM_PARM(ec_sdram_width),
 		DIMM_PARM(registered_dimm),
+		DIMM_PARM(mirrored_dimm),
 		DIMM_PARM(device_width),
 
 		DIMM_PARM(n_row_addr),
@@ -314,6 +338,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
 		DIMM_PARM(tckmax_ps),
 
 		DIMM_PARM(caslat_x),
+		DIMM_PARM_HEX(caslat_x),
 		DIMM_PARM(taa_ps),
 		DIMM_PARM(caslat_x_minus_1),
 		DIMM_PARM(caslat_x_minus_2),
@@ -322,6 +347,9 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
 		DIMM_PARM(trcd_ps),
 		DIMM_PARM(trp_ps),
 		DIMM_PARM(tras_ps),
+#if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3)
+		DIMM_PARM(tfaw_ps),
+#endif
 #ifdef CONFIG_SYS_FSL_DDR4
 		DIMM_PARM(trfc1_ps),
 		DIMM_PARM(trfc2_ps),
@@ -347,6 +375,27 @@ static void print_dimm_parameters(const dimm_params_t *pdimm)
 		DIMM_PARM(tdqsq_max_ps),
 		DIMM_PARM(tqhs_ps),
 #endif
+#ifdef CONFIG_SYS_FSL_DDR4
+		DIMM_PARM_HEX(dq_mapping[0]),
+		DIMM_PARM_HEX(dq_mapping[1]),
+		DIMM_PARM_HEX(dq_mapping[2]),
+		DIMM_PARM_HEX(dq_mapping[3]),
+		DIMM_PARM_HEX(dq_mapping[4]),
+		DIMM_PARM_HEX(dq_mapping[5]),
+		DIMM_PARM_HEX(dq_mapping[6]),
+		DIMM_PARM_HEX(dq_mapping[7]),
+		DIMM_PARM_HEX(dq_mapping[8]),
+		DIMM_PARM_HEX(dq_mapping[9]),
+		DIMM_PARM_HEX(dq_mapping[10]),
+		DIMM_PARM_HEX(dq_mapping[11]),
+		DIMM_PARM_HEX(dq_mapping[12]),
+		DIMM_PARM_HEX(dq_mapping[13]),
+		DIMM_PARM_HEX(dq_mapping[14]),
+		DIMM_PARM_HEX(dq_mapping[15]),
+		DIMM_PARM_HEX(dq_mapping[16]),
+		DIMM_PARM_HEX(dq_mapping[17]),
+		DIMM_PARM(dq_mapping_ors),
+#endif
 	};
 	static const unsigned int n_opts = ARRAY_SIZE(options);
 
diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c
index b72b242..fa22383 100644
--- a/drivers/ddr/fsl/main.c
+++ b/drivers/ddr/fsl/main.c
@@ -453,7 +453,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
 				retval = compute_dimm_parameters(
 							i, spd, pdimm, j);
 #ifdef CONFIG_SYS_DDR_RAW_TIMING
-				if (!i && !j && retval) {
+				if (!j && retval) {
 					printf("SPD error on controller %d! "
 					"Trying fallback to raw timing "
 					"calculation\n", i);
diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c
index 664081b..ce55aea 100644
--- a/drivers/ddr/fsl/util.c
+++ b/drivers/ddr/fsl/util.c
@@ -23,12 +23,34 @@
 
 #define ULL_8FS 0xFFFFFFFFULL
 
-u32 fsl_ddr_get_version(void)
+u32 fsl_ddr_get_version(unsigned int ctrl_num)
 {
 	struct ccsr_ddr __iomem *ddr;
 	u32 ver_major_minor_errata;
 
-	ddr = (void *)_DDR_ADDR;
+	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 0;
+	}
 	ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
 	ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
 
@@ -212,7 +234,7 @@ void print_ddr_info(unsigned int start_ctrl)
 
 	/* Calculate CAS latency based on timing cfg values */
 	cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
-	if (fsl_ddr_get_version() <= 0x40400)
+	if (fsl_ddr_get_version(0) <= 0x40400)
 		cas_lat += 1;
 	else
 		cas_lat += 2;
diff --git a/include/fsl_ddr.h b/include/fsl_ddr.h
index feccef9..4099a74 100644
--- a/include/fsl_ddr.h
+++ b/include/fsl_ddr.h
@@ -34,9 +34,7 @@
 #define ddr_clrsetbits32(a, clear, set)	clrsetbits_be32(a, clear, set)
 #endif
 
-#define _DDR_ADDR CONFIG_SYS_FSL_DDR_ADDR
-
-u32 fsl_ddr_get_version(void);
+u32 fsl_ddr_get_version(unsigned int ctrl_num);
 
 #if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM)
 /*
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 2/4] driver/ddr/fsl: Fix driver to support empty first slot
  2015-03-19 16:30 [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun
@ 2015-03-19 16:30 ` York Sun
  2015-03-19 16:30 ` [U-Boot] [PATCH 3/4] driver/ddr/fsl: Add built-in memory test for DDR4 driver York Sun
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: York Sun @ 2015-03-19 16:30 UTC (permalink / raw)
  To: u-boot

CS0 was not allowed to be empty by u-boot driver in the past to simplify
the driver. This may be inconvenient for some debugging. This patch lifts
the restrictions. Controller interleaving still requires CS0 populated.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 drivers/ddr/fsl/ctrl_regs.c             |   64 +++++++++++++++++++++----------
 drivers/ddr/fsl/ddr4_dimm_params.c      |    3 +-
 drivers/ddr/fsl/interactive.c           |    5 ++-
 drivers/ddr/fsl/lc_common_dimm_params.c |    5 +--
 drivers/ddr/fsl/options.c               |    7 +++-
 5 files changed, 56 insertions(+), 28 deletions(-)

diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 9ccddef..b692bdb 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -1116,8 +1116,14 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
 	int i;
 	unsigned short esdmode4 = 0;	/* Extended SDRAM mode 4 */
 	unsigned short esdmode5;	/* Extended SDRAM mode 5 */
+	int rtt_park = 0;
 
-	esdmode5 = 0x00000500;		/* Data mask enabled */
+	if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) {
+		esdmode5 = 0x00000500;	/* Data mask enable, RTT_PARK CS0 */
+		rtt_park = 1;
+	} else {
+		esdmode5 = 0x00000400;	/* Data mask enabled */
+	}
 
 	ddr->ddr_sdram_mode_9 = (0
 				 | ((esdmode4 & 0xffff) << 16)
@@ -1125,11 +1131,17 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
 				);
 
 	/* only mode_9 use 0x500, others use 0x400 */
-	esdmode5 = 0x00000400;		/* Data mask enabled */
 
 	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++) {
+			if (!rtt_park &&
+			    (ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) {
+				esdmode5 |= 0x00000500;	/* RTT_PARK */
+				rtt_park = 1;
+			} else {
+				esdmode5 = 0x00000400;
+			}
 			switch (i) {
 			case 1:
 				ddr->ddr_sdram_mode_11 = (0
@@ -1969,31 +1981,41 @@ static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
 			       const dimm_params_t *dimm_params)
 {
 	unsigned int acc_ecc_en = (ddr->ddr_sdram_cfg >> 2) & 0x1;
+	int i;
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (dimm_params[i].n_ranks)
+			break;
+	}
+	if (i >= CONFIG_DIMM_SLOTS_PER_CTLR) {
+		puts("DDR error: no DIMM found!\n");
+		return;
+	}
 
-	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_0 = ((dimm_params[i].dq_mapping[0] & 0x3F) << 26) |
+			((dimm_params[i].dq_mapping[1] & 0x3F) << 20) |
+			((dimm_params[i].dq_mapping[2] & 0x3F) << 14) |
+			((dimm_params[i].dq_mapping[3] & 0x3F) << 8) |
+			((dimm_params[i].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_1 = ((dimm_params[i].dq_mapping[5] & 0x3F) << 26) |
+			((dimm_params[i].dq_mapping[6] & 0x3F) << 20) |
+			((dimm_params[i].dq_mapping[7] & 0x3F) << 14) |
+			((dimm_params[i].dq_mapping[10] & 0x3F) << 8) |
+			((dimm_params[i].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_2 = ((dimm_params[i].dq_mapping[12] & 0x3F) << 26) |
+			((dimm_params[i].dq_mapping[13] & 0x3F) << 20) |
+			((dimm_params[i].dq_mapping[14] & 0x3F) << 14) |
+			((dimm_params[i].dq_mapping[15] & 0x3F) << 8) |
+			((dimm_params[i].dq_mapping[16] & 0x3F) << 2);
 
 	/* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
-	ddr->dq_map_3 = ((dimm_params->dq_mapping[17] & 0x3F) << 26) |
-			((dimm_params->dq_mapping[8] & 0x3F) << 20) |
+	ddr->dq_map_3 = ((dimm_params[i].dq_mapping[17] & 0x3F) << 26) |
+			((dimm_params[i].dq_mapping[8] & 0x3F) << 20) |
 			(acc_ecc_en ? 0 :
-			 (dimm_params->dq_mapping[9] & 0x3F) << 14) |
-			dimm_params->dq_mapping_ors;
+			 (dimm_params[i].dq_mapping[9] & 0x3F) << 14) |
+			dimm_params[i].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);
diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c
index bbfb4ee..42834ca 100644
--- a/drivers/ddr/fsl/ddr4_dimm_params.c
+++ b/drivers/ddr/fsl/ddr4_dimm_params.c
@@ -135,7 +135,8 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num,
 
 	if (spd->mem_type) {
 		if (spd->mem_type != SPD_MEMTYPE_DDR4) {
-			printf("DIMM %u: is not a DDR4 SPD.\n", dimm_number);
+			printf("Ctrl %u DIMM %u: is not a DDR4 SPD.\n",
+			       ctrl_num, dimm_number);
 			return 1;
 		}
 	} else {
diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c
index 57d14e8..d23e6e5 100644
--- a/drivers/ddr/fsl/interactive.c
+++ b/drivers/ddr/fsl/interactive.c
@@ -512,7 +512,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
 		CTRL_OPTIONS_CS(3, odt_rd_cfg),
 		CTRL_OPTIONS_CS(3, odt_wr_cfg),
 #endif
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 		CTRL_OPTIONS_CS(0, odt_rtt_norm),
 		CTRL_OPTIONS_CS(0, odt_rtt_wr),
 #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
@@ -802,7 +802,7 @@ static void print_memctl_options(const memctl_options_t *popts)
 		CTRL_OPTIONS_CS(3, odt_rd_cfg),
 		CTRL_OPTIONS_CS(3, odt_wr_cfg),
 #endif
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 		CTRL_OPTIONS_CS(0, odt_rtt_norm),
 		CTRL_OPTIONS_CS(0, odt_rtt_wr),
 #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
@@ -844,6 +844,7 @@ static void print_memctl_options(const memctl_options_t *popts)
 		CTRL_OPTIONS(twot_en),
 		CTRL_OPTIONS(threet_en),
 		CTRL_OPTIONS(registered_dimm_en),
+		CTRL_OPTIONS(mirrored_dimm),
 		CTRL_OPTIONS(ap_en),
 		CTRL_OPTIONS(x4_en),
 		CTRL_OPTIONS(bstopre),
diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c
index b295344..b12eeb9 100644
--- a/drivers/ddr/fsl/lc_common_dimm_params.c
+++ b/drivers/ddr/fsl/lc_common_dimm_params.c
@@ -22,7 +22,7 @@ compute_cas_latency(const unsigned int ctrl_num,
 	unsigned int common_caslat;
 	unsigned int caslat_actual;
 	unsigned int retry = 16;
-	unsigned int tmp;
+	unsigned int tmp = ~0;
 	const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
 #ifdef CONFIG_SYS_FSL_DDR3
 	const unsigned int taamax = 20000;
@@ -31,8 +31,7 @@ compute_cas_latency(const unsigned int ctrl_num,
 #endif
 
 	/* compute the common CAS latency supported between slots */
-	tmp = dimm_params[0].caslat_x;
-	for (i = 1; i < number_of_dimms; i++) {
+	for (i = 0; i < number_of_dimms; i++) {
 		if (dimm_params[i].n_ranks)
 			tmp &= dimm_params[i].caslat_x;
 	}
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index 5beb11b..3b30fa2 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -728,7 +728,12 @@ unsigned int populate_memctl_options(int all_dimms_registered,
 
 	/* Choose ddr controller address mirror mode */
 #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
-	popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (pdimm[i].n_ranks) {
+			popts->mirrored_dimm = pdimm[i].mirrored_dimm;
+			break;
+		}
+	}
 #endif
 
 	/* Global Timing Parameters. */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 3/4] driver/ddr/fsl: Add built-in memory test for DDR4 driver
  2015-03-19 16:30 [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun
  2015-03-19 16:30 ` [U-Boot] [PATCH 2/4] driver/ddr/fsl: Fix driver to support empty first slot York Sun
@ 2015-03-19 16:30 ` York Sun
  2015-03-19 16:30 ` [U-Boot] [PATCH 4/4] driver/ddr/fsl: Add workaround for DDR erratum A008511 York Sun
  2015-04-23 23:38 ` [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun
  3 siblings, 0 replies; 5+ messages in thread
From: York Sun @ 2015-03-19 16:30 UTC (permalink / raw)
  To: u-boot

Add built-in memory test to catch errors after DDR is initialized, before
any other transactions. To enable this test, define CONFIG_FSL_DDR_BIST.
An environmental variable "ddr_bist" is checked before starting test.
It takes a while (several seconds) depending on system memory size.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 README                         |    3 ++
 drivers/ddr/fsl/fsl_ddr_gen4.c |   73 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/README b/README
index b0124d6..f473515 100644
--- a/README
+++ b/README
@@ -4904,6 +4904,9 @@ Low Level (hardware related) configuration options:
 - CONFIG_FSL_DDR_SYNC_REFRESH
 		Enable sync of refresh for multiple controllers.
 
+- CONFIG_FSL_DDR_BIST
+		Enable built-in memory test for Freescale DDR controllers.
+
 - CONFIG_SYS_83XX_DDR_USES_CS0
 		Only for 83xx systems. If specified, then DDR should
 		be configured using CS0 and CS1 instead of CS2 and CS3.
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index d9fce7d..1d67983 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -36,6 +36,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	defined(CONFIG_SYS_FSL_ERRATUM_A008514)
 	u32 *eddrtqcr1;
 #endif
+#ifdef CONFIG_FSL_DDR_BIST
+	u32 mtcr, err_detect, err_sbe;
+	u32 cs0_bnds, cs1_bnds, cs2_bnds, cs3_bnds, cs0_config;
+#endif
+#ifdef CONFIG_FSL_DDR_BIST
+	char buffer[CONFIG_SYS_CBSIZE];
+#endif
 
 	switch (ctrl_num) {
 	case 0:
@@ -309,4 +316,70 @@ step2:
 		ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
 	}
 #endif
+
+#ifdef CONFIG_FSL_DDR_BIST
+#define BIST_PATTERN1	0xFFFFFFFF
+#define BIST_PATTERN2	0x0
+#define BIST_CR		0x80010000
+#define BIST_CR_EN	0x80000000
+#define BIST_CR_STAT	0x00000001
+#define CTLR_INTLV_MASK	0x20000000
+	/* Perform build-in test on memory. Three-way interleaving is not yet
+	 * supported by this code. */
+	if (getenv_f("ddr_bist", buffer, CONFIG_SYS_CBSIZE) >= 0) {
+		puts("Running BIST test. This will take a while...");
+		cs0_config = ddr_in32(&ddr->cs0_config);
+		if (cs0_config & CTLR_INTLV_MASK) {
+			cs0_bnds = ddr_in32(&cs0_bnds);
+			cs1_bnds = ddr_in32(&cs1_bnds);
+			cs2_bnds = ddr_in32(&cs2_bnds);
+			cs3_bnds = ddr_in32(&cs3_bnds);
+			/* set bnds to non-interleaving */
+			ddr_out32(&cs0_bnds, (cs0_bnds & 0xfffefffe) >> 1);
+			ddr_out32(&cs1_bnds, (cs1_bnds & 0xfffefffe) >> 1);
+			ddr_out32(&cs2_bnds, (cs2_bnds & 0xfffefffe) >> 1);
+			ddr_out32(&cs3_bnds, (cs3_bnds & 0xfffefffe) >> 1);
+		}
+		ddr_out32(&ddr->mtp1, BIST_PATTERN1);
+		ddr_out32(&ddr->mtp2, BIST_PATTERN1);
+		ddr_out32(&ddr->mtp3, BIST_PATTERN2);
+		ddr_out32(&ddr->mtp4, BIST_PATTERN2);
+		ddr_out32(&ddr->mtp5, BIST_PATTERN1);
+		ddr_out32(&ddr->mtp6, BIST_PATTERN1);
+		ddr_out32(&ddr->mtp7, BIST_PATTERN2);
+		ddr_out32(&ddr->mtp8, BIST_PATTERN2);
+		ddr_out32(&ddr->mtp9, BIST_PATTERN1);
+		ddr_out32(&ddr->mtp10, BIST_PATTERN2);
+		mtcr = BIST_CR;
+		ddr_out32(&ddr->mtcr, mtcr);
+		timeout = 100;
+		while (timeout > 0 && (mtcr & BIST_CR_EN)) {
+			mdelay(1000);
+			timeout--;
+			mtcr = ddr_in32(&ddr->mtcr);
+		}
+		if (timeout <= 0)
+			puts("Timeout\n");
+		else
+			puts("Done\n");
+		err_detect = ddr_in32(&ddr->err_detect);
+		err_sbe = ddr_in32(&ddr->err_sbe);
+		if (mtcr & BIST_CR_STAT) {
+			printf("BIST test failed on controller %d.\n",
+			       ctrl_num);
+		}
+		if (err_detect || (err_sbe & 0xffff)) {
+			printf("ECC error detected on controller %d.\n",
+			       ctrl_num);
+		}
+
+		if (cs0_config & CTLR_INTLV_MASK) {
+			/* restore bnds registers */
+			ddr_out32(&cs0_bnds, cs0_bnds);
+			ddr_out32(&cs1_bnds, cs1_bnds);
+			ddr_out32(&cs2_bnds, cs2_bnds);
+			ddr_out32(&cs3_bnds, cs3_bnds);
+		}
+	}
+#endif
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 4/4] driver/ddr/fsl: Add workaround for DDR erratum A008511
  2015-03-19 16:30 [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun
  2015-03-19 16:30 ` [U-Boot] [PATCH 2/4] driver/ddr/fsl: Fix driver to support empty first slot York Sun
  2015-03-19 16:30 ` [U-Boot] [PATCH 3/4] driver/ddr/fsl: Add built-in memory test for DDR4 driver York Sun
@ 2015-03-19 16:30 ` York Sun
  2015-04-23 23:38 ` [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun
  3 siblings, 0 replies; 5+ messages in thread
From: York Sun @ 2015-03-19 16:30 UTC (permalink / raw)
  To: u-boot

This erratum only applies to general purpose DDR controllers in LS2.
It shouldn't be applied to DP-DDR controller. Check DDRC versoin number
before applying workaround.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 drivers/ddr/fsl/fsl_ddr_gen4.c |   96 +++++++++++++++++++++++++++++++++++++++-
 include/fsl_ddr_sdram.h        |    2 +
 2 files changed, 97 insertions(+), 1 deletion(-)

diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index 1d67983..49e4688 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2014-2015 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -11,6 +11,22 @@
 #include <fsl_immap.h>
 #include <fsl_ddr.h>
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)
+{
+	int timeout = 1000;
+
+	ddr_out32(ptr, value);
+
+	while (ddr_in32(ptr) & bits) {
+		udelay(100);
+		timeout--;
+	}
+	if (timeout <= 0)
+		puts("Error: A007865 wait for clear timeout.\n");
+}
+#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
+
 #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
 #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
 #endif
@@ -36,6 +52,9 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	defined(CONFIG_SYS_FSL_ERRATUM_A008514)
 	u32 *eddrtqcr1;
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+	u32 temp32, mr6;
+#endif
 #ifdef CONFIG_FSL_DDR_BIST
 	u32 mtcr, err_detect, err_sbe;
 	u32 cs0_bnds, cs1_bnds, cs2_bnds, cs3_bnds, cs0_config;
@@ -221,6 +240,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 		ddr_setbits32(ddr->debug[28], 0x9 << 20);
 #endif
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+	/* Part 1 of 2 */
+	/* This erraum only applies to verion 5.2.0 */
+	if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
+		/* Disable DRAM VRef training */
+		ddr_out32(&ddr->ddr_cdr2,
+			  regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
+		/* Disable deskew */
+		ddr_out32(&ddr->debug[28], 0x400);
+		/* Disable D_INIT */
+		ddr_out32(&ddr->sdram_cfg_2,
+			  regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+		ddr_out32(&ddr->debug[25], 0x9000);
+	}
+#endif
 	/*
 	 * For RDIMMs, JEDEC spec requires clocks to be stable before reset is
 	 * deasserted. Clocks start when any chip select is enabled and clock
@@ -268,6 +302,66 @@ step2:
 	mb();
 	isb();
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_A008511
+	/* Part 2 of 2 */
+	/* This erraum only applies to verion 5.2.0 */
+	if (fsl_ddr_get_version(ctrl_num) == 0x50200) {
+		/* Wait for idle */
+		timeout = 200;
+		while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
+		       (timeout > 0)) {
+			udelay(100);
+			timeout--;
+		}
+		if (timeout <= 0) {
+			printf("Controler %d timeout, debug_2 = %x\n",
+			       ctrl_num, ddr_in32(&ddr->debug[1]));
+		}
+		/* Set VREF */
+		for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+			if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN))
+				continue;
+
+			mr6 = (regs->ddr_sdram_mode_10 >> 16)		|
+				 MD_CNTL_MD_EN				|
+				 MD_CNTL_CS_SEL(i)			|
+				 MD_CNTL_MD_SEL(6)			|
+				 0x00200000;
+			temp32 = mr6 | 0xc0;
+			set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+						temp32, MD_CNTL_MD_EN);
+			udelay(1);
+			debug("MR6 = 0x%08x\n", temp32);
+			temp32 = mr6 | 0xf0;
+			set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+						temp32, MD_CNTL_MD_EN);
+			udelay(1);
+			debug("MR6 = 0x%08x\n", temp32);
+			temp32 = mr6 | 0x70;
+			set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+						temp32, MD_CNTL_MD_EN);
+			udelay(1);
+			debug("MR6 = 0x%08x\n", temp32);
+		}
+		ddr_out32(&ddr->sdram_md_cntl, 0);
+		ddr_out32(&ddr->debug[28], 0);		/* Enable deskew */
+		ddr_out32(&ddr->debug[1], 0x400);	/* restart deskew */
+		/* wait for idle */
+		timeout = 200;
+		while (!(ddr_in32(&ddr->debug[1]) & 0x2) &&
+		       (timeout > 0)) {
+			udelay(100);
+			timeout--;
+		}
+		if (timeout <= 0) {
+			printf("Controler %d timeout, debug_2 = %x\n",
+			       ctrl_num, ddr_in32(&ddr->debug[1]));
+		}
+		/* Restore D_INIT */
+		ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+	}
+#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
+
 	total_gb_size_per_controller = 0;
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
 		if (!(regs->cs[i].config & 0x80000000))
diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h
index 095b33e..6358b6f 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -155,6 +155,8 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t;
 #define MD_CNTL_CKE_CNTL_HIGH	0x00200000
 #define MD_CNTL_WRCW		0x00080000
 #define MD_CNTL_MD_VALUE(x)	(x & 0x0000FFFF)
+#define MD_CNTL_CS_SEL(x)	(((x) & 0x7) << 28)
+#define MD_CNTL_MD_SEL(x)	(((x) & 0xf) << 24)
 
 /* DDR_CDR1 */
 #define DDR_CDR1_DHC_EN	0x80000000
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4
  2015-03-19 16:30 [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun
                   ` (2 preceding siblings ...)
  2015-03-19 16:30 ` [U-Boot] [PATCH 4/4] driver/ddr/fsl: Add workaround for DDR erratum A008511 York Sun
@ 2015-04-23 23:38 ` York Sun
  3 siblings, 0 replies; 5+ messages in thread
From: York Sun @ 2015-04-23 23:38 UTC (permalink / raw)
  To: u-boot



On 03/19/2015 09:30 AM, York Sun wrote:
> Add/update registers for DDR4, including DQ mappings. Allow raw timing
> method used for all controllers. Update mode_9 register to 0x500 for
> improved stability. Check DDR controller version number individually
> in case a SoC has multiple DDR controllers of different versions.
> Increase read-write turnaround for DDR4 high speeds.
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
> ---

This set is applied to fsl-qoriq master, awaiting upstream.

[U-Boot,1/4] drivers/ddr/fsl: Update DDR driver for DDR4
[U-Boot,2/4] driver/ddr/fsl: Fix driver to support empty first slot
[U-Boot,3/4] driver/ddr/fsl: Add built-in memory test for DDR4 driver
[U-Boot,4/4] driver/ddr/fsl: Add workaround for DDR erratum A008511

York

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-04-23 23:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-19 16:30 [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun
2015-03-19 16:30 ` [U-Boot] [PATCH 2/4] driver/ddr/fsl: Fix driver to support empty first slot York Sun
2015-03-19 16:30 ` [U-Boot] [PATCH 3/4] driver/ddr/fsl: Add built-in memory test for DDR4 driver York Sun
2015-03-19 16:30 ` [U-Boot] [PATCH 4/4] driver/ddr/fsl: Add workaround for DDR erratum A008511 York Sun
2015-04-23 23:38 ` [U-Boot] [PATCH 1/4] drivers/ddr/fsl: Update DDR driver for DDR4 York Sun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox