summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-versal/include/mach/hardware.h2
-rw-r--r--board/xilinx/versal/board.c8
-rw-r--r--drivers/firmware/firmware-zynqmp.c23
-rw-r--r--include/zynqmp_firmware.h4
4 files changed, 36 insertions, 1 deletions
diff --git a/arch/arm/mach-versal/include/mach/hardware.h b/arch/arm/mach-versal/include/mach/hardware.h
index 9d1c2f0dcfc..b5f80a8e3a9 100644
--- a/arch/arm/mach-versal/include/mach/hardware.h
+++ b/arch/arm/mach-versal/include/mach/hardware.h
@@ -87,6 +87,8 @@ struct crp_regs {
#define JTAG_MODE 0x00000000
#define BOOT_MODE_USE_ALT 0x100
#define BOOT_MODE_ALT_SHIFT 12
+#define PMC_MULTI_BOOT_REG 0xF1110004
+#define PMC_MULTI_BOOT_MASK 0x1FFF
#define FLASH_RESET_GPIO 0xc
#define WPROT_CRP 0xF126001C
diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c
index f6cf3c228e6..8ea9eee9a1f 100644
--- a/board/xilinx/versal/board.c
+++ b/board/xilinx/versal/board.c
@@ -61,12 +61,18 @@ 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;
- return readl(0xF1110004);
+ 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;
}
int board_init(void)
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index 2adc132b4cc..584397ba29a 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -218,6 +218,29 @@ u32 zynqmp_pm_get_bootmode_reg(void)
return ret_payload[1];
}
+u32 zynqmp_pm_get_pmc_multi_boot_reg(void)
+{
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_REG);
+ if (ret) {
+ printf("%s: IOCTL_READ_REG is not supported failed with error code: %d\n"
+ , __func__, ret);
+ return 0;
+ }
+
+ ret = xilinx_pm_request(PM_IOCTL, PM_REG_PMC_GLOBAL_NODE, IOCTL_READ_REG,
+ PMC_MULTI_BOOT_MODE_REG_OFFSET, 0, ret_payload);
+ if (ret) {
+ printf("%s: node 0x%x: get_bootmode 0x%x failed\n",
+ __func__, PM_REG_PMC_GLOBAL_NODE, PMC_MULTI_BOOT_MODE_REG_OFFSET);
+ return 0;
+ }
+
+ return ret_payload[1];
+}
+
int zynqmp_pm_feature(const u32 api_id)
{
int ret;
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index e7275f72fac..82781dfd16b 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -458,6 +458,7 @@ int zynqmp_mmio_read(const u32 address, u32 *value);
int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value);
int zynqmp_pm_feature(const u32 api_id);
u32 zynqmp_pm_get_bootmode_reg(void);
+u32 zynqmp_pm_get_pmc_multi_boot_reg(void);
/* Type of Config Object */
#define PM_CONFIG_OBJECT_TYPE_BASE 0x1U
@@ -504,4 +505,7 @@ struct zynqmp_ipi_msg {
#define CRP_BOOT_MODE_REG_NODE 0x30000001
#define CRP_BOOT_MODE_REG_OFFSET 0x200
+#define PM_REG_PMC_GLOBAL_NODE 0x30000004
+#define PMC_MULTI_BOOT_MODE_REG_OFFSET 0x4
+
#endif /* _ZYNQMP_FIRMWARE_H_ */