[U-Boot] [PATCH 1/3] armv8/ls1043: Add workaround for DDR erratum A-008850

Barrier transactions from CCI400 need to be disabled till the DDR is configured, otherwise it may lead to system hang. The patch adds workaround to fix the erratum.
Signed-off-by: Shengzhou Liu Shengzhou.Liu@nxp.com --- arch/arm/cpu/armv8/fsl-layerscape/soc.c | 18 ++++++++++++++++++ arch/arm/include/asm/arch-fsl-layerscape/config.h | 1 + board/freescale/ls1043aqds/ddr.c | 21 +++++++++++++++++++++ board/freescale/ls1043aqds/ls1043aqds.c | 8 -------- board/freescale/ls1043ardb/ddr.c | 22 ++++++++++++++++++++++ board/freescale/ls1043ardb/ls1043ardb.c | 8 -------- include/fsl_ddr_sdram.h | 4 ++++ 7 files changed, 66 insertions(+), 16 deletions(-)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 213ce3a..816bf1b 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -12,6 +12,8 @@ #include <asm/io.h> #include <asm/global_data.h> #include <asm/arch-fsl-layerscape/config.h> +#include <fsl_ddr_sdram.h> +#include <fsl_ddr.h> #ifdef CONFIG_CHAIN_OF_TRUST #include <fsl_validate.h> #endif @@ -231,6 +233,21 @@ static void erratum_a009660(void) #endif }
+static void erratum_a008850(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850 + /* part 1 of 2 */ + struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR; + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + + /* disables propagation of barrier transactions to DDRC from CCI400 */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); + + /* disable the re-ordering in DDRC */ + ddr_out32(&ddr->eor, DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS); +#endif +} + void fsl_lsch2_early_init_f(void) { struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; @@ -255,6 +272,7 @@ void fsl_lsch2_early_init_f(void) CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
/* Erratum */ + erratum_a008850(); erratum_a009929(); erratum_a009660(); } diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h index b0c112b..6ec7e50 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/config.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h @@ -176,6 +176,7 @@ #define GICD_BASE 0x01401000 #define GICC_BASE 0x01402000
+#define CONFIG_SYS_FSL_ERRATUM_A008850 #define CONFIG_SYS_FSL_ERRATUM_A009663 #define CONFIG_SYS_FSL_ERRATUM_A009929 #define CONFIG_SYS_FSL_ERRATUM_A009942 diff --git a/board/freescale/ls1043aqds/ddr.c b/board/freescale/ls1043aqds/ddr.c index 3d3c533..07d61f5 100644 --- a/board/freescale/ls1043aqds/ddr.c +++ b/board/freescale/ls1043aqds/ddr.c @@ -7,6 +7,8 @@ #include <common.h> #include <fsl_ddr_sdram.h> #include <fsl_ddr_dimm_params.h> +#include <fsl_ddr.h> +#include <asm/io.h> #ifdef CONFIG_FSL_DEEP_SLEEP #include <fsl_sleep.h> #endif @@ -105,6 +107,24 @@ found: #endif }
+static void erratum_a008850(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850 + /* part 2 of 2 */ + struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR; + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + u32 tmp; + + /* enable propagation of barrier transactions to DDRC from CCI400 */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + + /* enable the re-ordering in DDRC */ + tmp = ddr_in32(&ddr->eor); + tmp &= ~(DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS); + ddr_out32(&ddr->eor, tmp); +#endif +} + phys_size_t initdram(int board_type) { phys_size_t dram_size; @@ -116,6 +136,7 @@ phys_size_t initdram(int board_type)
dram_size = fsl_ddr_sdram(); #endif + erratum_a008850();
#ifdef CONFIG_FSL_DEEP_SLEEP fsl_dp_ddr_restore(); diff --git a/board/freescale/ls1043aqds/ls1043aqds.c b/board/freescale/ls1043aqds/ls1043aqds.c index a72fe52..4ccfc79 100644 --- a/board/freescale/ls1043aqds/ls1043aqds.c +++ b/board/freescale/ls1043aqds/ls1043aqds.c @@ -305,14 +305,6 @@ int misc_init_r(void)
int board_init(void) { - struct ccsr_cci400 *cci = (struct ccsr_cci400 *) - CONFIG_SYS_CCI400_ADDR; - - /* Set CCI-400 control override register to enable barrier - * transaction */ - out_le32(&cci->ctrl_ord, - CCI400_CTRLORD_EN_BARRIER); - select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); board_retimer_init();
diff --git a/board/freescale/ls1043ardb/ddr.c b/board/freescale/ls1043ardb/ddr.c index 11bc0f2..9aa9d18 100644 --- a/board/freescale/ls1043ardb/ddr.c +++ b/board/freescale/ls1043ardb/ddr.c @@ -6,6 +6,8 @@
#include <common.h> #include <fsl_ddr_sdram.h> +#include <fsl_ddr.h> +#include <asm/io.h> #include <fsl_ddr_dimm_params.h> #include "ddr.h" #ifdef CONFIG_FSL_DEEP_SLEEP @@ -167,6 +169,24 @@ int fsl_ddr_get_dimm_params(dimm_params_t *pdimm, } #endif
+static void erratum_a008850(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850 + /* part 2 of 2 */ + struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR; + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + u32 tmp; + + /* enable propagation of barrier transactions to DDRC from CCI400 */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + + /* enable the re-ordering in DDRC */ + tmp = ddr_in32(&ddr->eor); + tmp &= ~(DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS); + ddr_out32(&ddr->eor, tmp); +#endif +} + phys_size_t initdram(int board_type) { phys_size_t dram_size; @@ -177,6 +197,8 @@ phys_size_t initdram(int board_type) #else dram_size = fsl_ddr_sdram_size(); #endif + erratum_a008850(); + #ifdef CONFIG_FSL_DEEP_SLEEP fsl_dp_ddr_restore(); #endif diff --git a/board/freescale/ls1043ardb/ls1043ardb.c b/board/freescale/ls1043ardb/ls1043ardb.c index 66d974a..1e2ef83 100644 --- a/board/freescale/ls1043ardb/ls1043ardb.c +++ b/board/freescale/ls1043ardb/ls1043ardb.c @@ -82,14 +82,6 @@ int board_early_init_f(void)
int board_init(void) { - struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; - - /* - * Set CCI-400 control override register to enable barrier - * transaction - */ - out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); - #ifdef CONFIG_FSL_IFC init_final_memctl_regs(); #endif diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index cf316a4..44ae7fb 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -146,6 +146,10 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t; #define WR_DATA_DELAY_SHIFT 10 #endif
+/* DDR_EOR register */ +#define DDR_EOR_RD_REOD_DIS 0x07000000 +#define DDR_EOR_WD_REOD_DIS 0x00100000 + /* DDR_MD_CNTL */ #define MD_CNTL_MD_EN 0x80000000 #define MD_CNTL_CS_SEL_CS0 0x00000000

Per the latest erratum document, update step 4 and step 8, only DEBUG_29[21] is changed, all other bits should not be changed.
Signed-off-by: Shengzhou Liu Shengzhou.Liu@nxp.com --- drivers/ddr/fsl/fsl_ddr_gen4.c | 10 +++++++--- include/fsl_ddr_sdram.h | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 608810d..7cdb700 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -240,8 +240,10 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, /* 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 transmit bit deskew */ + temp32 = ddr_in32(&ddr->debug[28]); + temp32 |= DDR_TX_BD_DIS; + ddr_out32(&ddr->debug[28], temp32); /* Disable D_INIT */ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT); @@ -358,7 +360,9 @@ step2: debug("MR6 = 0x%08x\n", temp32); } ddr_out32(&ddr->sdram_md_cntl, 0); - ddr_out32(&ddr->debug[28], 0); /* Enable deskew */ + temp32 = ddr_in32(&ddr->debug[28]); + temp32 &= ~DDR_TX_BD_DIS; /* Enable deskew */ + ddr_out32(&ddr->debug[28], temp32); ddr_out32(&ddr->debug[1], 0x400); /* restart deskew */ /* wait for idle */ timeout = 40; diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index 44ae7fb..acddf14 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -189,6 +189,9 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t; #define DDR_MR5_CA_PARITY_LAT_4_CLK 0x1 /* for DDR4-1600/1866/2133 */ #define DDR_MR5_CA_PARITY_LAT_5_CLK 0x2 /* for DDR4-2400 */
+/* DEBUG_29 register */ +#define DDR_TX_BD_DIS (1 << 10) /* Transmit Bit Deskew Disable */ +
#if (defined(CONFIG_SYS_FSL_DDR_VER) && \ (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7))

On 03/15/2016 10:59 PM, Shengzhou Liu wrote:
Per the latest erratum document, update step 4 and step 8, only DEBUG_29[21] is changed, all other bits should not be changed.
Signed-off-by: Shengzhou Liu Shengzhou.Liu@nxp.com
drivers/ddr/fsl/fsl_ddr_gen4.c | 10 +++++++--- include/fsl_ddr_sdram.h | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-)
Applied to u-boot-fsl-qoriq master, awaiting upstream.
Thanks.
York

On 03/15/2016 10:59 PM, Shengzhou Liu wrote:
Per the latest erratum document, update step 4 and step 8, only DEBUG_29[21] is changed, all other bits should not be changed.
Signed-off-by: Shengzhou Liu Shengzhou.Liu@nxp.com
drivers/ddr/fsl/fsl_ddr_gen4.c | 10 +++++++--- include/fsl_ddr_sdram.h | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-)
Applied to u-boot-fsl-qoriq master, awaiting upstream.
Thanks.
York

The initial training for the DDRC may provide results that are not optimized. The workaround provides better read timing margins.
Signed-off-by: Shengzhou Liu Shengzhou.Liu@nxp.com --- arch/arm/include/asm/arch-fsl-layerscape/config.h | 1 + drivers/ddr/fsl/fsl_ddr_gen4.c | 7 +++++++ include/fsl_ddr_sdram.h | 4 ++++ 3 files changed, 12 insertions(+)
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h index 6ec7e50..ba06465 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/config.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h @@ -119,6 +119,7 @@ #define CONFIG_SYS_FSL_ERRATUM_A008751 #define CONFIG_SYS_FSL_ERRATUM_A009635 #define CONFIG_SYS_FSL_ERRATUM_A009663 +#define CONFIG_SYS_FSL_ERRATUM_A009801 #define CONFIG_SYS_FSL_ERRATUM_A009803 #define CONFIG_SYS_FSL_ERRATUM_A009942
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 7cdb700..1dc0631 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -251,6 +251,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, } #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009801 + temp32 = ddr_in32(&ddr->debug[25]); + temp32 &= ~DDR_CAS_TO_PRE_SUB_MASK; + temp32 |= 9 << DDR_CAS_TO_PRE_SUB_SHIFT; + 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]); diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index acddf14..486e47e 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -189,6 +189,10 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t; #define DDR_MR5_CA_PARITY_LAT_4_CLK 0x1 /* for DDR4-1600/1866/2133 */ #define DDR_MR5_CA_PARITY_LAT_5_CLK 0x2 /* for DDR4-2400 */
+/* DEBUG_26 register */ +#define DDR_CAS_TO_PRE_SUB_MASK 0x0000f000 /* CAS to preamble subtract value */ +#define DDR_CAS_TO_PRE_SUB_SHIFT 12 + /* DEBUG_29 register */ #define DDR_TX_BD_DIS (1 << 10) /* Transmit Bit Deskew Disable */

On 03/15/2016 10:59 PM, Shengzhou Liu wrote:
The initial training for the DDRC may provide results that are not optimized. The workaround provides better read timing margins.
Signed-off-by: Shengzhou Liu Shengzhou.Liu@nxp.com
arch/arm/include/asm/arch-fsl-layerscape/config.h | 1 + drivers/ddr/fsl/fsl_ddr_gen4.c | 7 +++++++ include/fsl_ddr_sdram.h | 4 ++++ 3 files changed, 12 insertions(+)
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h index 6ec7e50..ba06465 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/config.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h @@ -119,6 +119,7 @@ #define CONFIG_SYS_FSL_ERRATUM_A008751 #define CONFIG_SYS_FSL_ERRATUM_A009635 #define CONFIG_SYS_FSL_ERRATUM_A009663 +#define CONFIG_SYS_FSL_ERRATUM_A009801 #define CONFIG_SYS_FSL_ERRATUM_A009803 #define CONFIG_SYS_FSL_ERRATUM_A009942
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 7cdb700..1dc0631 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -251,6 +251,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, } #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009801
- temp32 = ddr_in32(&ddr->debug[25]);
- temp32 &= ~DDR_CAS_TO_PRE_SUB_MASK;
- temp32 |= 9 << DDR_CAS_TO_PRE_SUB_SHIFT;
- ddr_out32(&ddr->debug[25], temp32);
+#endif
Shengzhou,
Please examine workaround for A008511. This workaround has been included, but wasn't named as A009801. You can move out that code and put under A009801 if like.
York

On 03/15/2016 10:59 PM, Shengzhou Liu wrote:
Barrier transactions from CCI400 need to be disabled till the DDR is configured, otherwise it may lead to system hang. The patch adds workaround to fix the erratum.
Signed-off-by: Shengzhou Liu Shengzhou.Liu@nxp.com
arch/arm/cpu/armv8/fsl-layerscape/soc.c | 18 ++++++++++++++++++ arch/arm/include/asm/arch-fsl-layerscape/config.h | 1 + board/freescale/ls1043aqds/ddr.c | 21 +++++++++++++++++++++ board/freescale/ls1043aqds/ls1043aqds.c | 8 -------- board/freescale/ls1043ardb/ddr.c | 22 ++++++++++++++++++++++ board/freescale/ls1043ardb/ls1043ardb.c | 8 -------- include/fsl_ddr_sdram.h | 4 ++++ 7 files changed, 66 insertions(+), 16 deletions(-)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 213ce3a..816bf1b 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -12,6 +12,8 @@ #include <asm/io.h> #include <asm/global_data.h> #include <asm/arch-fsl-layerscape/config.h> +#include <fsl_ddr_sdram.h> +#include <fsl_ddr.h> #ifdef CONFIG_CHAIN_OF_TRUST #include <fsl_validate.h> #endif @@ -231,6 +233,21 @@ static void erratum_a009660(void) #endif }
+static void erratum_a008850(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850
- /* part 1 of 2 */
- struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR;
- struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
- /* disables propagation of barrier transactions to DDRC from CCI400 */
- out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
- /* disable the re-ordering in DDRC */
- ddr_out32(&ddr->eor, DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS);
+#endif +}
void fsl_lsch2_early_init_f(void) { struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; @@ -255,6 +272,7 @@ void fsl_lsch2_early_init_f(void) CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
/* Erratum */
- erratum_a008850(); erratum_a009929(); erratum_a009660();
} diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h index b0c112b..6ec7e50 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/config.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h @@ -176,6 +176,7 @@ #define GICD_BASE 0x01401000 #define GICC_BASE 0x01402000
+#define CONFIG_SYS_FSL_ERRATUM_A008850 #define CONFIG_SYS_FSL_ERRATUM_A009663 #define CONFIG_SYS_FSL_ERRATUM_A009929 #define CONFIG_SYS_FSL_ERRATUM_A009942 diff --git a/board/freescale/ls1043aqds/ddr.c b/board/freescale/ls1043aqds/ddr.c index 3d3c533..07d61f5 100644 --- a/board/freescale/ls1043aqds/ddr.c +++ b/board/freescale/ls1043aqds/ddr.c @@ -7,6 +7,8 @@ #include <common.h> #include <fsl_ddr_sdram.h> #include <fsl_ddr_dimm_params.h> +#include <fsl_ddr.h> +#include <asm/io.h> #ifdef CONFIG_FSL_DEEP_SLEEP #include <fsl_sleep.h> #endif @@ -105,6 +107,24 @@ found: #endif }
+static void erratum_a008850(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850
- /* part 2 of 2 */
- struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR;
- struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR;
- u32 tmp;
- /* enable propagation of barrier transactions to DDRC from CCI400 */
- out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
- /* enable the re-ordering in DDRC */
- tmp = ddr_in32(&ddr->eor);
- tmp &= ~(DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS);
- ddr_out32(&ddr->eor, tmp);
+#endif +}
phys_size_t initdram(int board_type) { phys_size_t dram_size; @@ -116,6 +136,7 @@ phys_size_t initdram(int board_type)
dram_size = fsl_ddr_sdram(); #endif
- erratum_a008850();
#ifdef CONFIG_FSL_DEEP_SLEEP fsl_dp_ddr_restore();
Shengzhou,
Is there any ill-effect if the second part is missed? I am concerned if a customer board misses this part. Is there anyway to put the second part into soc file?
York
participants (3)
-
Shengzhou Liu
-
York Sun
-
york sun