mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2 0/4] ARM: i.MX8: add DDRC-ECC support
@ 2026-03-09  7:46 Steffen Trumtrar
  2026-03-09  7:46 ` [PATCH v2 1/4] ARM: i.MX: esdctl: fix spelling of ad(d)ress Steffen Trumtrar
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Steffen Trumtrar @ 2026-03-09  7:46 UTC (permalink / raw)
  To: barebox, Sascha Hauer; +Cc: Steffen Trumtrar, David Jander

The i.MX8 DDRC controller supports using inline ECC with the DDR RAM.
Inline ECC reduces the usable RAM size by 1/8: 7/8 RAM is for data and
1/8 RAM is for the ECC bits. Also, measuring random memory writes in
linux with

    stress-ng --memthrash 4 --memthrash-method chunk1 -t 1m --metrics

shows a performance decrease by ~10%.

If a board wants to support ECC, the lpddr4 RAM settings in the
according lpddr4-timing-* must be adapted to enable and configure the
ECC registers.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
Changes in v2:
- prt8ml: move ram timings to header
- prt8ml: build two images: with and without ecc
- add RAM size and scrubbing function to generic code
- Link to v1: https://lore.barebox.org/20260304-v2026-02-0-topic-imx8-ecc-v1-0-700698530c5c@pengutronix.de

---
David Jander (3):
      arm: mach-imx: esdctl.c: Add support for imx8mp inline ECC
      drivers: ddr: imx8m: ddr_init.c: support ECC scrubbing
      arm: boards: protonic-imx8ml: Add ECC + scrubbing

Steffen Trumtrar (1):
      ARM: i.MX: esdctl: fix spelling of ad(d)ress

 arch/arm/boards/protonic-imx8m/Makefile            |    2 +-
 arch/arm/boards/protonic-imx8m/lowlevel-prt8ml.c   |   21 +-
 .../protonic-imx8m/lpddr4-timing-prt8ml-ecc.c      |   26 +
 .../boards/protonic-imx8m/lpddr4-timing-prt8ml.c   | 1100 +------------------
 .../boards/protonic-imx8m/lpddr4-timing-prt8ml.h   | 1123 ++++++++++++++++++++
 arch/arm/dts/imx8mp-prt8ml.dts                     |   10 +-
 arch/arm/mach-imx/Kconfig                          |    9 +
 arch/arm/mach-imx/esdctl.c                         |   91 +-
 drivers/ddr/imx/imx8m_ddr_init.c                   |   95 ++
 images/Makefile.imx                                |    2 +
 include/soc/imx/ddr.h                              |    1 +
 include/soc/imx8m/ddr.h                            |    4 +
 12 files changed, 1370 insertions(+), 1114 deletions(-)
---
base-commit: f4122cb473bf8ca2d3d84cf7cd3c981d1da3309f
change-id: 20260304-v2026-02-0-topic-imx8-ecc-9206fee1f037

Best regards,
-- 
Steffen Trumtrar <s.trumtrar@pengutronix.de>




^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/4] ARM: i.MX: esdctl: fix spelling of ad(d)ress
  2026-03-09  7:46 [PATCH v2 0/4] ARM: i.MX8: add DDRC-ECC support Steffen Trumtrar
@ 2026-03-09  7:46 ` Steffen Trumtrar
  2026-03-09 14:56   ` Ahmad Fatoum
  2026-03-09  7:46 ` [PATCH v2 2/4] arm: mach-imx: esdctl.c: Add support for imx8mp inline ECC Steffen Trumtrar
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Steffen Trumtrar @ 2026-03-09  7:46 UTC (permalink / raw)
  To: barebox, Sascha Hauer; +Cc: Steffen Trumtrar

address is spelled with two 'd's. Fix the spelling mistake.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 arch/arm/mach-imx/esdctl.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 935c3d3257..b6689b7ffc 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -262,7 +262,7 @@ static int imx_esdctl_v4_add_mem(void *esdctlbase, const struct imx_esdctl_data
 }
 
 /*
- * On i.MX6 the adress space reserved for SDRAM is 0x10000000 to 0xFFFFFFFF
+ * On i.MX6 the address space reserved for SDRAM is 0x10000000 to 0xFFFFFFFF
  * which makes the maximum supported RAM size 0xF0000000.
  */
 #define IMX6_MAX_SDRAM_SIZE 0xF0000000
@@ -380,7 +380,7 @@ static resource_size_t
 imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
 		    u8 col_max, const u8 col_b[], unsigned int col_b_num,
 		    u8 row_max, const u8 row_b[], unsigned int row_b_num,
-		    bool reduced_adress_space, unsigned int mstr)
+		    bool reduced_address_space, unsigned int mstr)
 {
 	unsigned int banks, ranks, columns, rows, active_ranks, width;
 	resource_size_t size;
@@ -459,7 +459,7 @@ imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
 		size = memory_sdram_size(columns, rows, 1 << banks, 1) >> 1;
 	size <<= ranks;
 
-	return reduced_adress_space ? size * 3 / 4 : size;
+	return reduced_address_space ? size * 3 / 4 : size;
 }
 
 static void imx_ddrc_set_mstr_device_config(u32 *mstr, unsigned bits)
@@ -505,7 +505,7 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswid
 		FIELD_GET(DDRC_ADDRMAP6_ROW_B12, addrmap[6]),
 		FIELD_GET(DDRC_ADDRMAP5_ROW_B11, addrmap[5]),
 	};
-	const bool reduced_adress_space =
+	const bool reduced_address_space =
 		FIELD_GET(DDRC_ADDRMAP6_LPDDR4_6GB_12GB_24GB, addrmap[6]);
 	u32 mstr = readl(ddrc + DDRC_MSTR);
 
@@ -516,7 +516,7 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswid
 	return imx_ddrc_sdram_size(ddrc, addrmap,
 				   12, ARRAY_AND_SIZE(col_b),
 				   18, ARRAY_AND_SIZE(row_b),
-				   reduced_adress_space, mstr);
+				   reduced_address_space, mstr);
 }
 
 static int _imx8m_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data,
@@ -630,7 +630,7 @@ static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
 		FIELD_GET(DDRC_ADDRMAP6_ROW_B12, addrmap[6]),
 		FIELD_GET(DDRC_ADDRMAP5_ROW_B11, addrmap[5]),
 	};
-	const bool reduced_adress_space =
+	const bool reduced_address_space =
 		FIELD_GET(DDRC_ADDRMAP6_LPDDR3_6GB_12GB, addrmap[6]);
 	u32 mstr = readl(ddrc + DDRC_MSTR);
 
@@ -640,7 +640,7 @@ static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
 	return imx_ddrc_sdram_size(ddrc, addrmap,
 				   11, ARRAY_AND_SIZE(col_b),
 				   15, ARRAY_AND_SIZE(row_b),
-				   reduced_adress_space, mstr);
+				   reduced_address_space, mstr);
 }
 
 static int imx7d_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data)

-- 
2.52.0




^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 2/4] arm: mach-imx: esdctl.c: Add support for imx8mp inline ECC
  2026-03-09  7:46 [PATCH v2 0/4] ARM: i.MX8: add DDRC-ECC support Steffen Trumtrar
  2026-03-09  7:46 ` [PATCH v2 1/4] ARM: i.MX: esdctl: fix spelling of ad(d)ress Steffen Trumtrar
@ 2026-03-09  7:46 ` Steffen Trumtrar
  2026-03-09 14:56   ` Ahmad Fatoum
  2026-03-09  7:46 ` [PATCH v2 3/4] drivers: ddr: imx8m: ddr_init.c: support ECC scrubbing Steffen Trumtrar
  2026-03-09  7:46 ` [PATCH v2 4/4] arm: boards: protonic-imx8ml: Add ECC + scrubbing Steffen Trumtrar
  3 siblings, 1 reply; 9+ messages in thread
From: Steffen Trumtrar @ 2026-03-09  7:46 UTC (permalink / raw)
  To: barebox, Sascha Hauer; +Cc: Steffen Trumtrar, David Jander

From: David Jander <david@protonic.nl>

This adds support for detecting the use of inline ECC and compute the
correct memory bank(s) in that case.
In case inline ECC is active the memory map is modified as follows:
The total memory size is reduced to 7/8th of the raw memory size.
If a reduced-address-space type RAM is used (0.75, 1.5, 3, 6... GiB), then
the whole address space is split up into 3 equal parts, separated by 1/3rd
of the raw address space, but each 7/8th that size.
The ECC area at the end of each part is not addressable and must be
excluded from the map.

Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 arch/arm/mach-imx/Kconfig  |  8 +++++
 arch/arm/mach-imx/esdctl.c | 77 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index d244c57580..08b0a955c6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1026,6 +1026,14 @@ config HABV3_IMG_CRT_DER
 
 endif
 
+config IMX8MP_DRAM_ECC
+	bool
+	depends on ARCH_IMX8MP
+	help
+	  The i.MX8MP SoC supports ECC on the LPDDR4 memory. Select Y to enable
+	  this feature. The total amount of memory available will be reduced by
+	  1/8th.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index b6689b7ffc..4c1015e2bf 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -332,6 +332,9 @@ static int vf610_ddrmc_add_mem(void *mmdcbase, const struct imx_esdctl_data *dat
 #define DDRC_MSTR_ACTIVE_RANKS			GENMASK(27, 24)
 #define DDRC_MSTR_DEVICE_CONFIG		GENMASK(31, 30)
 
+#define DDRC_ECCCFG0				0x0070
+#define DDRC_ECCCFG0_ECC_MODE			GENMASK(2, 0)
+
 #define DDRC_ADDRMAP0_CS_BIT1			GENMASK(12,  8)
 
 #define DDRC_ADDRMAP1_BANK_B2			GENMASK(20, 16)
@@ -362,6 +365,11 @@ static int vf610_ddrmc_add_mem(void *mmdcbase, const struct imx_esdctl_data *dat
 
 #define DDRC_ADDRMAP_LENGTH			9
 
+static inline int imx_esdctl_ecc_enabled(void __iomem *ddrc)
+{
+	return FIELD_GET(DDRC_ECCCFG0_ECC_MODE, readl(ddrc + DDRC_ECCCFG0));
+}
+
 static unsigned int
 imx_ddrc_count_bits(unsigned int bits, const u8 config[],
 		     unsigned int config_num)
@@ -519,6 +527,33 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswid
 				   reduced_address_space, mstr);
 }
 
+static resource_size_t imx8mp_ddrc_sdram_size(void __iomem *ddrc,
+		unsigned int *chunks, resource_size_t *stride)
+{
+	resource_size_t size = imx8m_ddrc_sdram_size(ddrc, 32);
+	const bool reduced_address_space = FIELD_GET(
+		DDRC_ADDRMAP6_LPDDR4_6GB_12GB_24GB, readl(ddrc + DDRC_ADDRMAP(6)));
+
+	/* ECC devides the accessible address space into 1 or 3 contiguous
+	 * regions depending on reduced_address_space. For simplicity, give
+	 * barebox only one contiguous region to use.
+	 * Each region is only 7/8th the raw size due to ECC data.
+	 */
+	if (chunks)
+		*chunks = 1;
+	if (imx_esdctl_ecc_enabled(ddrc)) {
+		if (reduced_address_space) {
+			size /= 3;
+			if (chunks)
+				*chunks = 3;
+			if (stride)
+				*stride = size;
+		}
+		size = (size * 7) / 8;
+	}
+	return size;
+}
+
 static int _imx8m_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data,
 			       unsigned int buswidth)
 {
@@ -559,6 +594,29 @@ static int imx8m_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data
 	return _imx8m_ddrc_add_mem(mmdcbase, data, 32);
 }
 
+static int imx8mp_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data)
+{
+	unsigned int chunks;
+	unsigned long base;
+	resource_size_t chunksize = 0, stride = 0;
+	int ret = -ENOMEM;
+	int i;
+	char name[5];
+
+	chunksize = imx8mp_ddrc_sdram_size(mmdcbase, &chunks, &stride);
+
+	base = data->base0;
+	for (i = 0; i < chunks; i++) {
+		snprintf(name, 5, "ram%d", i);
+		ret = arm_add_mem_device(name, base, chunksize);
+		if (ret)
+			break;
+		base += stride;
+	}
+
+	return ret;
+}
+
 static int imx8mn_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data)
 {
 	return _imx8m_ddrc_add_mem(mmdcbase, data, 16);
@@ -742,6 +800,11 @@ static __maybe_unused const struct imx_esdctl_data imx8mn_data = {
 	.add_mem = imx8mn_ddrc_add_mem,
 };
 
+static __maybe_unused const struct imx_esdctl_data imx8mp_data = {
+	.base0 = MX8M_DDR_CSD1_BASE_ADDR,
+	.add_mem = imx8mp_ddrc_add_mem,
+};
+
 static __maybe_unused const struct imx_esdctl_data imx9_data = {
 	.base0 = MX9_DDR_CSD1_BASE_ADDR,
 	.add_mem = imx9_ddrc_add_mem,
@@ -822,6 +885,12 @@ static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = {
 	}, {
 		.compatible = "fsl,imx8mn-ddrc",
 		.data = &imx8mn_data
+	}, {
+		.compatible = "fsl,imx8mp-ddrc",
+		.data = &imx8mp_data
+	}, {
+		.compatible = "fsl,imx8mq-ddrc",
+		.data = &imx8mp_data
 	}, {
 		.compatible = "fsl,imx93-ddrc",
 		.data = &imx9_data
@@ -1000,9 +1069,15 @@ void __noreturn vf610_barebox_entry(void *boarddata)
 
 resource_size_t imx8m_barebox_earlymem_size(unsigned buswidth)
 {
+	unsigned int chunks;
+	resource_size_t stride = 0;
 	resource_size_t size;
 
-	size = imx8m_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), buswidth);
+	if (imx_esdctl_ecc_enabled(IOMEM(MX8M_DDRC_CTL_BASE_ADDR)))
+		size = imx8mp_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), &chunks,
+				&stride);
+	else
+		size = imx8m_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), buswidth);
 	/*
 	 * We artificially limit detected memory size to force malloc
 	 * pool placement to be within 4GiB address space, so as to

-- 
2.52.0




^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 3/4] drivers: ddr: imx8m: ddr_init.c: support ECC scrubbing
  2026-03-09  7:46 [PATCH v2 0/4] ARM: i.MX8: add DDRC-ECC support Steffen Trumtrar
  2026-03-09  7:46 ` [PATCH v2 1/4] ARM: i.MX: esdctl: fix spelling of ad(d)ress Steffen Trumtrar
  2026-03-09  7:46 ` [PATCH v2 2/4] arm: mach-imx: esdctl.c: Add support for imx8mp inline ECC Steffen Trumtrar
@ 2026-03-09  7:46 ` Steffen Trumtrar
  2026-03-09 15:12   ` Ahmad Fatoum
  2026-03-09  7:46 ` [PATCH v2 4/4] arm: boards: protonic-imx8ml: Add ECC + scrubbing Steffen Trumtrar
  3 siblings, 1 reply; 9+ messages in thread
From: Steffen Trumtrar @ 2026-03-09  7:46 UTC (permalink / raw)
  To: barebox, Sascha Hauer; +Cc: Steffen Trumtrar, David Jander

From: David Jander <david@protonic.nl>

This code comes from u-boot [1] and was introducesd in commit [2].

A fix from the patch [3] is also included, which doesn't seem to be
added to u-boot, yet.

[1] https://github.com/u-boot/u-boot/
[2] commit f3acb02386f4 ("drivers: ddr: imx8mp: Add inline ECC feature support")
[3] https://patchwork.ozlabs.org/project/uboot/patch/20230123091702.7472-32-peng.fan@oss.nxp.com/

Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/ddr/imx/imx8m_ddr_init.c | 95 ++++++++++++++++++++++++++++++++++++++++
 include/soc/imx/ddr.h            |  1 +
 include/soc/imx8m/ddr.h          |  4 ++
 3 files changed, 100 insertions(+)

diff --git a/drivers/ddr/imx/imx8m_ddr_init.c b/drivers/ddr/imx/imx8m_ddr_init.c
index c16e04d274..f601a51348 100644
--- a/drivers/ddr/imx/imx8m_ddr_init.c
+++ b/drivers/ddr/imx/imx8m_ddr_init.c
@@ -45,6 +45,96 @@ static void ddr_cfg_umctl2(struct dram_controller *dram, struct dram_cfg_param *
 	}
 }
 
+#ifdef CONFIG_IMX8MP_DRAM_ECC
+static void ddrc_inline_ecc_scrub(unsigned int start_address,
+				  unsigned int range_address)
+{
+	unsigned int tmp;
+
+	pr_debug("ECC scrub %08x-%08x\n", start_address, range_address);
+	/* Step1: Enable quasi-dynamic programming */
+	reg32_write(DDRC_SWCTL(0), 0x00000000);
+	/* Step2: Set ECCCFG1.ecc_parity_region_lock to 1 */
+	reg32setbit(DDRC_ECCCFG1(0), 0x4);
+	/* Step3: Block the AXI ports from taking the transaction */
+	reg32_write(DDRC_PCTRL_0(0), 0x0);
+	/* Step4: Set scrub start address */
+	reg32_write(DDRC_SBRSTART0(0), start_address);
+	/* Step5: Set scrub range address */
+	reg32_write(DDRC_SBRRANGE0(0), range_address);
+	/* Step6: Set scrub_mode to write */
+	reg32_write(DDRC_SBRCTL(0), 0x00000014);
+	/* Step7: Set the desired pattern through SBRWDATA0 registers */
+	reg32_write(DDRC_SBRWDATA0(0), 0x55aa55aa);
+	/* Step8: Enable the SBR by programming SBRCTL.scrub_en=1 */
+	reg32setbit(DDRC_SBRCTL(0), 0x0);
+	/* Step9: Poll SBRSTAT.scrub_done=1 */
+	tmp = reg32_read(DDRC_SBRSTAT(0));
+	while (tmp != 0x00000002)
+		tmp = reg32_read(DDRC_SBRSTAT(0)) & 0x2;
+	/* Step10: Poll SBRSTAT.scrub_busy=0 */
+	tmp = reg32_read(DDRC_SBRSTAT(0));
+	while (tmp != 0x0)
+		tmp = reg32_read(DDRC_SBRSTAT(0)) & 0x1;
+	/* Step11: Disable SBR by programming SBRCTL.scrub_en=0 */
+	clrbits_le32(DDRC_SBRCTL(0), 0x1);
+	/* Step12: Prepare for normal scrub operation(Read) and set scrub_interval*/
+	reg32_write(DDRC_SBRCTL(0), 0xff20);
+	/* Step13: Enable the SBR by programming SBRCTL.scrub_en=1 */
+	reg32_write(DDRC_SBRCTL(0), 0xff21);
+	/* Step14: Enable AXI ports by programming */
+	reg32_write(DDRC_PCTRL_0(0), 0x1);
+	/* Step15: Disable quasi-dynamic programming */
+	reg32_write(DDRC_SWCTL(0), 0x00000001);
+}
+
+static void ddrc_inline_ecc_scrub_end(unsigned int start_address,
+				      unsigned int range_address)
+{
+	pr_debug("ECC  end %08x-%08x\n", start_address, range_address);
+	/* Step1: Enable quasi-dynamic programming */
+	reg32_write(DDRC_SWCTL(0), 0x00000000);
+	/* Step2: Block the AXI ports from taking the transaction */
+	reg32_write(DDRC_PCTRL_0(0), 0x0);
+	/* Step3: Set scrub start address */
+	reg32_write(DDRC_SBRSTART0(0), start_address);
+	/* Step4: Set scrub range address */
+	reg32_write(DDRC_SBRRANGE0(0), range_address);
+	/* Step5: Disable SBR by programming SBRCTL.scrub_en=0 */
+	clrbits_le32(DDRC_SBRCTL(0), 0x1);
+	/* Step6: Prepare for normal scrub operation(Read) and set scrub_interval */
+	reg32_write(DDRC_SBRCTL(0), 0x100);
+	/* Step7: Enable the SBR by programming SBRCTL.scrub_en=1 */
+	reg32_write(DDRC_SBRCTL(0), 0x101);
+	/* Step8: Enable AXI ports by programming */
+	reg32_write(DDRC_PCTRL_0(0), 0x1);
+	/* Step9: Disable quasi-dynamic programming */
+	reg32_write(DDRC_SWCTL(0), 0x00000001);
+}
+
+static void dram_ecc_scrub(struct dram_timing_info *dram_timing)
+{
+	/* memory range to scrub in words (=1.75G) */
+	unsigned int range_in_words = 0x1c000000;
+	/* start scrubbing at RAM address */
+	unsigned int start_address;
+	/* scrub up until this address */
+	unsigned int range_address;
+
+	BUG_ON(!dram_timing->size);
+
+	for (start_address = 0x0;
+	     start_address + range_in_words - 1 <= dram_timing->size / 4;
+	     start_address += range_in_words + 0x04000000) {
+		range_address = start_address + range_in_words - 1;
+		/* scrub in 1.75G chunk sizes */
+		ddrc_inline_ecc_scrub(start_address, range_address);
+	}
+	
+	ddrc_inline_ecc_scrub_end(0x0, dram_timing->size / 4 - 1);
+}
+#endif
+
 static unsigned int g_cdd_rr_max[4];
 static unsigned int g_cdd_rw_max[4];
 static unsigned int g_cdd_wr_max[4];
@@ -642,6 +732,11 @@ int imx8m_ddr_init(struct dram_controller *dram, struct dram_timing_info *dram_t
 	reg32_write(DDRC_PCTRL_0(0), 0x00000001);
 	pr_debug("ddrmix config done\n");
 
+#ifdef CONFIG_IMX8MP_DRAM_ECC
+	if (dram->ddrc_type == DDRC_TYPE_MP)
+		dram_ecc_scrub(dram_timing);
+#endif
+
 	/* save the dram timing config into memory */
 	dram_config_save(dram, dram_timing, IMX8M_SAVED_DRAM_TIMING_BASE);
 
diff --git a/include/soc/imx/ddr.h b/include/soc/imx/ddr.h
index 6426062900..9a5d341100 100644
--- a/include/soc/imx/ddr.h
+++ b/include/soc/imx/ddr.h
@@ -101,6 +101,7 @@ struct dram_timing_info {
 		unsigned int ddrphy_pie_num;
 		/* initialized drate table */
 		unsigned int fsp_table[4];
+		resource_size_t size;
 	);
 };
 
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
index 5df07772b3..f07cef9a9e 100644
--- a/include/soc/imx8m/ddr.h
+++ b/include/soc/imx8m/ddr.h
@@ -186,6 +186,8 @@
 #define DDRC_SBRWDATA0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf2c)
 #define DDRC_SBRWDATA1(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf30)
 #define DDRC_PDCH(X)             (DDRC_IPS_BASE_ADDR(X) + 0xf34)
+#define DDRC_SBRSTART0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf38)
+#define DDRC_SBRRANGE0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf40)
 
 #define DDRC_FREQ1_DERATEEN(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2020)
 #define DDRC_FREQ1_DERATEINT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2024)
@@ -380,4 +382,6 @@ static inline void imx8m_ddr_load_train_code(enum dram_type dram_type,
 	ddr_load_train_code(&imx8m_dram_controller, dram_type, fw_type);
 }
 
+#define DDRC_PHY_REG(x)	((x) * 4)
+
 #endif

-- 
2.52.0




^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 4/4] arm: boards: protonic-imx8ml: Add ECC + scrubbing
  2026-03-09  7:46 [PATCH v2 0/4] ARM: i.MX8: add DDRC-ECC support Steffen Trumtrar
                   ` (2 preceding siblings ...)
  2026-03-09  7:46 ` [PATCH v2 3/4] drivers: ddr: imx8m: ddr_init.c: support ECC scrubbing Steffen Trumtrar
@ 2026-03-09  7:46 ` Steffen Trumtrar
  2026-03-09 15:21   ` Ahmad Fatoum
  3 siblings, 1 reply; 9+ messages in thread
From: Steffen Trumtrar @ 2026-03-09  7:46 UTC (permalink / raw)
  To: barebox, Sascha Hauer; +Cc: Steffen Trumtrar, David Jander

From: David Jander <david@protonic.nl>

Enable ECC settings in DDRC and add inline ECC scrub on the 3 memory
regions.
The scrubbing is a simpler version than the one generated with
mscale_ddr_tool from NXP. This is much faster and seems to work equally
well.
Documentation of this procedure is nowhere to be found unfortunately, so
proving that it is correct is impossible beyond simply testing it.

Start up time increases by ~800ms with ECC scrubbing enabled.

Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 arch/arm/boards/protonic-imx8m/Makefile            |    2 +-
 arch/arm/boards/protonic-imx8m/lowlevel-prt8ml.c   |   21 +-
 .../protonic-imx8m/lpddr4-timing-prt8ml-ecc.c      |   26 +
 .../boards/protonic-imx8m/lpddr4-timing-prt8ml.c   | 1100 +------------------
 .../boards/protonic-imx8m/lpddr4-timing-prt8ml.h   | 1123 ++++++++++++++++++++
 arch/arm/dts/imx8mp-prt8ml.dts                     |   10 +-
 arch/arm/mach-imx/Kconfig                          |    1 +
 images/Makefile.imx                                |    2 +
 8 files changed, 1179 insertions(+), 1106 deletions(-)

diff --git a/arch/arm/boards/protonic-imx8m/Makefile b/arch/arm/boards/protonic-imx8m/Makefile
index 67cab48083..2adce73f62 100644
--- a/arch/arm/boards/protonic-imx8m/Makefile
+++ b/arch/arm/boards/protonic-imx8m/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 obj-y += board.o
-lwl-y += lowlevel-prt8mm.o lowlevel-prt8ml.o lpddr4-timing-prt8mm.o lpddr4-timing-prt8ml.o
+lwl-y += lowlevel-prt8mm.o lowlevel-prt8ml.o lpddr4-timing-prt8mm.o lpddr4-timing-prt8ml.o lpddr4-timing-prt8ml-ecc.o
 bbenv-y += defaultenv-prt8m
diff --git a/arch/arm/boards/protonic-imx8m/lowlevel-prt8ml.c b/arch/arm/boards/protonic-imx8m/lowlevel-prt8ml.c
index ffbc08b6bc..842d02a5c0 100644
--- a/arch/arm/boards/protonic-imx8m/lowlevel-prt8ml.c
+++ b/arch/arm/boards/protonic-imx8m/lowlevel-prt8ml.c
@@ -36,8 +36,9 @@ static void setup_uart(void)
 
 /* read piggydata via a bootrom callback and place it behind our copy in SDRAM */
 extern struct dram_timing_info prt8ml_dram_timing;
+extern struct dram_timing_info prt8ml_dram_ecc_timing;
 
-static void start_atf(void)
+static void start_atf(struct dram_timing_info *timing)
 {
 	/*
 	 * If we are in EL3 we are running for the first time and need to
@@ -51,7 +52,7 @@ static void start_atf(void)
 
 	imx8mp_early_clock_init();
 
-	imx8mp_ddr_init(&prt8ml_dram_timing, DRAM_TYPE_LPDDR4);
+	imx8mp_ddr_init(timing, DRAM_TYPE_LPDDR4);
 
 	imx8mp_load_and_start_image_via_tfa();
 }
@@ -72,11 +73,11 @@ static void start_atf(void)
  *
  * 4. Standard barebox boot flow continues
  */
-static __noreturn noinline void prt_prt8ml_start(void)
+static __noreturn noinline void prt_prt8ml_start(struct dram_timing_info *timing)
 {
 	setup_uart();
 
-	start_atf();
+	start_atf(timing);
 
 	/*
 	 * Standard entry we hit once we initialized both DDR and ATF
@@ -91,5 +92,15 @@ ENTRY_FUNCTION(start_prt_prt8ml, r0, r1, r2)
 	relocate_to_current_adr();
 	setup_c();
 
-	prt_prt8ml_start();
+	prt_prt8ml_start(&prt8ml_dram_timing);
+}
+
+ENTRY_FUNCTION(start_prt_prt8ml_ecc, r0, r1, r2)
+{
+	imx8mp_cpu_lowlevel_init();
+
+	relocate_to_current_adr();
+	setup_c();
+
+	prt_prt8ml_start(&prt8ml_dram_ecc_timing);
 }
diff --git a/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml-ecc.c b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml-ecc.c
new file mode 100644
index 0000000000..7a3960c118
--- /dev/null
+++ b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml-ecc.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <linux/sizes.h>
+#include <soc/imx8m/ddr.h>
+#include <soc/imx8m/lpddr4_define.h>
+
+#define USE_ECC
+#include "lpddr4-timing-prt8ml.h"
+
+/* ddr timing config params */
+struct dram_timing_info prt8ml_dram_ecc_timing = {
+	.ddrc_cfg = ddr_ddrc_cfg,
+	.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg),
+	.ddrphy_cfg = ddr_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg),
+	.fsp_msg = ddr_dram_fsp_msg,
+	.fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg),
+	.ddrphy_pie = ddr_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
+	.fsp_table = { 4000, 400, 100, },
+	.size = SZ_4G + SZ_2G,
+};
diff --git a/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml.c b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml.c
index 913db8786f..1db9c3bd5d 100644
--- a/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml.c
+++ b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml.c
@@ -7,1105 +7,7 @@
 #include <soc/imx8m/ddr.h>
 #include <soc/imx8m/lpddr4_define.h>
 
-static struct dram_cfg_param ddr_ddrc_cfg[] = {
-	/** Initialize DDRC registers **/
-	{ 0x3d400304, 0x1 },
-	{ 0x3d400030, 0x1 },
-	{ 0x3d400000, 0xe3080020 },
-	{ 0x3d400020, 0x1303 },
-	{ 0x3d400024, 0x1e84800 },
-	{ 0x3d400064, 0x7a017c },
-	{ 0x3d4000d0, 0xc00307a3 },
-	{ 0x3d4000d4, 0xc50000 },
-	{ 0x3d4000dc, 0xf4003f },
-	{ 0x3d4000e0, 0x330000 },
-	{ 0x3d4000e8, 0x660048 },
-	{ 0x3d4000ec, 0x160048 },
-	{ 0x3d400100, 0x2028222a },
-	{ 0x3d400104, 0x8083f },
-	{ 0x3d40010c, 0xe0e000 },
-	{ 0x3d400110, 0x12040a12 },
-	{ 0x3d400114, 0x2050f0f },
-	{ 0x3d400118, 0x1010009 },
-	{ 0x3d40011c, 0x501 },
-	{ 0x3d400130, 0x20800 },
-	{ 0x3d400134, 0xe100002 },
-	{ 0x3d400138, 0x184 },
-	{ 0x3d400144, 0xc80064 },
-	{ 0x3d400180, 0x3e8001e },
-	{ 0x3d400184, 0x3207a12 },
-	{ 0x3d400188, 0x0 },
-	{ 0x3d400190, 0x49f820e },
-	{ 0x3d400194, 0x80303 },
-	{ 0x3d4001b4, 0x1f0e },
-	{ 0x3d4001a0, 0xe0400018 },
-	{ 0x3d4001a4, 0xdf00e4 },
-	{ 0x3d4001a8, 0x80000000 },
-	{ 0x3d4001b0, 0x11 },
-	{ 0x3d4001c0, 0x1 },
-	{ 0x3d4001c4, 0x1 },
-
-	{ 0x3d4000f4, 0xc99 },
-	{ 0x3d400108, 0x9121c1c },
-	{ 0x3d400200, 0x16 },
-	{ 0x3d40020c, 0x0 },
-	{ 0x3d400210, 0x1f1f },
-	{ 0x3d400204, 0x80808 },
-	{ 0x3d400214, 0x7070707 },
-	{ 0x3d400218, 0x68070707 },
-	{ 0x3d40021c, 0xf08 },
-	{ 0x3d400250, 0x00001705 },
-	{ 0x3d400254, 0x2c },
-	{ 0x3d40025c, 0x4000030 },
-	{ 0x3d400264, 0x900093e7 },
-	{ 0x3d40026c, 0x2005574 },
-	{ 0x3d400400, 0x111 },
-	{ 0x3d400404, 0x72ff },
-	{ 0x3d400408, 0x72ff },
-	{ 0x3d400494, 0x2100e07 },
-	{ 0x3d400498, 0x620096 },
-	{ 0x3d40049c, 0x1100e07 },
-	{ 0x3d4004a0, 0xc8012c },
-
-/* DDR 200MHz clock configuration */
-	{ 0x3d402020, 0x1001 },
-	{ 0x3d402024, 0x30d400 },
-	{ 0x3d402050, 0x20d000 },
-	{ 0x3d402064, 0xc0026 },
-	{ 0x3d4020dc, 0x840000 },
-	{ 0x3d4020e0, 0x330000 },
-	{ 0x3d4020e8, 0x660048 },
-	{ 0x3d4020ec, 0x160048 },
-	{ 0x3d402100, 0xa040305 },
-	{ 0x3d402104, 0x30407 },
-	{ 0x3d402108, 0x203060b },
-	{ 0x3d40210c, 0x505000 },
-	{ 0x3d402110, 0x2040202 },
-	{ 0x3d402114, 0x2030202 },
-	{ 0x3d402118, 0x1010004 },
-	{ 0x3d40211c, 0x301 },
-	{ 0x3d402130, 0x20300 },
-	{ 0x3d402134, 0xa100002 },
-	{ 0x3d402138, 0x27 },
-	{ 0x3d402144, 0x14000a },
-	{ 0x3d402180, 0x640004 },
-	{ 0x3d402190, 0x3818200 },
-	{ 0x3d402194, 0x80303 },
-	{ 0x3d4021b4, 0x100 },
-	{ 0x3d4020f4, 0xc99 },
-
-/* DDR 50MHz clock configuration */
-	{ 0x3d403020, 0x1001 },
-	{ 0x3d403024, 0xc3500 },
-	{ 0x3d403050, 0x20d000 },
-	{ 0x3d403064, 0x3000a },
-	{ 0x3d4030dc, 0x840000 },
-	{ 0x3d4030e0, 0x330000 },
-	{ 0x3d4030e8, 0x660048 },
-	{ 0x3d4030ec, 0x160048 },
-	{ 0x3d403100, 0xa010102 },
-	{ 0x3d403104, 0x30404 },
-	{ 0x3d403108, 0x203060b },
-	{ 0x3d40310c, 0x505000 },
-	{ 0x3d403110, 0x2040202 },
-	{ 0x3d403114, 0x2030202 },
-	{ 0x3d403118, 0x1010004 },
-	{ 0x3d40311c, 0x301 },
-	{ 0x3d403130, 0x20300 },
-	{ 0x3d403134, 0xa100002 },
-	{ 0x3d403138, 0xa },
-	{ 0x3d403144, 0x50003 },
-	{ 0x3d403180, 0x190004 },
-	{ 0x3d403190, 0x3818200 },
-	{ 0x3d403194, 0x80303 },
-	{ 0x3d4031b4, 0x100 },
-	{ 0x3d4030f4, 0xc99 },
-	{ 0x3d400028, 0x0 },
-};
-
-/* PHY Initialize Configuration */
-static struct dram_cfg_param ddr_ddrphy_cfg[] = {
-	{ 0x100a0, 0x1 },
-	{ 0x100a1, 0x0 },
-	{ 0x100a2, 0x5 },
-	{ 0x100a3, 0x3 },
-	{ 0x100a4, 0x2 },
-	{ 0x100a5, 0x4 },
-	{ 0x100a6, 0x6 },
-	{ 0x100a7, 0x7 },
-	{ 0x110a0, 0x0 },
-	{ 0x110a1, 0x1 },
-	{ 0x110a2, 0x2 },
-	{ 0x110a3, 0x3 },
-	{ 0x110a4, 0x4 },
-	{ 0x110a5, 0x5 },
-	{ 0x110a6, 0x6 },
-	{ 0x110a7, 0x7 },
-	{ 0x120a0, 0x0 },
-	{ 0x120a1, 0x1 },
-	{ 0x120a2, 0x3 },
-	{ 0x120a3, 0x2 },
-	{ 0x120a4, 0x5 },
-	{ 0x120a5, 0x4 },
-	{ 0x120a6, 0x6 },
-	{ 0x120a7, 0x7 },
-	{ 0x130a0, 0x1 },
-	{ 0x130a1, 0x0 },
-	{ 0x130a2, 0x5 },
-	{ 0x130a3, 0x3 },
-	{ 0x130a4, 0x2 },
-	{ 0x130a5, 0x4 },
-	{ 0x130a6, 0x6 },
-	{ 0x130a7, 0x7 },
-	{ 0x1005f, 0x1ff },
-	{ 0x1015f, 0x1ff },
-	{ 0x1105f, 0x1ff },
-	{ 0x1115f, 0x1ff },
-	{ 0x1205f, 0x1ff },
-	{ 0x1215f, 0x1ff },
-	{ 0x1305f, 0x1ff },
-	{ 0x1315f, 0x1ff },
-	{ 0x11005f, 0x1ff },
-	{ 0x11015f, 0x1ff },
-	{ 0x11105f, 0x1ff },
-	{ 0x11115f, 0x1ff },
-	{ 0x11205f, 0x1ff },
-	{ 0x11215f, 0x1ff },
-	{ 0x11305f, 0x1ff },
-	{ 0x11315f, 0x1ff },
-	{ 0x21005f, 0x1ff },
-	{ 0x21015f, 0x1ff },
-	{ 0x21105f, 0x1ff },
-	{ 0x21115f, 0x1ff },
-	{ 0x21205f, 0x1ff },
-	{ 0x21215f, 0x1ff },
-	{ 0x21305f, 0x1ff },
-	{ 0x21315f, 0x1ff },
-	{ 0x55, 0x1ff },
-	{ 0x1055, 0x1ff },
-	{ 0x2055, 0x1ff },
-	{ 0x3055, 0x1ff },
-	{ 0x4055, 0x1ff },
-	{ 0x5055, 0x1ff },
-	{ 0x6055, 0x1ff },
-	{ 0x7055, 0x1ff },
-	{ 0x8055, 0x1ff },
-	{ 0x9055, 0x1ff },
-	{ 0x200c5, 0x18 },
-	{ 0x1200c5, 0x7 },
-	{ 0x2200c5, 0x7 },
-	{ 0x2002e, 0x2 },
-	{ 0x12002e, 0x2 },
-	{ 0x22002e, 0x2 },
-	{ 0x90204, 0x0 },
-	{ 0x190204, 0x0 },
-	{ 0x290204, 0x0 },
-	{ 0x20024, 0x1e3 },
-	{ 0x2003a, 0x2 },
-	{ 0x120024, 0x1e3 },
-	{ 0x2003a, 0x2 },
-	{ 0x220024, 0x1e3 },
-	{ 0x2003a, 0x2 },
-	{ 0x20056, 0x3 },
-	{ 0x120056, 0x3 },
-	{ 0x220056, 0x3 },
-	{ 0x1004d, 0xe00 },
-	{ 0x1014d, 0xe00 },
-	{ 0x1104d, 0xe00 },
-	{ 0x1114d, 0xe00 },
-	{ 0x1204d, 0xe00 },
-	{ 0x1214d, 0xe00 },
-	{ 0x1304d, 0xe00 },
-	{ 0x1314d, 0xe00 },
-	{ 0x11004d, 0xe00 },
-	{ 0x11014d, 0xe00 },
-	{ 0x11104d, 0xe00 },
-	{ 0x11114d, 0xe00 },
-	{ 0x11204d, 0xe00 },
-	{ 0x11214d, 0xe00 },
-	{ 0x11304d, 0xe00 },
-	{ 0x11314d, 0xe00 },
-	{ 0x21004d, 0xe00 },
-	{ 0x21014d, 0xe00 },
-	{ 0x21104d, 0xe00 },
-	{ 0x21114d, 0xe00 },
-	{ 0x21204d, 0xe00 },
-	{ 0x21214d, 0xe00 },
-	{ 0x21304d, 0xe00 },
-	{ 0x21314d, 0xe00 },
-	{ 0x10049, 0xeba },
-	{ 0x10149, 0xeba },
-	{ 0x11049, 0xeba },
-	{ 0x11149, 0xeba },
-	{ 0x12049, 0xeba },
-	{ 0x12149, 0xeba },
-	{ 0x13049, 0xeba },
-	{ 0x13149, 0xeba },
-	{ 0x110049, 0xeba },
-	{ 0x110149, 0xeba },
-	{ 0x111049, 0xeba },
-	{ 0x111149, 0xeba },
-	{ 0x112049, 0xeba },
-	{ 0x112149, 0xeba },
-	{ 0x113049, 0xeba },
-	{ 0x113149, 0xeba },
-	{ 0x210049, 0xeba },
-	{ 0x210149, 0xeba },
-	{ 0x211049, 0xeba },
-	{ 0x211149, 0xeba },
-	{ 0x212049, 0xeba },
-	{ 0x212149, 0xeba },
-	{ 0x213049, 0xeba },
-	{ 0x213149, 0xeba },
-	{ 0x43, 0x63 },
-	{ 0x1043, 0x63 },
-	{ 0x2043, 0x63 },
-	{ 0x3043, 0x63 },
-	{ 0x4043, 0x63 },
-	{ 0x5043, 0x63 },
-	{ 0x6043, 0x63 },
-	{ 0x7043, 0x63 },
-	{ 0x8043, 0x63 },
-	{ 0x9043, 0x63 },
-	{ 0x20018, 0x3 },
-	{ 0x20075, 0x4 },
-	{ 0x20050, 0x0 },
-	{ 0x20008, 0x3e8 },
-	{ 0x120008, 0x64 },
-	{ 0x220008, 0x19 },
-	{ 0x20088, 0x9 },
-	{ 0x200b2, 0x104 },
-	{ 0x10043, 0x5a1 },
-	{ 0x10143, 0x5a1 },
-	{ 0x11043, 0x5a1 },
-	{ 0x11143, 0x5a1 },
-	{ 0x12043, 0x5a1 },
-	{ 0x12143, 0x5a1 },
-	{ 0x13043, 0x5a1 },
-	{ 0x13143, 0x5a1 },
-	{ 0x1200b2, 0x104 },
-	{ 0x110043, 0x5a1 },
-	{ 0x110143, 0x5a1 },
-	{ 0x111043, 0x5a1 },
-	{ 0x111143, 0x5a1 },
-	{ 0x112043, 0x5a1 },
-	{ 0x112143, 0x5a1 },
-	{ 0x113043, 0x5a1 },
-	{ 0x113143, 0x5a1 },
-	{ 0x2200b2, 0x104 },
-	{ 0x210043, 0x5a1 },
-	{ 0x210143, 0x5a1 },
-	{ 0x211043, 0x5a1 },
-	{ 0x211143, 0x5a1 },
-	{ 0x212043, 0x5a1 },
-	{ 0x212143, 0x5a1 },
-	{ 0x213043, 0x5a1 },
-	{ 0x213143, 0x5a1 },
-	{ 0x200fa, 0x1 },
-	{ 0x1200fa, 0x1 },
-	{ 0x2200fa, 0x1 },
-	{ 0x20019, 0x1 },
-	{ 0x120019, 0x1 },
-	{ 0x220019, 0x1 },
-	{ 0x200f0, 0x660 },
-	{ 0x200f1, 0x0 },
-	{ 0x200f2, 0x4444 },
-	{ 0x200f3, 0x8888 },
-	{ 0x200f4, 0x5665 },
-	{ 0x200f5, 0x0 },
-	{ 0x200f6, 0x0 },
-	{ 0x200f7, 0xf000 },
-	{ 0x20025, 0x0 },
-	{ 0x2002d, 0x0 },
-	{ 0x12002d, 0x0 },
-	{ 0x22002d, 0x0 },
-	{ 0x2007d, 0x212 },
-	{ 0x12007d, 0x212 },
-	{ 0x22007d, 0x212 },
-	{ 0x2007c, 0x61 },
-	{ 0x12007c, 0x61 },
-	{ 0x22007c, 0x61 },
-	{ 0x1004a, 0x500 },
-	{ 0x1104a, 0x500 },
-	{ 0x1204a, 0x500 },
-	{ 0x1304a, 0x500 },
-	{ 0x2002c, 0x0 },
-};
-
-/* P0 message block paremeter for training firmware */
-static struct dram_cfg_param ddr_fsp0_cfg[] = {
-	{ 0xd0000, 0x0 },
-	{ 0x54003, 0xfa0 },
-	{ 0x54004, 0x2 },
-	{ 0x54005, 0x2228 },
-	{ 0x54006, 0x14 },
-	{ 0x54008, 0x131f },
-	{ 0x54009, 0xc8 },
-	{ 0x5400b, 0x2 },
-	{ 0x5400f, 0x100 },
-	{ 0x54012, 0x310 },
-	{ 0x54019, 0x3ff4 },
-	{ 0x5401a, 0x33 },
-	{ 0x5401b, 0x4866 },
-	{ 0x5401c, 0x4800 },
-	{ 0x5401e, 0x16 },
-	{ 0x5401f, 0x3ff4 },
-	{ 0x54020, 0x33 },
-	{ 0x54021, 0x4866 },
-	{ 0x54022, 0x4800 },
-	{ 0x54024, 0x16 },
-	{ 0x5402b, 0x1000 },
-	{ 0x5402c, 0x3 },
-	{ 0x54032, 0xf400 },
-	{ 0x54033, 0x333f },
-	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x48 },
-	{ 0x54036, 0x48 },
-	{ 0x54037, 0x1600 },
-	{ 0x54038, 0xf400 },
-	{ 0x54039, 0x333f },
-	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x48 },
-	{ 0x5403c, 0x48 },
-	{ 0x5403d, 0x1600 },
-	{ 0xd0000, 0x1 },
-};
-
-/* P1 message block paremeter for training firmware */
-static struct dram_cfg_param ddr_fsp1_cfg[] = {
-	{ 0xd0000, 0x0 },
-	{ 0x54002, 0x101 },
-	{ 0x54003, 0x190 },
-	{ 0x54004, 0x2 },
-	{ 0x54005, 0x2228 },
-	{ 0x54006, 0x14 },
-	{ 0x54008, 0x121f },
-	{ 0x54009, 0xc8 },
-	{ 0x5400b, 0x2 },
-	{ 0x5400f, 0x100 },
-	{ 0x54012, 0x310 },
-	{ 0x54019, 0x84 },
-	{ 0x5401a, 0x33 },
-	{ 0x5401b, 0x4866 },
-	{ 0x5401c, 0x4800 },
-	{ 0x5401e, 0x16 },
-	{ 0x5401f, 0x84 },
-	{ 0x54020, 0x33 },
-	{ 0x54021, 0x4866 },
-	{ 0x54022, 0x4800 },
-	{ 0x54024, 0x16 },
-	{ 0x5402b, 0x1000 },
-	{ 0x5402c, 0x3 },
-	{ 0x54032, 0x8400 },
-	{ 0x54033, 0x3300 },
-	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x48 },
-	{ 0x54036, 0x48 },
-	{ 0x54037, 0x1600 },
-	{ 0x54038, 0x8400 },
-	{ 0x54039, 0x3300 },
-	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x48 },
-	{ 0x5403c, 0x48 },
-	{ 0x5403d, 0x1600 },
-	{ 0xd0000, 0x1 },
-};
-
-/* P2 message block paremeter for training firmware */
-static struct dram_cfg_param ddr_fsp2_cfg[] = {
-	{ 0xd0000, 0x0 },
-	{ 0x54002, 0x102 },
-	{ 0x54003, 0x64 },
-	{ 0x54004, 0x2 },
-	{ 0x54005, 0x2228 },
-	{ 0x54006, 0x14 },
-	{ 0x54008, 0x121f },
-	{ 0x54009, 0xc8 },
-	{ 0x5400b, 0x2 },
-	{ 0x5400f, 0x100 },
-	{ 0x54012, 0x310 },
-	{ 0x54019, 0x84 },
-	{ 0x5401a, 0x33 },
-	{ 0x5401b, 0x4866 },
-	{ 0x5401c, 0x4800 },
-	{ 0x5401e, 0x16 },
-	{ 0x5401f, 0x84 },
-	{ 0x54020, 0x33 },
-	{ 0x54021, 0x4866 },
-	{ 0x54022, 0x4800 },
-	{ 0x54024, 0x16 },
-	{ 0x5402b, 0x1000 },
-	{ 0x5402c, 0x3 },
-	{ 0x54032, 0x8400 },
-	{ 0x54033, 0x3300 },
-	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x48 },
-	{ 0x54036, 0x48 },
-	{ 0x54037, 0x1600 },
-	{ 0x54038, 0x8400 },
-	{ 0x54039, 0x3300 },
-	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x48 },
-	{ 0x5403c, 0x48 },
-	{ 0x5403d, 0x1600 },
-	{ 0xd0000, 0x1 },
-};
-
-/* P0 2D message block paremeter for training firmware */
-static struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
-	{ 0xd0000, 0x0 },
-	{ 0x54003, 0xfa0 },
-	{ 0x54004, 0x2 },
-	{ 0x54005, 0x2228 },
-	{ 0x54006, 0x14 },
-	{ 0x54008, 0x61 },
-	{ 0x54009, 0xc8 },
-	{ 0x5400b, 0x2 },
-	{ 0x5400f, 0x100 },
-	{ 0x54010, 0x1f7f },
-	{ 0x54012, 0x310 },
-	{ 0x54019, 0x3ff4 },
-	{ 0x5401a, 0x33 },
-	{ 0x5401b, 0x4866 },
-	{ 0x5401c, 0x4800 },
-	{ 0x5401e, 0x16 },
-	{ 0x5401f, 0x3ff4 },
-	{ 0x54020, 0x33 },
-	{ 0x54021, 0x4866 },
-	{ 0x54022, 0x4800 },
-	{ 0x54024, 0x16 },
-	{ 0x5402b, 0x1000 },
-	{ 0x5402c, 0x3 },
-	{ 0x54032, 0xf400 },
-	{ 0x54033, 0x333f },
-	{ 0x54034, 0x6600 },
-	{ 0x54035, 0x48 },
-	{ 0x54036, 0x48 },
-	{ 0x54037, 0x1600 },
-	{ 0x54038, 0xf400 },
-	{ 0x54039, 0x333f },
-	{ 0x5403a, 0x6600 },
-	{ 0x5403b, 0x48 },
-	{ 0x5403c, 0x48 },
-	{ 0x5403d, 0x1600 },
-	{ 0xd0000, 0x1 },
-};
-
-/* DRAM PHY init engine image */
-static struct dram_cfg_param ddr_phy_pie[] = {
-	{ 0xd0000, 0x0 },
-	{ 0x90000, 0x10 },
-	{ 0x90001, 0x400 },
-	{ 0x90002, 0x10e },
-	{ 0x90003, 0x0 },
-	{ 0x90004, 0x0 },
-	{ 0x90005, 0x8 },
-	{ 0x90029, 0xb },
-	{ 0x9002a, 0x480 },
-	{ 0x9002b, 0x109 },
-	{ 0x9002c, 0x8 },
-	{ 0x9002d, 0x448 },
-	{ 0x9002e, 0x139 },
-	{ 0x9002f, 0x8 },
-	{ 0x90030, 0x478 },
-	{ 0x90031, 0x109 },
-	{ 0x90032, 0x0 },
-	{ 0x90033, 0xe8 },
-	{ 0x90034, 0x109 },
-	{ 0x90035, 0x2 },
-	{ 0x90036, 0x10 },
-	{ 0x90037, 0x139 },
-	{ 0x90038, 0xb },
-	{ 0x90039, 0x7c0 },
-	{ 0x9003a, 0x139 },
-	{ 0x9003b, 0x44 },
-	{ 0x9003c, 0x633 },
-	{ 0x9003d, 0x159 },
-	{ 0x9003e, 0x14f },
-	{ 0x9003f, 0x630 },
-	{ 0x90040, 0x159 },
-	{ 0x90041, 0x47 },
-	{ 0x90042, 0x633 },
-	{ 0x90043, 0x149 },
-	{ 0x90044, 0x4f },
-	{ 0x90045, 0x633 },
-	{ 0x90046, 0x179 },
-	{ 0x90047, 0x8 },
-	{ 0x90048, 0xe0 },
-	{ 0x90049, 0x109 },
-	{ 0x9004a, 0x0 },
-	{ 0x9004b, 0x7c8 },
-	{ 0x9004c, 0x109 },
-	{ 0x9004d, 0x0 },
-	{ 0x9004e, 0x1 },
-	{ 0x9004f, 0x8 },
-	{ 0x90050, 0x0 },
-	{ 0x90051, 0x45a },
-	{ 0x90052, 0x9 },
-	{ 0x90053, 0x0 },
-	{ 0x90054, 0x448 },
-	{ 0x90055, 0x109 },
-	{ 0x90056, 0x40 },
-	{ 0x90057, 0x633 },
-	{ 0x90058, 0x179 },
-	{ 0x90059, 0x1 },
-	{ 0x9005a, 0x618 },
-	{ 0x9005b, 0x109 },
-	{ 0x9005c, 0x40c0 },
-	{ 0x9005d, 0x633 },
-	{ 0x9005e, 0x149 },
-	{ 0x9005f, 0x8 },
-	{ 0x90060, 0x4 },
-	{ 0x90061, 0x48 },
-	{ 0x90062, 0x4040 },
-	{ 0x90063, 0x633 },
-	{ 0x90064, 0x149 },
-	{ 0x90065, 0x0 },
-	{ 0x90066, 0x4 },
-	{ 0x90067, 0x48 },
-	{ 0x90068, 0x40 },
-	{ 0x90069, 0x633 },
-	{ 0x9006a, 0x149 },
-	{ 0x9006b, 0x10 },
-	{ 0x9006c, 0x4 },
-	{ 0x9006d, 0x18 },
-	{ 0x9006e, 0x0 },
-	{ 0x9006f, 0x4 },
-	{ 0x90070, 0x78 },
-	{ 0x90071, 0x549 },
-	{ 0x90072, 0x633 },
-	{ 0x90073, 0x159 },
-	{ 0x90074, 0xd49 },
-	{ 0x90075, 0x633 },
-	{ 0x90076, 0x159 },
-	{ 0x90077, 0x94a },
-	{ 0x90078, 0x633 },
-	{ 0x90079, 0x159 },
-	{ 0x9007a, 0x441 },
-	{ 0x9007b, 0x633 },
-	{ 0x9007c, 0x149 },
-	{ 0x9007d, 0x42 },
-	{ 0x9007e, 0x633 },
-	{ 0x9007f, 0x149 },
-	{ 0x90080, 0x1 },
-	{ 0x90081, 0x633 },
-	{ 0x90082, 0x149 },
-	{ 0x90083, 0x0 },
-	{ 0x90084, 0xe0 },
-	{ 0x90085, 0x109 },
-	{ 0x90086, 0xa },
-	{ 0x90087, 0x10 },
-	{ 0x90088, 0x109 },
-	{ 0x90089, 0x9 },
-	{ 0x9008a, 0x3c0 },
-	{ 0x9008b, 0x149 },
-	{ 0x9008c, 0x9 },
-	{ 0x9008d, 0x3c0 },
-	{ 0x9008e, 0x159 },
-	{ 0x9008f, 0x18 },
-	{ 0x90090, 0x10 },
-	{ 0x90091, 0x109 },
-	{ 0x90092, 0x0 },
-	{ 0x90093, 0x3c0 },
-	{ 0x90094, 0x109 },
-	{ 0x90095, 0x18 },
-	{ 0x90096, 0x4 },
-	{ 0x90097, 0x48 },
-	{ 0x90098, 0x18 },
-	{ 0x90099, 0x4 },
-	{ 0x9009a, 0x58 },
-	{ 0x9009b, 0xb },
-	{ 0x9009c, 0x10 },
-	{ 0x9009d, 0x109 },
-	{ 0x9009e, 0x1 },
-	{ 0x9009f, 0x10 },
-	{ 0x900a0, 0x109 },
-	{ 0x900a1, 0x5 },
-	{ 0x900a2, 0x7c0 },
-	{ 0x900a3, 0x109 },
-	{ 0x40000, 0x811 },
-	{ 0x40020, 0x880 },
-	{ 0x40040, 0x0 },
-	{ 0x40060, 0x0 },
-	{ 0x40001, 0x4008 },
-	{ 0x40021, 0x83 },
-	{ 0x40041, 0x4f },
-	{ 0x40061, 0x0 },
-	{ 0x40002, 0x4040 },
-	{ 0x40022, 0x83 },
-	{ 0x40042, 0x51 },
-	{ 0x40062, 0x0 },
-	{ 0x40003, 0x811 },
-	{ 0x40023, 0x880 },
-	{ 0x40043, 0x0 },
-	{ 0x40063, 0x0 },
-	{ 0x40004, 0x720 },
-	{ 0x40024, 0xf },
-	{ 0x40044, 0x1740 },
-	{ 0x40064, 0x0 },
-	{ 0x40005, 0x16 },
-	{ 0x40025, 0x83 },
-	{ 0x40045, 0x4b },
-	{ 0x40065, 0x0 },
-	{ 0x40006, 0x716 },
-	{ 0x40026, 0xf },
-	{ 0x40046, 0x2001 },
-	{ 0x40066, 0x0 },
-	{ 0x40007, 0x716 },
-	{ 0x40027, 0xf },
-	{ 0x40047, 0x2800 },
-	{ 0x40067, 0x0 },
-	{ 0x40008, 0x716 },
-	{ 0x40028, 0xf },
-	{ 0x40048, 0xf00 },
-	{ 0x40068, 0x0 },
-	{ 0x40009, 0x720 },
-	{ 0x40029, 0xf },
-	{ 0x40049, 0x1400 },
-	{ 0x40069, 0x0 },
-	{ 0x4000a, 0xe08 },
-	{ 0x4002a, 0xc15 },
-	{ 0x4004a, 0x0 },
-	{ 0x4006a, 0x0 },
-	{ 0x4000b, 0x625 },
-	{ 0x4002b, 0x15 },
-	{ 0x4004b, 0x0 },
-	{ 0x4006b, 0x0 },
-	{ 0x4000c, 0x4028 },
-	{ 0x4002c, 0x80 },
-	{ 0x4004c, 0x0 },
-	{ 0x4006c, 0x0 },
-	{ 0x4000d, 0xe08 },
-	{ 0x4002d, 0xc1a },
-	{ 0x4004d, 0x0 },
-	{ 0x4006d, 0x0 },
-	{ 0x4000e, 0x625 },
-	{ 0x4002e, 0x1a },
-	{ 0x4004e, 0x0 },
-	{ 0x4006e, 0x0 },
-	{ 0x4000f, 0x4040 },
-	{ 0x4002f, 0x80 },
-	{ 0x4004f, 0x0 },
-	{ 0x4006f, 0x0 },
-	{ 0x40010, 0x2604 },
-	{ 0x40030, 0x15 },
-	{ 0x40050, 0x0 },
-	{ 0x40070, 0x0 },
-	{ 0x40011, 0x708 },
-	{ 0x40031, 0x5 },
-	{ 0x40051, 0x0 },
-	{ 0x40071, 0x2002 },
-	{ 0x40012, 0x8 },
-	{ 0x40032, 0x80 },
-	{ 0x40052, 0x0 },
-	{ 0x40072, 0x0 },
-	{ 0x40013, 0x2604 },
-	{ 0x40033, 0x1a },
-	{ 0x40053, 0x0 },
-	{ 0x40073, 0x0 },
-	{ 0x40014, 0x708 },
-	{ 0x40034, 0xa },
-	{ 0x40054, 0x0 },
-	{ 0x40074, 0x2002 },
-	{ 0x40015, 0x4040 },
-	{ 0x40035, 0x80 },
-	{ 0x40055, 0x0 },
-	{ 0x40075, 0x0 },
-	{ 0x40016, 0x60a },
-	{ 0x40036, 0x15 },
-	{ 0x40056, 0x1200 },
-	{ 0x40076, 0x0 },
-	{ 0x40017, 0x61a },
-	{ 0x40037, 0x15 },
-	{ 0x40057, 0x1300 },
-	{ 0x40077, 0x0 },
-	{ 0x40018, 0x60a },
-	{ 0x40038, 0x1a },
-	{ 0x40058, 0x1200 },
-	{ 0x40078, 0x0 },
-	{ 0x40019, 0x642 },
-	{ 0x40039, 0x1a },
-	{ 0x40059, 0x1300 },
-	{ 0x40079, 0x0 },
-	{ 0x4001a, 0x4808 },
-	{ 0x4003a, 0x880 },
-	{ 0x4005a, 0x0 },
-	{ 0x4007a, 0x0 },
-	{ 0x900a4, 0x0 },
-	{ 0x900a5, 0x790 },
-	{ 0x900a6, 0x11a },
-	{ 0x900a7, 0x8 },
-	{ 0x900a8, 0x7aa },
-	{ 0x900a9, 0x2a },
-	{ 0x900aa, 0x10 },
-	{ 0x900ab, 0x7b2 },
-	{ 0x900ac, 0x2a },
-	{ 0x900ad, 0x0 },
-	{ 0x900ae, 0x7c8 },
-	{ 0x900af, 0x109 },
-	{ 0x900b0, 0x10 },
-	{ 0x900b1, 0x10 },
-	{ 0x900b2, 0x109 },
-	{ 0x900b3, 0x10 },
-	{ 0x900b4, 0x2a8 },
-	{ 0x900b5, 0x129 },
-	{ 0x900b6, 0x8 },
-	{ 0x900b7, 0x370 },
-	{ 0x900b8, 0x129 },
-	{ 0x900b9, 0xa },
-	{ 0x900ba, 0x3c8 },
-	{ 0x900bb, 0x1a9 },
-	{ 0x900bc, 0xc },
-	{ 0x900bd, 0x408 },
-	{ 0x900be, 0x199 },
-	{ 0x900bf, 0x14 },
-	{ 0x900c0, 0x790 },
-	{ 0x900c1, 0x11a },
-	{ 0x900c2, 0x8 },
-	{ 0x900c3, 0x4 },
-	{ 0x900c4, 0x18 },
-	{ 0x900c5, 0xe },
-	{ 0x900c6, 0x408 },
-	{ 0x900c7, 0x199 },
-	{ 0x900c8, 0x8 },
-	{ 0x900c9, 0x8568 },
-	{ 0x900ca, 0x108 },
-	{ 0x900cb, 0x18 },
-	{ 0x900cc, 0x790 },
-	{ 0x900cd, 0x16a },
-	{ 0x900ce, 0x8 },
-	{ 0x900cf, 0x1d8 },
-	{ 0x900d0, 0x169 },
-	{ 0x900d1, 0x10 },
-	{ 0x900d2, 0x8558 },
-	{ 0x900d3, 0x168 },
-	{ 0x900d4, 0x70 },
-	{ 0x900d5, 0x788 },
-	{ 0x900d6, 0x16a },
-	{ 0x900d7, 0x1ff8 },
-	{ 0x900d8, 0x85a8 },
-	{ 0x900d9, 0x1e8 },
-	{ 0x900da, 0x50 },
-	{ 0x900db, 0x798 },
-	{ 0x900dc, 0x16a },
-	{ 0x900dd, 0x60 },
-	{ 0x900de, 0x7a0 },
-	{ 0x900df, 0x16a },
-	{ 0x900e0, 0x8 },
-	{ 0x900e1, 0x8310 },
-	{ 0x900e2, 0x168 },
-	{ 0x900e3, 0x8 },
-	{ 0x900e4, 0xa310 },
-	{ 0x900e5, 0x168 },
-	{ 0x900e6, 0xa },
-	{ 0x900e7, 0x408 },
-	{ 0x900e8, 0x169 },
-	{ 0x900e9, 0x6e },
-	{ 0x900ea, 0x0 },
-	{ 0x900eb, 0x68 },
-	{ 0x900ec, 0x0 },
-	{ 0x900ed, 0x408 },
-	{ 0x900ee, 0x169 },
-	{ 0x900ef, 0x0 },
-	{ 0x900f0, 0x8310 },
-	{ 0x900f1, 0x168 },
-	{ 0x900f2, 0x0 },
-	{ 0x900f3, 0xa310 },
-	{ 0x900f4, 0x168 },
-	{ 0x900f5, 0x1ff8 },
-	{ 0x900f6, 0x85a8 },
-	{ 0x900f7, 0x1e8 },
-	{ 0x900f8, 0x68 },
-	{ 0x900f9, 0x798 },
-	{ 0x900fa, 0x16a },
-	{ 0x900fb, 0x78 },
-	{ 0x900fc, 0x7a0 },
-	{ 0x900fd, 0x16a },
-	{ 0x900fe, 0x68 },
-	{ 0x900ff, 0x790 },
-	{ 0x90100, 0x16a },
-	{ 0x90101, 0x8 },
-	{ 0x90102, 0x8b10 },
-	{ 0x90103, 0x168 },
-	{ 0x90104, 0x8 },
-	{ 0x90105, 0xab10 },
-	{ 0x90106, 0x168 },
-	{ 0x90107, 0xa },
-	{ 0x90108, 0x408 },
-	{ 0x90109, 0x169 },
-	{ 0x9010a, 0x58 },
-	{ 0x9010b, 0x0 },
-	{ 0x9010c, 0x68 },
-	{ 0x9010d, 0x0 },
-	{ 0x9010e, 0x408 },
-	{ 0x9010f, 0x169 },
-	{ 0x90110, 0x0 },
-	{ 0x90111, 0x8b10 },
-	{ 0x90112, 0x168 },
-	{ 0x90113, 0x1 },
-	{ 0x90114, 0xab10 },
-	{ 0x90115, 0x168 },
-	{ 0x90116, 0x0 },
-	{ 0x90117, 0x1d8 },
-	{ 0x90118, 0x169 },
-	{ 0x90119, 0x80 },
-	{ 0x9011a, 0x790 },
-	{ 0x9011b, 0x16a },
-	{ 0x9011c, 0x18 },
-	{ 0x9011d, 0x7aa },
-	{ 0x9011e, 0x6a },
-	{ 0x9011f, 0xa },
-	{ 0x90120, 0x0 },
-	{ 0x90121, 0x1e9 },
-	{ 0x90122, 0x8 },
-	{ 0x90123, 0x8080 },
-	{ 0x90124, 0x108 },
-	{ 0x90125, 0xf },
-	{ 0x90126, 0x408 },
-	{ 0x90127, 0x169 },
-	{ 0x90128, 0xc },
-	{ 0x90129, 0x0 },
-	{ 0x9012a, 0x68 },
-	{ 0x9012b, 0x9 },
-	{ 0x9012c, 0x0 },
-	{ 0x9012d, 0x1a9 },
-	{ 0x9012e, 0x0 },
-	{ 0x9012f, 0x408 },
-	{ 0x90130, 0x169 },
-	{ 0x90131, 0x0 },
-	{ 0x90132, 0x8080 },
-	{ 0x90133, 0x108 },
-	{ 0x90134, 0x8 },
-	{ 0x90135, 0x7aa },
-	{ 0x90136, 0x6a },
-	{ 0x90137, 0x0 },
-	{ 0x90138, 0x8568 },
-	{ 0x90139, 0x108 },
-	{ 0x9013a, 0xb7 },
-	{ 0x9013b, 0x790 },
-	{ 0x9013c, 0x16a },
-	{ 0x9013d, 0x1f },
-	{ 0x9013e, 0x0 },
-	{ 0x9013f, 0x68 },
-	{ 0x90140, 0x8 },
-	{ 0x90141, 0x8558 },
-	{ 0x90142, 0x168 },
-	{ 0x90143, 0xf },
-	{ 0x90144, 0x408 },
-	{ 0x90145, 0x169 },
-	{ 0x90146, 0xd },
-	{ 0x90147, 0x0 },
-	{ 0x90148, 0x68 },
-	{ 0x90149, 0x0 },
-	{ 0x9014a, 0x408 },
-	{ 0x9014b, 0x169 },
-	{ 0x9014c, 0x0 },
-	{ 0x9014d, 0x8558 },
-	{ 0x9014e, 0x168 },
-	{ 0x9014f, 0x8 },
-	{ 0x90150, 0x3c8 },
-	{ 0x90151, 0x1a9 },
-	{ 0x90152, 0x3 },
-	{ 0x90153, 0x370 },
-	{ 0x90154, 0x129 },
-	{ 0x90155, 0x20 },
-	{ 0x90156, 0x2aa },
-	{ 0x90157, 0x9 },
-	{ 0x90158, 0x8 },
-	{ 0x90159, 0xe8 },
-	{ 0x9015a, 0x109 },
-	{ 0x9015b, 0x0 },
-	{ 0x9015c, 0x8140 },
-	{ 0x9015d, 0x10c },
-	{ 0x9015e, 0x10 },
-	{ 0x9015f, 0x8138 },
-	{ 0x90160, 0x104 },
-	{ 0x90161, 0x8 },
-	{ 0x90162, 0x448 },
-	{ 0x90163, 0x109 },
-	{ 0x90164, 0xf },
-	{ 0x90165, 0x7c0 },
-	{ 0x90166, 0x109 },
-	{ 0x90167, 0x0 },
-	{ 0x90168, 0xe8 },
-	{ 0x90169, 0x109 },
-	{ 0x9016a, 0x47 },
-	{ 0x9016b, 0x630 },
-	{ 0x9016c, 0x109 },
-	{ 0x9016d, 0x8 },
-	{ 0x9016e, 0x618 },
-	{ 0x9016f, 0x109 },
-	{ 0x90170, 0x8 },
-	{ 0x90171, 0xe0 },
-	{ 0x90172, 0x109 },
-	{ 0x90173, 0x0 },
-	{ 0x90174, 0x7c8 },
-	{ 0x90175, 0x109 },
-	{ 0x90176, 0x8 },
-	{ 0x90177, 0x8140 },
-	{ 0x90178, 0x10c },
-	{ 0x90179, 0x0 },
-	{ 0x9017a, 0x478 },
-	{ 0x9017b, 0x109 },
-	{ 0x9017c, 0x0 },
-	{ 0x9017d, 0x1 },
-	{ 0x9017e, 0x8 },
-	{ 0x9017f, 0x8 },
-	{ 0x90180, 0x4 },
-	{ 0x90181, 0x0 },
-	{ 0x90006, 0x8 },
-	{ 0x90007, 0x7c8 },
-	{ 0x90008, 0x109 },
-	{ 0x90009, 0x0 },
-	{ 0x9000a, 0x400 },
-	{ 0x9000b, 0x106 },
-	{ 0xd00e7, 0x400 },
-	{ 0x90017, 0x0 },
-	{ 0x9001f, 0x29 },
-	{ 0x90026, 0x68 },
-	{ 0x400d0, 0x0 },
-	{ 0x400d1, 0x101 },
-	{ 0x400d2, 0x105 },
-	{ 0x400d3, 0x107 },
-	{ 0x400d4, 0x10f },
-	{ 0x400d5, 0x202 },
-	{ 0x400d6, 0x20a },
-	{ 0x400d7, 0x20b },
-	{ 0x2003a, 0x2 },
-	{ 0x200be, 0x3 },
-	{ 0x2000b, 0x7d },
-	{ 0x2000c, 0xfa },
-	{ 0x2000d, 0x9c4 },
-	{ 0x2000e, 0x2c },
-	{ 0x12000b, 0xc },
-	{ 0x12000c, 0x19 },
-	{ 0x12000d, 0xfa },
-	{ 0x12000e, 0x10 },
-	{ 0x22000b, 0x3 },
-	{ 0x22000c, 0x6 },
-	{ 0x22000d, 0x3e },
-	{ 0x22000e, 0x10 },
-	{ 0x9000c, 0x0 },
-	{ 0x9000d, 0x173 },
-	{ 0x9000e, 0x60 },
-	{ 0x9000f, 0x6110 },
-	{ 0x90010, 0x2152 },
-	{ 0x90011, 0xdfbd },
-	{ 0x90012, 0x2060 },
-	{ 0x90013, 0x6152 },
-	{ 0x20010, 0x5a },
-	{ 0x20011, 0x3 },
-	{ 0x40080, 0xe0 },
-	{ 0x40081, 0x12 },
-	{ 0x40082, 0xe0 },
-	{ 0x40083, 0x12 },
-	{ 0x40084, 0xe0 },
-	{ 0x40085, 0x12 },
-	{ 0x140080, 0xe0 },
-	{ 0x140081, 0x12 },
-	{ 0x140082, 0xe0 },
-	{ 0x140083, 0x12 },
-	{ 0x140084, 0xe0 },
-	{ 0x140085, 0x12 },
-	{ 0x240080, 0xe0 },
-	{ 0x240081, 0x12 },
-	{ 0x240082, 0xe0 },
-	{ 0x240083, 0x12 },
-	{ 0x240084, 0xe0 },
-	{ 0x240085, 0x12 },
-	{ 0x400fd, 0xf },
-	{ 0x10011, 0x1 },
-	{ 0x10012, 0x1 },
-	{ 0x10013, 0x180 },
-	{ 0x10018, 0x1 },
-	{ 0x10002, 0x6209 },
-	{ 0x100b2, 0x1 },
-	{ 0x101b4, 0x1 },
-	{ 0x102b4, 0x1 },
-	{ 0x103b4, 0x1 },
-	{ 0x104b4, 0x1 },
-	{ 0x105b4, 0x1 },
-	{ 0x106b4, 0x1 },
-	{ 0x107b4, 0x1 },
-	{ 0x108b4, 0x1 },
-	{ 0x11011, 0x1 },
-	{ 0x11012, 0x1 },
-	{ 0x11013, 0x180 },
-	{ 0x11018, 0x1 },
-	{ 0x11002, 0x6209 },
-	{ 0x110b2, 0x1 },
-	{ 0x111b4, 0x1 },
-	{ 0x112b4, 0x1 },
-	{ 0x113b4, 0x1 },
-	{ 0x114b4, 0x1 },
-	{ 0x115b4, 0x1 },
-	{ 0x116b4, 0x1 },
-	{ 0x117b4, 0x1 },
-	{ 0x118b4, 0x1 },
-	{ 0x12011, 0x1 },
-	{ 0x12012, 0x1 },
-	{ 0x12013, 0x180 },
-	{ 0x12018, 0x1 },
-	{ 0x12002, 0x6209 },
-	{ 0x120b2, 0x1 },
-	{ 0x121b4, 0x1 },
-	{ 0x122b4, 0x1 },
-	{ 0x123b4, 0x1 },
-	{ 0x124b4, 0x1 },
-	{ 0x125b4, 0x1 },
-	{ 0x126b4, 0x1 },
-	{ 0x127b4, 0x1 },
-	{ 0x128b4, 0x1 },
-	{ 0x13011, 0x1 },
-	{ 0x13012, 0x1 },
-	{ 0x13013, 0x180 },
-	{ 0x13018, 0x1 },
-	{ 0x13002, 0x6209 },
-	{ 0x130b2, 0x1 },
-	{ 0x131b4, 0x1 },
-	{ 0x132b4, 0x1 },
-	{ 0x133b4, 0x1 },
-	{ 0x134b4, 0x1 },
-	{ 0x135b4, 0x1 },
-	{ 0x136b4, 0x1 },
-	{ 0x137b4, 0x1 },
-	{ 0x138b4, 0x1 },
-	{ 0x20089, 0x1 },
-	{ 0x20088, 0x19 },
-	{ 0xc0080, 0x2 },
-	{ 0xd0000, 0x1 }
-};
-
-static struct dram_fsp_msg ddr_dram_fsp_msg[] = {
-	{
-		/* P0 4000mts 1D */
-		.drate = 4000,
-		.fw_type = FW_1D_IMAGE,
-		.fsp_cfg = ddr_fsp0_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
-	},
-	{
-		/* P1 400mts 1D */
-		.drate = 400,
-		.fw_type = FW_1D_IMAGE,
-		.fsp_cfg = ddr_fsp1_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg),
-	},
-	{
-		/* P2 100mts 1D */
-		.drate = 100,
-		.fw_type = FW_1D_IMAGE,
-		.fsp_cfg = ddr_fsp2_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg),
-	},
-	{
-		/* P0 4000mts 2D */
-		.drate = 4000,
-		.fw_type = FW_2D_IMAGE,
-		.fsp_cfg = ddr_fsp0_2d_cfg,
-		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg),
-	},
-};
+#include "lpddr4-timing-prt8ml.h"
 
 /* ddr timing config params */
 struct dram_timing_info prt8ml_dram_timing = {
diff --git a/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml.h b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml.h
new file mode 100644
index 0000000000..1e7a6f8aad
--- /dev/null
+++ b/arch/arm/boards/protonic-imx8m/lpddr4-timing-prt8ml.h
@@ -0,0 +1,1123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <soc/imx8m/ddr.h>
+#include <soc/imx8m/lpddr4_define.h>
+
+static struct dram_cfg_param ddr_ddrc_cfg[] = {
+	/** Initialize DDRC registers **/
+	{ 0x3d400304, 0x1 },
+	{ 0x3d400030, 0x1 },
+	{ 0x3d400000, 0xe3080020 },
+	{ 0x3d400020, 0x1303 },
+	{ 0x3d400024, 0x1e84800 },
+	{ 0x3d400064, 0x7a017c },
+#ifdef USE_ECC
+	{ 0x3d400070, 0x01027f54 },
+#else
+	{ 0x3d400070, 0x01027f10 },
+#endif
+	{ 0x3d400074, 0x000007b0 },
+	{ 0x3d4000d0, 0xc00307a3 },
+	{ 0x3d4000d4, 0xc50000 },
+	{ 0x3d4000dc, 0xf4003f },
+	{ 0x3d4000e0, 0x330000 },
+	{ 0x3d4000e8, 0x660048 },
+	{ 0x3d4000ec, 0x160048 },
+	{ 0x3d400100, 0x2028222a },
+	{ 0x3d400104, 0x8083f },
+	{ 0x3d40010c, 0xe0e000 },
+	{ 0x3d400110, 0x12040a12 },
+	{ 0x3d400114, 0x2050f0f },
+	{ 0x3d400118, 0x1010009 },
+	{ 0x3d40011c, 0x501 },
+	{ 0x3d400130, 0x20800 },
+	{ 0x3d400134, 0xe100002 },
+	{ 0x3d400138, 0x184 },
+	{ 0x3d400144, 0xc80064 },
+	{ 0x3d400180, 0x3e8001e },
+	{ 0x3d400184, 0x3207a12 },
+	{ 0x3d400188, 0x0 },
+	{ 0x3d400190, 0x49f820e },
+	{ 0x3d400194, 0x80303 },
+	{ 0x3d4001b4, 0x1f0e },
+	{ 0x3d4001a0, 0xe0400018 },
+	{ 0x3d4001a4, 0xdf00e4 },
+	{ 0x3d4001a8, 0x80000000 },
+	{ 0x3d4001b0, 0x11 },
+	{ 0x3d4001c0, 0x1 },
+	{ 0x3d4001c4, 0x1 },
+
+	{ 0x3d4000f4, 0xc99 },
+	{ 0x3d400108, 0x9121c1c },
+#ifdef USE_ECC
+	{ 0x3d400200, 0x13 },
+	{ 0x3d400204, 0x00050505 },
+	{ 0x3d40020c, 0x13131300 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400214, 0x04040404 },
+	{ 0x3d400218, 0x68040404 },
+#else
+	{ 0x3d400200, 0x16 },
+	{ 0x3d40020c, 0x0 },
+	{ 0x3d400204, 0x80808 },
+	{ 0x3d400210, 0x1f1f },
+	{ 0x3d400214, 0x7070707 },
+	{ 0x3d400218, 0x68070707 },
+#endif
+	{ 0x3d40021c, 0xf08 },
+	{ 0x3d400250, 0x00001705 },
+	{ 0x3d400254, 0x2c },
+	{ 0x3d40025c, 0x4000030 },
+	{ 0x3d400264, 0x900093e7 },
+	{ 0x3d40026c, 0x2005574 },
+	{ 0x3d400400, 0x111 },
+	{ 0x3d400404, 0x72ff },
+	{ 0x3d400408, 0x72ff },
+	{ 0x3d400494, 0x2100e07 },
+	{ 0x3d400498, 0x620096 },
+	{ 0x3d40049c, 0x1100e07 },
+	{ 0x3d4004a0, 0xc8012c },
+
+/* DDR 200MHz clock configuration */
+	{ 0x3d402020, 0x1001 },
+	{ 0x3d402024, 0x30d400 },
+	{ 0x3d402050, 0x20d000 },
+	{ 0x3d402064, 0xc0026 },
+	{ 0x3d4020dc, 0x840000 },
+	{ 0x3d4020e0, 0x330000 },
+	{ 0x3d4020e8, 0x660048 },
+	{ 0x3d4020ec, 0x160048 },
+	{ 0x3d402100, 0xa040305 },
+	{ 0x3d402104, 0x30407 },
+	{ 0x3d402108, 0x203060b },
+	{ 0x3d40210c, 0x505000 },
+	{ 0x3d402110, 0x2040202 },
+	{ 0x3d402114, 0x2030202 },
+	{ 0x3d402118, 0x1010004 },
+	{ 0x3d40211c, 0x301 },
+	{ 0x3d402130, 0x20300 },
+	{ 0x3d402134, 0xa100002 },
+	{ 0x3d402138, 0x27 },
+	{ 0x3d402144, 0x14000a },
+	{ 0x3d402180, 0x640004 },
+	{ 0x3d402190, 0x3818200 },
+	{ 0x3d402194, 0x80303 },
+	{ 0x3d4021b4, 0x100 },
+	{ 0x3d4020f4, 0xc99 },
+
+/* DDR 50MHz clock configuration */
+	{ 0x3d403020, 0x1001 },
+	{ 0x3d403024, 0xc3500 },
+	{ 0x3d403050, 0x20d000 },
+	{ 0x3d403064, 0x3000a },
+	{ 0x3d4030dc, 0x840000 },
+	{ 0x3d4030e0, 0x330000 },
+	{ 0x3d4030e8, 0x660048 },
+	{ 0x3d4030ec, 0x160048 },
+	{ 0x3d403100, 0xa010102 },
+	{ 0x3d403104, 0x30404 },
+	{ 0x3d403108, 0x203060b },
+	{ 0x3d40310c, 0x505000 },
+	{ 0x3d403110, 0x2040202 },
+	{ 0x3d403114, 0x2030202 },
+	{ 0x3d403118, 0x1010004 },
+	{ 0x3d40311c, 0x301 },
+	{ 0x3d403130, 0x20300 },
+	{ 0x3d403134, 0xa100002 },
+	{ 0x3d403138, 0xa },
+	{ 0x3d403144, 0x50003 },
+	{ 0x3d403180, 0x190004 },
+	{ 0x3d403190, 0x3818200 },
+	{ 0x3d403194, 0x80303 },
+	{ 0x3d4031b4, 0x100 },
+	{ 0x3d4030f4, 0xc99 },
+	{ 0x3d400028, 0x0 },
+};
+
+/* PHY Initialize Configuration */
+static struct dram_cfg_param ddr_ddrphy_cfg[] = {
+	{ 0x100a0, 0x1 },
+	{ 0x100a1, 0x0 },
+	{ 0x100a2, 0x5 },
+	{ 0x100a3, 0x3 },
+	{ 0x100a4, 0x2 },
+	{ 0x100a5, 0x4 },
+	{ 0x100a6, 0x6 },
+	{ 0x100a7, 0x7 },
+	{ 0x110a0, 0x0 },
+	{ 0x110a1, 0x1 },
+	{ 0x110a2, 0x2 },
+	{ 0x110a3, 0x3 },
+	{ 0x110a4, 0x4 },
+	{ 0x110a5, 0x5 },
+	{ 0x110a6, 0x6 },
+	{ 0x110a7, 0x7 },
+	{ 0x120a0, 0x0 },
+	{ 0x120a1, 0x1 },
+	{ 0x120a2, 0x3 },
+	{ 0x120a3, 0x2 },
+	{ 0x120a4, 0x5 },
+	{ 0x120a5, 0x4 },
+	{ 0x120a6, 0x6 },
+	{ 0x120a7, 0x7 },
+	{ 0x130a0, 0x1 },
+	{ 0x130a1, 0x0 },
+	{ 0x130a2, 0x5 },
+	{ 0x130a3, 0x3 },
+	{ 0x130a4, 0x2 },
+	{ 0x130a5, 0x4 },
+	{ 0x130a6, 0x6 },
+	{ 0x130a7, 0x7 },
+	{ 0x1005f, 0x1ff },
+	{ 0x1015f, 0x1ff },
+	{ 0x1105f, 0x1ff },
+	{ 0x1115f, 0x1ff },
+	{ 0x1205f, 0x1ff },
+	{ 0x1215f, 0x1ff },
+	{ 0x1305f, 0x1ff },
+	{ 0x1315f, 0x1ff },
+	{ 0x11005f, 0x1ff },
+	{ 0x11015f, 0x1ff },
+	{ 0x11105f, 0x1ff },
+	{ 0x11115f, 0x1ff },
+	{ 0x11205f, 0x1ff },
+	{ 0x11215f, 0x1ff },
+	{ 0x11305f, 0x1ff },
+	{ 0x11315f, 0x1ff },
+	{ 0x21005f, 0x1ff },
+	{ 0x21015f, 0x1ff },
+	{ 0x21105f, 0x1ff },
+	{ 0x21115f, 0x1ff },
+	{ 0x21205f, 0x1ff },
+	{ 0x21215f, 0x1ff },
+	{ 0x21305f, 0x1ff },
+	{ 0x21315f, 0x1ff },
+	{ 0x55, 0x1ff },
+	{ 0x1055, 0x1ff },
+	{ 0x2055, 0x1ff },
+	{ 0x3055, 0x1ff },
+	{ 0x4055, 0x1ff },
+	{ 0x5055, 0x1ff },
+	{ 0x6055, 0x1ff },
+	{ 0x7055, 0x1ff },
+	{ 0x8055, 0x1ff },
+	{ 0x9055, 0x1ff },
+	{ 0x200c5, 0x18 },
+	{ 0x1200c5, 0x7 },
+	{ 0x2200c5, 0x7 },
+	{ 0x2002e, 0x2 },
+	{ 0x12002e, 0x2 },
+	{ 0x22002e, 0x2 },
+	{ 0x90204, 0x0 },
+	{ 0x190204, 0x0 },
+	{ 0x290204, 0x0 },
+	{ 0x20024, 0x1e3 },
+	{ 0x2003a, 0x2 },
+	{ 0x120024, 0x1e3 },
+	{ 0x2003a, 0x2 },
+	{ 0x220024, 0x1e3 },
+	{ 0x2003a, 0x2 },
+	{ 0x20056, 0x3 },
+	{ 0x120056, 0x3 },
+	{ 0x220056, 0x3 },
+	{ 0x1004d, 0xe00 },
+	{ 0x1014d, 0xe00 },
+	{ 0x1104d, 0xe00 },
+	{ 0x1114d, 0xe00 },
+	{ 0x1204d, 0xe00 },
+	{ 0x1214d, 0xe00 },
+	{ 0x1304d, 0xe00 },
+	{ 0x1314d, 0xe00 },
+	{ 0x11004d, 0xe00 },
+	{ 0x11014d, 0xe00 },
+	{ 0x11104d, 0xe00 },
+	{ 0x11114d, 0xe00 },
+	{ 0x11204d, 0xe00 },
+	{ 0x11214d, 0xe00 },
+	{ 0x11304d, 0xe00 },
+	{ 0x11314d, 0xe00 },
+	{ 0x21004d, 0xe00 },
+	{ 0x21014d, 0xe00 },
+	{ 0x21104d, 0xe00 },
+	{ 0x21114d, 0xe00 },
+	{ 0x21204d, 0xe00 },
+	{ 0x21214d, 0xe00 },
+	{ 0x21304d, 0xe00 },
+	{ 0x21314d, 0xe00 },
+	{ 0x10049, 0xeba },
+	{ 0x10149, 0xeba },
+	{ 0x11049, 0xeba },
+	{ 0x11149, 0xeba },
+	{ 0x12049, 0xeba },
+	{ 0x12149, 0xeba },
+	{ 0x13049, 0xeba },
+	{ 0x13149, 0xeba },
+	{ 0x110049, 0xeba },
+	{ 0x110149, 0xeba },
+	{ 0x111049, 0xeba },
+	{ 0x111149, 0xeba },
+	{ 0x112049, 0xeba },
+	{ 0x112149, 0xeba },
+	{ 0x113049, 0xeba },
+	{ 0x113149, 0xeba },
+	{ 0x210049, 0xeba },
+	{ 0x210149, 0xeba },
+	{ 0x211049, 0xeba },
+	{ 0x211149, 0xeba },
+	{ 0x212049, 0xeba },
+	{ 0x212149, 0xeba },
+	{ 0x213049, 0xeba },
+	{ 0x213149, 0xeba },
+	{ 0x43, 0x63 },
+	{ 0x1043, 0x63 },
+	{ 0x2043, 0x63 },
+	{ 0x3043, 0x63 },
+	{ 0x4043, 0x63 },
+	{ 0x5043, 0x63 },
+	{ 0x6043, 0x63 },
+	{ 0x7043, 0x63 },
+	{ 0x8043, 0x63 },
+	{ 0x9043, 0x63 },
+	{ 0x20018, 0x3 },
+	{ 0x20075, 0x4 },
+	{ 0x20050, 0x0 },
+	{ 0x20008, 0x3e8 },
+	{ 0x120008, 0x64 },
+	{ 0x220008, 0x19 },
+	{ 0x20088, 0x9 },
+	{ 0x200b2, 0x104 },
+	{ 0x10043, 0x5a1 },
+	{ 0x10143, 0x5a1 },
+	{ 0x11043, 0x5a1 },
+	{ 0x11143, 0x5a1 },
+	{ 0x12043, 0x5a1 },
+	{ 0x12143, 0x5a1 },
+	{ 0x13043, 0x5a1 },
+	{ 0x13143, 0x5a1 },
+	{ 0x1200b2, 0x104 },
+	{ 0x110043, 0x5a1 },
+	{ 0x110143, 0x5a1 },
+	{ 0x111043, 0x5a1 },
+	{ 0x111143, 0x5a1 },
+	{ 0x112043, 0x5a1 },
+	{ 0x112143, 0x5a1 },
+	{ 0x113043, 0x5a1 },
+	{ 0x113143, 0x5a1 },
+	{ 0x2200b2, 0x104 },
+	{ 0x210043, 0x5a1 },
+	{ 0x210143, 0x5a1 },
+	{ 0x211043, 0x5a1 },
+	{ 0x211143, 0x5a1 },
+	{ 0x212043, 0x5a1 },
+	{ 0x212143, 0x5a1 },
+	{ 0x213043, 0x5a1 },
+	{ 0x213143, 0x5a1 },
+	{ 0x200fa, 0x1 },
+	{ 0x1200fa, 0x1 },
+	{ 0x2200fa, 0x1 },
+	{ 0x20019, 0x1 },
+	{ 0x120019, 0x1 },
+	{ 0x220019, 0x1 },
+	{ 0x200f0, 0x660 },
+	{ 0x200f1, 0x0 },
+	{ 0x200f2, 0x4444 },
+	{ 0x200f3, 0x8888 },
+	{ 0x200f4, 0x5665 },
+	{ 0x200f5, 0x0 },
+	{ 0x200f6, 0x0 },
+	{ 0x200f7, 0xf000 },
+	{ 0x20025, 0x0 },
+	{ 0x2002d, 0x0 },
+	{ 0x12002d, 0x0 },
+	{ 0x22002d, 0x0 },
+	{ 0x2007d, 0x212 },
+	{ 0x12007d, 0x212 },
+	{ 0x22007d, 0x212 },
+	{ 0x2007c, 0x61 },
+	{ 0x12007c, 0x61 },
+	{ 0x22007c, 0x61 },
+	{ 0x1004a, 0x500 },
+	{ 0x1104a, 0x500 },
+	{ 0x1204a, 0x500 },
+	{ 0x1304a, 0x500 },
+	{ 0x2002c, 0x0 },
+};
+
+/* P0 message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp0_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0xfa0 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x14 },
+	{ 0x54008, 0x131f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x3ff4 },
+	{ 0x5401a, 0x33 },
+	{ 0x5401b, 0x4866 },
+	{ 0x5401c, 0x4800 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x3ff4 },
+	{ 0x54020, 0x33 },
+	{ 0x54021, 0x4866 },
+	{ 0x54022, 0x4800 },
+	{ 0x54024, 0x16 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x54032, 0xf400 },
+	{ 0x54033, 0x333f },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x48 },
+	{ 0x54036, 0x48 },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0xf400 },
+	{ 0x54039, 0x333f },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x48 },
+	{ 0x5403c, 0x48 },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P1 message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp1_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54002, 0x101 },
+	{ 0x54003, 0x190 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x14 },
+	{ 0x54008, 0x121f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x84 },
+	{ 0x5401a, 0x33 },
+	{ 0x5401b, 0x4866 },
+	{ 0x5401c, 0x4800 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x84 },
+	{ 0x54020, 0x33 },
+	{ 0x54021, 0x4866 },
+	{ 0x54022, 0x4800 },
+	{ 0x54024, 0x16 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x54032, 0x8400 },
+	{ 0x54033, 0x3300 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x48 },
+	{ 0x54036, 0x48 },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0x8400 },
+	{ 0x54039, 0x3300 },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x48 },
+	{ 0x5403c, 0x48 },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P2 message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp2_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54002, 0x102 },
+	{ 0x54003, 0x64 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x14 },
+	{ 0x54008, 0x121f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x84 },
+	{ 0x5401a, 0x33 },
+	{ 0x5401b, 0x4866 },
+	{ 0x5401c, 0x4800 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x84 },
+	{ 0x54020, 0x33 },
+	{ 0x54021, 0x4866 },
+	{ 0x54022, 0x4800 },
+	{ 0x54024, 0x16 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x54032, 0x8400 },
+	{ 0x54033, 0x3300 },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x48 },
+	{ 0x54036, 0x48 },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0x8400 },
+	{ 0x54039, 0x3300 },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x48 },
+	{ 0x5403c, 0x48 },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P0 2D message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp0_2d_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54003, 0xfa0 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, 0x2228 },
+	{ 0x54006, 0x14 },
+	{ 0x54008, 0x61 },
+	{ 0x54009, 0xc8 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400f, 0x100 },
+	{ 0x54010, 0x1f7f },
+	{ 0x54012, 0x310 },
+	{ 0x54019, 0x3ff4 },
+	{ 0x5401a, 0x33 },
+	{ 0x5401b, 0x4866 },
+	{ 0x5401c, 0x4800 },
+	{ 0x5401e, 0x16 },
+	{ 0x5401f, 0x3ff4 },
+	{ 0x54020, 0x33 },
+	{ 0x54021, 0x4866 },
+	{ 0x54022, 0x4800 },
+	{ 0x54024, 0x16 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x54032, 0xf400 },
+	{ 0x54033, 0x333f },
+	{ 0x54034, 0x6600 },
+	{ 0x54035, 0x48 },
+	{ 0x54036, 0x48 },
+	{ 0x54037, 0x1600 },
+	{ 0x54038, 0xf400 },
+	{ 0x54039, 0x333f },
+	{ 0x5403a, 0x6600 },
+	{ 0x5403b, 0x48 },
+	{ 0x5403c, 0x48 },
+	{ 0x5403d, 0x1600 },
+	{ 0xd0000, 0x1 },
+};
+
+/* DRAM PHY init engine image */
+static struct dram_cfg_param ddr_phy_pie[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x90000, 0x10 },
+	{ 0x90001, 0x400 },
+	{ 0x90002, 0x10e },
+	{ 0x90003, 0x0 },
+	{ 0x90004, 0x0 },
+	{ 0x90005, 0x8 },
+	{ 0x90029, 0xb },
+	{ 0x9002a, 0x480 },
+	{ 0x9002b, 0x109 },
+	{ 0x9002c, 0x8 },
+	{ 0x9002d, 0x448 },
+	{ 0x9002e, 0x139 },
+	{ 0x9002f, 0x8 },
+	{ 0x90030, 0x478 },
+	{ 0x90031, 0x109 },
+	{ 0x90032, 0x0 },
+	{ 0x90033, 0xe8 },
+	{ 0x90034, 0x109 },
+	{ 0x90035, 0x2 },
+	{ 0x90036, 0x10 },
+	{ 0x90037, 0x139 },
+	{ 0x90038, 0xb },
+	{ 0x90039, 0x7c0 },
+	{ 0x9003a, 0x139 },
+	{ 0x9003b, 0x44 },
+	{ 0x9003c, 0x633 },
+	{ 0x9003d, 0x159 },
+	{ 0x9003e, 0x14f },
+	{ 0x9003f, 0x630 },
+	{ 0x90040, 0x159 },
+	{ 0x90041, 0x47 },
+	{ 0x90042, 0x633 },
+	{ 0x90043, 0x149 },
+	{ 0x90044, 0x4f },
+	{ 0x90045, 0x633 },
+	{ 0x90046, 0x179 },
+	{ 0x90047, 0x8 },
+	{ 0x90048, 0xe0 },
+	{ 0x90049, 0x109 },
+	{ 0x9004a, 0x0 },
+	{ 0x9004b, 0x7c8 },
+	{ 0x9004c, 0x109 },
+	{ 0x9004d, 0x0 },
+	{ 0x9004e, 0x1 },
+	{ 0x9004f, 0x8 },
+	{ 0x90050, 0x0 },
+	{ 0x90051, 0x45a },
+	{ 0x90052, 0x9 },
+	{ 0x90053, 0x0 },
+	{ 0x90054, 0x448 },
+	{ 0x90055, 0x109 },
+	{ 0x90056, 0x40 },
+	{ 0x90057, 0x633 },
+	{ 0x90058, 0x179 },
+	{ 0x90059, 0x1 },
+	{ 0x9005a, 0x618 },
+	{ 0x9005b, 0x109 },
+	{ 0x9005c, 0x40c0 },
+	{ 0x9005d, 0x633 },
+	{ 0x9005e, 0x149 },
+	{ 0x9005f, 0x8 },
+	{ 0x90060, 0x4 },
+	{ 0x90061, 0x48 },
+	{ 0x90062, 0x4040 },
+	{ 0x90063, 0x633 },
+	{ 0x90064, 0x149 },
+	{ 0x90065, 0x0 },
+	{ 0x90066, 0x4 },
+	{ 0x90067, 0x48 },
+	{ 0x90068, 0x40 },
+	{ 0x90069, 0x633 },
+	{ 0x9006a, 0x149 },
+	{ 0x9006b, 0x10 },
+	{ 0x9006c, 0x4 },
+	{ 0x9006d, 0x18 },
+	{ 0x9006e, 0x0 },
+	{ 0x9006f, 0x4 },
+	{ 0x90070, 0x78 },
+	{ 0x90071, 0x549 },
+	{ 0x90072, 0x633 },
+	{ 0x90073, 0x159 },
+	{ 0x90074, 0xd49 },
+	{ 0x90075, 0x633 },
+	{ 0x90076, 0x159 },
+	{ 0x90077, 0x94a },
+	{ 0x90078, 0x633 },
+	{ 0x90079, 0x159 },
+	{ 0x9007a, 0x441 },
+	{ 0x9007b, 0x633 },
+	{ 0x9007c, 0x149 },
+	{ 0x9007d, 0x42 },
+	{ 0x9007e, 0x633 },
+	{ 0x9007f, 0x149 },
+	{ 0x90080, 0x1 },
+	{ 0x90081, 0x633 },
+	{ 0x90082, 0x149 },
+	{ 0x90083, 0x0 },
+	{ 0x90084, 0xe0 },
+	{ 0x90085, 0x109 },
+	{ 0x90086, 0xa },
+	{ 0x90087, 0x10 },
+	{ 0x90088, 0x109 },
+	{ 0x90089, 0x9 },
+	{ 0x9008a, 0x3c0 },
+	{ 0x9008b, 0x149 },
+	{ 0x9008c, 0x9 },
+	{ 0x9008d, 0x3c0 },
+	{ 0x9008e, 0x159 },
+	{ 0x9008f, 0x18 },
+	{ 0x90090, 0x10 },
+	{ 0x90091, 0x109 },
+	{ 0x90092, 0x0 },
+	{ 0x90093, 0x3c0 },
+	{ 0x90094, 0x109 },
+	{ 0x90095, 0x18 },
+	{ 0x90096, 0x4 },
+	{ 0x90097, 0x48 },
+	{ 0x90098, 0x18 },
+	{ 0x90099, 0x4 },
+	{ 0x9009a, 0x58 },
+	{ 0x9009b, 0xb },
+	{ 0x9009c, 0x10 },
+	{ 0x9009d, 0x109 },
+	{ 0x9009e, 0x1 },
+	{ 0x9009f, 0x10 },
+	{ 0x900a0, 0x109 },
+	{ 0x900a1, 0x5 },
+	{ 0x900a2, 0x7c0 },
+	{ 0x900a3, 0x109 },
+	{ 0x40000, 0x811 },
+	{ 0x40020, 0x880 },
+	{ 0x40040, 0x0 },
+	{ 0x40060, 0x0 },
+	{ 0x40001, 0x4008 },
+	{ 0x40021, 0x83 },
+	{ 0x40041, 0x4f },
+	{ 0x40061, 0x0 },
+	{ 0x40002, 0x4040 },
+	{ 0x40022, 0x83 },
+	{ 0x40042, 0x51 },
+	{ 0x40062, 0x0 },
+	{ 0x40003, 0x811 },
+	{ 0x40023, 0x880 },
+	{ 0x40043, 0x0 },
+	{ 0x40063, 0x0 },
+	{ 0x40004, 0x720 },
+	{ 0x40024, 0xf },
+	{ 0x40044, 0x1740 },
+	{ 0x40064, 0x0 },
+	{ 0x40005, 0x16 },
+	{ 0x40025, 0x83 },
+	{ 0x40045, 0x4b },
+	{ 0x40065, 0x0 },
+	{ 0x40006, 0x716 },
+	{ 0x40026, 0xf },
+	{ 0x40046, 0x2001 },
+	{ 0x40066, 0x0 },
+	{ 0x40007, 0x716 },
+	{ 0x40027, 0xf },
+	{ 0x40047, 0x2800 },
+	{ 0x40067, 0x0 },
+	{ 0x40008, 0x716 },
+	{ 0x40028, 0xf },
+	{ 0x40048, 0xf00 },
+	{ 0x40068, 0x0 },
+	{ 0x40009, 0x720 },
+	{ 0x40029, 0xf },
+	{ 0x40049, 0x1400 },
+	{ 0x40069, 0x0 },
+	{ 0x4000a, 0xe08 },
+	{ 0x4002a, 0xc15 },
+	{ 0x4004a, 0x0 },
+	{ 0x4006a, 0x0 },
+	{ 0x4000b, 0x625 },
+	{ 0x4002b, 0x15 },
+	{ 0x4004b, 0x0 },
+	{ 0x4006b, 0x0 },
+	{ 0x4000c, 0x4028 },
+	{ 0x4002c, 0x80 },
+	{ 0x4004c, 0x0 },
+	{ 0x4006c, 0x0 },
+	{ 0x4000d, 0xe08 },
+	{ 0x4002d, 0xc1a },
+	{ 0x4004d, 0x0 },
+	{ 0x4006d, 0x0 },
+	{ 0x4000e, 0x625 },
+	{ 0x4002e, 0x1a },
+	{ 0x4004e, 0x0 },
+	{ 0x4006e, 0x0 },
+	{ 0x4000f, 0x4040 },
+	{ 0x4002f, 0x80 },
+	{ 0x4004f, 0x0 },
+	{ 0x4006f, 0x0 },
+	{ 0x40010, 0x2604 },
+	{ 0x40030, 0x15 },
+	{ 0x40050, 0x0 },
+	{ 0x40070, 0x0 },
+	{ 0x40011, 0x708 },
+	{ 0x40031, 0x5 },
+	{ 0x40051, 0x0 },
+	{ 0x40071, 0x2002 },
+	{ 0x40012, 0x8 },
+	{ 0x40032, 0x80 },
+	{ 0x40052, 0x0 },
+	{ 0x40072, 0x0 },
+	{ 0x40013, 0x2604 },
+	{ 0x40033, 0x1a },
+	{ 0x40053, 0x0 },
+	{ 0x40073, 0x0 },
+	{ 0x40014, 0x708 },
+	{ 0x40034, 0xa },
+	{ 0x40054, 0x0 },
+	{ 0x40074, 0x2002 },
+	{ 0x40015, 0x4040 },
+	{ 0x40035, 0x80 },
+	{ 0x40055, 0x0 },
+	{ 0x40075, 0x0 },
+	{ 0x40016, 0x60a },
+	{ 0x40036, 0x15 },
+	{ 0x40056, 0x1200 },
+	{ 0x40076, 0x0 },
+	{ 0x40017, 0x61a },
+	{ 0x40037, 0x15 },
+	{ 0x40057, 0x1300 },
+	{ 0x40077, 0x0 },
+	{ 0x40018, 0x60a },
+	{ 0x40038, 0x1a },
+	{ 0x40058, 0x1200 },
+	{ 0x40078, 0x0 },
+	{ 0x40019, 0x642 },
+	{ 0x40039, 0x1a },
+	{ 0x40059, 0x1300 },
+	{ 0x40079, 0x0 },
+	{ 0x4001a, 0x4808 },
+	{ 0x4003a, 0x880 },
+	{ 0x4005a, 0x0 },
+	{ 0x4007a, 0x0 },
+	{ 0x900a4, 0x0 },
+	{ 0x900a5, 0x790 },
+	{ 0x900a6, 0x11a },
+	{ 0x900a7, 0x8 },
+	{ 0x900a8, 0x7aa },
+	{ 0x900a9, 0x2a },
+	{ 0x900aa, 0x10 },
+	{ 0x900ab, 0x7b2 },
+	{ 0x900ac, 0x2a },
+	{ 0x900ad, 0x0 },
+	{ 0x900ae, 0x7c8 },
+	{ 0x900af, 0x109 },
+	{ 0x900b0, 0x10 },
+	{ 0x900b1, 0x10 },
+	{ 0x900b2, 0x109 },
+	{ 0x900b3, 0x10 },
+	{ 0x900b4, 0x2a8 },
+	{ 0x900b5, 0x129 },
+	{ 0x900b6, 0x8 },
+	{ 0x900b7, 0x370 },
+	{ 0x900b8, 0x129 },
+	{ 0x900b9, 0xa },
+	{ 0x900ba, 0x3c8 },
+	{ 0x900bb, 0x1a9 },
+	{ 0x900bc, 0xc },
+	{ 0x900bd, 0x408 },
+	{ 0x900be, 0x199 },
+	{ 0x900bf, 0x14 },
+	{ 0x900c0, 0x790 },
+	{ 0x900c1, 0x11a },
+	{ 0x900c2, 0x8 },
+	{ 0x900c3, 0x4 },
+	{ 0x900c4, 0x18 },
+	{ 0x900c5, 0xe },
+	{ 0x900c6, 0x408 },
+	{ 0x900c7, 0x199 },
+	{ 0x900c8, 0x8 },
+	{ 0x900c9, 0x8568 },
+	{ 0x900ca, 0x108 },
+	{ 0x900cb, 0x18 },
+	{ 0x900cc, 0x790 },
+	{ 0x900cd, 0x16a },
+	{ 0x900ce, 0x8 },
+	{ 0x900cf, 0x1d8 },
+	{ 0x900d0, 0x169 },
+	{ 0x900d1, 0x10 },
+	{ 0x900d2, 0x8558 },
+	{ 0x900d3, 0x168 },
+	{ 0x900d4, 0x70 },
+	{ 0x900d5, 0x788 },
+	{ 0x900d6, 0x16a },
+	{ 0x900d7, 0x1ff8 },
+	{ 0x900d8, 0x85a8 },
+	{ 0x900d9, 0x1e8 },
+	{ 0x900da, 0x50 },
+	{ 0x900db, 0x798 },
+	{ 0x900dc, 0x16a },
+	{ 0x900dd, 0x60 },
+	{ 0x900de, 0x7a0 },
+	{ 0x900df, 0x16a },
+	{ 0x900e0, 0x8 },
+	{ 0x900e1, 0x8310 },
+	{ 0x900e2, 0x168 },
+	{ 0x900e3, 0x8 },
+	{ 0x900e4, 0xa310 },
+	{ 0x900e5, 0x168 },
+	{ 0x900e6, 0xa },
+	{ 0x900e7, 0x408 },
+	{ 0x900e8, 0x169 },
+	{ 0x900e9, 0x6e },
+	{ 0x900ea, 0x0 },
+	{ 0x900eb, 0x68 },
+	{ 0x900ec, 0x0 },
+	{ 0x900ed, 0x408 },
+	{ 0x900ee, 0x169 },
+	{ 0x900ef, 0x0 },
+	{ 0x900f0, 0x8310 },
+	{ 0x900f1, 0x168 },
+	{ 0x900f2, 0x0 },
+	{ 0x900f3, 0xa310 },
+	{ 0x900f4, 0x168 },
+	{ 0x900f5, 0x1ff8 },
+	{ 0x900f6, 0x85a8 },
+	{ 0x900f7, 0x1e8 },
+	{ 0x900f8, 0x68 },
+	{ 0x900f9, 0x798 },
+	{ 0x900fa, 0x16a },
+	{ 0x900fb, 0x78 },
+	{ 0x900fc, 0x7a0 },
+	{ 0x900fd, 0x16a },
+	{ 0x900fe, 0x68 },
+	{ 0x900ff, 0x790 },
+	{ 0x90100, 0x16a },
+	{ 0x90101, 0x8 },
+	{ 0x90102, 0x8b10 },
+	{ 0x90103, 0x168 },
+	{ 0x90104, 0x8 },
+	{ 0x90105, 0xab10 },
+	{ 0x90106, 0x168 },
+	{ 0x90107, 0xa },
+	{ 0x90108, 0x408 },
+	{ 0x90109, 0x169 },
+	{ 0x9010a, 0x58 },
+	{ 0x9010b, 0x0 },
+	{ 0x9010c, 0x68 },
+	{ 0x9010d, 0x0 },
+	{ 0x9010e, 0x408 },
+	{ 0x9010f, 0x169 },
+	{ 0x90110, 0x0 },
+	{ 0x90111, 0x8b10 },
+	{ 0x90112, 0x168 },
+	{ 0x90113, 0x1 },
+	{ 0x90114, 0xab10 },
+	{ 0x90115, 0x168 },
+	{ 0x90116, 0x0 },
+	{ 0x90117, 0x1d8 },
+	{ 0x90118, 0x169 },
+	{ 0x90119, 0x80 },
+	{ 0x9011a, 0x790 },
+	{ 0x9011b, 0x16a },
+	{ 0x9011c, 0x18 },
+	{ 0x9011d, 0x7aa },
+	{ 0x9011e, 0x6a },
+	{ 0x9011f, 0xa },
+	{ 0x90120, 0x0 },
+	{ 0x90121, 0x1e9 },
+	{ 0x90122, 0x8 },
+	{ 0x90123, 0x8080 },
+	{ 0x90124, 0x108 },
+	{ 0x90125, 0xf },
+	{ 0x90126, 0x408 },
+	{ 0x90127, 0x169 },
+	{ 0x90128, 0xc },
+	{ 0x90129, 0x0 },
+	{ 0x9012a, 0x68 },
+	{ 0x9012b, 0x9 },
+	{ 0x9012c, 0x0 },
+	{ 0x9012d, 0x1a9 },
+	{ 0x9012e, 0x0 },
+	{ 0x9012f, 0x408 },
+	{ 0x90130, 0x169 },
+	{ 0x90131, 0x0 },
+	{ 0x90132, 0x8080 },
+	{ 0x90133, 0x108 },
+	{ 0x90134, 0x8 },
+	{ 0x90135, 0x7aa },
+	{ 0x90136, 0x6a },
+	{ 0x90137, 0x0 },
+	{ 0x90138, 0x8568 },
+	{ 0x90139, 0x108 },
+	{ 0x9013a, 0xb7 },
+	{ 0x9013b, 0x790 },
+	{ 0x9013c, 0x16a },
+	{ 0x9013d, 0x1f },
+	{ 0x9013e, 0x0 },
+	{ 0x9013f, 0x68 },
+	{ 0x90140, 0x8 },
+	{ 0x90141, 0x8558 },
+	{ 0x90142, 0x168 },
+	{ 0x90143, 0xf },
+	{ 0x90144, 0x408 },
+	{ 0x90145, 0x169 },
+	{ 0x90146, 0xd },
+	{ 0x90147, 0x0 },
+	{ 0x90148, 0x68 },
+	{ 0x90149, 0x0 },
+	{ 0x9014a, 0x408 },
+	{ 0x9014b, 0x169 },
+	{ 0x9014c, 0x0 },
+	{ 0x9014d, 0x8558 },
+	{ 0x9014e, 0x168 },
+	{ 0x9014f, 0x8 },
+	{ 0x90150, 0x3c8 },
+	{ 0x90151, 0x1a9 },
+	{ 0x90152, 0x3 },
+	{ 0x90153, 0x370 },
+	{ 0x90154, 0x129 },
+	{ 0x90155, 0x20 },
+	{ 0x90156, 0x2aa },
+	{ 0x90157, 0x9 },
+	{ 0x90158, 0x8 },
+	{ 0x90159, 0xe8 },
+	{ 0x9015a, 0x109 },
+	{ 0x9015b, 0x0 },
+	{ 0x9015c, 0x8140 },
+	{ 0x9015d, 0x10c },
+	{ 0x9015e, 0x10 },
+	{ 0x9015f, 0x8138 },
+	{ 0x90160, 0x104 },
+	{ 0x90161, 0x8 },
+	{ 0x90162, 0x448 },
+	{ 0x90163, 0x109 },
+	{ 0x90164, 0xf },
+	{ 0x90165, 0x7c0 },
+	{ 0x90166, 0x109 },
+	{ 0x90167, 0x0 },
+	{ 0x90168, 0xe8 },
+	{ 0x90169, 0x109 },
+	{ 0x9016a, 0x47 },
+	{ 0x9016b, 0x630 },
+	{ 0x9016c, 0x109 },
+	{ 0x9016d, 0x8 },
+	{ 0x9016e, 0x618 },
+	{ 0x9016f, 0x109 },
+	{ 0x90170, 0x8 },
+	{ 0x90171, 0xe0 },
+	{ 0x90172, 0x109 },
+	{ 0x90173, 0x0 },
+	{ 0x90174, 0x7c8 },
+	{ 0x90175, 0x109 },
+	{ 0x90176, 0x8 },
+	{ 0x90177, 0x8140 },
+	{ 0x90178, 0x10c },
+	{ 0x90179, 0x0 },
+	{ 0x9017a, 0x478 },
+	{ 0x9017b, 0x109 },
+	{ 0x9017c, 0x0 },
+	{ 0x9017d, 0x1 },
+	{ 0x9017e, 0x8 },
+	{ 0x9017f, 0x8 },
+	{ 0x90180, 0x4 },
+	{ 0x90181, 0x0 },
+	{ 0x90006, 0x8 },
+	{ 0x90007, 0x7c8 },
+	{ 0x90008, 0x109 },
+	{ 0x90009, 0x0 },
+	{ 0x9000a, 0x400 },
+	{ 0x9000b, 0x106 },
+	{ 0xd00e7, 0x400 },
+	{ 0x90017, 0x0 },
+	{ 0x9001f, 0x29 },
+	{ 0x90026, 0x68 },
+	{ 0x400d0, 0x0 },
+	{ 0x400d1, 0x101 },
+	{ 0x400d2, 0x105 },
+	{ 0x400d3, 0x107 },
+	{ 0x400d4, 0x10f },
+	{ 0x400d5, 0x202 },
+	{ 0x400d6, 0x20a },
+	{ 0x400d7, 0x20b },
+	{ 0x2003a, 0x2 },
+	{ 0x200be, 0x3 },
+	{ 0x2000b, 0x7d },
+	{ 0x2000c, 0xfa },
+	{ 0x2000d, 0x9c4 },
+	{ 0x2000e, 0x2c },
+	{ 0x12000b, 0xc },
+	{ 0x12000c, 0x19 },
+	{ 0x12000d, 0xfa },
+	{ 0x12000e, 0x10 },
+	{ 0x22000b, 0x3 },
+	{ 0x22000c, 0x6 },
+	{ 0x22000d, 0x3e },
+	{ 0x22000e, 0x10 },
+	{ 0x9000c, 0x0 },
+	{ 0x9000d, 0x173 },
+	{ 0x9000e, 0x60 },
+	{ 0x9000f, 0x6110 },
+	{ 0x90010, 0x2152 },
+	{ 0x90011, 0xdfbd },
+	{ 0x90012, 0x2060 },
+	{ 0x90013, 0x6152 },
+	{ 0x20010, 0x5a },
+	{ 0x20011, 0x3 },
+	{ 0x40080, 0xe0 },
+	{ 0x40081, 0x12 },
+	{ 0x40082, 0xe0 },
+	{ 0x40083, 0x12 },
+	{ 0x40084, 0xe0 },
+	{ 0x40085, 0x12 },
+	{ 0x140080, 0xe0 },
+	{ 0x140081, 0x12 },
+	{ 0x140082, 0xe0 },
+	{ 0x140083, 0x12 },
+	{ 0x140084, 0xe0 },
+	{ 0x140085, 0x12 },
+	{ 0x240080, 0xe0 },
+	{ 0x240081, 0x12 },
+	{ 0x240082, 0xe0 },
+	{ 0x240083, 0x12 },
+	{ 0x240084, 0xe0 },
+	{ 0x240085, 0x12 },
+	{ 0x400fd, 0xf },
+	{ 0x10011, 0x1 },
+	{ 0x10012, 0x1 },
+	{ 0x10013, 0x180 },
+	{ 0x10018, 0x1 },
+	{ 0x10002, 0x6209 },
+	{ 0x100b2, 0x1 },
+	{ 0x101b4, 0x1 },
+	{ 0x102b4, 0x1 },
+	{ 0x103b4, 0x1 },
+	{ 0x104b4, 0x1 },
+	{ 0x105b4, 0x1 },
+	{ 0x106b4, 0x1 },
+	{ 0x107b4, 0x1 },
+	{ 0x108b4, 0x1 },
+	{ 0x11011, 0x1 },
+	{ 0x11012, 0x1 },
+	{ 0x11013, 0x180 },
+	{ 0x11018, 0x1 },
+	{ 0x11002, 0x6209 },
+	{ 0x110b2, 0x1 },
+	{ 0x111b4, 0x1 },
+	{ 0x112b4, 0x1 },
+	{ 0x113b4, 0x1 },
+	{ 0x114b4, 0x1 },
+	{ 0x115b4, 0x1 },
+	{ 0x116b4, 0x1 },
+	{ 0x117b4, 0x1 },
+	{ 0x118b4, 0x1 },
+	{ 0x12011, 0x1 },
+	{ 0x12012, 0x1 },
+	{ 0x12013, 0x180 },
+	{ 0x12018, 0x1 },
+	{ 0x12002, 0x6209 },
+	{ 0x120b2, 0x1 },
+	{ 0x121b4, 0x1 },
+	{ 0x122b4, 0x1 },
+	{ 0x123b4, 0x1 },
+	{ 0x124b4, 0x1 },
+	{ 0x125b4, 0x1 },
+	{ 0x126b4, 0x1 },
+	{ 0x127b4, 0x1 },
+	{ 0x128b4, 0x1 },
+	{ 0x13011, 0x1 },
+	{ 0x13012, 0x1 },
+	{ 0x13013, 0x180 },
+	{ 0x13018, 0x1 },
+	{ 0x13002, 0x6209 },
+	{ 0x130b2, 0x1 },
+	{ 0x131b4, 0x1 },
+	{ 0x132b4, 0x1 },
+	{ 0x133b4, 0x1 },
+	{ 0x134b4, 0x1 },
+	{ 0x135b4, 0x1 },
+	{ 0x136b4, 0x1 },
+	{ 0x137b4, 0x1 },
+	{ 0x138b4, 0x1 },
+	{ 0x20089, 0x1 },
+	{ 0x20088, 0x19 },
+	{ 0xc0080, 0x2 },
+	{ 0xd0000, 0x1 }
+};
+
+static struct dram_fsp_msg ddr_dram_fsp_msg[] = {
+	{
+		/* P0 4000mts 1D */
+		.drate = 4000,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp0_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg),
+	},
+	{
+		/* P1 400mts 1D */
+		.drate = 400,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp1_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg),
+	},
+	{
+		/* P2 100mts 1D */
+		.drate = 100,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp2_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg),
+	},
+	{
+		/* P0 4000mts 2D */
+		.drate = 4000,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = ddr_fsp0_2d_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg),
+	},
+};
diff --git a/arch/arm/dts/imx8mp-prt8ml.dts b/arch/arm/dts/imx8mp-prt8ml.dts
index 15c3e710ae..b23d64f2d1 100644
--- a/arch/arm/dts/imx8mp-prt8ml.dts
+++ b/arch/arm/dts/imx8mp-prt8ml.dts
@@ -20,8 +20,16 @@ environment-emmc {
 			status = "disabled";
 		};
 	};
-};
 
+	/* Minimum contiguous memory region is 1792MiB
+	 * The probe function of the ddrc will either expand this
+	 * to 6GiB (without ECC) or 5.25GiB (with inline ECC, in 3 regions).
+	 */
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0x0 0x40000000 0x0 0x70000000>;
+	};
+};
 
 &usdhc2 {
 	#address-cells = <1>;
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 08b0a955c6..a738737528 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -731,6 +731,7 @@ config MACH_PROTONIC_IMX8M
 	select MCI_IMX_ESDHC_PBL
 	select IMX8M_DRAM
 	select USB_GADGET_DRIVER_ARC_PBL
+	select IMX8MP_DRAM_ECC
 
 config MACH_SKOV_IMX8MP
 	bool "Skov i.MX8MP based boards"
diff --git a/images/Makefile.imx b/images/Makefile.imx
index f66c0af6a4..17a687bcd3 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -513,6 +513,8 @@ $(call build_imx8m_habv4img, CONFIG_MACH_POLYHEX_DEBIX, start_polyhex_debix_som_
 
 $(call build_imx8m_habv4img, CONFIG_MACH_PROTONIC_IMX8M, start_prt_prt8ml, protonic-imx8m/flash-header-prt8ml, prt-prt8ml)
 
+$(call build_imx8m_habv4img, CONFIG_MACH_PROTONIC_IMX8M, start_prt_prt8ml_ecc, protonic-imx8m/flash-header-prt8ml, prt-prt8ml-ecc)
+
 $(call build_imx8m_habv4img, CONFIG_MACH_VARISCITE_DT8MCUSTOMBOARD_IMX8MP, start_variscite_imx8mp_dart, variscite-dt8mcustomboard-imx8mp/flash-header-imx8mp-dart, variscite-imx8mp-dart-cb)
 
 # ----------------------- i.MX8mq based boards --------------------------

-- 
2.52.0




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/4] arm: mach-imx: esdctl.c: Add support for imx8mp inline ECC
  2026-03-09  7:46 ` [PATCH v2 2/4] arm: mach-imx: esdctl.c: Add support for imx8mp inline ECC Steffen Trumtrar
@ 2026-03-09 14:56   ` Ahmad Fatoum
  0 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2026-03-09 14:56 UTC (permalink / raw)
  To: Steffen Trumtrar, barebox, Sascha Hauer; +Cc: David Jander



On 3/9/26 8:46 AM, Steffen Trumtrar wrote:
> From: David Jander <david@protonic.nl>
> 
> This adds support for detecting the use of inline ECC and compute the
> correct memory bank(s) in that case.
> In case inline ECC is active the memory map is modified as follows:
> The total memory size is reduced to 7/8th of the raw memory size.
> If a reduced-address-space type RAM is used (0.75, 1.5, 3, 6... GiB), then
> the whole address space is split up into 3 equal parts, separated by 1/3rd
> of the raw address space, but each 7/8th that size.
> The ECC area at the end of each part is not addressable and must be
> excluded from the map.
> 
> Signed-off-by: David Jander <david@protonic.nl>
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> ---
>  arch/arm/mach-imx/Kconfig  |  8 +++++
>  arch/arm/mach-imx/esdctl.c | 77 +++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 84 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index d244c57580..08b0a955c6 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -1026,6 +1026,14 @@ config HABV3_IMG_CRT_DER
>  
>  endif
>  
> +config IMX8MP_DRAM_ECC
> +	bool
> +	depends on ARCH_IMX8MP
> +	help
> +	  The i.MX8MP SoC supports ECC on the LPDDR4 memory. Select Y to enable
> +	  this feature. The total amount of memory available will be reduced by
> +	  1/8th.

Help text doesn't reflect reality anymore after removal of the prompt.
Suggestion:

This option is selected by boards that make use of the inline ECC
support for LPDDR4 memory on i.MX8MP SoCs. For board images that
configure ECC, the total amount of memory available will be reduced by
1/8th.
Boards that don't explicitly make use of it are not affected.

> +static resource_size_t imx8mp_ddrc_sdram_size(void __iomem *ddrc,
> +		unsigned int *chunks, resource_size_t *stride)
> +{
> +	resource_size_t size = imx8m_ddrc_sdram_size(ddrc, 32);
> +	const bool reduced_address_space = FIELD_GET(
> +		DDRC_ADDRMAP6_LPDDR4_6GB_12GB_24GB, readl(ddrc + DDRC_ADDRMAP(6)));
> +
> +	/* ECC devides the accessible address space into 1 or 3 contiguous

divides


> +static int imx8mp_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data)
> +{
> +	unsigned int chunks;
> +	unsigned long base;
> +	resource_size_t chunksize = 0, stride = 0;
> +	int ret = -ENOMEM;
> +	int i;
> +	char name[5];
> +
> +	chunksize = imx8mp_ddrc_sdram_size(mmdcbase, &chunks, &stride);
> +
> +	base = data->base0;
> +	for (i = 0; i < chunks; i++) {
> +		snprintf(name, 5, "ram%d", i);

sizeof(name)

>  static __maybe_unused const struct imx_esdctl_data imx9_data = {
>  	.base0 = MX9_DDR_CSD1_BASE_ADDR,
>  	.add_mem = imx9_ddrc_add_mem,
> @@ -822,6 +885,12 @@ static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = {
>  	}, {
>  		.compatible = "fsl,imx8mn-ddrc",
>  		.data = &imx8mn_data
> +	}, {
> +		.compatible = "fsl,imx8mp-ddrc",
> +		.data = &imx8mp_data
> +	}, {
> +		.compatible = "fsl,imx8mq-ddrc",
> +		.data = &imx8mp_data

Are you sure that the original i.MX8M Quad supports ECC?

>  	}, {
>  		.compatible = "fsl,imx93-ddrc",
>  		.data = &imx9_data
> @@ -1000,9 +1069,15 @@ void __noreturn vf610_barebox_entry(void *boarddata)
>  
>  resource_size_t imx8m_barebox_earlymem_size(unsigned buswidth)
>  {
> +	unsigned int chunks;
> +	resource_size_t stride = 0;

Drop and just pass NULL as pointer?

>  	resource_size_t size;
>  
> -	size = imx8m_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), buswidth);
> +	if (imx_esdctl_ecc_enabled(IOMEM(MX8M_DDRC_CTL_BASE_ADDR)))
> +		size = imx8mp_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), &chunks,
> +				&stride);
> +	else
> +		size = imx8m_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), buswidth);
>  	/*
>  	 * We artificially limit detected memory size to force malloc
>  	 * pool placement to be within 4GiB address space, so as to
> 

Cheers,
Ahmad

-- 
Pengutronix e.K.                  |                             |
Steuerwalder Str. 21              | http://www.pengutronix.de/  |
31137 Hildesheim, Germany         | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/4] ARM: i.MX: esdctl: fix spelling of ad(d)ress
  2026-03-09  7:46 ` [PATCH v2 1/4] ARM: i.MX: esdctl: fix spelling of ad(d)ress Steffen Trumtrar
@ 2026-03-09 14:56   ` Ahmad Fatoum
  0 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2026-03-09 14:56 UTC (permalink / raw)
  To: Steffen Trumtrar, barebox, Sascha Hauer



On 3/9/26 8:46 AM, Steffen Trumtrar wrote:
> address is spelled with two 'd's. Fix the spelling mistake.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>

Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>

> ---
>  arch/arm/mach-imx/esdctl.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
> index 935c3d3257..b6689b7ffc 100644
> --- a/arch/arm/mach-imx/esdctl.c
> +++ b/arch/arm/mach-imx/esdctl.c
> @@ -262,7 +262,7 @@ static int imx_esdctl_v4_add_mem(void *esdctlbase, const struct imx_esdctl_data
>  }
>  
>  /*
> - * On i.MX6 the adress space reserved for SDRAM is 0x10000000 to 0xFFFFFFFF
> + * On i.MX6 the address space reserved for SDRAM is 0x10000000 to 0xFFFFFFFF
>   * which makes the maximum supported RAM size 0xF0000000.
>   */
>  #define IMX6_MAX_SDRAM_SIZE 0xF0000000
> @@ -380,7 +380,7 @@ static resource_size_t
>  imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
>  		    u8 col_max, const u8 col_b[], unsigned int col_b_num,
>  		    u8 row_max, const u8 row_b[], unsigned int row_b_num,
> -		    bool reduced_adress_space, unsigned int mstr)
> +		    bool reduced_address_space, unsigned int mstr)
>  {
>  	unsigned int banks, ranks, columns, rows, active_ranks, width;
>  	resource_size_t size;
> @@ -459,7 +459,7 @@ imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
>  		size = memory_sdram_size(columns, rows, 1 << banks, 1) >> 1;
>  	size <<= ranks;
>  
> -	return reduced_adress_space ? size * 3 / 4 : size;
> +	return reduced_address_space ? size * 3 / 4 : size;
>  }
>  
>  static void imx_ddrc_set_mstr_device_config(u32 *mstr, unsigned bits)
> @@ -505,7 +505,7 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswid
>  		FIELD_GET(DDRC_ADDRMAP6_ROW_B12, addrmap[6]),
>  		FIELD_GET(DDRC_ADDRMAP5_ROW_B11, addrmap[5]),
>  	};
> -	const bool reduced_adress_space =
> +	const bool reduced_address_space =
>  		FIELD_GET(DDRC_ADDRMAP6_LPDDR4_6GB_12GB_24GB, addrmap[6]);
>  	u32 mstr = readl(ddrc + DDRC_MSTR);
>  
> @@ -516,7 +516,7 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswid
>  	return imx_ddrc_sdram_size(ddrc, addrmap,
>  				   12, ARRAY_AND_SIZE(col_b),
>  				   18, ARRAY_AND_SIZE(row_b),
> -				   reduced_adress_space, mstr);
> +				   reduced_address_space, mstr);
>  }
>  
>  static int _imx8m_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data,
> @@ -630,7 +630,7 @@ static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
>  		FIELD_GET(DDRC_ADDRMAP6_ROW_B12, addrmap[6]),
>  		FIELD_GET(DDRC_ADDRMAP5_ROW_B11, addrmap[5]),
>  	};
> -	const bool reduced_adress_space =
> +	const bool reduced_address_space =
>  		FIELD_GET(DDRC_ADDRMAP6_LPDDR3_6GB_12GB, addrmap[6]);
>  	u32 mstr = readl(ddrc + DDRC_MSTR);
>  
> @@ -640,7 +640,7 @@ static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
>  	return imx_ddrc_sdram_size(ddrc, addrmap,
>  				   11, ARRAY_AND_SIZE(col_b),
>  				   15, ARRAY_AND_SIZE(row_b),
> -				   reduced_adress_space, mstr);
> +				   reduced_address_space, mstr);
>  }
>  
>  static int imx7d_ddrc_add_mem(void *mmdcbase, const struct imx_esdctl_data *data)
> 

-- 
Pengutronix e.K.                  |                             |
Steuerwalder Str. 21              | http://www.pengutronix.de/  |
31137 Hildesheim, Germany         | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/4] drivers: ddr: imx8m: ddr_init.c: support ECC scrubbing
  2026-03-09  7:46 ` [PATCH v2 3/4] drivers: ddr: imx8m: ddr_init.c: support ECC scrubbing Steffen Trumtrar
@ 2026-03-09 15:12   ` Ahmad Fatoum
  0 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2026-03-09 15:12 UTC (permalink / raw)
  To: Steffen Trumtrar, barebox, Sascha Hauer; +Cc: David Jander

Hi,

On 3/9/26 8:46 AM, Steffen Trumtrar wrote:
> From: David Jander <david@protonic.nl>
> 
> This code comes from u-boot [1] and was introducesd in commit [2].

introduced*

> A fix from the patch [3] is also included, which doesn't seem to be
> added to u-boot, yet.
> 
> [1] https://github.com/u-boot/u-boot/
> [2] commit f3acb02386f4 ("drivers: ddr: imx8mp: Add inline ECC feature support")
> [3] https://patchwork.ozlabs.org/project/uboot/patch/20230123091702.7472-32-peng.fan@oss.nxp.com/

Interesting. Appears to still be unmerged.

> +#ifdef CONFIG_IMX8MP_DRAM_ECC

Remove the #ifdef here and use IS_ENABLED() below.

> +static void ddrc_inline_ecc_scrub(unsigned int start_address,
> +				  unsigned int range_address)
> +{
> +	unsigned int tmp;
> +
> +	pr_debug("ECC scrub %08x-%08x\n", start_address, range_address);
> +	/* Step1: Enable quasi-dynamic programming */
> +	reg32_write(DDRC_SWCTL(0), 0x00000000);
> +	/* Step2: Set ECCCFG1.ecc_parity_region_lock to 1 */
> +	reg32setbit(DDRC_ECCCFG1(0), 0x4);
> +	/* Step3: Block the AXI ports from taking the transaction */
> +	reg32_write(DDRC_PCTRL_0(0), 0x0);
> +	/* Step4: Set scrub start address */
> +	reg32_write(DDRC_SBRSTART0(0), start_address);
> +	/* Step5: Set scrub range address */
> +	reg32_write(DDRC_SBRRANGE0(0), range_address);
> +	/* Step6: Set scrub_mode to write */
> +	reg32_write(DDRC_SBRCTL(0), 0x00000014);
> +	/* Step7: Set the desired pattern through SBRWDATA0 registers */
> +	reg32_write(DDRC_SBRWDATA0(0), 0x55aa55aa);
> +	/* Step8: Enable the SBR by programming SBRCTL.scrub_en=1 */
> +	reg32setbit(DDRC_SBRCTL(0), 0x0);
> +	/* Step9: Poll SBRSTAT.scrub_done=1 */
> +	tmp = reg32_read(DDRC_SBRSTAT(0));
> +	while (tmp != 0x00000002)
> +		tmp = reg32_read(DDRC_SBRSTAT(0)) & 0x2;
> +	/* Step10: Poll SBRSTAT.scrub_busy=0 */
> +	tmp = reg32_read(DDRC_SBRSTAT(0));
> +	while (tmp != 0x0)
> +		tmp = reg32_read(DDRC_SBRSTAT(0)) & 0x1;
> +	/* Step11: Disable SBR by programming SBRCTL.scrub_en=0 */
> +	clrbits_le32(DDRC_SBRCTL(0), 0x1);
> +	/* Step12: Prepare for normal scrub operation(Read) and set scrub_interval*/
> +	reg32_write(DDRC_SBRCTL(0), 0xff20);
> +	/* Step13: Enable the SBR by programming SBRCTL.scrub_en=1 */
> +	reg32_write(DDRC_SBRCTL(0), 0xff21);
> +	/* Step14: Enable AXI ports by programming */
> +	reg32_write(DDRC_PCTRL_0(0), 0x1);
> +	/* Step15: Disable quasi-dynamic programming */
> +	reg32_write(DDRC_SWCTL(0), 0x00000001);
> +}
> +
> +static void ddrc_inline_ecc_scrub_end(unsigned int start_address,
> +				      unsigned int range_address)
> +{
> +	pr_debug("ECC  end %08x-%08x\n", start_address, range_address);
> +	/* Step1: Enable quasi-dynamic programming */
> +	reg32_write(DDRC_SWCTL(0), 0x00000000);
> +	/* Step2: Block the AXI ports from taking the transaction */
> +	reg32_write(DDRC_PCTRL_0(0), 0x0);
> +	/* Step3: Set scrub start address */
> +	reg32_write(DDRC_SBRSTART0(0), start_address);
> +	/* Step4: Set scrub range address */
> +	reg32_write(DDRC_SBRRANGE0(0), range_address);
> +	/* Step5: Disable SBR by programming SBRCTL.scrub_en=0 */
> +	clrbits_le32(DDRC_SBRCTL(0), 0x1);
> +	/* Step6: Prepare for normal scrub operation(Read) and set scrub_interval */
> +	reg32_write(DDRC_SBRCTL(0), 0x100);
> +	/* Step7: Enable the SBR by programming SBRCTL.scrub_en=1 */
> +	reg32_write(DDRC_SBRCTL(0), 0x101);
> +	/* Step8: Enable AXI ports by programming */
> +	reg32_write(DDRC_PCTRL_0(0), 0x1);
> +	/* Step9: Disable quasi-dynamic programming */
> +	reg32_write(DDRC_SWCTL(0), 0x00000001);
> +}
> +
> +static void dram_ecc_scrub(struct dram_timing_info *dram_timing)
> +{
> +	/* memory range to scrub in words (=1.75G) */
> +	unsigned int range_in_words = 0x1c000000;

For clarity, maybe define some macros? Something like

ECC_STRIDE	SZ_2G
ECC_INLINE_SIZE	...
ECC_SCRUB_CHUNK ECC_STRIDE - ECC_INLINE_SIZE

and use that instead of the hex constants?

> +	/* start scrubbing at RAM address */
> +	unsigned int start_address;
> +	/* scrub up until this address */
> +	unsigned int range_address;
> +
> +	BUG_ON(!dram_timing->size);

Wouldn't this panic on all non-ECC board entry points? Mixing boards
with inline ECC and without should continue to work.

See also below for naming the member for clarity.

> +
> +	for (start_address = 0x0;
> +	     start_address + range_in_words - 1 <= dram_timing->size / 4;
> +	     start_address += range_in_words + 0x04000000) {
> +		range_address = start_address + range_in_words - 1;
> +		/* scrub in 1.75G chunk sizes */
> +		ddrc_inline_ecc_scrub(start_address, range_address);
> +	}
> +	
> +	ddrc_inline_ecc_scrub_end(0x0, dram_timing->size / 4 - 1);
> +}
> +#endif
> +
>  static unsigned int g_cdd_rr_max[4];
>  static unsigned int g_cdd_rw_max[4];
>  static unsigned int g_cdd_wr_max[4];
> @@ -642,6 +732,11 @@ int imx8m_ddr_init(struct dram_controller *dram, struct dram_timing_info *dram_t
>  	reg32_write(DDRC_PCTRL_0(0), 0x00000001);
>  	pr_debug("ddrmix config done\n");
>  
> +#ifdef CONFIG_IMX8MP_DRAM_ECC
> +	if (dram->ddrc_type == DDRC_TYPE_MP)

if (IS_ENABLED(CONFIG_IMX8MP_DRAM_ECC) && dram->ddrc_type == DDRC_TYPE_MP)

> +		dram_ecc_scrub(dram_timing);
> +#endif
> +
>  	/* save the dram timing config into memory */
>  	dram_config_save(dram, dram_timing, IMX8M_SAVED_DRAM_TIMING_BASE);
>  
> diff --git a/include/soc/imx/ddr.h b/include/soc/imx/ddr.h
> index 6426062900..9a5d341100 100644
> --- a/include/soc/imx/ddr.h
> +++ b/include/soc/imx/ddr.h
> @@ -101,6 +101,7 @@ struct dram_timing_info {
>  		unsigned int ddrphy_pie_num;
>  		/* initialized drate table */
>  		unsigned int fsp_table[4];
> +		resource_size_t size;

The member name should either have ecc in it or there should be an extra
member that enables ecc, e.g.:

dram_timing::ecc_full_size

or

dram_timing::size
dram_timing::enable_ecc

or something along these lines.

>  	);
>  };
>  
> diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
> index 5df07772b3..f07cef9a9e 100644
> --- a/include/soc/imx8m/ddr.h
> +++ b/include/soc/imx8m/ddr.h
> @@ -186,6 +186,8 @@
>  #define DDRC_SBRWDATA0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf2c)
>  #define DDRC_SBRWDATA1(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf30)
>  #define DDRC_PDCH(X)             (DDRC_IPS_BASE_ADDR(X) + 0xf34)
> +#define DDRC_SBRSTART0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf38)
> +#define DDRC_SBRRANGE0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf40)
>  
>  #define DDRC_FREQ1_DERATEEN(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2020)
>  #define DDRC_FREQ1_DERATEINT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2024)
> @@ -380,4 +382,6 @@ static inline void imx8m_ddr_load_train_code(enum dram_type dram_type,
>  	ddr_load_train_code(&imx8m_dram_controller, dram_type, fw_type);
>  }
>  
> +#define DDRC_PHY_REG(x)	((x) * 4)

Unused?

> +
>  #endif
> 

-- 
Pengutronix e.K.                  |                             |
Steuerwalder Str. 21              | http://www.pengutronix.de/  |
31137 Hildesheim, Germany         | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/4] arm: boards: protonic-imx8ml: Add ECC + scrubbing
  2026-03-09  7:46 ` [PATCH v2 4/4] arm: boards: protonic-imx8ml: Add ECC + scrubbing Steffen Trumtrar
@ 2026-03-09 15:21   ` Ahmad Fatoum
  0 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2026-03-09 15:21 UTC (permalink / raw)
  To: Steffen Trumtrar, barebox, Sascha Hauer; +Cc: David Jander

On 3/9/26 8:46 AM, Steffen Trumtrar wrote:
> +ENTRY_FUNCTION(start_prt_prt8ml_ecc, r0, r1, r2)
> +{
> +	imx8mp_cpu_lowlevel_init();
> +
> +	relocate_to_current_adr();
> +	setup_c();
> +
> +	prt_prt8ml_start(&prt8ml_dram_ecc_timing);

Taking the address of a global variable in a function that calls
relocate_to_* is not a good idea, see commit f36c980fd6e5 ("ARM: cpu:
add compiler barrier around unrelocated access") for an example where
GCC miscompiled such a pattern.

I would suggest you pass an ecc = true/false here and move taking the
address into the noinline function. I expect that the compiler should
optimize the other struct away. If not, you will have to define two
noinline functions instead...

Sorry about that, I hope we will get rid of this error prone wart in the
coming months, so that the board entry point runs with relocations
applied right away.

Thanks,
Ahmad

-- 
Pengutronix e.K.                  |                             |
Steuerwalder Str. 21              | http://www.pengutronix.de/  |
31137 Hildesheim, Germany         | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |




^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-03-09 15:22 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-09  7:46 [PATCH v2 0/4] ARM: i.MX8: add DDRC-ECC support Steffen Trumtrar
2026-03-09  7:46 ` [PATCH v2 1/4] ARM: i.MX: esdctl: fix spelling of ad(d)ress Steffen Trumtrar
2026-03-09 14:56   ` Ahmad Fatoum
2026-03-09  7:46 ` [PATCH v2 2/4] arm: mach-imx: esdctl.c: Add support for imx8mp inline ECC Steffen Trumtrar
2026-03-09 14:56   ` Ahmad Fatoum
2026-03-09  7:46 ` [PATCH v2 3/4] drivers: ddr: imx8m: ddr_init.c: support ECC scrubbing Steffen Trumtrar
2026-03-09 15:12   ` Ahmad Fatoum
2026-03-09  7:46 ` [PATCH v2 4/4] arm: boards: protonic-imx8ml: Add ECC + scrubbing Steffen Trumtrar
2026-03-09 15:21   ` Ahmad Fatoum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox