]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
arm: armv8: Improve SPL data save and restore implementation
authorAlif Zakuan Yuslaimi <alif.zakuan.yuslaimi@intel.com>
Tue, 18 Feb 2025 08:35:06 +0000 (16:35 +0800)
committerTom Rini <trini@konsulko.com>
Tue, 25 Feb 2025 16:54:02 +0000 (10:54 -0600)
Introduce a new symbol in the beginning of .data section in
the common ARMv8 linker script and use that as a reference
for data save and restore.

Previously, the code would rely on calculating the start of
the .data section address via data size, however, we observed
that the data size does not really reflect the SPL mapped
addresses.

In our case, the binman_sym section size was not included in
the data size, which will result in a wrong address for the
.data start section, which prevents us from properly saving
and restoring SPL data.

This approach skips the calculation for the starting address
of the .data section, and instead just defines the beginning
address of the .data section and calling the symbol as needed,
in which we think as a simpler and much more robust method.

Signed-off-by: Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi@altera.com>
Signed-off-by: Tien Fong Chee <tien.fong.chee@altera.com>
Reviewed-by: Tien Fong Chee <tien.fong.chee@altera.com>
arch/arm/cpu/armv8/spl_data.c
arch/arm/cpu/armv8/u-boot-spl.lds
arch/arm/mach-socfpga/spl_agilex5.c
configs/socfpga_agilex5_defconfig

index 259b49ff3640e1e711b072a85e9dc41ffc66990a..492353c93dfbc3faf26c0f1fe73889cc6eaa12ad 100644 (file)
@@ -5,23 +5,28 @@
 
 #include <spl.h>
 
+char __data_start[0] __section(".__data_start");
 char __data_save_start[0] __section(".__data_save_start");
 char __data_save_end[0] __section(".__data_save_end");
 
 u32 cold_reboot_flag = 1;
 
+u32 __weak reset_flag(void)
+{
+       return 1;
+}
+
 void spl_save_restore_data(void)
 {
        u32 data_size = __data_save_end - __data_save_start;
+       cold_reboot_flag = reset_flag();
 
        if (cold_reboot_flag == 1) {
                /* Save data section to data_save section */
-               memcpy(__data_save_start, __data_save_start - data_size,
-                      data_size);
+               memcpy(__data_save_start, __data_start, data_size);
        } else {
                /* Restore the data_save section to data section */
-               memcpy(__data_save_start - data_size, __data_save_start,
-                      data_size);
+               memcpy(__data_start, __data_save_start, data_size);
        }
 
        cold_reboot_flag++;
index fed69644b5534fe939b5763150d2e9ff5c8037e2..c4f83ec9cfc470f0cef0fff56e0c2e1a160fb4cc 100644 (file)
@@ -37,6 +37,7 @@ SECTIONS
 
        .data : {
                . = ALIGN(8);
+               *(.__data_start)
                *(.data*)
        } >.sram
 
index c87e9ed1641ef4ae399596623aa70693fe439435..3451611082dcd7bfba6442c6594350b46e14007a 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+u32 reset_flag(void)
+{
+       /* Check rstmgr.stat for warm reset status */
+       u32 status = readl(SOCFPGA_RSTMGR_ADDRESS);
+
+       /* Check whether any L4 watchdogs or SDM had triggered warm reset */
+       u32 warm_reset_mask = RSTMGR_L4WD_MPU_WARMRESET_MASK;
+
+       if (status & warm_reset_mask)
+               return 0;
+
+       return 1;
+}
+
 void board_init_f(ulong dummy)
 {
        int ret;
        struct udevice *dev;
 
+       /* Enable Async */
+       asm volatile("msr daifclr, #4");
+
+#ifdef CONFIG_SPL_BUILD
+       spl_save_restore_data();
+#endif
+
        ret = spl_early_init();
        if (ret)
                hang();
index 10686a0a7b30bd6201248c9141f55db265344488..61ce065a2bf44d779e1b7a5d45d22b8de431de2c 100644 (file)
@@ -97,3 +97,4 @@ CONFIG_BLOBLIST=y
 CONFIG_BLOBLIST_SIZE=0x1000
 CONFIG_BLOBLIST_ADDR=0x7e000
 CONFIG_HANDOFF=y
+CONFIG_SPL_RECOVER_DATA_SECTION=y