[PATCH 9/9] ddr: imx9: Add errata registers support
Peng Fan (OSS)
peng.fan at oss.nxp.com
Mon Jul 28 05:24:55 CEST 2025
From: Viorel Suman <viorel.suman at nxp.com>
Collect errata registers values after the training and restore errata
registers values before starting quick boot firmware.
Signed-off-by: Viorel Suman <viorel.suman at nxp.com>
Reviewed-by: Tom Zheng <haidong.zheng at nxp.com>
Reviewed-by: Ye Li <ye.li at nxp.com>
Tested-by: Florin Pavelescu <florin.pavelescu 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/phy/Makefile | 4 ++--
drivers/ddr/imx/phy/ddrphy_qb.c | 4 ++++
drivers/ddr/imx/phy/ddrphy_qb_errata.c | 39 ++++++++++++++++++++++++++++++++++
drivers/ddr/imx/phy/ddrphy_qb_gen.c | 3 +++
5 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/arch-imx9/ddr.h b/arch/arm/include/asm/arch-imx9/ddr.h
index 6e5a3e3b6793d0171c2fbe6415821968ac1d3ba4..e30274035ca620fbcee46932b33374055aba3378 100644
--- a/arch/arm/include/asm/arch-imx9/ddr.h
+++ b/arch/arm/include/asm/arch-imx9/ddr.h
@@ -103,6 +103,7 @@ extern struct dram_timing_info dram_timing;
#if (defined(CONFIG_IMX_SNPS_DDR_PHY_QB_GEN) || defined(CONFIG_IMX_SNPS_DDR_PHY_QB))
#define DDRPHY_QB_FSP_SIZE 3
+#define DDRPHY_QB_ERR_SIZE 6
#define DDRPHY_QB_CSR_SIZE 1792
#define DDRPHY_QB_FLAG_2D BIT(0) /* =1 if First boot used 2D training, =0 otherwise */
@@ -110,13 +111,15 @@ struct ddrphy_qb_state {
u32 crc;
u32 flags;
u32 fsp[DDRPHY_QB_FSP_SIZE];
+ u32 err[DDRPHY_QB_ERR_SIZE];
u32 csr[DDRPHY_QB_CSR_SIZE];
};
#define DDRPHY_QB_STATE_SIZE \
- (sizeof(u32) * (1 + DDRPHY_QB_FSP_SIZE + DDRPHY_QB_CSR_SIZE))
+ (sizeof(u32) * (1 + DDRPHY_QB_FSP_SIZE + DDRPHY_QB_ERR_SIZE + DDRPHY_QB_CSR_SIZE))
extern struct ddrphy_qb_state qb_state;
+extern const u32 ddrphy_err_cfg[DDRPHY_QB_ERR_SIZE];
#if defined(CONFIG_IMX_SNPS_DDR_PHY_QB_GEN)
int ddrphy_qb_save(void);
diff --git a/drivers/ddr/imx/phy/Makefile b/drivers/ddr/imx/phy/Makefile
index 2310e69ab5c3036a2903465f4c4e95a79bf0b2c5..75c11625e8a23152e81700b747b216338af1406b 100644
--- a/drivers/ddr/imx/phy/Makefile
+++ b/drivers/ddr/imx/phy/Makefile
@@ -6,6 +6,6 @@
ifdef CONFIG_XPL_BUILD
obj-$(CONFIG_IMX_SNPS_DDR_PHY) += helper.o ddrphy_utils.o ddrphy_train.o
-obj-$(CONFIG_IMX_SNPS_DDR_PHY_QB_GEN) += ddrphy_qb_gen.o
-obj-$(CONFIG_IMX_SNPS_DDR_PHY_QB) += ddrphy_qb.o
+obj-$(CONFIG_IMX_SNPS_DDR_PHY_QB_GEN) += ddrphy_qb_gen.o ddrphy_qb_errata.o
+obj-$(CONFIG_IMX_SNPS_DDR_PHY_QB) += ddrphy_qb.o ddrphy_qb_errata.o
endif
diff --git a/drivers/ddr/imx/phy/ddrphy_qb.c b/drivers/ddr/imx/phy/ddrphy_qb.c
index 04a6520be5464ac26e30a516265b1b6993eec38c..2bd34bf91fad46e41b3581d79db3523b5442654e 100644
--- a/drivers/ddr/imx/phy/ddrphy_qb.c
+++ b/drivers/ddr/imx/phy/ddrphy_qb.c
@@ -47,6 +47,10 @@ static int ddrphy_qb_restore(struct dram_timing_info *info, int fsp_id)
ddrphy_w(0x5403c, 0x78, qb_state.fsp[2] >> 8); /* TrainedVREFDQ_B1 -> MR14_B1 */
}
+ /* restore errata registers */
+ for (i = 0; i < DDRPHY_QB_ERR_SIZE; i++)
+ dwc_ddrphy_apb_wr(ddrphy_err_cfg[i], qb_state.err[i]);
+
/* save CSRs to address starting with 0x54800 */
for (i = 0, to_addr = 0x54800; i < DDRPHY_QB_CSR_SIZE; i++, to_addr++)
dwc_ddrphy_apb_wr(to_addr, qb_state.csr[i]);
diff --git a/drivers/ddr/imx/phy/ddrphy_qb_errata.c b/drivers/ddr/imx/phy/ddrphy_qb_errata.c
new file mode 100644
index 0000000000000000000000000000000000000000..91843ab2d939fc973af35ce07a63b1b375463b92
--- /dev/null
+++ b/drivers/ddr/imx/phy/ddrphy_qb_errata.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <asm/arch/ddr.h>
+#include <linux/types.h>
+
+/** Errata CSRs
+ * STAR_3141216 0x020021 -> in ddrphy_csr_cfg
+ * STAR_3256585 0x02000b -> in ddrphy_csr_cfg
+ * 0x12000b -> in ddrphy_csr_cfg
+ * 0x22000b -> in ddrphy_csr_cfg
+ * STAR_3975199 0x0200c7
+ * 0x0200ca
+ * 0x1200c7
+ * 0x1200ca
+ * 0x2200c7
+ * 0x2200ca
+ * STAR_4101789 0x0200c7 -> covered by STAR_3975199
+ * 0x0200c5 -> in ddrphy_csr_cfg
+ * 0x1200c7 -> covered by STAR_3975199
+ * 0x1200c5 -> in ddrphy_csr_cfg
+ * 0x2200c7 -> covered by STAR_3975199
+ * 0x2200c5 -> in ddrphy_csr_cfg
+ */
+
+/**
+ * All from STAR_3975199, the remaining errata registers
+ * are covered by either ddrphy_csr_cfg or STAR_3975199
+ */
+const u32 ddrphy_err_cfg[DDRPHY_QB_ERR_SIZE] = {
+ 0x000200c7,
+ 0x000200ca,
+ 0x001200c7,
+ 0x001200ca,
+ 0x002200c7,
+ 0x002200ca,
+};
diff --git a/drivers/ddr/imx/phy/ddrphy_qb_gen.c b/drivers/ddr/imx/phy/ddrphy_qb_gen.c
index d77bb8480d85770d29e4408c2a723b20377833f0..981bfa88dc59c69905d14ffc6cfad4a92da35843 100644
--- a/drivers/ddr/imx/phy/ddrphy_qb_gen.c
+++ b/drivers/ddr/imx/phy/ddrphy_qb_gen.c
@@ -1819,6 +1819,9 @@ int ddrphy_qb_save(void)
/* enable the ddrphy apb */
dwc_ddrphy_apb_wr(0xd0000, 0x0);
+ for (i = 0; i < DDRPHY_QB_ERR_SIZE; i++)
+ qb_state.err[i] = dwc_ddrphy_apb_rd(ddrphy_err_cfg[i]);
+
for (i = 0; i < DDRPHY_QB_CSR_SIZE; i++)
qb_state.csr[i] = dwc_ddrphy_apb_rd(ddrphy_csr_cfg[i]);
--
2.35.3
More information about the U-Boot
mailing list