From dd8e740c789350fadeb9a13ab367380da2b9b42f Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Thu, 10 Mar 2016 17:36:57 +0800 Subject: [PATCH] driver/ddr/fsl: Add workaround for erratum A-009803 During initial DDR training, false parity errors may be detected. This patch adds workaround to fix the erratum. Tested on LS2085QDS and LS2080RDB. Signed-off-by: Shengzhou Liu Reviewed-by: York Sun --- .../include/asm/arch-fsl-layerscape/config.h | 1 + drivers/ddr/fsl/fsl_ddr_gen4.c | 44 ++++++++++++++++--- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h index 22f9c8fd65..bfaece2d67 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/config.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h @@ -121,6 +121,7 @@ #define CONFIG_SYS_FSL_ERRATUM_A008751 #define CONFIG_SYS_FSL_ERRATUM_A009635 #define CONFIG_SYS_FSL_ERRATUM_A009663 +#define CONFIG_SYS_FSL_ERRATUM_A009803 #define CONFIG_SYS_FSL_ERRATUM_A009942 /* ARM A57 CORE ERRATA */ diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 6f76980d31..608810d4e2 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -12,7 +12,8 @@ #include #include -#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008511) | \ + defined(CONFIG_SYS_FSL_ERRATUM_A009803) static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits) { int timeout = 1000; @@ -24,9 +25,9 @@ static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits) timeout--; } if (timeout <= 0) - puts("Error: A007865 wait for clear timeout.\n"); + puts("Error: wait for clear timeout.\n"); } -#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ +#endif #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL @@ -201,7 +202,18 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2); } + +#ifdef CONFIG_SYS_FSL_ERRATUM_A009803 + /* part 1 of 2 */ + if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { /* for RDIMM */ + ddr_out32(&ddr->ddr_sdram_rcw_2, + regs->ddr_sdram_rcw_2 & ~0x0f000000); + } + + ddr_out32(&ddr->err_disable, regs->err_disable | DDR_ERR_DISABLE_APED); +#else ddr_out32(&ddr->err_disable, regs->err_disable); +#endif ddr_out32(&ddr->err_int_en, regs->err_int_en); for (i = 0; i < 32; i++) { if (regs->debug[i]) { @@ -297,7 +309,8 @@ step2: mb(); isb(); -#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008511) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A009803) /* Part 2 of 2 */ /* This erraum only applies to verion 5.2.0 */ if (fsl_ddr_get_version(ctrl_num) == 0x50200) { @@ -313,6 +326,7 @@ step2: ctrl_num, ddr_in32(&ddr->debug[1])); } +#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 /* The vref setting sequence is different for range 2 */ if (regs->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2) vref_seq = vref_seq2; @@ -359,9 +373,29 @@ step2: } /* Restore D_INIT */ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); - } #endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009803 + /* if it's RDIMM */ + if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN)) + continue; + set_wait_for_bits_clear(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL(i) | + 0x070000ed, + MD_CNTL_MD_EN); + udelay(1); + } + } + + ddr_out32(&ddr->err_disable, + regs->err_disable & ~DDR_ERR_DISABLE_APED); +#endif + } +#endif + total_gb_size_per_controller = 0; for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { if (!(regs->cs[i].config & 0x80000000)) -- 2.39.5