[U-Boot] [RFC v2 2/3] arm: socfpga: scrub the SDRAM to properly enable ECC support
Dinh Nguyen
dinguyen at kernel.org
Fri Dec 9 18:03:33 CET 2016
In order for SDRAM ECC to work correctly, the SDRAM needs to get zero'd which
enables the ECC bit. By using the PL330 DMA to fill the SDRAM with zeroes,
the operation is completed in ~1.2 seconds, versus ~14 seconds with a memset.
Signed-off-by: Dinh Nguyen <dinguyen at opensource.altera.com>
---
v2: explanation for size of pl330_buf
remove reset manager defines
---
arch/arm/mach-socfpga/include/mach/sdram.h | 2 ++
arch/arm/mach-socfpga/spl.c | 8 ++++++++
arch/arm/mach-socfpga/wrap_sdram_config.c | 32 ++++++++++++++++++++++++++++++
configs/socfpga_cyclone5_defconfig | 2 ++
4 files changed, 44 insertions(+)
diff --git a/arch/arm/mach-socfpga/include/mach/sdram.h b/arch/arm/mach-socfpga/include/mach/sdram.h
index b11228f..a70d5c6 100644
--- a/arch/arm/mach-socfpga/include/mach/sdram.h
+++ b/arch/arm/mach-socfpga/include/mach/sdram.h
@@ -20,6 +20,8 @@ const struct socfpga_sdram_rw_mgr_config *socfpga_get_sdram_rwmgr_config(void);
const struct socfpga_sdram_io_config *socfpga_get_sdram_io_config(void);
const struct socfpga_sdram_misc_config *socfpga_get_sdram_misc_config(void);
+void sdram_ecc_init(void);
+
#define SDR_CTRLGRP_ADDRESS (SOCFPGA_SDR_ADDRESS | 0x5000)
struct socfpga_sdr_ctrl {
diff --git a/arch/arm/mach-socfpga/spl.c b/arch/arm/mach-socfpga/spl.c
index fec4c7a..26688ad 100644
--- a/arch/arm/mach-socfpga/spl.c
+++ b/arch/arm/mach-socfpga/spl.c
@@ -30,6 +30,8 @@ static struct nic301_registers *nic301_regs =
(struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS;
static struct socfpga_system_manager *sysmgr_regs =
(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
+static const struct socfpga_reset_manager *reset_manager_base =
+ (void *)SOCFPGA_RSTMGR_ADDRESS;
u32 spl_boot_device(void)
{
@@ -85,6 +87,9 @@ void board_init_f(ulong dummy)
#endif
unsigned long sdram_size;
unsigned long reg;
+ u32 rst_mgr_status;
+
+ rst_mgr_status = readl(&reset_manager_base->status);
/*
* First C code to run. Clear fake OCRAM ECC first as SBE
@@ -179,6 +184,9 @@ void board_init_f(ulong dummy)
socfpga_bridges_reset(1);
+ if ((rst_mgr_status & RSTMGR_WARMRST_MASK) == 0)
+ sdram_ecc_init();
+
/* Configure simple malloc base pointer into RAM. */
gd->malloc_base = CONFIG_SYS_TEXT_BASE + (1024 * 1024);
}
diff --git a/arch/arm/mach-socfpga/wrap_sdram_config.c b/arch/arm/mach-socfpga/wrap_sdram_config.c
index 8fb808a..1509cba 100644
--- a/arch/arm/mach-socfpga/wrap_sdram_config.c
+++ b/arch/arm/mach-socfpga/wrap_sdram_config.c
@@ -5,8 +5,10 @@
*/
#include <common.h>
+#include <dma.h>
#include <errno.h>
#include <asm/arch/sdram.h>
+#include <asm/pl330.h>
/* Board-specific header. */
#include <qts/sdram_config.h>
@@ -317,3 +319,33 @@ const struct socfpga_sdram_misc_config *socfpga_get_sdram_misc_config(void)
{
return &misc_config;
}
+
+#if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ECCEN == 1)
+/* init the whole SDRAM ECC bit */
+void sdram_ecc_init(void)
+{
+ struct pl330_transfer_struct pl330;
+ /*
+ * 1200 bytes is the buffer size needed to handle the microcode for
+ * transferring 1GB of zero's.
+ */
+ u8 pl330_buf[1200];
+
+ pl330.dst_addr = CONFIG_SYS_SDRAM_BASE;
+ pl330.len = sdram_calculate_size();
+ pl330.channel_num = 0;
+ pl330.buf_size = sizeof(pl330_buf);
+ pl330.buf = pl330_buf;
+
+ pl330.transfer_type = DMA_SUPPORTS_DEV_TO_MEM;
+ pl330.reg_base = (void __iomem *)SOCFPGA_DMASECURE_ADDRESS;
+
+ puts("SDRAM: Initializing SDRAM ECC\n");
+
+ arm_pl330_transfer(&pl330);
+
+ printf("SDRAM: ECC initialized successfully\n");
+}
+#else
+void sdram_ecc_init(void) {}
+#endif
diff --git a/configs/socfpga_cyclone5_defconfig b/configs/socfpga_cyclone5_defconfig
index 905f766..8a8c71b 100644
--- a/configs/socfpga_cyclone5_defconfig
+++ b/configs/socfpga_cyclone5_defconfig
@@ -63,3 +63,5 @@ CONFIG_G_DNL_MANUFACTURER="altera"
CONFIG_G_DNL_VENDOR_NUM=0x0525
CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
CONFIG_USE_TINY_PRINTF=y
+CONFIG_SPL_DMA_SUPPORT=y
+CONFIG_PL330_DMA=y
--
2.7.4
More information about the U-Boot
mailing list