[U-Boot] [PATCH 1/2] fsl/ddr: Revise erratum a009942 and clean related erratum

Shengzhou Liu Shengzhou.Liu at nxp.com
Tue Nov 1 09:09:03 CET 2016


- add additional function erratum_a009942_check_cpo to check if the
  board needs tuning CPO calibration for optimal setting.
- move ERRATUM_A009942(with revision to check cpo_sample option) from
  fsl_ddr_gen4.c to ctrl_regs.c for reuse on all DDR4/DDR3 parts.
- move ERRATUM_A008378 from fsl_ddr_gen4.c to ctrl_regs.c
- remove obsolete ERRATUM_A004934 which is replaced with ERRATUM_A009942.

Signed-off-by: Shengzhou Liu <Shengzhou.Liu at nxp.com>
---
 arch/arm/cpu/armv8/fsl-layerscape/cpu.c   |   7 ++-
 arch/powerpc/cpu/mpc85xx/cpu_init.c       |   6 +-
 arch/powerpc/include/asm/config_mpc85xx.h |   2 -
 board/freescale/ls1021aqds/ls1021aqds.c   |   6 +-
 board/freescale/ls1021atwr/ls1021atwr.c   |   5 +-
 drivers/ddr/fsl/ctrl_regs.c               | 100 +++++++++++++++++++++++++++++-
 drivers/ddr/fsl/fsl_ddr_gen4.c            |  23 -------
 drivers/ddr/fsl/mpc85xx_ddr_gen3.c        |   3 -
 include/fsl_ddr.h                         |   2 +
 include/fsl_ddr_sdram.h                   |   3 +-
 10 files changed, 122 insertions(+), 35 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index b7a2e0c..19de15e 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -25,6 +25,9 @@
 #ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
 #include <asm/armv8/sec_firmware.h>
 #endif
+#ifdef CONFIG_SYS_FSL_DDR
+#include <fsl_ddr.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -400,7 +403,9 @@ int arch_early_init_r(void)
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009635
 	erratum_a009635();
 #endif
-
+#if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR)
+	erratum_a009942_check_cpo();
+#endif
 #ifdef CONFIG_MP
 #if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && defined(CONFIG_ARMV8_PSCI)
 	/* Check the psci version to determine if the psci is supported */
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index 53b3729..c1dbd9c 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -45,7 +45,7 @@
 #include <nand.h>
 #include <errno.h>
 #endif
-
+#include <fsl_ddr.h>
 #include "../../../../drivers/block/fsl_sata.h"
 #ifdef CONFIG_U_QE
 #include <fsl_qe.h>
@@ -947,6 +947,10 @@ int cpu_init_r(void)
 
 #endif /* CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE */
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
+	erratum_a009942_check_cpo();
+#endif
+
 #ifdef CONFIG_FMAN_ENET
 	fman_enet_init();
 #endif
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index 6d845e8..1e62a9c 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -681,7 +681,6 @@
 #define CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 #define CONFIG_SYS_FSL_ERRATUM_A004468
-#define CONFIG_SYS_FSL_ERRATUM_A_004934
 #define CONFIG_SYS_FSL_ERRATUM_A005871
 #define CONFIG_SYS_FSL_ERRATUM_A006379
 #define CONFIG_SYS_FSL_ERRATUM_A007186
@@ -720,7 +719,6 @@
 #define CONFIG_SYS_FSL_TBCLK_DIV	16
 #define CONFIG_SYS_FSL_PCIE_COMPAT	"fsl,qoriq-pcie-v2.4"
 #define CONFIG_SYS_FSL_USB1_PHY_ENABLE
-#define CONFIG_SYS_FSL_ERRATUM_A_004934
 #define CONFIG_SYS_FSL_ERRATUM_A005871
 #define CONFIG_SYS_FSL_ERRATUM_A006379
 #define CONFIG_SYS_FSL_ERRATUM_A007186
diff --git a/board/freescale/ls1021aqds/ls1021aqds.c b/board/freescale/ls1021aqds/ls1021aqds.c
index 4eb38a7..79078d2 100644
--- a/board/freescale/ls1021aqds/ls1021aqds.c
+++ b/board/freescale/ls1021aqds/ls1021aqds.c
@@ -22,7 +22,7 @@
 #include <spl.h>
 #include <fsl_devdis.h>
 #include <fsl_validate.h>
-
+#include <fsl_ddr.h>
 #include "../common/sleep.h"
 #include "../common/qixis.h"
 #include "ls1021aqds_qixis.h"
@@ -433,7 +433,9 @@ int board_init(void)
 #ifdef CONFIG_SYS_FSL_ERRATUM_A010315
 	erratum_a010315();
 #endif
-
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
+	erratum_a009942_check_cpo();
+#endif
 	major = get_soc_major_rev();
 	if (major == SOC_MAJOR_VER_1_0) {
 		/* Set CCI-400 control override register to
diff --git a/board/freescale/ls1021atwr/ls1021atwr.c b/board/freescale/ls1021atwr/ls1021atwr.c
index d96fd77..4bebe22 100644
--- a/board/freescale/ls1021atwr/ls1021atwr.c
+++ b/board/freescale/ls1021atwr/ls1021atwr.c
@@ -30,7 +30,7 @@
 #include <fsl_qe.h>
 #endif
 #include <fsl_validate.h>
-
+#include <fsl_ddr.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -488,6 +488,9 @@ int board_init(void)
 #ifdef CONFIG_SYS_FSL_ERRATUM_A010315
 	erratum_a010315();
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
+	erratum_a009942_check_cpo();
+#endif
 
 #ifndef CONFIG_SYS_FSL_NO_SERDES
 	fsl_serdes_init();
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 24fd366..29d1970 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -5,7 +5,7 @@
  */
 
 /*
- * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Generic driver for Freescale DDR/DDR2/DDR3/DDR4 memory controller.
  * Based on code from spd_sdram.c
  * Author: James Yang [at freescale.com]
  */
@@ -2305,6 +2305,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
 	unsigned int wrlvl_en;
 	unsigned int ip_rev = 0;
 	unsigned int unq_mrs_en = 0;
+	unsigned int ddr_freq;
 	int cs_en = 1;
 
 	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
@@ -2526,5 +2527,102 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
 		ddr->debug[2] |= 0x00000200;	/* set bit 22 */
 #endif
 
+#if defined(CONFIG_SYS_FSL_ERRATUM_A008378) && defined(CONFIG_SYS_FSL_DDRC_GEN4)
+	/* Erratum applies when accumulated ECC is used, or DBI is enabled */
+#define IS_ACC_ECC_EN(v) ((v) & 0x4)
+#define IS_DBI(v) ((((v) >> 12) & 0x3) == 0x2)
+	if (has_erratum_a008378()) {
+		if (IS_ACC_ECC_EN(ddr->ddr_sdram_cfg) ||
+		    IS_DBI(ddr->ddr_sdram_cfg_3))
+			ddr->debug[28] |= (0x9 << 20);
+	}
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
+	/* the POR value of debug_29 register is zero */
+	ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
+	if (ddr_freq <= 1333)
+		ddr->debug[28] |= 0x0080006a;
+	else if (ddr_freq <= 1600)
+		ddr->debug[28] |= 0x0070006f;
+	else if (ddr_freq <= 1867)
+		ddr->debug[28] |= 0x00700076;
+	else if (ddr_freq <= 2133)
+		ddr->debug[28] |= 0x0060007b;
+	if (popts->cpo_sample)
+		ddr->debug[28] = (ddr->debug[28] & 0xffffff00) |
+				  popts->cpo_sample;
+#endif
+
 	return check_fsl_memctl_config_regs(ddr);
 }
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
+/*
+ * This additional workaround of A009942 checks the condition to determine if
+ * the CPO value set by the existing A009942 workaround needs to be updated.
+ * If need, print a warning to prompt user reconfigure DDR debug_29[24:31] with
+ * expected optimal value, the optimal value is highly board dependent.
+ */
+void erratum_a009942_check_cpo(void)
+{
+	struct ccsr_ddr __iomem *ddr =
+		(struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR);
+	u32 cpo, cpo_e, cpo_o, cpo_target, cpo_optimal;
+	u32 min_cpo = 0, max_cpo = 0;
+	u32 sdram_cfg, i, tmp, lanes, ddr_type;
+	bool update_cpo = false, has_ecc = false;
+
+	sdram_cfg = ddr_in32(&ddr->sdram_cfg);
+	if (sdram_cfg & SDRAM_CFG_32_BE)
+		lanes = 4;
+	else if (sdram_cfg & SDRAM_CFG_16_BE)
+		lanes = 2;
+	else
+		lanes = 8;
+
+	if (sdram_cfg & SDRAM_CFG_ECC_EN)
+		has_ecc = true;
+
+	/* determine the maximum and minimum CPO values */
+	for (i = 9; i < 9 + lanes / 2; i++) {
+		cpo = ddr_in32(&ddr->debug[i]);
+		cpo_e = cpo >> 24;
+		cpo_o = (cpo >> 8) & 0xff;
+		tmp = min(cpo_e, cpo_o);
+		if (tmp < min_cpo)
+			min_cpo = tmp;
+		tmp = max(cpo_e, cpo_o);
+		if (tmp > max_cpo)
+			max_cpo = tmp;
+	}
+
+	if (has_ecc) {
+		cpo = ddr_in32(&ddr->debug[13]);
+		cpo = cpo >> 24;
+		if (cpo << min_cpo)
+			min_cpo = cpo;
+		if (cpo > max_cpo)
+			max_cpo = cpo;
+	}
+
+	cpo_target = ddr_in32(&ddr->debug[28]) & 0xff;
+	cpo_optimal = ((max_cpo + min_cpo) >> 1) + 0x27;
+	debug("cpo_optimal = 0x%x, cpo_target = 0x%x\n", cpo_optimal,
+	      cpo_target);
+	debug("max_cpo = 0x%x, min_cpo = 0x%x\n", max_cpo, min_cpo);
+
+	ddr_type = (sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
+		    SDRAM_CFG_SDRAM_TYPE_SHIFT;
+	if (ddr_type == SDRAM_TYPE_DDR4)
+		update_cpo = (min_cpo + 0x3b) < cpo_target ? true : false;
+	else if (ddr_type == SDRAM_TYPE_DDR3)
+		update_cpo = (min_cpo + 0x3f) < cpo_target ? true : false;
+
+	if (update_cpo) {
+		printf("WARN: This board needs to optimize debug_29, pls set ");
+		printf("\'popts->cpo_sample = 0x%x\' in <board>/ddr.c\n",
+			cpo_optimal);
+	}
+}
+#endif
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index 042af09..2a5066a 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -230,16 +230,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 			ddr_out32(&ddr->debug[i], regs->debug[i]);
 		}
 	}
-#ifdef CONFIG_SYS_FSL_ERRATUM_A008378
-	/* Erratum applies when accumulated ECC is used, or DBI is enabled */
-#define IS_ACC_ECC_EN(v) ((v) & 0x4)
-#define IS_DBI(v) ((((v) >> 12) & 0x3) == 0x2)
-	if (has_erratum_a008378()) {
-		if (IS_ACC_ECC_EN(regs->ddr_sdram_cfg) ||
-		    IS_DBI(regs->ddr_sdram_cfg_3))
-			ddr_setbits32(&ddr->debug[28], 0x9 << 20);
-	}
-#endif
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A008511
 	/* Part 1 of 2 */
@@ -277,19 +267,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	ddr_out32(&ddr->debug[25], temp32);
 #endif
 
-#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
-	ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
-	tmp = ddr_in32(&ddr->debug[28]);
-	if (ddr_freq <= 1333)
-		ddr_out32(&ddr->debug[28], tmp | 0x0080006a);
-	else if (ddr_freq <= 1600)
-		ddr_out32(&ddr->debug[28], tmp | 0x0070006f);
-	else if (ddr_freq <= 1867)
-		ddr_out32(&ddr->debug[28], tmp | 0x00700076);
-	else if (ddr_freq <= 2133)
-		ddr_out32(&ddr->debug[28], tmp | 0x0060007b);
-#endif
-
 #ifdef CONFIG_SYS_FSL_ERRATUM_A010165
 	ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
 	if ((ddr_freq > 1900) && (ddr_freq < 2300)) {
diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
index 653b7f0..1bfb9d4 100644
--- a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
+++ b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
@@ -174,9 +174,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 			out_be32(&ddr->debug[i], regs->debug[i]);
 		}
 	}
-#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934
-	out_be32(&ddr->debug[28], 0x30003000);
-#endif
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474
 	out_be32(&ddr->debug[12], 0x00000015);
diff --git a/include/fsl_ddr.h b/include/fsl_ddr.h
index 3351acd..0c3be0e 100644
--- a/include/fsl_ddr.h
+++ b/include/fsl_ddr.h
@@ -138,4 +138,6 @@ int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
 void update_spd_address(unsigned int ctrl_num,
 			unsigned int slot,
 			unsigned int *addr);
+
+void erratum_a009942_check_cpo(void);
 #endif
diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h
index 36bd9d7..1404c57 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -374,7 +374,8 @@ typedef struct memctl_options_s {
 	unsigned int additive_latency_override_value;
 
 	unsigned int clk_adjust;		/* */
-	unsigned int cpo_override;
+	unsigned int cpo_override;		/* override timing_cfg_2[CPO]*/
+	unsigned int cpo_sample;		/* optimize debug_29[24:31] */
 	unsigned int write_data_delay;		/* DQS adjust */
 
 	unsigned int cswl_override;
-- 
2.1.0.27.g96db324



More information about the U-Boot mailing list