[PATCH] xilinx: versal: add firmware access to PMC multi Boot mode register
Michal Simek
michal.simek at amd.com
Mon Mar 10 09:08:03 CET 2025
On 3/5/25 14:48, Prasad Kummari wrote:
> Added extended support for retrieving the PMC muti boot mode
> register via the firmware interface, which is preferred when
> U-Boot runs in EL2 and cannot directly access PMC registers
> via raw reads. Ideally, all secure registers should be accessed
> via xilinx_pm_request(). Introduced the secure
> zynqmp_pm_get_pmc_multi_boot_reg() call, which uses
> xilinx_pm_request() to read the PMC multi boot mode register.
>
> BootROM increments the MultiBoot register (PMC_MULTI_BOOT) read
> address offset by 32 KB and retries. For SD and eMMC boot modes,
> it can search up to 8191 FAT files for the identification string.
> A 13-bit mask (0x1FFF) is applied to PMC_MULTI_BOOT_MASK to obtain
> the correct values in BootROM.
>
> Signed-off-by: Prasad Kummari <prasad.kummari at amd.com>
> ---
> arch/arm/mach-versal/include/mach/hardware.h | 2 ++
> board/xilinx/versal/board.c | 8 ++++++-
> drivers/firmware/firmware-zynqmp.c | 23 ++++++++++++++++++++
> include/zynqmp_firmware.h | 4 ++++
> 4 files changed, 36 insertions(+), 1 deletion(-)
>
> 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 3046fd7e5f0..6c4a2f5ead6 100644
> --- a/board/xilinx/versal/board.c
> +++ b/board/xilinx/versal/board.c
> @@ -60,12 +60,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..5474f66078c 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_ */
Applied.
M
More information about the U-Boot
mailing list