Message ID | 20161010155223.23751-5-dinguyen@kernel.org |
---|---|
State | RFC |
Headers | show |
On Mon, 2016-10-10 at 10:52 -0500, Dinh Nguyen wrote: > 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/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]; Would need size of 2500 if the SDRAM size is 2GB Thanks Chin Liang
On 10/10/2016 05:52 PM, Dinh Nguyen wrote: > 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) This should go into separate patch. > #endif /* _RESET_MANAGER_H_ */ [...] > 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]; Why is the buffer 2000 bytes long ? > + 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 This probably shouldn't be enabled by default, or should it ? What about ArriaV SoCDK ?
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