[U-Boot] [PATCH] ddr: altera: Add ECC DRAM scrubbing support for Stratix 10
tien.fong.chee at intel.com
tien.fong.chee at intel.com
Mon Jul 23 08:20:19 UTC 2018
From: Tien Fong Chee <tien.fong.chee at intel.com>
The SDRAM must first be rewritten by zeroes if ECC is used to initialize
the ECC metadata. Make the CPU overwrite the DRAM with zeroes in such a
case. This scrubbing implementation turns the caches on temporarily, then
overwrites the whole RAM with zeroes, flushes the caches and turns them
off again. This provides satisfactory performance.
Signed-off-by: Tien Fong Chee <tien.fong.chee at intel.com>
---
drivers/ddr/altera/sdram_s10.c | 44 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/drivers/ddr/altera/sdram_s10.c b/drivers/ddr/altera/sdram_s10.c
index 48f4f47..cce261f 100644
--- a/drivers/ddr/altera/sdram_s10.c
+++ b/drivers/ddr/altera/sdram_s10.c
@@ -8,6 +8,7 @@
#include <errno.h>
#include <div64.h>
#include <asm/io.h>
+#include <linux/sizes.h>
#include <wait_bit.h>
#include <asm/arch/firewall_s10.h>
#include <asm/arch/sdram_s10.h>
@@ -134,6 +135,47 @@ static int poll_hmc_clock_status(void)
SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
}
+/* Initialize SDRAM ECC bits to avoid false DBE */
+static void sdram_init_ecc_bits(unsigned long long size)
+{
+ /* 1GB per chunk */
+ unsigned long long size_byte = SZ_1G;
+ unsigned long long remaining_size;
+ unsigned long long dst_addr = 0x8000;
+ unsigned int start = get_timer(0);
+
+ icache_enable();
+
+ memset(0, 0, dst_addr);
+ gd->arch.tlb_addr = 0x4000;
+ gd->arch.tlb_size = PGTABLE_SIZE;
+
+ dcache_enable();
+
+ remaining_size = size - dst_addr;
+ printf("DDRCAL: Scrubbing ECC RAM (%d MiB).\n", (u32)(size >> 20));
+
+ while (remaining_size) {
+ if (remaining_size <= size_byte) {
+ memset((void *)dst_addr, 0, remaining_size);
+ break;
+ } else {
+ memset((void *)dst_addr, 0, size_byte);
+ dst_addr += size_byte;
+ }
+
+ WATCHDOG_RESET();
+ remaining_size -= size_byte;
+ }
+
+ flush_dcache_all();
+ printf("DDRCAL: Scrubbing ECC RAM done.\n");
+ dcache_disable();
+
+ printf("SDRAM-ECC: Initialized success with %d ms\n",
+ (unsigned)get_timer(start));
+}
+
/**
* sdram_mmr_init_full() - Function to initialize SDRAM MMR
*
@@ -351,6 +393,8 @@ int sdram_mmr_init_full(unsigned int unused)
setbits_le32(SOCFPGA_SDR_ADDRESS + ECCCTRL2,
(DDR_HMC_ECCCTL2_RMW_EN_SET_MSK |
DDR_HMC_ECCCTL2_AWB_EN_SET_MSK));
+
+ sdram_init_ecc_bits(gd->ram_size);
} else {
clrbits_le32(SOCFPGA_SDR_ADDRESS + ECCCTRL1,
(DDR_HMC_ECCCTL_AWB_CNT_RST_SET_MSK |
--
1.7.7.4
More information about the U-Boot
mailing list