[PATCH] ddr: socfpga: Improve A10 SDRAM ECC init function to support watchdog reset

teik.heng.chong at intel.com teik.heng.chong at intel.com
Mon Sep 19 02:57:29 CEST 2022


From: Tien Fong Chee <tien.fong.chee at intel.com>

There is a potential risk that memset on DDR taking too long than the
timeout set for watchdog, hence the function is restructured so that
splitting up the DDR into chunks for memset and resetting the watchdog for
each chunk memory.

Signed-off-by: Tien Fong Chee <tien.fong.chee at intel.com>
Signed-off-by: Teik Heng Chong <teik.heng.chong at intel.com>
---
 drivers/ddr/altera/sdram_arria10.c | 38 ++++++++++++++++++++++++++----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/ddr/altera/sdram_arria10.c b/drivers/ddr/altera/sdram_arria10.c
index 4a8f8dea1c..6eb7a34bc0 100644
--- a/drivers/ddr/altera/sdram_arria10.c
+++ b/drivers/ddr/altera/sdram_arria10.c
@@ -22,6 +22,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/sizes.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -48,6 +49,8 @@ static u64 sdram_size_calc(void);
 #define CORE2SEQ_INT_REQ	0xF
 #define SEQ2CORE_INT_RESP_BIT	3
 
+#define PGTABLE_OFF	0x4000
+
 static const struct socfpga_ecc_hmc *socfpga_ecc_hmc_base =
 		(void *)SOCFPGA_SDR_ADDRESS;
 static const struct socfpga_noc_ddr_scheduler *socfpga_noc_ddr_scheduler_base =
@@ -196,19 +199,44 @@ static int sdram_is_ecc_enabled(void)
 /* Initialize SDRAM ECC bits to avoid false DBE */
 static void sdram_init_ecc_bits(u32 size)
 {
-	icache_enable();
+	u32 start, size_init, start_addr;
+
+	start = get_timer(0);
+
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	gd->bd->bi_dram[0].size = size;
 
-	memset(0, 0, 0x8000);
-	gd->arch.tlb_addr = 0x4000;
+	gd->arch.tlb_addr = gd->bd->bi_dram[0].start + PGTABLE_OFF;
 	gd->arch.tlb_size = PGTABLE_SIZE;
 
+	memset((void *)gd->bd->bi_dram[0].start, 0, gd->arch.tlb_addr +
+	       gd->arch.tlb_size + SZ_1K);
+
+	icache_enable();
 	dcache_enable();
 
-	printf("DDRCAL: Scrubbing ECC RAM (%i MiB).\n", size >> 20);
-	memset((void *)0x8000, 0, size - 0x8000);
+	start_addr = gd->arch.tlb_addr + gd->arch.tlb_size;
+	size -= (gd->arch.tlb_addr + gd->arch.tlb_size);
+
+	printf("DDRCAL: Scrubbing ECC RAM (%d MiB).\n", size >> 20);
+
+
+	while (size > 0) {
+		size_init = min((phys_addr_t)SZ_1G, (phys_addr_t)size);
+		memset((void *)start_addr, 0, size_init);
+		size -= size_init;
+		start_addr += size_init;
+		WATCHDOG_RESET();
+	}
+
 	flush_dcache_all();
+
 	printf("DDRCAL: Scrubbing ECC RAM done.\n");
+
 	dcache_disable();
+
+	printf("DDRCAL: SDRAM-ECC initialized success with %d ms\n",
+	       (u32)get_timer(start));
 }
 
 /* Function to startup the SDRAM*/
-- 
2.25.1



More information about the U-Boot mailing list