[U-Boot] [RFC 4/4] arm: socfpga: scrub the SDRAM to properly enable ECC support

Dinh Nguyen
2016-10-10T15:52:23Z

From: Dinh Nguyen <dinguyen@opensource.altera.com>

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@opensource.altera.com>
---
arch/arm/mach-socfpga/include/mach/reset_manager.h | 21 ++++++++++++++++
arch/arm/mach-socfpga/include/mach/sdram.h | 2 ++
arch/arm/mach-socfpga/spl.c | 8 +++++++
arch/arm/mach-socfpga/wrap_sdram_config.c | 28 ++++++++++++++++++++++
configs/socfpga_cyclone5_defconfig | 2 ++
5 files changed, 61 insertions(+)

diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager.h b/arch/arm/mach-socfpga/include/mach/reset_manager.h
index 2f070f2..9750026 100644
--- a/arch/arm/mach-socfpga/include/mach/reset_manager.h
+++ b/arch/arm/mach-socfpga/include/mach/reset_manager.h
@@ -79,4 +79,25 @@ struct socfpga_reset_manager {
/* Create a human-readable reference to SoCFPGA reset. */
#define SOCFPGA_RESET(_name) RSTMGR_##_name

+#define RSTMGR_STAT_L4WD1RST_MASK 0x00008000
+#define RSTMGR_STAT_L4WD0RST_MASK 0x00004000
+#define RSTMGR_STAT_MPUWD1RST_MASK 0x00002000
+#define RSTMGR_STAT_MPUWD0RST_MASK 0x00001000
+#define RSTMGR_STAT_SWWARMRST_MASK 0x00000400
+#define RSTMGR_STAT_FPGAWARMRST_MASK 0x00000200
+#define RSTMGR_STAT_NRSTPINRST_MASK 0x00000100
+#define RSTMGR_STAT_SWCOLDRST_MASK 0x00000010
+#define RSTMGR_STAT_CONFIGIOCOLDRST_MASK 0x00000008
+#define RSTMGR_STAT_FPGACOLDRST_MASK 0x00000004
+#define RSTMGR_STAT_NPORPINRST_MASK 0x00000002
+#define RSTMGR_STAT_PORVOLTRST_MASK 0x00000001
+
+#define RSTMGR_WARMRST_MASK (RSTMGR_STAT_SWWARMRST_MASK | \
+ RSTMGR_STAT_L4WD0RST_MASK | \
+ RSTMGR_STAT_L4WD1RST_MASK | \
+ RSTMGR_STAT_MPUWD1RST_MASK | \
+ RSTMGR_STAT_MPUWD0RST_MASK | \
+ RSTMGR_STAT_FPGAWARMRST_MASK | \
+ RSTMGR_STAT_NRSTPINRST_MASK)
+
#endif /* _RESET_MANAGER_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/sdram.h b/arch/arm/mach-socfpga/include/mach/sdram.h
index f12bb84..5154ad2 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 31cc7de..dfa6423 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>
@@ -310,3 +312,29 @@ 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;
+ u8 pl330_buf[2000];
+
+ 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 42b71c3..89c3398 100644
--- a/configs/socfpga_cyclone5_defconfig
+++ b/configs/socfpga_cyclone5_defconfig
@@ -59,3 +59,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.8.3