From: Ye Li <ye...@nxp.com> Support DDR inline ECC feature for i.MX9 DDR driver. It uses top 1/8 DDR size for ECC data.
Reviewed-by: Peng Fan <peng....@nxp.com> Signed-off-by: Ye Li <ye...@nxp.com> Signed-off-by: Peng Fan <peng....@nxp.com> --- arch/arm/include/asm/arch-imx9/ddr.h | 5 ++++ drivers/ddr/imx/imx9/Kconfig | 6 +++++ drivers/ddr/imx/imx9/ddr_init.c | 35 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/arch/arm/include/asm/arch-imx9/ddr.h b/arch/arm/include/asm/arch-imx9/ddr.h index 10aaf486f29..45d1f69dac1 100644 --- a/arch/arm/include/asm/arch-imx9/ddr.h +++ b/arch/arm/include/asm/arch-imx9/ddr.h @@ -13,12 +13,17 @@ #define DDR_PHY_BASE 0x4E100000 #define DDRMIX_BLK_CTRL_BASE 0x4E010000 +#define REG_DDR_CS0_BNDS (DDR_CTL_BASE + 0x0) +#define REG_DDR_CS1_BNDS (DDR_CTL_BASE + 0x8) #define REG_DDR_TIMING_CFG_0 (DDR_CTL_BASE + 0x104) #define REG_DDR_SDRAM_CFG (DDR_CTL_BASE + 0x110) +#define REG_DDR_SDRAM_CFG2 (DDR_CTL_BASE + 0x114) #define REG_DDR_TIMING_CFG_4 (DDR_CTL_BASE + 0x160) #define REG_DDRDSR_2 (DDR_CTL_BASE + 0xB24) #define REG_DDR_DEBUG_19 (DDR_CTL_BASE + 0xF48) +#define REG_DDR_ERR_EN (DDR_CTL_BASE + 0x1000) + #define SRC_BASE_ADDR (0x44460000) #define SRC_DPHY_BASE_ADDR (SRC_BASE_ADDR + 0x1400) #define REG_SRC_DPHY_SW_CTRL (SRC_DPHY_BASE_ADDR + 0x20) diff --git a/drivers/ddr/imx/imx9/Kconfig b/drivers/ddr/imx/imx9/Kconfig index 123ad173cfc..95e15e5f800 100644 --- a/drivers/ddr/imx/imx9/Kconfig +++ b/drivers/ddr/imx/imx9/Kconfig @@ -17,6 +17,12 @@ config IMX9_DRAM_PM_COUNTER help Enable DDR controller performance monitor counter for reference events. +config IMX9_DRAM_INLINE_ECC + bool "Enable DDR INLINE ECC feature" + default n + help + Select to enable DDR INLINE ECC feature + config SAVED_DRAM_TIMING_BASE hex "Define the base address for saved dram timing" help diff --git a/drivers/ddr/imx/imx9/ddr_init.c b/drivers/ddr/imx/imx9/ddr_init.c index 651612611aa..ad298793929 100644 --- a/drivers/ddr/imx/imx9/ddr_init.c +++ b/drivers/ddr/imx/imx9/ddr_init.c @@ -196,6 +196,37 @@ void update_umctl2_rank_space_setting(unsigned int pstat_num) writel(tmp_t, REG_DDR_TIMING_CFG_4); } +void update_inline_ecc_setting(void) +{ + u32 val, sa, ea; + + val = readl(REG_DDR_CS0_BNDS); + if (val != 0) { + sa = (val >> 16) & 0xff; + ea = val & 0xff; + + /* 1/8 size is used for inline ecc */ + ea = ea - ((ea + 1 - sa) >> 3); + writel((sa << 16) | ea, REG_DDR_CS0_BNDS); + } + + val = readl(REG_DDR_CS1_BNDS); + if (val != 0) { + sa = (val >> 16) & 0xff; + ea = val & 0xff; + + /* 1/8 size is used for inline ecc */ + ea = ea - ((ea + 1 - sa) >> 3); + writel((sa << 16) | ea, REG_DDR_CS1_BNDS); + } + + /* Enable Inline ECC */ + setbits_le32(REG_DDR_ERR_EN, BIT(31) | BIT(30)); + + /* Enable data initialization */ + setbits_le32(REG_DDR_SDRAM_CFG2, BIT(4)); +} + int ddr_init(struct dram_timing_info *dram_timing) { unsigned int initial_drate; @@ -232,6 +263,10 @@ int ddr_init(struct dram_timing_info *dram_timing) update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1); +#ifdef CONFIG_IMX9_DRAM_INLINE_ECC + update_inline_ecc_setting(); +#endif + #ifdef CONFIG_IMX9_DRAM_PM_COUNTER writel(0x200000, REG_DDR_DEBUG_19); #endif -- 2.36.0