Hi Alif,

On Thu, Dec 18, 2025 at 2:43 PM Yuslaimi, Alif Zakuan
<[email protected]> wrote:
>
> Hi Brian,
>
> On 17/12/2025 3:50 pm, Sune Brian wrote:
> > [CAUTION: This email is from outside your organization. Unless you trust 
> > the sender, do not click on links or open attachments as it may be a 
> > fraudulent email attempting to steal your information and/or compromise 
> > your computer.]
> >
> > Hi Alif,
> >
> > On Wed, Dec 17, 2025 at 3:27 PM Yuslaimi, Alif Zakuan
> > <[email protected]> wrote:
> >>
> >> Hi Brian,
> >>
> >> On 16/12/2025 5:46 pm, Sune Brian wrote:
> >>> [CAUTION: This email is from outside your organization. Unless you trust 
> >>> the sender, do not click on links or open attachments as it may be a 
> >>> fraudulent email attempting to steal your information and/or compromise 
> >>> your computer.]
> >>>
> >>> Hi Alif,
> >>>
> >>> I have a question on sdram_arria10.c
> >>> Why spl_gen5.c requires:
> >>> static struct bd_info bdata __attribute__ ((section(".data")));
> >>> with gd->bd = &bdata;
> >>> But on arria10 this is not required, it is done on another file?
> >>>
> >>> Thank you,
> >>> Brian
> >>>
> >>
> >> I found that removing these will cause failure to boot U-Boot SPL after
> >> trying to reboot from Linux, SPL will keep on looping during DDR
> >> initialization.
> >>
> >> This could be because of the missing board info in the memory, leading
> >> to a failed initialization as gd->bd is not set up properly after a warm
> >> reset.
> >>
> >> SPL runs from the small OCRAM before DRAM is available. CycloneV has a
> >> much more limited OCRAM space compared to Arria10.
> >
> > I am referring to the A10 case here. Maybe you confused my previous 
> > question.
> > Why I am asking this question is because both A10 and GEN5 aka C5 use
> > the same soc32.c. Hence, the ECC will require the gd->bd-> to be defined
> > in order for .size or .start etc to be used.
> >
> > +       start_addr = gd->bd->bi_dram[0].start;
> > +       size = gd->bd->bi_dram[0].size;
> >
> > So your dynamic means it is well set up before the ECC init uses those
> > variables?
> > As I am not finding, gd->bd is not set in the a10_spl.c at least not
> > really distinct as "="
> >
> > Thanks,
> > Brian
> >
>
> Yes, just like you have mentioned, both Arria10 and Gen5 require gd->bd
> to be defined before ECC scrubbing in sdram_soc32.c.
>
> However, unlike Gen5, Arria10 is able to leverage common SPL’s
> (common/spl/spl.c) generic fallback function - spl_set_bd(), thanks to
> the larger OCRAM which allows more flexibility for SPL to use U-Boot’s
> generic memory allocation and initialization mechanisms.

So for the GEN 5 case the spl_set_bd() is not possible I guess.
1M vs 64K on A10 indeed much much more room to work things.
Thank you for the detailed explanations.

Brian

>
> Thanks,
> Alif
>
> >>
> >> Due to this memory space limitation, there is no dynamic memory
> >> allocation in Gen5 SPL, therefore bd_info must be allocated statically.
> >>
> >> By declaring bd_info as static and placing it in .data section, we can
> >> minimize Gen5 SPL OCRAM usage, as well as making the SPL execution much
> >> more simpler and robust.
> >>
> >> Thanks,
> >> Alif
> >>
> >>> On Tue, Dec 16, 2025 at 4:46 PM <[email protected]> wrote:
> >>>>
> >>>> From: Alif Zakuan Yuslaimi <[email protected]>
> >>>>
> >>>> 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 <[email protected]>
> >>>> Signed-off-by: Alif Zakuan Yuslaimi <[email protected]>
> >>>> ---
> >>>>    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_ */
> >>>> --
> >>>> 2.43.7
> >>>>
> >>
>

Reply via email to