FPGA2SDRAM setup fix
authorBrian Sune <briansune@gmail.com>
Mon, 20 Oct 2025 13:35:54 +0000 (21:35 +0800)
committerTien Fong Chee <tien.fong.chee@intel.com>
Mon, 1 Dec 2025 05:55:27 +0000 (13:55 +0800)
After testing, w/o proper setup
the FPGA2SDRAM bridge will not work and stall.
Pulling from official fix and w/o this initialization,
both 2025.07 and 2025.10 also suffer stall on U-Boot
and distro. Any FPGA to HPS-SDRAM action will immediate
stall the CPU. As such, this patch fix the issue.

Signed-off-by: Brian Sune <briansune@gmail.com>
Reviewed-by: Tien Fong Chee <tien.fong.chee@altera.com>
arch/arm/mach-socfpga/misc_gen5.c

index b136691..5259ef5 100644 (file)
@@ -217,6 +217,34 @@ int arch_early_init_r(void)
 static struct socfpga_sdr_ctrl *sdr_ctrl =
        (struct socfpga_sdr_ctrl *)SDR_CTRLGRP_ADDRESS;
 
+void socfpga_sdram_apply_static_cfg(void)
+{
+       const u32 applymask = 0x8;
+       u32 val = readl(&sdr_ctrl->static_cfg) | applymask;
+
+       /*
+        * SDRAM staticcfg register specific:
+        * When applying the register setting, the CPU must not access
+        * SDRAM. Luckily for us, we can use i-cache here to help us
+        * circumvent the SDRAM access issue. The idea is to make sure
+        * that the code is in one full i-cache line by branching past
+        * it and back. Once it is in the i-cache, we execute the core
+        * of the code and apply the register settings.
+        *
+        * The code below uses 7 instructions, while the Cortex-A9 has
+        * 32-byte cachelines, thus the limit is 8 instructions total.
+        */
+       asm volatile(".align    5                       \n"
+                    "          b 2f                    \n"
+                    "1:        str %0, [%1]            \n"
+                    "          dsb                     \n"
+                    "          isb                     \n"
+                    "          b 3f                    \n"
+                    "2:        b 1b                    \n"
+                    "3:        nop                     \n"
+                   : : "r"(val), "r"(&sdr_ctrl->static_cfg) : "memory", "cc");
+}
+
 void do_bridge_reset(int enable, unsigned int mask)
 {
        int i;
@@ -234,7 +262,10 @@ void do_bridge_reset(int enable, unsigned int mask)
                writel(iswgrp_handoff[2],
                       socfpga_get_sysmgr_addr() +
                       SYSMGR_GEN5_FPGAINFGRP_MODULE);
-               writel(iswgrp_handoff[3], &sdr_ctrl->fpgaport_rst);
+               if (iswgrp_handoff[3]) {
+                       writel(iswgrp_handoff[3], &sdr_ctrl->fpgaport_rst);
+                       socfpga_sdram_apply_static_cfg();
+               }
                writel(iswgrp_handoff[0],
                       socfpga_get_rstmgr_addr() + RSTMGR_GEN5_BRGMODRST);
                writel(iswgrp_handoff[1], &nic301_regs->remap);
@@ -246,6 +277,7 @@ void do_bridge_reset(int enable, unsigned int mask)
                writel(0, socfpga_get_sysmgr_addr() +
                       SYSMGR_GEN5_FPGAINFGRP_MODULE);
                writel(0, &sdr_ctrl->fpgaport_rst);
+               socfpga_sdram_apply_static_cfg();
                writel(0x7, socfpga_get_rstmgr_addr() + RSTMGR_GEN5_BRGMODRST);
                writel(1, &nic301_regs->remap);
        }