[PATCH 34/41] ddr: imx9: Add DDR inline ECC support

Peng Fan (OSS) peng.fan at oss.nxp.com
Mon Jan 23 10:16:53 CET 2023


From: Ye Li <ye.li at 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.fan at nxp.com>
Signed-off-by: Ye Li <ye.li at nxp.com>
Signed-off-by: Peng Fan <peng.fan at 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



More information about the U-Boot mailing list