summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2022-10-11 14:21:04 +0800
committerYe Li <ye.li@nxp.com>2022-10-11 16:07:54 +0800
commit026521c7d6553ecc50b24bea61dba33ba7a5168d (patch)
tree171cd7d57772ba44703f10a505eed2b984888b40
parenta555a21be6916ac7238c84bf1fb70aa10cb44be2 (diff)
LFU-417-1 ddr: imx: imx9: Add DDR inline ECC support
Support DDR inline ECC feature for i.MX9 DDR driver. It uses top 1/8 DDR size for ECC data. Signed-off-by: Ye Li <ye.li@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com>
-rw-r--r--arch/arm/include/asm/arch-imx9/ddr.h4
-rw-r--r--drivers/ddr/imx/imx9/Kconfig6
-rw-r--r--drivers/ddr/imx/imx9/ddr_init.c35
3 files changed, 45 insertions, 0 deletions
diff --git a/arch/arm/include/asm/arch-imx9/ddr.h b/arch/arm/include/asm/arch-imx9/ddr.h
index 83983ed391..af5e6b5764 100644
--- a/arch/arm/include/asm/arch-imx9/ddr.h
+++ b/arch/arm/include/asm/arch-imx9/ddr.h
@@ -13,11 +13,15 @@
#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_DDRDSR_2 (DDR_CTL_BASE + 0xB24)
#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_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)
diff --git a/drivers/ddr/imx/imx9/Kconfig b/drivers/ddr/imx/imx9/Kconfig
index b1795eec35..0c2ee89c31 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 7cf1142f9a..17b4b259ac 100644
--- a/drivers/ddr/imx/imx9/ddr_init.c
+++ b/drivers/ddr/imx/imx9/ddr_init.c
@@ -197,6 +197,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;
@@ -233,6 +264,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