[PATCH v1 2/5] ddr: socfpga: Add ECC DRAM scrubbing support for Gen5/Arria10

Chee, Tien Fong tienfong.chee at altera.com
Tue Jan 27 08:56:28 CET 2026


On 16/12/2025 4:46 pm, alif.zakuan.yuslaimi at altera.com wrote:
> From: Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi at altera.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.
>
> Move common code sdram_init_ecc_bits() to new common file sdram_soc32.c.
> Preparation for Gen5 uses the same memory initialization function as
> Arria10.
>
> Signed-off-by: Tien Fong Chee <tien.fong.chee at altera.com>
> Signed-off-by: Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi at altera.com>
> ---
>   arch/arm/mach-socfpga/spl_gen5.c   |  4 ++
>   drivers/ddr/altera/Makefile        |  4 +-
>   drivers/ddr/altera/sdram_arria10.c | 25 +++-------
>   drivers/ddr/altera/sdram_gen5.c    | 18 ++++++++
>   drivers/ddr/altera/sdram_soc32.c   | 74 ++++++++++++++++++++++++++++++
>   drivers/ddr/altera/sdram_soc32.h   | 11 +++++
>   6 files changed, 115 insertions(+), 21 deletions(-)
>   create mode 100644 drivers/ddr/altera/sdram_soc32.c
>   create mode 100644 drivers/ddr/altera/sdram_soc32.h
>
> diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c
> index df79cfe0f7f..5c78a4c1fea 100644
> --- a/arch/arm/mach-socfpga/spl_gen5.c
> +++ b/arch/arm/mach-socfpga/spl_gen5.c
> @@ -27,6 +27,8 @@
>   
>   DECLARE_GLOBAL_DATA_PTR;
>   
> +static struct bd_info bdata __attribute__ ((section(".data")));
> +
>   u32 spl_boot_device(void)
>   {
>   	const u32 bsel = readl(socfpga_get_sysmgr_addr() +
> @@ -146,6 +148,8 @@ void board_init_f(ulong dummy)
>   	/* enable console uart printing */
>   	preloader_console_init();
>   
> +	gd->bd = &bdata;
> +
>   	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
>   	if (ret) {
>   		debug("DRAM init failed: %d\n", ret);
> diff --git a/drivers/ddr/altera/Makefile b/drivers/ddr/altera/Makefile
> index 7ed43965be5..b9e3302d714 100644
> --- a/drivers/ddr/altera/Makefile
> +++ b/drivers/ddr/altera/Makefile
> @@ -7,8 +7,8 @@
>   # Copyright (C) 2014-2025 Altera Corporation <www.altera.com>
>   
>   ifdef CONFIG_$(PHASE_)ALTERA_SDRAM
> -obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += sdram_gen5.o sequencer.o
> -obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += sdram_arria10.o
> +obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += sdram_soc32.o sdram_gen5.o sequencer.o
> +obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += sdram_soc32.o sdram_arria10.o
>   obj-$(CONFIG_TARGET_SOCFPGA_STRATIX10) += sdram_soc64.o sdram_s10.o
>   obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += sdram_soc64.o sdram_agilex.o
>   obj-$(CONFIG_TARGET_SOCFPGA_N5X) += sdram_soc64.o sdram_n5x.o
> diff --git a/drivers/ddr/altera/sdram_arria10.c b/drivers/ddr/altera/sdram_arria10.c
> index d3305a6c82d..0e3a1d42f34 100644
> --- a/drivers/ddr/altera/sdram_arria10.c
> +++ b/drivers/ddr/altera/sdram_arria10.c
> @@ -21,9 +21,14 @@
>   #include <linux/bitops.h>
>   #include <linux/delay.h>
>   #include <linux/kernel.h>
> +#include <linux/sizes.h>
> +
> +#include "sdram_soc32.h"
>   
>   DECLARE_GLOBAL_DATA_PTR;
>   
> +#define PGTABLE_OFF	0x4000
> +
>   static void sdram_mmr_init(void);
>   static u64 sdram_size_calc(void);
>   
> @@ -192,24 +197,6 @@ static int sdram_is_ecc_enabled(void)
>   		  ALT_ECC_HMC_OCP_ECCCTL_ECC_EN_SET_MSK);
>   }
>   
> -/* Initialize SDRAM ECC bits to avoid false DBE */
> -static void sdram_init_ecc_bits(u32 size)
> -{
> -	icache_enable();
> -
> -	memset(0, 0, 0x8000);
> -	gd->arch.tlb_addr = 0x4000;
> -	gd->arch.tlb_size = PGTABLE_SIZE;
> -
> -	dcache_enable();
> -
> -	printf("DDRCAL: Scrubbing ECC RAM (%i MiB).\n", size >> 20);
> -	memset((void *)0x8000, 0, size - 0x8000);
> -	flush_dcache_all();
> -	printf("DDRCAL: Scrubbing ECC RAM done.\n");
> -	dcache_disable();
> -}
> -
>   /* Function to startup the SDRAM*/
>   static int sdram_startup(void)
>   {
> @@ -706,7 +693,7 @@ int ddr_calibration_sequence(void)
>   		puts("FW: Error Configuring Firewall\n");
>   
>   	if (sdram_is_ecc_enabled())
> -		sdram_init_ecc_bits(gd->ram_size);
> +		sdram_init_ecc_bits();
>   
>   	return 0;
>   }
> diff --git a/drivers/ddr/altera/sdram_gen5.c b/drivers/ddr/altera/sdram_gen5.c
> index 3c79bb11802..7a0a043557b 100644
> --- a/drivers/ddr/altera/sdram_gen5.c
> +++ b/drivers/ddr/altera/sdram_gen5.c
> @@ -2,6 +2,7 @@
>   /*
>    * Copyright Altera Corporation (C) 2014-2015
>    */
> +#include <cpu_func.h>
>   #include <dm.h>
>   #include <errno.h>
>   #include <div64.h>
> @@ -17,8 +18,12 @@
>   #include <asm/bitops.h>
>   #include <asm/io.h>
>   #include <dm/device_compat.h>
> +#include <linux/sizes.h>
>   
>   #include "sequencer.h"
> +#include "sdram_soc32.h"
> +
> +#define PGTABLE_OFF	0x4000
>   
>   #ifdef CONFIG_XPL_BUILD
>   
> @@ -562,6 +567,12 @@ static unsigned long sdram_calculate_size(struct socfpga_sdr_ctrl *sdr_ctrl)
>   	return temp;
>   }
>   
> +static int sdram_is_ecc_enabled(struct socfpga_sdr_ctrl *sdr_ctrl)
> +{
> +	return !!(readl(&sdr_ctrl->ctrl_cfg) &
> +		  SDR_CTRLGRP_CTRLCFG_ECCEN_MASK);
> +}
> +
>   static int altera_gen5_sdram_of_to_plat(struct udevice *dev)
>   {
>   	struct altera_gen5_sdram_plat *plat = dev_get_plat(dev);
> @@ -604,6 +615,13 @@ static int altera_gen5_sdram_probe(struct udevice *dev)
>   	sdram_size = sdram_calculate_size(sdr_ctrl);
>   	debug("SDRAM: %ld MiB\n", sdram_size >> 20);
>   
> +	if (sdram_is_ecc_enabled(sdr_ctrl)) {
> +		/* Must set USEECCASDATA to 0 if ECC is enabled */
> +		clrbits_le32(&sdr_ctrl->static_cfg,
> +			     SDR_CTRLGRP_STATICCFG_USEECCASDATA_MASK);
> +		sdram_init_ecc_bits();
> +	}
> +
>   	/* Sanity check ensure correct SDRAM size specified */
>   	if (get_ram_size(0, sdram_size) != sdram_size) {
>   		puts("SDRAM size check failed!\n");
> diff --git a/drivers/ddr/altera/sdram_soc32.c b/drivers/ddr/altera/sdram_soc32.c
> new file mode 100644
> index 00000000000..b8b42ef8e03
> --- /dev/null
> +++ b/drivers/ddr/altera/sdram_soc32.c
> @@ -0,0 +1,74 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2025 Altera Corporation <www.altera.com>
> + */
> +
> +#include "sdram_soc32.h"
> +#include <string.h>
> +#include <linux/sizes.h>
> +#include <cpu_func.h>
> +#include <watchdog.h>
> +#include <wait_bit.h>
> +#include <asm/global_data.h>
> +#include <asm/system.h>
> +#if !defined(CONFIG_HW_WATCHDOG)
> +#include <asm/arch/reset_manager.h>
> +#endif
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define PGTABLE_OFF	0x4000
> +
> +/* Initialize SDRAM ECC bits to avoid false DBE */
> +void sdram_init_ecc_bits(void)
> +{
> +	u32 start;
> +	phys_addr_t start_addr;
> +	phys_size_t size, size_init;
> +
> +	start = get_timer(0);
> +
> +	start_addr = gd->bd->bi_dram[0].start;
> +	size = gd->bd->bi_dram[0].size;
> +
> +	printf("DDRCAL: Scrubbing ECC RAM (%ld MiB).\n", size >> 20);
> +
> +	memset((void *)start_addr, 0, PGTABLE_SIZE + PGTABLE_OFF);
> +	gd->arch.tlb_addr = start_addr + PGTABLE_OFF;
> +	gd->arch.tlb_size = PGTABLE_SIZE;
> +	start_addr += PGTABLE_SIZE + PGTABLE_OFF;
> +	size -= PGTABLE_OFF + PGTABLE_SIZE;
> +
> +	dcache_enable();
> +
> +	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;
> +
> +#ifdef CONFIG_HW_WATCHDOG
> +		/*
> +		 * In case the watchdog is enabled, make sure to
> +		 * (re-)configure watchdog so that the defined timeout is
> +		 * valid.
> +		 */
> +		debug("%s: %d\n", __func__, __LINE__);
> +		hw_watchdog_init();
> +#else
> +		/*
> +		 * If the HW watchdog is NOT enabled, make sure it is not
> +		 * running, because it is enabled in the preloader and
> +		 * causing boot loop if is not handled.
> +		 */
> +		debug("%s: %d\n", __func__, __LINE__);
> +		socfpga_per_reset(SOCFPGA_RESET(L4WD0), 1);
> +		socfpga_per_reset(SOCFPGA_RESET(L4WD0), 0);
> +#endif
> +	}
> +
> +	dcache_disable();
> +
> +	printf("DDRCAL: SDRAM-ECC initialized success with %d ms\n",
> +	       (u32)get_timer(start));
> +}
> diff --git a/drivers/ddr/altera/sdram_soc32.h b/drivers/ddr/altera/sdram_soc32.h
> new file mode 100644
> index 00000000000..85a951a5a74
> --- /dev/null
> +++ b/drivers/ddr/altera/sdram_soc32.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2025 Altera Corporation <www.altera.com>
> + */
> +
> +#ifndef	_SDRAM_SOC32_H_
> +#define	_SDRAM_SOC32_H_
> +
> +void sdram_init_ecc_bits(void);
> +
> +#endif /* _SDRAM_SOC32_H_ */


Reviewed-by: Tien Fong Chee <tien.fong.chee at altera.com>

Best regards,
Tien Fong



More information about the U-Boot mailing list