* [PATCH 00/18] arm64: xilinx: Decouple firmware interface
@ 2026-06-23 12:53 Michal Simek
2026-06-23 12:53 ` [PATCH 01/18] arm: xilinx: Guard mach sys_proto.h against multiple inclusion Michal Simek
` (17 more replies)
0 siblings, 18 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Francois Berder, Naman Trivedi, Neal Frager, Padmarao Begari,
Pranav Sanwal, Pranav Tilak, Sean Anderson,
Senthil Nathan Thangaraj, Suraj Kakade, Tom Rini,
Venkatesh Yadav Abbarapu
Hi,
firmware calls are spread across board functions and even drivers.
It shouldn't be like that and it is time to clean it up. Pretty much board
or drivers shouldn't really have zynqmp_firmware.h included. Generic
functions should be called which have MMIO version or firmware version when
firmware is enabled. This is the first set of patches to achieve this goal.
Thanks,
Michal
Michal Simek (18):
arm: xilinx: Guard mach sys_proto.h against multiple inclusion
arm64: versal2: Decouple multiboot register access from firmware
arm64: versal2: Move bootmode decoding out of board code
arm64: versal: Decouple multiboot register access from firmware
arm64: versal: Move bootmode decoding out of board code
arm64: versal: Move board_early_init_r clock setup to mach code
arm64: versal2: Move board_early_init_r clock setup to mach code
arm64: versal-net: Move board_early_init_r clock setup to mach code
arm64: zynqmp: Move board_early_init_r clock setup to mach code
arm64: versal2: Move SoC detection out of board code
arm64: versal-net: Move SoC detection out of board code
arm64: versal-net: Move bootmode decoding out of board code
arm64: zynqmp: Decouple MMIO accessors from firmware
arm64: versal-net: Deduplicate SPI bootmode handling
arm64: versal-net: Simplify spi_get_bootseq() bootmode switch
arm64: versal-net: Do not print bootmode from spi_get_env_dev()
arm64: versal-net: Look up eMMC device in boot_targets_setup()
arm64: versal-net: Add mmc_get_env_dev() and deduplicate MMC handling
arch/arm/mach-versal-net/cpu.c | 149 +++++++++
.../mach-versal-net/include/mach/sys_proto.h | 6 +
arch/arm/mach-versal/cpu.c | 68 ++++
arch/arm/mach-versal/include/mach/sys_proto.h | 16 +
arch/arm/mach-versal2/cpu.c | 143 +++++++++
.../arm/mach-versal2/include/mach/sys_proto.h | 14 +
arch/arm/mach-zynqmp/cpu.c | 69 ++--
arch/arm/mach-zynqmp/include/mach/sys_proto.h | 5 +
board/amd/versal2/board.c | 133 +-------
board/xilinx/versal-net/board.c | 295 +++++-------------
board/xilinx/versal/board.c | 66 +---
board/xilinx/zynqmp/zynqmp.c | 18 +-
drivers/firmware/firmware-zynqmp.c | 89 ++++++
13 files changed, 606 insertions(+), 465 deletions(-)
---
base-commit: e01bb5b8ad09464b8cbf9c4186683e998c2d40fe
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 01/18] arm: xilinx: Guard mach sys_proto.h against multiple inclusion
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 02/18] arm64: versal2: Decouple multiboot register access from firmware Michal Simek
` (16 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Pranav Sanwal, Tom Rini
The Versal and Versal Gen 2 mach sys_proto.h headers lacked an include
guard. mach-versal/sys_proto.h additionally defines enum tcm_mode, so
including it twice in one translation unit fails to build with a
redeclaration error.
This is about to happen in firmware-zynqmp.c, which needs the SoC
prototypes unconditionally for the upcoming weak/strong multiboot and
bootmode accessors. Add the standard _ASM_ARCH_SYS_PROTO_H guard, as
already used by mach-zynqmp, so the header can be included more than once.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-versal/include/mach/sys_proto.h | 5 +++++
arch/arm/mach-versal2/include/mach/sys_proto.h | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h
index a6dfa556966d..b53e616e47be 100644
--- a/arch/arm/mach-versal/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal/include/mach/sys_proto.h
@@ -3,6 +3,9 @@
* Copyright 2016 - 2018 Xilinx, Inc.
*/
+#ifndef _ASM_ARCH_SYS_PROTO_H
+#define _ASM_ARCH_SYS_PROTO_H
+
#include <linux/build_bug.h>
enum tcm_mode {
@@ -13,3 +16,5 @@ enum tcm_mode {
void initialize_tcm(enum tcm_mode mode);
void tcm_init(enum tcm_mode mode);
void mem_map_fill(void);
+
+#endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/arch/arm/mach-versal2/include/mach/sys_proto.h b/arch/arm/mach-versal2/include/mach/sys_proto.h
index cee134886208..3ed0b25be802 100644
--- a/arch/arm/mach-versal2/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal2/include/mach/sys_proto.h
@@ -4,8 +4,13 @@
* Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
*/
+#ifndef _ASM_ARCH_SYS_PROTO_H
+#define _ASM_ARCH_SYS_PROTO_H
+
#include <linux/build_bug.h>
#include <asm/armv8/mmu.h>
void mem_map_fill(struct mm_region *bank_info, u32 num_banks);
void fill_bd_mem_info(void);
+
+#endif /* _ASM_ARCH_SYS_PROTO_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 02/18] arm64: versal2: Decouple multiboot register access from firmware
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
2026-06-23 12:53 ` [PATCH 01/18] arm: xilinx: Guard mach sys_proto.h against multiple inclusion Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 03/18] arm64: versal2: Move bootmode decoding out of board code Michal Simek
` (15 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Francois Berder, Naman Trivedi, Padmarao Begari, Pranav Sanwal,
Pranav Tilak, Sean Anderson, Senthil Nathan Thangaraj,
Suraj Kakade, Tom Rini, Venkatesh Yadav Abbarapu
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 <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(-)
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index e264ef0f2924..0c7a5040cffb 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -128,6 +128,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 3ed0b25be802..e0576754836a 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 6e4f0c6e9b8f..06d144db4f02 100644
--- a/board/amd/versal2/board.c
+++ b/board/amd/versal2/board.c
@@ -29,7 +29,6 @@
#include <dm/device.h>
#include <dm/uclass.h>
#include <versalpl.h>
-#include <zynqmp_firmware.h>
#include "../../xilinx/common/board.h"
#include <linux/bitfield.h>
@@ -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 ea14ed4ef950..70d205ff3ef9 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -7,6 +7,7 @@
*/
#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <cpu_func.h>
#include <dm.h>
@@ -16,6 +17,7 @@
#include <zynqmp_firmware.h>
#include <asm/cache.h>
#include <asm/ptrace.h>
+#include <asm/system.h>
#include <linux/bitfield.h>
#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;
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 03/18] arm64: versal2: Move bootmode decoding out of board code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
2026-06-23 12:53 ` [PATCH 01/18] arm: xilinx: Guard mach sys_proto.h against multiple inclusion Michal Simek
2026-06-23 12:53 ` [PATCH 02/18] arm64: versal2: Decouple multiboot register access from firmware Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 04/18] arm64: versal: Decouple multiboot register access from firmware Michal Simek
` (14 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Francois Berder, Padmarao Begari, Pranav Sanwal, Suraj Kakade,
Tom Rini
versal2_get_bootmode() lived in board code and accessed the CRP boot
mode register with a direct readl(). To keep generic board code free of
SoC register details and ready for firmware/SCMI based access, move the
whole function, including the alt-shift and mask decoding, into
arch/arm/mach-versal2 as a __weak default.
Board code now simply calls versal2_get_bootmode(). When a firmware
based implementation is available and tested it can provide a strong
definition that overrides the weak one at link time; until then only the
weak MMIO version is built.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-versal2/cpu.c | 15 +++++++++++++++
arch/arm/mach-versal2/include/mach/sys_proto.h | 2 ++
board/amd/versal2/board.c | 15 ---------------
3 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index 0c7a5040cffb..c278dc3d3be5 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -138,6 +138,21 @@ u32 __weak versal2_pmc_multi_boot(void)
return versal2_multi_boot_reg();
}
+u8 __weak versal2_get_bootmode(void)
+{
+ u8 bootmode;
+ u32 reg;
+
+ 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;
+}
+
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 e0576754836a..b3118c208e8f 100644
--- a/arch/arm/mach-versal2/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal2/include/mach/sys_proto.h
@@ -17,5 +17,7 @@ void fill_bd_mem_info(void);
u32 versal2_pmc_multi_boot(void);
/* Direct MMIO read of the multiboot register (EL3 / no-firmware path) */
u32 versal2_multi_boot_reg(void);
+/* Weak bootmode decode (MMIO default); a firmware/SCMI build may override */
+u8 versal2_get_bootmode(void);
#endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/board/amd/versal2/board.c b/board/amd/versal2/board.c
index 06d144db4f02..c4e88440d64e 100644
--- a/board/amd/versal2/board.c
+++ b/board/amd/versal2/board.c
@@ -176,21 +176,6 @@ int board_early_init_r(void)
return 0;
}
-static u8 versal2_get_bootmode(void)
-{
- u8 bootmode;
- u32 reg = 0;
-
- 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 versal2_multi_boot(void)
{
u8 bootmode = versal2_get_bootmode();
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 04/18] arm64: versal: Decouple multiboot register access from firmware
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (2 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 03/18] arm64: versal2: Move bootmode decoding out of board code Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 05/18] arm64: versal: Move bootmode decoding out of board code Michal Simek
` (13 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Naman Trivedi, Padmarao Begari, Sean Anderson,
Senthil Nathan Thangaraj, Tom Rini, Venkatesh Yadav Abbarapu
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 <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(-)
diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c
index 62f8a87ce321..1ef4e3435c22 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 b53e616e47be..d7ab25496583 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 8666f2ceff4e..110490b96729 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 70d205ff3ef9..c8943b8d23a3 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)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 05/18] arm64: versal: Move bootmode decoding out of board code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (3 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 04/18] arm64: versal: Decouple multiboot register access from firmware Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 06/18] arm64: versal: Move board_early_init_r clock setup to mach code Michal Simek
` (12 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Naman Trivedi, Padmarao Begari, Sean Anderson,
Senthil Nathan Thangaraj, Tom Rini, Venkatesh Yadav Abbarapu
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 <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(-)
diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c
index 1ef4e3435c22..2a2b683b1fd4 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 d7ab25496583..f8836db5ef05 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 110490b96729..d0c15fed1e93 100644
--- a/board/xilinx/versal/board.c
+++ b/board/xilinx/versal/board.c
@@ -28,7 +28,6 @@
#include <dm/device.h>
#include <dm/uclass.h>
#include <versalpl.h>
-#include <zynqmp_firmware.h>
#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 c8943b8d23a3..f3ca0b08762c 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)
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 06/18] arm64: versal: Move board_early_init_r clock setup to mach code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (4 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 05/18] arm64: versal: Move bootmode decoding out of board code Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 07/18] arm64: versal2: " Michal Simek
` (11 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Padmarao Begari, Tom Rini
board_early_init_r() programmed the IOU switch clock and the system
timestamp counter directly with readl()/writel() in board code. This is
SoC register setup rather than board policy, and the same block is
duplicated across the Xilinx SoCs.
Move it into versal_timer_setup() in arch/arm/mach-versal so the board
hook only keeps the EL3 guard and calls the helper.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-versal/cpu.c | 43 +++++++++++++++++++
arch/arm/mach-versal/include/mach/sys_proto.h | 2 +
board/xilinx/versal/board.c | 38 +---------------
3 files changed, 46 insertions(+), 37 deletions(-)
diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c
index 2a2b683b1fd4..76cf3181e28c 100644
--- a/arch/arm/mach-versal/cpu.c
+++ b/arch/arm/mach-versal/cpu.c
@@ -7,6 +7,8 @@
*/
#include <init.h>
+#include <log.h>
+#include <time.h>
#include <asm/armv8/mmu.h>
#include <asm/cache.h>
#include <asm/global_data.h>
@@ -120,6 +122,47 @@ u32 __weak versal_pmc_multi_boot(void)
return versal_multi_boot_reg();
}
+void versal_timer_setup(void)
+{
+ u32 val;
+
+ debug("iou_switch ctrl div0 %x\n",
+ readl(&crlapb_base->iou_switch_ctrl));
+
+ writel(IOU_SWITCH_CTRL_CLKACT_BIT |
+ (CONFIG_IOU_SWITCH_DIVISOR0 << IOU_SWITCH_CTRL_DIVISOR0_SHIFT),
+ &crlapb_base->iou_switch_ctrl);
+
+ /* Global timer init - Program time stamp reference clk */
+ val = readl(&crlapb_base->timestamp_ref_ctrl);
+ val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
+ writel(val, &crlapb_base->timestamp_ref_ctrl);
+
+ debug("ref ctrl 0x%x\n",
+ readl(&crlapb_base->timestamp_ref_ctrl));
+
+ /* Clear reset of timestamp reg */
+ writel(0, &crlapb_base->rst_timestamp);
+
+ /*
+ * Program freq register in System counter and
+ * enable system counter.
+ */
+ writel(CONFIG_COUNTER_FREQUENCY,
+ &iou_scntr_secure->base_frequency_id_register);
+
+ debug("counter val 0x%x\n",
+ readl(&iou_scntr_secure->base_frequency_id_register));
+
+ writel(IOU_SCNTRS_CONTROL_EN,
+ &iou_scntr_secure->counter_control_register);
+
+ debug("scntrs control 0x%x\n",
+ readl(&iou_scntr_secure->counter_control_register));
+ debug("timer 0x%llx\n", get_ticks());
+ debug("timer 0x%llx\n", get_ticks());
+}
+
u32 versal_bootmode_reg(void)
{
return readl(&crp_base->boot_mode_usr);
diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h
index f8836db5ef05..cb373e6fad91 100644
--- a/arch/arm/mach-versal/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal/include/mach/sys_proto.h
@@ -25,5 +25,7 @@ u32 versal_multi_boot_reg(void);
u8 versal_get_bootmode(void);
/* Direct MMIO read of the bootmode register (EL3 / no-firmware path) */
u32 versal_bootmode_reg(void);
+/* EL3 clock/timer register setup, called from board_early_init_r() */
+void versal_timer_setup(void);
#endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c
index d0c15fed1e93..0537517b1b2e 100644
--- a/board/xilinx/versal/board.c
+++ b/board/xilinx/versal/board.c
@@ -68,46 +68,10 @@ int board_init(void)
int board_early_init_r(void)
{
- u32 val;
-
if (current_el() != 3)
return 0;
- debug("iou_switch ctrl div0 %x\n",
- readl(&crlapb_base->iou_switch_ctrl));
-
- writel(IOU_SWITCH_CTRL_CLKACT_BIT |
- (CONFIG_IOU_SWITCH_DIVISOR0 << IOU_SWITCH_CTRL_DIVISOR0_SHIFT),
- &crlapb_base->iou_switch_ctrl);
-
- /* Global timer init - Program time stamp reference clk */
- val = readl(&crlapb_base->timestamp_ref_ctrl);
- val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
- writel(val, &crlapb_base->timestamp_ref_ctrl);
-
- debug("ref ctrl 0x%x\n",
- readl(&crlapb_base->timestamp_ref_ctrl));
-
- /* Clear reset of timestamp reg */
- writel(0, &crlapb_base->rst_timestamp);
-
- /*
- * Program freq register in System counter and
- * enable system counter.
- */
- writel(CONFIG_COUNTER_FREQUENCY,
- &iou_scntr_secure->base_frequency_id_register);
-
- debug("counter val 0x%x\n",
- readl(&iou_scntr_secure->base_frequency_id_register));
-
- writel(IOU_SCNTRS_CONTROL_EN,
- &iou_scntr_secure->counter_control_register);
-
- debug("scntrs control 0x%x\n",
- readl(&iou_scntr_secure->counter_control_register));
- debug("timer 0x%llx\n", get_ticks());
- debug("timer 0x%llx\n", get_ticks());
+ versal_timer_setup();
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 07/18] arm64: versal2: Move board_early_init_r clock setup to mach code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (5 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 06/18] arm64: versal: Move board_early_init_r clock setup to mach code Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 08/18] arm64: versal-net: " Michal Simek
` (10 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Francois Berder, Padmarao Begari, Pranav Sanwal, Pranav Tilak,
Suraj Kakade, Tom Rini, Venkatesh Yadav Abbarapu
board_early_init_r() programmed the IOU switch clock and the system
timestamp counter directly with readl()/writel() in board code. This is
SoC register setup rather than board policy, and the same block is
duplicated across the Xilinx SoCs.
Move it into versal2_timer_setup() in arch/arm/mach-versal2 so the board
hook only keeps the EL3 guard and calls the helper.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-versal2/cpu.c | 43 +++++++++++++++++++
.../arm/mach-versal2/include/mach/sys_proto.h | 2 +
board/amd/versal2/board.c | 38 +---------------
3 files changed, 46 insertions(+), 37 deletions(-)
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index c278dc3d3be5..d28c0e131711 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -7,6 +7,8 @@
*/
#include <init.h>
+#include <log.h>
+#include <time.h>
#include <asm/armv8/mmu.h>
#include <asm/cache.h>
#include <asm/global_data.h>
@@ -153,6 +155,47 @@ u8 __weak versal2_get_bootmode(void)
return bootmode;
}
+void versal2_timer_setup(void)
+{
+ u32 val;
+
+ debug("iou_switch ctrl div0 %x\n",
+ readl(&crlapb_base->iou_switch_ctrl));
+
+ writel(IOU_SWITCH_CTRL_CLKACT_BIT |
+ (CONFIG_IOU_SWITCH_DIVISOR0 << IOU_SWITCH_CTRL_DIVISOR0_SHIFT),
+ &crlapb_base->iou_switch_ctrl);
+
+ /* Global timer init - Program time stamp reference clk */
+ val = readl(&crlapb_base->timestamp_ref_ctrl);
+ val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
+ writel(val, &crlapb_base->timestamp_ref_ctrl);
+
+ debug("ref ctrl 0x%x\n",
+ readl(&crlapb_base->timestamp_ref_ctrl));
+
+ /* Clear reset of timestamp reg */
+ writel(0, &crlapb_base->rst_timestamp);
+
+ /*
+ * Program freq register in System counter and
+ * enable system counter.
+ */
+ writel(CONFIG_COUNTER_FREQUENCY,
+ &iou_scntr_secure->base_frequency_id_register);
+
+ debug("counter val 0x%x\n",
+ readl(&iou_scntr_secure->base_frequency_id_register));
+
+ writel(IOU_SCNTRS_CONTROL_EN,
+ &iou_scntr_secure->counter_control_register);
+
+ debug("scntrs control 0x%x\n",
+ readl(&iou_scntr_secure->counter_control_register));
+ debug("timer 0x%llx\n", get_ticks());
+ debug("timer 0x%llx\n", get_ticks());
+}
+
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 b3118c208e8f..b8d12d1dd3bb 100644
--- a/arch/arm/mach-versal2/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal2/include/mach/sys_proto.h
@@ -19,5 +19,7 @@ u32 versal2_pmc_multi_boot(void);
u32 versal2_multi_boot_reg(void);
/* Weak bootmode decode (MMIO default); a firmware/SCMI build may override */
u8 versal2_get_bootmode(void);
+/* EL3 clock/timer register setup, called from board_early_init_r() */
+void versal2_timer_setup(void);
#endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/board/amd/versal2/board.c b/board/amd/versal2/board.c
index c4e88440d64e..7f2fb4c1ec63 100644
--- a/board/amd/versal2/board.c
+++ b/board/amd/versal2/board.c
@@ -132,46 +132,10 @@ bool soc_detection(void)
int board_early_init_r(void)
{
- u32 val;
-
if (current_el() != 3)
return 0;
- debug("iou_switch ctrl div0 %x\n",
- readl(&crlapb_base->iou_switch_ctrl));
-
- writel(IOU_SWITCH_CTRL_CLKACT_BIT |
- (CONFIG_IOU_SWITCH_DIVISOR0 << IOU_SWITCH_CTRL_DIVISOR0_SHIFT),
- &crlapb_base->iou_switch_ctrl);
-
- /* Global timer init - Program time stamp reference clk */
- val = readl(&crlapb_base->timestamp_ref_ctrl);
- val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
- writel(val, &crlapb_base->timestamp_ref_ctrl);
-
- debug("ref ctrl 0x%x\n",
- readl(&crlapb_base->timestamp_ref_ctrl));
-
- /* Clear reset of timestamp reg */
- writel(0, &crlapb_base->rst_timestamp);
-
- /*
- * Program freq register in System counter and
- * enable system counter.
- */
- writel(CONFIG_COUNTER_FREQUENCY,
- &iou_scntr_secure->base_frequency_id_register);
-
- debug("counter val 0x%x\n",
- readl(&iou_scntr_secure->base_frequency_id_register));
-
- writel(IOU_SCNTRS_CONTROL_EN,
- &iou_scntr_secure->counter_control_register);
-
- debug("scntrs control 0x%x\n",
- readl(&iou_scntr_secure->counter_control_register));
- debug("timer 0x%llx\n", get_ticks());
- debug("timer 0x%llx\n", get_ticks());
+ versal2_timer_setup();
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 08/18] arm64: versal-net: Move board_early_init_r clock setup to mach code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (6 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 07/18] arm64: versal2: " Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 09/18] arm64: zynqmp: " Michal Simek
` (9 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Tom Rini
board_early_init_r() programmed the IOU switch clock and the system
timestamp counter directly with readl()/writel() in board code. This is
SoC register setup rather than board policy, and the same block is
duplicated across the Xilinx SoCs.
Move it into versal_net_timer_setup() in arch/arm/mach-versal-net so the
board hook only keeps the EL3 guard and calls the helper.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-versal-net/cpu.c | 43 +++++++++++++++++++
.../mach-versal-net/include/mach/sys_proto.h | 2 +
board/xilinx/versal-net/board.c | 38 +---------------
3 files changed, 46 insertions(+), 37 deletions(-)
diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c
index d088e440f638..5e7c1bebf2cc 100644
--- a/arch/arm/mach-versal-net/cpu.c
+++ b/arch/arm/mach-versal-net/cpu.c
@@ -7,6 +7,8 @@
*/
#include <init.h>
+#include <log.h>
+#include <time.h>
#include <asm/armv8/mmu.h>
#include <asm/cache.h>
#include <asm/global_data.h>
@@ -88,6 +90,47 @@ u64 get_page_table_size(void)
return 0x14000;
}
+void versal_net_timer_setup(void)
+{
+ u32 val;
+
+ debug("iou_switch ctrl div0 %x\n",
+ readl(&crlapb_base->iou_switch_ctrl));
+
+ writel(IOU_SWITCH_CTRL_CLKACT_BIT |
+ (CONFIG_IOU_SWITCH_DIVISOR0 << IOU_SWITCH_CTRL_DIVISOR0_SHIFT),
+ &crlapb_base->iou_switch_ctrl);
+
+ /* Global timer init - Program time stamp reference clk */
+ val = readl(&crlapb_base->timestamp_ref_ctrl);
+ val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
+ writel(val, &crlapb_base->timestamp_ref_ctrl);
+
+ debug("ref ctrl 0x%x\n",
+ readl(&crlapb_base->timestamp_ref_ctrl));
+
+ /* Clear reset of timestamp reg */
+ writel(0, &crlapb_base->rst_timestamp);
+
+ /*
+ * Program freq register in System counter and
+ * enable system counter.
+ */
+ writel(CONFIG_COUNTER_FREQUENCY,
+ &iou_scntr_secure->base_frequency_id_register);
+
+ debug("counter val 0x%x\n",
+ readl(&iou_scntr_secure->base_frequency_id_register));
+
+ writel(IOU_SCNTRS_CONTROL_EN,
+ &iou_scntr_secure->counter_control_register);
+
+ debug("scntrs control 0x%x\n",
+ readl(&iou_scntr_secure->counter_control_register));
+ debug("timer 0x%llx\n", get_ticks());
+ debug("timer 0x%llx\n", get_ticks());
+}
+
U_BOOT_DRVINFO(soc_xilinx_versal_net) = {
.name = "soc_xilinx_versal_net",
};
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 23374d10a6b4..33253ca88bfe 100644
--- a/arch/arm/mach-versal-net/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal-net/include/mach/sys_proto.h
@@ -7,3 +7,5 @@
#include <linux/build_bug.h>
void mem_map_fill(void);
+/* EL3 clock/timer register setup, called from board_early_init_r() */
+void versal_net_timer_setup(void);
diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c
index 65b2a451ad7a..a40039a1dc8e 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -148,46 +148,10 @@ int board_early_init_f(void)
int board_early_init_r(void)
{
- u32 val;
-
if (current_el() != 3)
return 0;
- debug("iou_switch ctrl div0 %x\n",
- readl(&crlapb_base->iou_switch_ctrl));
-
- writel(IOU_SWITCH_CTRL_CLKACT_BIT |
- (CONFIG_IOU_SWITCH_DIVISOR0 << IOU_SWITCH_CTRL_DIVISOR0_SHIFT),
- &crlapb_base->iou_switch_ctrl);
-
- /* Global timer init - Program time stamp reference clk */
- val = readl(&crlapb_base->timestamp_ref_ctrl);
- val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
- writel(val, &crlapb_base->timestamp_ref_ctrl);
-
- debug("ref ctrl 0x%x\n",
- readl(&crlapb_base->timestamp_ref_ctrl));
-
- /* Clear reset of timestamp reg */
- writel(0, &crlapb_base->rst_timestamp);
-
- /*
- * Program freq register in System counter and
- * enable system counter.
- */
- writel(CONFIG_COUNTER_FREQUENCY,
- &iou_scntr_secure->base_frequency_id_register);
-
- debug("counter val 0x%x\n",
- readl(&iou_scntr_secure->base_frequency_id_register));
-
- writel(IOU_SCNTRS_CONTROL_EN,
- &iou_scntr_secure->counter_control_register);
-
- debug("scntrs control 0x%x\n",
- readl(&iou_scntr_secure->counter_control_register));
- debug("timer 0x%llx\n", get_ticks());
- debug("timer 0x%llx\n", get_ticks());
+ versal_net_timer_setup();
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 09/18] arm64: zynqmp: Move board_early_init_r clock setup to mach code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (7 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 08/18] arm64: versal-net: " Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 10/18] arm64: versal2: Move SoC detection out of board code Michal Simek
` (8 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Naman Trivedi, Neal Frager, Pranav Sanwal,
Senthil Nathan Thangaraj, Tom Rini, Venkatesh Yadav Abbarapu
board_early_init_r() programmed the system timestamp counter directly
with readl()/writel() in board code. This is SoC register setup rather
than board policy, and similar code exists across the Xilinx SoCs.
Move it into zynqmp_timer_setup() in arch/arm/mach-zynqmp so the board
hook only keeps the EL3 guard and calls the helper. The asm/arch/clk.h
include (for zynqmp_get_system_timer_freq()) moves to cpu.c along with
the code.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-zynqmp/cpu.c | 22 +++++++++++++++++++
arch/arm/mach-zynqmp/include/mach/sys_proto.h | 2 ++
board/xilinx/zynqmp/zynqmp.c | 18 +--------------
3 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c
index 5f194aaff9a4..5ab25e385eb6 100644
--- a/arch/arm/mach-zynqmp/cpu.c
+++ b/arch/arm/mach-zynqmp/cpu.c
@@ -8,6 +8,7 @@
#include <time.h>
#include <linux/errno.h>
#include <linux/types.h>
+#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/armv8/mmu.h>
@@ -234,6 +235,27 @@ int zynqmp_mmio_read(const u32 address, u32 *value)
return ret;
}
+void zynqmp_timer_setup(void)
+{
+ u32 val;
+
+ val = readl(&crlapb_base->timestamp_ref_ctrl);
+ val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
+
+ if (!val) {
+ val = readl(&crlapb_base->timestamp_ref_ctrl);
+ val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
+ writel(val, &crlapb_base->timestamp_ref_ctrl);
+
+ /* Program freq register in System counter */
+ writel(zynqmp_get_system_timer_freq(),
+ &iou_scntr_secure->base_frequency_id_register);
+ /* And enable system counter */
+ writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
+ &iou_scntr_secure->counter_control_register);
+ }
+}
+
U_BOOT_DRVINFO(soc_xilinx_zynqmp) = {
.name = "soc_xilinx_zynqmp",
};
diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
index b6a41df1da47..723e7593cf7b 100644
--- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
@@ -54,5 +54,7 @@ void mem_map_fill(void);
#if defined(CONFIG_DEFINE_TCM_OCM_MMAP)
void tcm_init(enum tcm_mode mode);
#endif
+/* EL3 clock/timer register setup, called from board_early_init_r() */
+void zynqmp_timer_setup(void);
#endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index eb41f84c198d..d50fab4f6779 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -24,7 +24,6 @@
#include <malloc.h>
#include <memalign.h>
#include <wdt.h>
-#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/psu_init_gpl.h>
@@ -214,26 +213,11 @@ int board_init(void)
int board_early_init_r(void)
{
- u32 val;
-
if (current_el() != 3)
return 0;
- val = readl(&crlapb_base->timestamp_ref_ctrl);
- val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
-
- if (!val) {
- val = readl(&crlapb_base->timestamp_ref_ctrl);
- val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
- writel(val, &crlapb_base->timestamp_ref_ctrl);
+ zynqmp_timer_setup();
- /* Program freq register in System counter */
- writel(zynqmp_get_system_timer_freq(),
- &iou_scntr_secure->base_frequency_id_register);
- /* And enable system counter */
- writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
- &iou_scntr_secure->counter_control_register);
- }
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 10/18] arm64: versal2: Move SoC detection out of board code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (8 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 09/18] arm64: zynqmp: " Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 11/18] arm64: versal-net: " Michal Simek
` (7 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Francois Berder, Padmarao Begari, Pranav Sanwal, Pranav Tilak,
Suraj Kakade, Tom Rini, Venkatesh Yadav Abbarapu
soc_detection() and soc_name_decode() read the PMC_TAP version/idcode
registers and decode the platform. This is SoC information rather than
board policy, and a firmware interface could provide it instead, so it
does not belong in board code.
Move both functions, together with the shared platform_id and
platform_version state, into arch/arm/mach-versal2 where they still
override the weak stubs in the Xilinx common board code. The board file
drops the now unused linux/bitfield.h include.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-versal2/cpu.c | 75 +++++++++++++++++++++++++++++++++++++
board/amd/versal2/board.c | 71 -----------------------------------
2 files changed, 75 insertions(+), 71 deletions(-)
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index d28c0e131711..f5db0660ad54 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -8,15 +8,21 @@
#include <init.h>
#include <log.h>
+#include <malloc.h>
#include <time.h>
+#include <vsprintf.h>
#include <asm/armv8/mmu.h>
#include <asm/cache.h>
#include <asm/global_data.h>
#include <asm/io.h>
+#include <asm/system.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/cache.h>
#include <dm/platdata.h>
+#include <linux/bitfield.h>
+#include <linux/string.h>
+#include "../../../board/xilinx/common/board.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -196,6 +202,75 @@ void versal2_timer_setup(void)
debug("timer 0x%llx\n", get_ticks());
}
+static u32 platform_id, platform_version;
+
+char *soc_name_decode(void)
+{
+ char *name, *platform_name;
+
+ switch (platform_id) {
+ case VERSAL2_SPP:
+ platform_name = "spp";
+ break;
+ case VERSAL2_EMU:
+ platform_name = "emu";
+ break;
+ case VERSAL2_SPP_MMD:
+ platform_name = "spp-mmd";
+ break;
+ case VERSAL2_EMU_MMD:
+ platform_name = "emu-mmd";
+ break;
+ case VERSAL2_QEMU:
+ platform_name = "qemu";
+ break;
+ default:
+ return NULL;
+ }
+
+ /*
+ * --rev.-el are 9 chars
+ * max platform name is emu-mmd which is 7 chars
+ * platform version number are 1+1
+ * el is 1 char
+ * Plus 1 char for NULL byte
+ */
+ name = calloc(1, strlen(CONFIG_SYS_BOARD) + 20);
+ if (!name)
+ return NULL;
+
+ sprintf(name, "%s-%s-rev%d.%d-el%d", CONFIG_SYS_BOARD,
+ platform_name, platform_version / 10,
+ platform_version % 10, current_el());
+
+ return name;
+}
+
+bool soc_detection(void)
+{
+ u32 version, ps_version;
+
+ version = readl(PMC_TAP_VERSION);
+ platform_id = FIELD_GET(PLATFORM_MASK, version);
+ ps_version = FIELD_GET(PS_VERSION_MASK, version);
+
+ debug("idcode %x, version %x, usercode %x\n",
+ readl(PMC_TAP_IDCODE), version,
+ readl(PMC_TAP_USERCODE));
+
+ debug("pmc_ver %lx, ps version %x, rtl version %lx\n",
+ FIELD_GET(PMC_VERSION_MASK, version),
+ ps_version,
+ FIELD_GET(RTL_VERSION_MASK, version));
+
+ platform_version = FIELD_GET(PLATFORM_VERSION_MASK, version);
+
+ debug("Platform id: %d version: %d.%d\n", platform_id,
+ platform_version / 10, platform_version % 10);
+
+ return true;
+}
+
U_BOOT_DRVINFO(soc_amd_versal2) = {
.name = "soc_amd_versal2",
};
diff --git a/board/amd/versal2/board.c b/board/amd/versal2/board.c
index 7f2fb4c1ec63..2afd283b8ddd 100644
--- a/board/amd/versal2/board.c
+++ b/board/amd/versal2/board.c
@@ -31,8 +31,6 @@
#include <versalpl.h>
#include "../../xilinx/common/board.h"
-#include <linux/bitfield.h>
-#include <linux/sizes.h>
#include <debug_uart.h>
#include <generated/dt.h>
#include <linux/ioport.h>
@@ -61,75 +59,6 @@ int board_init(void)
return 0;
}
-static u32 platform_id, platform_version;
-
-char *soc_name_decode(void)
-{
- char *name, *platform_name;
-
- switch (platform_id) {
- case VERSAL2_SPP:
- platform_name = "spp";
- break;
- case VERSAL2_EMU:
- platform_name = "emu";
- break;
- case VERSAL2_SPP_MMD:
- platform_name = "spp-mmd";
- break;
- case VERSAL2_EMU_MMD:
- platform_name = "emu-mmd";
- break;
- case VERSAL2_QEMU:
- platform_name = "qemu";
- break;
- default:
- return NULL;
- }
-
- /*
- * --rev.-el are 9 chars
- * max platform name is emu-mmd which is 7 chars
- * platform version number are 1+1
- * el is 1 char
- * Plus 1 char for NULL byte
- */
- name = calloc(1, strlen(CONFIG_SYS_BOARD) + 20);
- if (!name)
- return NULL;
-
- sprintf(name, "%s-%s-rev%d.%d-el%d", CONFIG_SYS_BOARD,
- platform_name, platform_version / 10,
- platform_version % 10, current_el());
-
- return name;
-}
-
-bool soc_detection(void)
-{
- u32 version, ps_version;
-
- version = readl(PMC_TAP_VERSION);
- platform_id = FIELD_GET(PLATFORM_MASK, version);
- ps_version = FIELD_GET(PS_VERSION_MASK, version);
-
- debug("idcode %x, version %x, usercode %x\n",
- readl(PMC_TAP_IDCODE), version,
- readl(PMC_TAP_USERCODE));
-
- debug("pmc_ver %lx, ps version %x, rtl version %lx\n",
- FIELD_GET(PMC_VERSION_MASK, version),
- ps_version,
- FIELD_GET(RTL_VERSION_MASK, version));
-
- platform_version = FIELD_GET(PLATFORM_VERSION_MASK, version);
-
- debug("Platform id: %d version: %d.%d\n", platform_id,
- platform_version / 10, platform_version % 10);
-
- return true;
-}
-
int board_early_init_r(void)
{
if (current_el() != 3)
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 11/18] arm64: versal-net: Move SoC detection out of board code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (9 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 10/18] arm64: versal2: Move SoC detection out of board code Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 12/18] arm64: versal-net: Move bootmode decoding " Michal Simek
` (6 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Tom Rini
soc_detection() and soc_name_decode() read the PMC_TAP version/idcode
registers and decode the platform. This is SoC information rather than
board policy, and a firmware interface could provide it instead, so it
does not belong in board code.
Move both functions, together with the shared platform_id and
platform_version state, into arch/arm/mach-versal-net where they still
override the weak stubs in the Xilinx common board code. The board file
drops the now unused linux/bitfield.h include.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
arch/arm/mach-versal-net/cpu.c | 91 +++++++++++++++++++++++++++++++++
board/xilinx/versal-net/board.c | 87 -------------------------------
2 files changed, 91 insertions(+), 87 deletions(-)
diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c
index 5e7c1bebf2cc..4cbcb119ccb8 100644
--- a/arch/arm/mach-versal-net/cpu.c
+++ b/arch/arm/mach-versal-net/cpu.c
@@ -8,7 +8,9 @@
#include <init.h>
#include <log.h>
+#include <malloc.h>
#include <time.h>
+#include <vsprintf.h>
#include <asm/armv8/mmu.h>
#include <asm/cache.h>
#include <asm/global_data.h>
@@ -17,6 +19,9 @@
#include <asm/arch/sys_proto.h>
#include <asm/cache.h>
#include <dm/platdata.h>
+#include <linux/bitfield.h>
+#include <linux/string.h>
+#include "../../../board/xilinx/common/board.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -131,6 +136,92 @@ void versal_net_timer_setup(void)
debug("timer 0x%llx\n", get_ticks());
}
+static u32 platform_id, platform_version;
+
+char *soc_name_decode(void)
+{
+ char *name, *platform_name;
+
+ switch (platform_id) {
+ case VERSAL_NET_SPP:
+ platform_name = "ipp";
+ break;
+ case VERSAL_NET_EMU:
+ platform_name = "emu";
+ break;
+ case VERSAL_NET_QEMU:
+ platform_name = "qemu";
+ break;
+ default:
+ return NULL;
+ }
+
+ /*
+ * --rev. are 6 chars
+ * max platform name is qemu which is 4 chars
+ * platform version number are 1+1
+ * Plus 1 char for \n
+ */
+ name = calloc(1, strlen(CONFIG_SYS_BOARD) + 13);
+ if (!name)
+ return NULL;
+
+ sprintf(name, "%s-%s-rev%d.%d", CONFIG_SYS_BOARD,
+ platform_name, platform_version / 10,
+ platform_version % 10);
+
+ return name;
+}
+
+bool soc_detection(void)
+{
+ u32 version, ps_version;
+
+ version = readl(PMC_TAP_VERSION);
+ platform_id = FIELD_GET(PLATFORM_MASK, version);
+ ps_version = FIELD_GET(PS_VERSION_MASK, version);
+
+ debug("idcode %x, version %x, usercode %x\n",
+ readl(PMC_TAP_IDCODE), version,
+ readl(PMC_TAP_USERCODE));
+
+ debug("pmc_ver %lx, ps version %x, rtl version %lx\n",
+ FIELD_GET(PMC_VERSION_MASK, version),
+ ps_version,
+ FIELD_GET(RTL_VERSION_MASK, version));
+
+ platform_version = FIELD_GET(PLATFORM_VERSION_MASK, version);
+
+ if (platform_id == VERSAL_NET_SPP ||
+ platform_id == VERSAL_NET_EMU) {
+ if (ps_version == PS_VERSION_PRODUCTION) {
+ /*
+ * ES1 version ends at 1.9 version where there was +9
+ * used because of IPP/SPP conversion. Production
+ * version have platform_version started from 0 again
+ * that's why adding +20 to continue with the same line.
+ * It means the last ES1 version ends at 1.9 version and
+ * new PRODUCTION line starts at 2.0.
+ */
+ platform_version += 20;
+ } else {
+ /*
+ * 9 is diff for
+ * 0 means 0.9 version
+ * 1 means 1.0 version
+ * 2 means 1.1 version
+ * etc,
+ */
+ platform_version += 9;
+ }
+ }
+
+ debug("Platform id: %d version: %d.%d\n", platform_id,
+ platform_version / 10, platform_version % 10);
+
+ return true;
+}
+
U_BOOT_DRVINFO(soc_xilinx_versal_net) = {
.name = "soc_xilinx_versal_net",
};
diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c
index a40039a1dc8e..3c69edc22606 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -25,7 +25,6 @@
#include <versalpl.h>
#include "../common/board.h"
-#include <linux/bitfield.h>
#include <debug_uart.h>
#include <generated/dt.h>
@@ -49,92 +48,6 @@ int board_init(void)
return 0;
}
-static u32 platform_id, platform_version;
-
-char *soc_name_decode(void)
-{
- char *name, *platform_name;
-
- switch (platform_id) {
- case VERSAL_NET_SPP:
- platform_name = "ipp";
- break;
- case VERSAL_NET_EMU:
- platform_name = "emu";
- break;
- case VERSAL_NET_QEMU:
- platform_name = "qemu";
- break;
- default:
- return NULL;
- }
-
- /*
- * --rev. are 6 chars
- * max platform name is qemu which is 4 chars
- * platform version number are 1+1
- * Plus 1 char for \n
- */
- name = calloc(1, strlen(CONFIG_SYS_BOARD) + 13);
- if (!name)
- return NULL;
-
- sprintf(name, "%s-%s-rev%d.%d", CONFIG_SYS_BOARD,
- platform_name, platform_version / 10,
- platform_version % 10);
-
- return name;
-}
-
-bool soc_detection(void)
-{
- u32 version, ps_version;
-
- version = readl(PMC_TAP_VERSION);
- platform_id = FIELD_GET(PLATFORM_MASK, version);
- ps_version = FIELD_GET(PS_VERSION_MASK, version);
-
- debug("idcode %x, version %x, usercode %x\n",
- readl(PMC_TAP_IDCODE), version,
- readl(PMC_TAP_USERCODE));
-
- debug("pmc_ver %lx, ps version %x, rtl version %lx\n",
- FIELD_GET(PMC_VERSION_MASK, version),
- ps_version,
- FIELD_GET(RTL_VERSION_MASK, version));
-
- platform_version = FIELD_GET(PLATFORM_VERSION_MASK, version);
-
- if (platform_id == VERSAL_NET_SPP ||
- platform_id == VERSAL_NET_EMU) {
- if (ps_version == PS_VERSION_PRODUCTION) {
- /*
- * ES1 version ends at 1.9 version where there was +9
- * used because of IPP/SPP conversion. Production
- * version have platform_version started from 0 again
- * that's why adding +20 to continue with the same line.
- * It means the last ES1 version ends at 1.9 version and
- * new PRODUCTION line starts at 2.0.
- */
- platform_version += 20;
- } else {
- /*
- * 9 is diff for
- * 0 means 0.9 version
- * 1 means 1.0 version
- * 2 means 1.1 version
- * etc,
- */
- platform_version += 9;
- }
- }
-
- debug("Platform id: %d version: %d.%d\n", platform_id,
- platform_version / 10, platform_version % 10);
-
- return true;
-}
-
int board_early_init_f(void)
{
if (IS_ENABLED(CONFIG_DEBUG_UART)) {
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 12/18] arm64: versal-net: Move bootmode decoding out of board code
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (10 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 11/18] arm64: versal-net: " Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 13/18] arm64: zynqmp: Decouple MMIO accessors from firmware Michal Simek
` (5 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Naman Trivedi, Padmarao Begari, Sean Anderson,
Senthil Nathan Thangaraj, Tom Rini
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 <michal.simek@amd.com>
---
arch/arm/mach-versal-net/cpu.c | 15 ++++++++++++++
.../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(-)
diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c
index 4cbcb119ccb8..84fd8a67aa2f 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 33253ca88bfe..4907dae1108f 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 3c69edc22606..bb099c1e7ca5 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -21,7 +21,6 @@
#include <asm/arch/sys_proto.h>
#include <dm/device.h>
#include <dm/uclass.h>
-#include <zynqmp_firmware.h>
#include <versalpl.h>
#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 f3ca0b08762c..4c4f4c19ae4b 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)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 13/18] arm64: zynqmp: Decouple MMIO accessors from firmware
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (11 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 12/18] arm64: versal-net: Move bootmode decoding " Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 14/18] arm64: versal-net: Deduplicate SPI bootmode handling Michal Simek
` (4 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git
Cc: Naman Trivedi, Padmarao Begari, Sean Anderson,
Senthil Nathan Thangaraj, Tom Rini, Venkatesh Yadav Abbarapu
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 <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(-)
diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c
index 5ab25e385eb6..f0d95b3376e0 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 723e7593cf7b..d2bb10ffcbbb 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 4c4f4c19ae4b..6052a31b5b40 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)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 14/18] arm64: versal-net: Deduplicate SPI bootmode handling
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (12 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 13/18] arm64: zynqmp: Decouple MMIO accessors from firmware Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 15/18] arm64: versal-net: Simplify spi_get_bootseq() bootmode switch Michal Simek
` (3 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Tom Rini
spi_get_env_dev() and boot_targets_setup() both decoded the QSPI/OSPI
boot modes into a SPI device sequence number with identical
uclass_get_device_by_name() lookups.
Factor that logic into a single spi_get_bootseq() helper that takes the
bootmode and returns the device sequence. spi_get_env_dev() becomes a
thin wrapper around it, and boot_targets_setup() calls it for the
QSPI/OSPI cases instead of open-coding the lookups. Passing the bootmode
in avoids reading the bootmode register twice in boot_targets_setup().
No functional change.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
board/xilinx/versal-net/board.c | 38 +++++++++------------------------
1 file changed, 10 insertions(+), 28 deletions(-)
diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c
index bb099c1e7ca5..5ad8c8d6426a 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -68,12 +68,12 @@ int board_early_init_r(void)
return 0;
}
-int spi_get_env_dev(void)
+static int spi_get_bootseq(u8 bootmode)
{
struct udevice *dev;
int bootseq = -1;
- switch (versal_net_get_bootmode()) {
+ switch (bootmode) {
case QSPI_MODE_24BIT:
puts("QSPI_MODE_24\n");
if (uclass_get_device_by_name(UCLASS_SPI,
@@ -109,6 +109,11 @@ int spi_get_env_dev(void)
return bootseq;
}
+int spi_get_env_dev(void)
+{
+ return spi_get_bootseq(versal_net_get_bootmode());
+}
+
static int boot_targets_setup(void)
{
u8 bootmode;
@@ -133,34 +138,11 @@ static int boot_targets_setup(void)
mode = "jtag pxe dhcp";
break;
case QSPI_MODE_24BIT:
- puts("QSPI_MODE_24\n");
- if (uclass_get_device_by_name(UCLASS_SPI,
- "spi@f1030000", &dev)) {
- debug("QSPI driver for QSPI device is not present\n");
- break;
- }
- mode = "xspi";
- bootseq = dev_seq(dev);
- break;
case QSPI_MODE_32BIT:
- puts("QSPI_MODE_32\n");
- if (uclass_get_device_by_name(UCLASS_SPI,
- "spi@f1030000", &dev)) {
- debug("QSPI driver for QSPI device is not present\n");
- break;
- }
- mode = "xspi";
- bootseq = dev_seq(dev);
- break;
case OSPI_MODE:
- puts("OSPI_MODE\n");
- if (uclass_get_device_by_name(UCLASS_SPI,
- "spi@f1010000", &dev)) {
- debug("OSPI driver for OSPI device is not present\n");
- break;
- }
- mode = "xspi";
- bootseq = dev_seq(dev);
+ bootseq = spi_get_bootseq(bootmode);
+ if (bootseq >= 0)
+ mode = "xspi";
break;
case EMMC_MODE:
puts("EMMC_MODE\n");
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 15/18] arm64: versal-net: Simplify spi_get_bootseq() bootmode switch
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (13 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 14/18] arm64: versal-net: Deduplicate SPI bootmode handling Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 16/18] arm64: versal-net: Do not print bootmode from spi_get_env_dev() Michal Simek
` (2 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Tom Rini
The QSPI and OSPI cases only differ in the SPI device name. Pick the name
in the switch and perform a single uclass_get_device_by_name() lookup
afterwards, instead of repeating the lookup and dev_seq() in every case.
No functional change.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
board/xilinx/versal-net/board.c | 33 +++++++++++++--------------------
1 file changed, 13 insertions(+), 20 deletions(-)
diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c
index 5ad8c8d6426a..50dd49927be2 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -71,41 +71,34 @@ int board_early_init_r(void)
static int spi_get_bootseq(u8 bootmode)
{
struct udevice *dev;
- int bootseq = -1;
+ const char *name;
+ int bootseq;
switch (bootmode) {
case QSPI_MODE_24BIT:
puts("QSPI_MODE_24\n");
- if (uclass_get_device_by_name(UCLASS_SPI,
- "spi@f1030000", &dev)) {
- debug("QSPI driver for QSPI device is not present\n");
- break;
- }
- bootseq = dev_seq(dev);
+ name = "spi@f1030000";
break;
case QSPI_MODE_32BIT:
puts("QSPI_MODE_32\n");
- if (uclass_get_device_by_name(UCLASS_SPI,
- "spi@f1030000", &dev)) {
- debug("QSPI driver for QSPI device is not present\n");
- break;
- }
- bootseq = dev_seq(dev);
+ name = "spi@f1030000";
break;
case OSPI_MODE:
puts("OSPI_MODE\n");
- if (uclass_get_device_by_name(UCLASS_SPI,
- "spi@f1010000", &dev)) {
- debug("OSPI driver for OSPI device is not present\n");
- break;
- }
- bootseq = dev_seq(dev);
+ name = "spi@f1010000";
break;
default:
- break;
+ return -1;
}
+ if (uclass_get_device_by_name(UCLASS_SPI, name, &dev)) {
+ debug("SPI driver for %s is not present\n", name);
+ return -1;
+ }
+
+ bootseq = dev_seq(dev);
debug("bootseq %d\n", bootseq);
+
return bootseq;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 16/18] arm64: versal-net: Do not print bootmode from spi_get_env_dev()
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (14 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 15/18] arm64: versal-net: Simplify spi_get_bootseq() bootmode switch Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 17/18] arm64: versal-net: Look up eMMC device in boot_targets_setup() Michal Simek
2026-06-23 12:53 ` [PATCH 18/18] arm64: versal-net: Add mmc_get_env_dev() and deduplicate MMC handling Michal Simek
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Tom Rini
spi_get_bootseq() printed the QSPI/OSPI mode banner, which is noise when
called from spi_get_env_dev() during environment setup. The banner is
only meaningful for the "Bootmode:" announcement in boot_targets_setup().
Make spi_get_bootseq() a pure lookup that returns the banner string
through an optional output argument instead of printing it.
spi_get_env_dev() passes NULL and stays silent, while
boot_targets_setup() prints the returned mode name as before.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
board/xilinx/versal-net/board.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c
index 50dd49927be2..687d042d1062 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -68,7 +68,7 @@ int board_early_init_r(void)
return 0;
}
-static int spi_get_bootseq(u8 bootmode)
+static int spi_get_bootseq(u8 bootmode, const char **modename)
{
struct udevice *dev;
const char *name;
@@ -76,15 +76,18 @@ static int spi_get_bootseq(u8 bootmode)
switch (bootmode) {
case QSPI_MODE_24BIT:
- puts("QSPI_MODE_24\n");
+ if (modename)
+ *modename = "QSPI_MODE_24\n";
name = "spi@f1030000";
break;
case QSPI_MODE_32BIT:
- puts("QSPI_MODE_32\n");
+ if (modename)
+ *modename = "QSPI_MODE_32\n";
name = "spi@f1030000";
break;
case OSPI_MODE:
- puts("OSPI_MODE\n");
+ if (modename)
+ *modename = "OSPI_MODE\n";
name = "spi@f1010000";
break;
default:
@@ -104,7 +107,7 @@ static int spi_get_bootseq(u8 bootmode)
int spi_get_env_dev(void)
{
- return spi_get_bootseq(versal_net_get_bootmode());
+ return spi_get_bootseq(versal_net_get_bootmode(), NULL);
}
static int boot_targets_setup(void)
@@ -115,6 +118,7 @@ static int boot_targets_setup(void)
int bootseq_len = 0;
int env_targets_len = 0;
const char *mode = NULL;
+ const char *modename = NULL;
char *new_targets;
char *env_targets;
@@ -133,7 +137,9 @@ static int boot_targets_setup(void)
case QSPI_MODE_24BIT:
case QSPI_MODE_32BIT:
case OSPI_MODE:
- bootseq = spi_get_bootseq(bootmode);
+ bootseq = spi_get_bootseq(bootmode, &modename);
+ if (modename)
+ puts(modename);
if (bootseq >= 0)
mode = "xspi";
break;
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 17/18] arm64: versal-net: Look up eMMC device in boot_targets_setup()
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (15 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 16/18] arm64: versal-net: Do not print bootmode from spi_get_env_dev() Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
2026-06-23 12:53 ` [PATCH 18/18] arm64: versal-net: Add mmc_get_env_dev() and deduplicate MMC handling Michal Simek
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Tom Rini
The EMMC_MODE case set bootseq from dev_seq(dev) without ever assigning
dev, so it used an uninitialized pointer and produced a bogus device
sequence in boot_targets.
eMMC is wired to the SD1 controller (mmc@f1050000, see
versal-net-mini-emmc.dts). Look that device up like the SD cases do
before using its sequence number.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
board/xilinx/versal-net/board.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c
index 687d042d1062..9c0490cba980 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -145,6 +145,11 @@ static int boot_targets_setup(void)
break;
case EMMC_MODE:
puts("EMMC_MODE\n");
+ if (uclass_get_device_by_name(UCLASS_MMC,
+ "mmc@f1050000", &dev)) {
+ debug("eMMC driver for eMMC device is not present\n");
+ break;
+ }
mode = "mmc";
bootseq = dev_seq(dev);
break;
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 18/18] arm64: versal-net: Add mmc_get_env_dev() and deduplicate MMC handling
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
` (16 preceding siblings ...)
2026-06-23 12:53 ` [PATCH 17/18] arm64: versal-net: Look up eMMC device in boot_targets_setup() Michal Simek
@ 2026-06-23 12:53 ` Michal Simek
17 siblings, 0 replies; 19+ messages in thread
From: Michal Simek @ 2026-06-23 12:53 UTC (permalink / raw)
To: u-boot, git; +Cc: Tom Rini
The SD and eMMC cases in boot_targets_setup() duplicated the MMC device
lookup, and versal-net relied on the weak mmc_get_env_dev() default
instead of selecting the device matching the boot mode (unlike versal and
zynqmp).
Factor the lookup into mmc_get_bootseq(), mirroring spi_get_bootseq():
it maps the boot mode to the MMC node and returns the device sequence,
optionally handing back the mode banner so only boot_targets_setup()
prints it. mmc_get_env_dev() is now provided as a thin wrapper, and the
SD/eMMC cases call the helper instead of open-coding the lookups. The
local udevice pointer in boot_targets_setup() is no longer needed.
Signed-off-by: Michal Simek <michal.simek@amd.com>
---
board/xilinx/versal-net/board.c | 80 +++++++++++++++++++--------------
1 file changed, 47 insertions(+), 33 deletions(-)
diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c
index 9c0490cba980..ddac92660dfa 100644
--- a/board/xilinx/versal-net/board.c
+++ b/board/xilinx/versal-net/board.c
@@ -12,6 +12,7 @@
#include <env_internal.h>
#include <log.h>
#include <malloc.h>
+#include <mmc.h>
#include <spi.h>
#include <time.h>
#include <asm/cache.h>
@@ -110,10 +111,48 @@ int spi_get_env_dev(void)
return spi_get_bootseq(versal_net_get_bootmode(), NULL);
}
+static int mmc_get_bootseq(u8 bootmode, const char **modename)
+{
+ struct udevice *dev;
+ const char *name;
+
+ switch (bootmode) {
+ case SD_MODE:
+ if (modename)
+ *modename = "SD_MODE\n";
+ name = "mmc@f1040000";
+ break;
+ case EMMC_MODE:
+ if (modename)
+ *modename = "EMMC_MODE\n";
+ name = "mmc@f1050000";
+ break;
+ case SD_MODE1:
+ case SD1_LSHFT_MODE:
+ if (modename)
+ *modename = "SD_MODE1\n";
+ name = "mmc@f1050000";
+ break;
+ default:
+ return -1;
+ }
+
+ if (uclass_get_device_by_name(UCLASS_MMC, name, &dev)) {
+ debug("MMC driver for %s is not present\n", name);
+ return -1;
+ }
+
+ return dev_seq(dev);
+}
+
+int mmc_get_env_dev(void)
+{
+ return mmc_get_bootseq(versal_net_get_bootmode(), NULL);
+}
+
static int boot_targets_setup(void)
{
u8 bootmode;
- struct udevice *dev;
int bootseq = -1;
int bootseq_len = 0;
int env_targets_len = 0;
@@ -143,45 +182,20 @@ static int boot_targets_setup(void)
if (bootseq >= 0)
mode = "xspi";
break;
- case EMMC_MODE:
- puts("EMMC_MODE\n");
- if (uclass_get_device_by_name(UCLASS_MMC,
- "mmc@f1050000", &dev)) {
- debug("eMMC driver for eMMC device is not present\n");
- break;
- }
- mode = "mmc";
- bootseq = dev_seq(dev);
- break;
case SELECTMAP_MODE:
puts("SELECTMAP_MODE\n");
break;
- case SD_MODE:
- puts("SD_MODE\n");
- if (uclass_get_device_by_name(UCLASS_MMC,
- "mmc@f1040000", &dev)) {
- debug("SD0 driver for SD0 device is not present\n");
- break;
- }
- debug("mmc0 device found at %p, seq %d\n", dev, dev_seq(dev));
-
- mode = "mmc";
- bootseq = dev_seq(dev);
- break;
case SD1_LSHFT_MODE:
puts("LVL_SHFT_");
fallthrough;
+ case SD_MODE:
+ case EMMC_MODE:
case SD_MODE1:
- puts("SD_MODE1\n");
- if (uclass_get_device_by_name(UCLASS_MMC,
- "mmc@f1050000", &dev)) {
- debug("SD1 driver for SD1 device is not present\n");
- break;
- }
- debug("mmc1 device found at %p, seq %d\n", dev, dev_seq(dev));
-
- mode = "mmc";
- bootseq = dev_seq(dev);
+ bootseq = mmc_get_bootseq(bootmode, &modename);
+ if (modename)
+ puts(modename);
+ if (bootseq >= 0)
+ mode = "mmc";
break;
default:
printf("Invalid Boot Mode:0x%x\n", bootmode);
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-06-23 12:57 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-23 12:53 [PATCH 00/18] arm64: xilinx: Decouple firmware interface Michal Simek
2026-06-23 12:53 ` [PATCH 01/18] arm: xilinx: Guard mach sys_proto.h against multiple inclusion Michal Simek
2026-06-23 12:53 ` [PATCH 02/18] arm64: versal2: Decouple multiboot register access from firmware Michal Simek
2026-06-23 12:53 ` [PATCH 03/18] arm64: versal2: Move bootmode decoding out of board code Michal Simek
2026-06-23 12:53 ` [PATCH 04/18] arm64: versal: Decouple multiboot register access from firmware Michal Simek
2026-06-23 12:53 ` [PATCH 05/18] arm64: versal: Move bootmode decoding out of board code Michal Simek
2026-06-23 12:53 ` [PATCH 06/18] arm64: versal: Move board_early_init_r clock setup to mach code Michal Simek
2026-06-23 12:53 ` [PATCH 07/18] arm64: versal2: " Michal Simek
2026-06-23 12:53 ` [PATCH 08/18] arm64: versal-net: " Michal Simek
2026-06-23 12:53 ` [PATCH 09/18] arm64: zynqmp: " Michal Simek
2026-06-23 12:53 ` [PATCH 10/18] arm64: versal2: Move SoC detection out of board code Michal Simek
2026-06-23 12:53 ` [PATCH 11/18] arm64: versal-net: " Michal Simek
2026-06-23 12:53 ` [PATCH 12/18] arm64: versal-net: Move bootmode decoding " Michal Simek
2026-06-23 12:53 ` [PATCH 13/18] arm64: zynqmp: Decouple MMIO accessors from firmware Michal Simek
2026-06-23 12:53 ` [PATCH 14/18] arm64: versal-net: Deduplicate SPI bootmode handling Michal Simek
2026-06-23 12:53 ` [PATCH 15/18] arm64: versal-net: Simplify spi_get_bootseq() bootmode switch Michal Simek
2026-06-23 12:53 ` [PATCH 16/18] arm64: versal-net: Do not print bootmode from spi_get_env_dev() Michal Simek
2026-06-23 12:53 ` [PATCH 17/18] arm64: versal-net: Look up eMMC device in boot_targets_setup() Michal Simek
2026-06-23 12:53 ` [PATCH 18/18] arm64: versal-net: Add mmc_get_env_dev() and deduplicate MMC handling Michal Simek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox