From f436398f469b20a822ee84aab96ff6594a5fbd0c Mon Sep 17 00:00:00 2001 From: Pranav Tilak Date: Tue, 23 Jun 2026 09:23:51 +0530 Subject: ufs: amd-versal2: Fix missing .priv_auto in driver registration Add missing .priv_auto field to the driver. Without it, struct ufs_versal2_priv is never properly allocated and dev_get_priv() returns NULL, leading to DDR corruption at low DDR addresses. Fixes: b5ac5f030720 ("ufs: ufs-amd-versal2: Add support for AMD UFS controller") Signed-off-by: Pranav Tilak Reviewed-by: Neil Armstrong Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20260623035411.2088224-1-pranav.vinaytilak@amd.com --- drivers/ufs/ufs-amd-versal2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ufs/ufs-amd-versal2.c b/drivers/ufs/ufs-amd-versal2.c index 6c949b2ca76..3369d32d924 100644 --- a/drivers/ufs/ufs-amd-versal2.c +++ b/drivers/ufs/ufs-amd-versal2.c @@ -563,4 +563,5 @@ U_BOOT_DRIVER(ufs_versal2_pltfm) = { .id = UCLASS_UFS, .of_match = ufs_versal2_ids, .probe = ufs_versal2_probe, + .priv_auto = sizeof(struct ufs_versal2_priv), }; -- cgit v1.3.1 From 7edbbfca632a97104b9bbe0ba6ba7accea395822 Mon Sep 17 00:00:00 2001 From: Danish Ahmad Rosdi Date: Mon, 8 Jun 2026 17:45:47 +0800 Subject: drivers: fpga: Use FPGA_INTEL_SDM_MAILBOX conditional instead of Agilex/Stratix10 Replace the conditional compilation checks for CONFIG_ARCH_SOCFPGA_AGILEX and CONFIG_ARCH_SOCFPGA_STRATIX10 with CONFIG_FPGA_INTEL_SDM_MAILBOX. Signed-off-by: Danish Ahmad Rosdi Signed-off-by: Chen Huei Lok Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20260608094547.3026-1-chen.huei.lok@altera.com --- drivers/fpga/altera.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c index 822183c5785..69d7111a5f1 100644 --- a/drivers/fpga/altera.c +++ b/drivers/fpga/altera.c @@ -12,8 +12,7 @@ /* * Altera FPGA support */ -#if IS_ENABLED(CONFIG_ARCH_SOCFPGA_AGILEX) || \ - IS_ENABLED(CONFIG_ARCH_SOCFPGA_STRATIX10) +#if IS_ENABLED(CONFIG_FPGA_INTEL_SDM_MAILBOX) #include #endif #include @@ -48,8 +47,7 @@ static const struct altera_fpga { #endif }; -#if IS_ENABLED(CONFIG_ARCH_SOCFPGA_AGILEX) || \ - IS_ENABLED(CONFIG_ARCH_SOCFPGA_STRATIX10) +#if IS_ENABLED(CONFIG_FPGA_INTEL_SDM_MAILBOX) int fpga_is_partial_data(int devnum, size_t img_len) { /* -- cgit v1.3.1 From 1d24edabfed9d32be7e35a53946ae177d4b4121a Mon Sep 17 00:00:00 2001 From: Padmarao Begari Date: Tue, 23 Jun 2026 20:38:22 +0530 Subject: soc: xilinx: zynqmp: Add TCG variant detection for ZU3TCG The XCZU3TCG device shares IDCODE 0x04718093 with XCZU3TEG but has the GPU disable eFuse bit set (Consumer Grade, no GPU). Previously, the TEG detection branch appended "teg" unconditionally, causing U-Boot to report the device as zu3teg and failing bitstream ID checks for xczu3tcg bitstreams. Check EFUSE_GPU_DIS_MASK in the TEG branch to distinguish the two sub-variants, mirroring the existing EG/CG detection logic: - GPU disabled -> TCG family -> "zu3tcg" - GPU enabled -> TEG family -> "zu3teg" Fixes: fa2f0c97af96 ("soc: zynqmp: Add the IDcode for TEG variant") Signed-off-by: Padmarao Begari Signed-off-by: Michal Simek Link: https://patch.msgid.link/20260623150943.2662500-1-padmarao.begari@amd.com --- drivers/soc/soc_xilinx_zynqmp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/soc_xilinx_zynqmp.c b/drivers/soc/soc_xilinx_zynqmp.c index 4abc73013eb..0e13e230914 100644 --- a/drivers/soc/soc_xilinx_zynqmp.c +++ b/drivers/soc/soc_xilinx_zynqmp.c @@ -358,7 +358,9 @@ static int soc_xilinx_zynqmp_detect_machine(struct udevice *dev, u32 idcode, } else if (device->variants & ZYNQMP_VARIANT_DR_SE) { strlcat(priv->machine, "dr_SE", sizeof(priv->machine)); } else if (device->variants & ZYNQMP_VARIANT_TEG) { - strlcat(priv->machine, "teg", sizeof(priv->machine)); + /* Devices with TEG variant might be TEG or TCG family */ + strlcat(priv->machine, (idcode2 & EFUSE_GPU_DIS_MASK) ? + "tcg" : "teg", sizeof(priv->machine)); } return 0; -- cgit v1.3.1 From da4783f7835630141d684369518141d1b0e86fe1 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Jun 2026 14:53:27 +0200 Subject: arm64: versal2: Decouple multiboot register access from firmware versal2_multi_boot() in board code selected between the firmware call zynqmp_pm_get_pmc_multi_boot_reg() and a direct readl() based on an IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) check. Generic board code should not carry firmware-specific ifdefs, and this becomes harder to maintain once SCMI introduces yet another access method. Introduce an overridable accessor versal2_pmc_multi_boot(). The weak default lives in arch/arm/mach-versal2 and performs the plain MMIO read (used at EL3 and when no firmware is present). When CONFIG_ZYNQMP_FIRMWARE is enabled, firmware-zynqmp.c provides a strong definition that issues the firmware call, falling back to the direct read at EL3 where the SMC path to firmware is unavailable. The shared MMIO read is factored into versal2_multi_boot_reg() so the firmware override does not duplicate it. versal2_multi_boot() keeps the generic JTAG/QEMU workaround and simply calls the accessor, so board code no longer references the firmware interface and the now unused zynqmp_firmware.h include is dropped. The firmware-vs-MMIO decision is selected at link time, and adding SCMI later only requires a third strong definition with no board-code changes. Signed-off-by: Michal Simek Link: https://patch.msgid.link/0033a1fa8efb4ae0c3ac6a6f5c5c1b4e0f22f02c.1782219202.git.michal.simek@amd.com --- arch/arm/mach-versal2/cpu.c | 10 ++++++++++ arch/arm/mach-versal2/include/mach/sys_proto.h | 5 +++++ board/amd/versal2/board.c | 9 +-------- drivers/firmware/firmware-zynqmp.c | 13 +++++++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c index d66109abd78..9991d6bbab0 100644 --- a/arch/arm/mach-versal2/cpu.c +++ b/arch/arm/mach-versal2/cpu.c @@ -127,6 +127,16 @@ u64 get_page_table_size(void) } #endif +u32 versal2_multi_boot_reg(void) +{ + return readl(PMC_MULTI_BOOT_REG) & PMC_MULTI_BOOT_MASK; +} + +u32 __weak versal2_pmc_multi_boot(void) +{ + return versal2_multi_boot_reg(); +} + U_BOOT_DRVINFO(soc_amd_versal2) = { .name = "soc_amd_versal2", }; diff --git a/arch/arm/mach-versal2/include/mach/sys_proto.h b/arch/arm/mach-versal2/include/mach/sys_proto.h index 3ed0b25be80..e0576754836 100644 --- a/arch/arm/mach-versal2/include/mach/sys_proto.h +++ b/arch/arm/mach-versal2/include/mach/sys_proto.h @@ -13,4 +13,9 @@ void mem_map_fill(struct mm_region *bank_info, u32 num_banks); void fill_bd_mem_info(void); +/* Overridable PMC multiboot accessor: weak MMIO default, firmware override */ +u32 versal2_pmc_multi_boot(void); +/* Direct MMIO read of the multiboot register (EL3 / no-firmware path) */ +u32 versal2_multi_boot_reg(void); + #endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/board/amd/versal2/board.c b/board/amd/versal2/board.c index 6e4f0c6e9b8..06d144db4f0 100644 --- a/board/amd/versal2/board.c +++ b/board/amd/versal2/board.c @@ -29,7 +29,6 @@ #include #include #include -#include #include "../../xilinx/common/board.h" #include @@ -195,18 +194,12 @@ static u8 versal2_get_bootmode(void) static u32 versal2_multi_boot(void) { u8 bootmode = versal2_get_bootmode(); - u32 reg = 0; /* Mostly workaround for QEMU CI pipeline */ if (bootmode == JTAG_MODE) return 0; - if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) && current_el() != 3) - reg = zynqmp_pm_get_pmc_multi_boot_reg(); - else - reg = readl(PMC_MULTI_BOOT_REG); - - return reg & PMC_MULTI_BOOT_MASK; + return versal2_pmc_multi_boot(); } static int boot_targets_setup(void) diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index ea14ed4ef95..70d205ff3ef 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #if defined(CONFIG_ZYNQMP_IPI) @@ -326,6 +328,17 @@ u32 zynqmp_pm_get_pmc_multi_boot_reg(void) } #endif +#if defined(CONFIG_ARCH_VERSAL2) +u32 versal2_pmc_multi_boot(void) +{ + /* At EL3 the SMC path to firmware is unavailable, read directly */ + if (current_el() == 3) + return versal2_multi_boot_reg(); + + return zynqmp_pm_get_pmc_multi_boot_reg() & PMC_MULTI_BOOT_MASK; +} +#endif + int zynqmp_pm_feature(const u32 api_id) { int ret; -- cgit v1.3.1 From b444110e51f09444f55367c18168ef04fcb1b6a2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Jun 2026 14:53:29 +0200 Subject: arm64: versal: Decouple multiboot register access from firmware versal_multi_boot() in board code selected between the firmware call zynqmp_pm_get_pmc_multi_boot_reg() and a direct readl() based on an IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) check. Generic board code should not carry firmware-specific ifdefs, and this becomes harder to maintain once SCMI introduces yet another access method. Introduce an overridable accessor versal_pmc_multi_boot(). The weak default lives in arch/arm/mach-versal and performs the plain MMIO read (used at EL3 and when no firmware is present). When CONFIG_ZYNQMP_FIRMWARE is enabled, firmware-zynqmp.c provides a strong definition that issues the firmware call, falling back to the direct read at EL3 where the SMC path to firmware is unavailable. The shared MMIO read is factored into versal_multi_boot_reg() so the firmware override does not duplicate it. versal_multi_boot() keeps the generic JTAG/QEMU workaround and simply calls the accessor, so board code no longer references the firmware interface for the multiboot register. The firmware-vs-MMIO decision is selected at link time, and adding SCMI later only requires a third strong definition with no board-code changes. Signed-off-by: Michal Simek Link: https://patch.msgid.link/199ef6a1411c54f154fe4a43b5fef166b9927f7a.1782219202.git.michal.simek@amd.com --- arch/arm/mach-versal/cpu.c | 10 ++++++++++ arch/arm/mach-versal/include/mach/sys_proto.h | 5 +++++ board/xilinx/versal/board.c | 8 +------- drivers/firmware/firmware-zynqmp.c | 11 +++++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c index 7ffd35fe89c..7ad93982e8d 100644 --- a/arch/arm/mach-versal/cpu.c +++ b/arch/arm/mach-versal/cpu.c @@ -110,6 +110,16 @@ int arm_reserve_mmu(void) } #endif +u32 versal_multi_boot_reg(void) +{ + return readl(PMC_MULTI_BOOT_REG) & PMC_MULTI_BOOT_MASK; +} + +u32 __weak versal_pmc_multi_boot(void) +{ + return versal_multi_boot_reg(); +} + U_BOOT_DRVINFO(soc_xilinx_versal) = { .name = "soc_xilinx_versal", }; diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h index b53e616e47b..d7ab2549658 100644 --- a/arch/arm/mach-versal/include/mach/sys_proto.h +++ b/arch/arm/mach-versal/include/mach/sys_proto.h @@ -17,4 +17,9 @@ void initialize_tcm(enum tcm_mode mode); void tcm_init(enum tcm_mode mode); void mem_map_fill(void); +/* Overridable PMC multiboot accessor: weak MMIO default, firmware override */ +u32 versal_pmc_multi_boot(void); +/* Direct MMIO read of the multiboot register (EL3 / no-firmware path) */ +u32 versal_multi_boot_reg(void); + #endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c index 8666f2ceff4..110490b9672 100644 --- a/board/xilinx/versal/board.c +++ b/board/xilinx/versal/board.c @@ -62,18 +62,12 @@ static u8 versal_get_bootmode(void) static u32 versal_multi_boot(void) { u8 bootmode = versal_get_bootmode(); - u32 reg = 0; /* Mostly workaround for QEMU CI pipeline */ if (bootmode == JTAG_MODE) return 0; - if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) && current_el() != 3) - reg = zynqmp_pm_get_pmc_multi_boot_reg(); - else - reg = readl(PMC_MULTI_BOOT_REG); - - return reg & PMC_MULTI_BOOT_MASK; + return versal_pmc_multi_boot(); } int board_init(void) diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 70d205ff3ef..c8943b8d23a 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -328,6 +328,17 @@ u32 zynqmp_pm_get_pmc_multi_boot_reg(void) } #endif +#if defined(CONFIG_ARCH_VERSAL) +u32 versal_pmc_multi_boot(void) +{ + /* At EL3 the SMC path to firmware is unavailable, read directly */ + if (current_el() == 3) + return versal_multi_boot_reg(); + + return zynqmp_pm_get_pmc_multi_boot_reg() & PMC_MULTI_BOOT_MASK; +} +#endif + #if defined(CONFIG_ARCH_VERSAL2) u32 versal2_pmc_multi_boot(void) { -- cgit v1.3.1 From 70236dca329910b05bf35b3e05fd460d6e9d2d76 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Jun 2026 14:53:30 +0200 Subject: arm64: versal: Move bootmode decoding out of board code versal_get_bootmode() lived in board code and open-coded the IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) selection between the firmware call zynqmp_pm_get_bootmode_reg() and a direct readl(). To keep generic board code free of firmware specifics and SoC register details and ready for SCMI, move the whole function, including the alt-shift and mask decoding, behind an overridable hook. The weak versal_get_bootmode() in arch/arm/mach-versal does the plain MMIO read via versal_bootmode_reg() and decodes it (used at EL3 and without firmware). When CONFIG_ZYNQMP_FIRMWARE is enabled, firmware-zynqmp.c provides a strong definition that reads the register through the firmware call, falling back to the direct read at EL3 where the SMC path to firmware is unavailable. This preserves the existing firmware-based bootmode behaviour while removing the firmware interface from board code; the now unused zynqmp_firmware.h include is dropped. Signed-off-by: Michal Simek Link: https://patch.msgid.link/d60073feed8da8d3aff9eabee6ab132e0bbd0f8e.1782219202.git.michal.simek@amd.com --- arch/arm/mach-versal/cpu.c | 15 +++++++++++++++ arch/arm/mach-versal/include/mach/sys_proto.h | 4 ++++ board/xilinx/versal/board.c | 20 -------------------- drivers/firmware/firmware-zynqmp.c | 16 ++++++++++++++++ 4 files changed, 35 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c index 7ad93982e8d..5cb013d5f2e 100644 --- a/arch/arm/mach-versal/cpu.c +++ b/arch/arm/mach-versal/cpu.c @@ -120,6 +120,21 @@ u32 __weak versal_pmc_multi_boot(void) return versal_multi_boot_reg(); } +u32 versal_bootmode_reg(void) +{ + return readl(&crp_base->boot_mode_usr); +} + +u8 __weak versal_get_bootmode(void) +{ + u32 reg = versal_bootmode_reg(); + + if (reg >> BOOT_MODE_ALT_SHIFT) + reg >>= BOOT_MODE_ALT_SHIFT; + + return reg & BOOT_MODES_MASK; +} + U_BOOT_DRVINFO(soc_xilinx_versal) = { .name = "soc_xilinx_versal", }; diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h index d7ab2549658..f8836db5ef0 100644 --- a/arch/arm/mach-versal/include/mach/sys_proto.h +++ b/arch/arm/mach-versal/include/mach/sys_proto.h @@ -21,5 +21,9 @@ void mem_map_fill(void); u32 versal_pmc_multi_boot(void); /* Direct MMIO read of the multiboot register (EL3 / no-firmware path) */ u32 versal_multi_boot_reg(void); +/* Overridable bootmode decode: weak MMIO default, firmware override */ +u8 versal_get_bootmode(void); +/* Direct MMIO read of the bootmode register (EL3 / no-firmware path) */ +u32 versal_bootmode_reg(void); #endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c index 110490b9672..d0c15fed1e9 100644 --- a/board/xilinx/versal/board.c +++ b/board/xilinx/versal/board.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "../common/board.h" DECLARE_GLOBAL_DATA_PTR; @@ -40,25 +39,6 @@ static xilinx_desc versalpl = { }; #endif -static u8 versal_get_bootmode(void) -{ - u8 bootmode; - u32 reg = 0; - - if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) && current_el() != 3) { - reg = zynqmp_pm_get_bootmode_reg(); - } else { - reg = readl(&crp_base->boot_mode_usr); - } - - if (reg >> BOOT_MODE_ALT_SHIFT) - reg >>= BOOT_MODE_ALT_SHIFT; - - bootmode = reg & BOOT_MODES_MASK; - - return bootmode; -} - static u32 versal_multi_boot(void) { u8 bootmode = versal_get_bootmode(); diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index c8943b8d23a..f3ca0b08762 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -337,6 +337,22 @@ u32 versal_pmc_multi_boot(void) return zynqmp_pm_get_pmc_multi_boot_reg() & PMC_MULTI_BOOT_MASK; } + +u8 versal_get_bootmode(void) +{ + u32 reg; + + /* At EL3 the SMC path to firmware is unavailable, read directly */ + if (current_el() == 3) + reg = versal_bootmode_reg(); + else + reg = zynqmp_pm_get_bootmode_reg(); + + if (reg >> BOOT_MODE_ALT_SHIFT) + reg >>= BOOT_MODE_ALT_SHIFT; + + return reg & BOOT_MODES_MASK; +} #endif #if defined(CONFIG_ARCH_VERSAL2) -- cgit v1.3.1 From 9048a9c44d5ffc99a38227df4167d401f7129aae Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Jun 2026 14:53:37 +0200 Subject: arm64: versal-net: Move bootmode decoding out of board code versal_net_get_bootmode() open-coded the IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) selection between the firmware call zynqmp_pm_get_bootmode_reg() and a direct readl() in board code. Like the Versal change, move the whole function behind an overridable hook so generic board code stays free of firmware specifics and is ready for SCMI. The weak versal_net_get_bootmode() in arch/arm/mach-versal-net does the plain MMIO read via versal_net_bootmode_reg() and decodes it (used at EL3 and without firmware). When CONFIG_ZYNQMP_FIRMWARE is enabled, firmware-zynqmp.c provides a strong definition that reads the register through the firmware call, falling back to the direct read at EL3 where the SMC path to firmware is unavailable. This preserves the existing firmware-based bootmode behaviour while removing the firmware interface from board code; the now unused zynqmp_firmware.h include is dropped. Signed-off-by: Michal Simek Link: https://patch.msgid.link/be67e9c6d0bc36840a46594413886d2003967c64.1782219202.git.michal.simek@amd.com --- arch/arm/mach-versal-net/cpu.c | 15 +++++++++++++++ arch/arm/mach-versal-net/include/mach/sys_proto.h | 4 ++++ board/xilinx/versal-net/board.c | 20 -------------------- drivers/firmware/firmware-zynqmp.c | 18 ++++++++++++++++++ 4 files changed, 37 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c index 2974d89f902..7df7c49ac71 100644 --- a/arch/arm/mach-versal-net/cpu.c +++ b/arch/arm/mach-versal-net/cpu.c @@ -136,6 +136,21 @@ void versal_net_timer_setup(void) debug("timer 0x%llx\n", get_ticks()); } +u32 versal_net_bootmode_reg(void) +{ + return readl(&crp_base->boot_mode_usr); +} + +u8 __weak versal_net_get_bootmode(void) +{ + u32 reg = versal_net_bootmode_reg(); + + if (reg >> BOOT_MODE_ALT_SHIFT) + reg >>= BOOT_MODE_ALT_SHIFT; + + return reg & BOOT_MODES_MASK; +} + static u32 platform_id, platform_version; char *soc_name_decode(void) diff --git a/arch/arm/mach-versal-net/include/mach/sys_proto.h b/arch/arm/mach-versal-net/include/mach/sys_proto.h index 33253ca88bf..4907dae1108 100644 --- a/arch/arm/mach-versal-net/include/mach/sys_proto.h +++ b/arch/arm/mach-versal-net/include/mach/sys_proto.h @@ -9,3 +9,7 @@ void mem_map_fill(void); /* EL3 clock/timer register setup, called from board_early_init_r() */ void versal_net_timer_setup(void); +/* Overridable bootmode decode: weak MMIO default, firmware override */ +u8 versal_net_get_bootmode(void); +/* Direct MMIO read of the bootmode register (EL3 / no-firmware path) */ +u32 versal_net_bootmode_reg(void); diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c index 3c69edc2260..bb099c1e7ca 100644 --- a/board/xilinx/versal-net/board.c +++ b/board/xilinx/versal-net/board.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "../common/board.h" @@ -69,25 +68,6 @@ int board_early_init_r(void) return 0; } -static u8 versal_net_get_bootmode(void) -{ - u8 bootmode; - u32 reg = 0; - - if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) && current_el() != 3) { - reg = zynqmp_pm_get_bootmode_reg(); - } else { - reg = readl(&crp_base->boot_mode_usr); - } - - if (reg >> BOOT_MODE_ALT_SHIFT) - reg >>= BOOT_MODE_ALT_SHIFT; - - bootmode = reg & BOOT_MODES_MASK; - - return bootmode; -} - int spi_get_env_dev(void) { struct udevice *dev; diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index f3ca0b08762..4c4f4c19ae4 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -355,6 +355,24 @@ u8 versal_get_bootmode(void) } #endif +#if defined(CONFIG_ARCH_VERSAL_NET) +u8 versal_net_get_bootmode(void) +{ + u32 reg; + + /* At EL3 the SMC path to firmware is unavailable, read directly */ + if (current_el() == 3) + reg = versal_net_bootmode_reg(); + else + reg = zynqmp_pm_get_bootmode_reg(); + + if (reg >> BOOT_MODE_ALT_SHIFT) + reg >>= BOOT_MODE_ALT_SHIFT; + + return reg & BOOT_MODES_MASK; +} +#endif + #if defined(CONFIG_ARCH_VERSAL2) u32 versal2_pmc_multi_boot(void) { -- cgit v1.3.1 From 4b62fc1b7e9e6ead90bbc5a5c9e82b8ee03fbfef Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Jun 2026 14:53:38 +0200 Subject: arm64: zynqmp: Decouple MMIO accessors from firmware zynqmp_mmio_read() and zynqmp_mmio_write() selected between direct MMIO and the firmware (PM_MMIO_READ/WRITE) interface with an in-function IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) / current_el() check. Generic arch code should not carry firmware-specific ifdefs, and with SCMI the access method changes again. Split the accessors like the multiboot and bootmode hooks: the weak default in arch/arm/mach-zynqmp does the direct MMIO access (used in SPL, at EL3 and when no firmware is present), while firmware-zynqmp.c provides a strong definition that issues the firmware call and falls back to the direct access in SPL/EL3 where the SMC path is unavailable. The raw MMIO primitives zynqmp_mmio_rawread() and zynqmp_mmio_rawwrite() are exported for the shared fallback, and the read-modify-write helper now uses the raw read instead of routing through the firmware-aware accessor. The firmware-vs-MMIO decision is selected at link time, so adding SCMI later only requires a third strong definition with no changes to generic code. Signed-off-by: Michal Simek Link: https://patch.msgid.link/d532df144d2c8e34be835bad6d0de3b26befdf01.1782219202.git.michal.simek@amd.com --- arch/arm/mach-zynqmp/cpu.c | 49 ++++++++------------------- arch/arm/mach-zynqmp/include/mach/sys_proto.h | 3 ++ drivers/firmware/firmware-zynqmp.c | 31 +++++++++++++++++ 3 files changed, 48 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c index e6f2e0b3ee0..088cc962189 100644 --- a/arch/arm/mach-zynqmp/cpu.c +++ b/arch/arm/mach-zynqmp/cpu.c @@ -172,15 +172,19 @@ unsigned int zynqmp_get_silicon_version(void) return ZYNQMP_CSU_VERSION_SILICON; } -static int zynqmp_mmio_rawwrite(const u32 address, - const u32 mask, - const u32 value) +int zynqmp_mmio_rawread(const u32 address, u32 *value) +{ + *value = readl((ulong)address); + return 0; +} + +int zynqmp_mmio_rawwrite(const u32 address, const u32 mask, const u32 value) { u32 data; u32 value_local = value; int ret; - ret = zynqmp_mmio_read(address, &data); + ret = zynqmp_mmio_rawread(address, &data); if (ret) return ret; @@ -191,48 +195,23 @@ static int zynqmp_mmio_rawwrite(const u32 address, return 0; } -static int zynqmp_mmio_rawread(const u32 address, u32 *value) -{ - *value = readl((ulong)address); - return 0; -} - -int zynqmp_mmio_write(const u32 address, - const u32 mask, - const u32 value) +int __weak zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value) { if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) return zynqmp_mmio_rawwrite(address, mask, value); -#if defined(CONFIG_ZYNQMP_FIRMWARE) - else - return xilinx_pm_request(PM_MMIO_WRITE, address, mask, - value, 0, 0, 0, NULL); -#endif return -EINVAL; } -int zynqmp_mmio_read(const u32 address, u32 *value) +int __weak zynqmp_mmio_read(const u32 address, u32 *value) { - u32 ret = -EINVAL; - if (!value) - return ret; - - if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) { - ret = zynqmp_mmio_rawread(address, value); - } -#if defined(CONFIG_ZYNQMP_FIRMWARE) - else { - u32 ret_payload[PAYLOAD_ARG_CNT]; + return -EINVAL; - ret = xilinx_pm_request(PM_MMIO_READ, address, 0, 0, - 0, 0, 0, ret_payload); - *value = ret_payload[1]; - } -#endif + if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) + return zynqmp_mmio_rawread(address, value); - return ret; + return -EINVAL; } void zynqmp_timer_setup(void) diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h index 723e7593cf7..d2bb10ffcbb 100644 --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h @@ -56,5 +56,8 @@ void tcm_init(enum tcm_mode mode); #endif /* EL3 clock/timer register setup, called from board_early_init_r() */ void zynqmp_timer_setup(void); +/* Direct MMIO accessors (EL3/SPL or no-firmware path) */ +int zynqmp_mmio_rawread(const u32 address, u32 *value); +int zynqmp_mmio_rawwrite(const u32 address, const u32 mask, const u32 value); #endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 4c4f4c19ae4..6052a31b5b4 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -373,6 +373,37 @@ u8 versal_net_get_bootmode(void) } #endif +#if defined(CONFIG_ARCH_ZYNQMP) +int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value) +{ + /* At EL3 or in SPL the firmware (SMC) path is unavailable */ + if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) + return zynqmp_mmio_rawwrite(address, mask, value); + + return xilinx_pm_request(PM_MMIO_WRITE, address, mask, value, + 0, 0, 0, NULL); +} + +int zynqmp_mmio_read(const u32 address, u32 *value) +{ + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + if (!value) + return -EINVAL; + + /* At EL3 or in SPL the firmware (SMC) path is unavailable */ + if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) + return zynqmp_mmio_rawread(address, value); + + ret = xilinx_pm_request(PM_MMIO_READ, address, 0, 0, 0, 0, 0, + ret_payload); + *value = ret_payload[1]; + + return ret; +} +#endif + #if defined(CONFIG_ARCH_VERSAL2) u32 versal2_pmc_multi_boot(void) { -- cgit v1.3.1