ARM: imx: Update DRAM timings with inline ECC on DH i.MX8MP DHCOM SoM

Import DRAM timings generated by the DDR tool 3.31 which introduce assorted
tweaks to the DRAM controller settings. Furthermore, enable DBI to improve
noise resilience of the DRAM bus by reducing the number of bit changes on
the bus.

Reduce the DRAM rate to 3600 MTps to remove all remaining correctable errors
reported by EDAC . It is not entirely clear why the slightly faster setting
does produce sporadic correctable errors, while this one does not, but this
could be related to simpler PLL setting at 3600 MTps.

Enable inline ECC which is necessary to detect ECC errors and collect
statistics by the EDAC driver in Linux. This reduces the DRAM size by
64 MiB for each 512 MiB of DRAM, so for a 4 GiB device the available
DRAM size becomes 3.5 GiB and for 2 GiB device the available DRAM size
becomes 1.8 GiB.

Signed-off-by: Marek Vasut <marex@denx.de>
diff --git a/board/dhelectronics/dh_imx8mp/spl.c b/board/dhelectronics/dh_imx8mp/spl.c
index 21b12a7..7d228da 100644
--- a/board/dhelectronics/dh_imx8mp/spl.c
+++ b/board/dhelectronics/dh_imx8mp/spl.c
@@ -11,6 +11,7 @@
 #include <asm/io.h>
 #include <asm-generic/gpio.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/ddr.h>
 #include <asm/arch/imx8mp_pins.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/boot_mode.h>
@@ -134,7 +135,34 @@
 	}
 
 	ddr_init(dram_timing_info[memcfg]);
+
+	printf("DDR:   Inline ECC %sabled\n",
+	       (readl(DDRC_ECCCFG0(0)) & DDRC_ECCCFG0_ECC_MODE_MASK) ?
+	       "en" : "dis");
+}
+
+#if IS_ENABLED(CONFIG_IMX8M_DRAM_INLINE_ECC)
+static const scrub_func_t dram_scrub_fn[8] = {
+	NULL,					/* 512 MiB */
+	NULL,					/* 1024 MiB */
+	NULL,					/* 1536 MiB */
+	dh_imx8mp_dhcom_dram_scrub_16g_x32,	/* 2048 MiB */
+	NULL,					/* 3072 MiB */
+	dh_imx8mp_dhcom_dram_scrub_32g_x32,	/* 4096 MiB */
+	NULL,					/* 6144 MiB */
+	NULL,					/* 8192 MiB */
+};
+
+void board_dram_ecc_scrub(void)
+{
+	u8 memcfg = dh_get_memcfg();
+
+	if (!dram_scrub_fn[memcfg])
+		return;
+
+	dram_scrub_fn[memcfg]();
 }
+#endif
 
 void spl_board_init(void)
 {