[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