[PATCH] firmware: xilinx: Prepare code for new SMC firmware format
Michal Simek
michal.simek at amd.com
Wed Jul 2 08:34:52 CEST 2025
On 6/25/25 15:29, Michal Simek wrote:
> Separate code to own function to be able to add new enhancement format.
>
> Signed-off-by: Michal Simek <michal.simek at amd.com>
> ---
>
> drivers/firmware/firmware-zynqmp.c | 60 +++++++++++++++++-------------
> include/zynqmp_firmware.h | 9 +++++
> 2 files changed, 44 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
> index 2940181e83e9..d18ae523b6bc 100644
> --- a/drivers/firmware/firmware-zynqmp.c
> +++ b/drivers/firmware/firmware-zynqmp.c
> @@ -422,6 +422,30 @@ U_BOOT_DRIVER(zynqmp_power) = {
> };
> #endif
>
> +smc_call_handler_t __data smc_call_handler;
> +
> +static int smc_call_legacy(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
> + u32 arg3, u32 *ret_payload)
> +{
> + struct pt_regs regs;
> +
> + regs.regs[0] = PM_SIP_SVC | api_id;
> + regs.regs[1] = ((u64)arg1 << 32) | arg0;
> + regs.regs[2] = ((u64)arg3 << 32) | arg2;
> +
> + smc_call(®s);
> +
> + if (ret_payload) {
> + ret_payload[0] = (u32)regs.regs[0];
> + ret_payload[1] = upper_32_bits(regs.regs[0]);
> + ret_payload[2] = (u32)regs.regs[1];
> + ret_payload[3] = upper_32_bits(regs.regs[1]);
> + ret_payload[4] = (u32)regs.regs[2];
> + }
> +
> + return (ret_payload) ? ret_payload[0] : 0;
> +}
> +
> int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
> u32 arg3, u32 *ret_payload)
> {
> @@ -450,38 +474,20 @@ int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
> PAYLOAD_ARG_CNT);
> if (ret)
> return ret;
> +
> + return (ret_payload) ? ret_payload[0] : 0;
> #else
> return -EPERM;
> #endif
> - } else {
> - /*
> - * Added SIP service call Function Identifier
> - * Make sure to stay in x0 register
> - */
> - struct pt_regs regs;
> -
> - regs.regs[0] = PM_SIP_SVC | api_id;
> - regs.regs[1] = ((u64)arg1 << 32) | arg0;
> - regs.regs[2] = ((u64)arg3 << 32) | arg2;
> -
> - smc_call(®s);
> -
> - if (ret_payload) {
> - ret_payload[0] = (u32)regs.regs[0];
> - ret_payload[1] = upper_32_bits(regs.regs[0]);
> - ret_payload[2] = (u32)regs.regs[1];
> - ret_payload[3] = upper_32_bits(regs.regs[1]);
> - ret_payload[4] = (u32)regs.regs[2];
> - }
> -
> }
> - return (ret_payload) ? ret_payload[0] : 0;
> +
> + return smc_call_handler(api_id, arg0, arg1, arg2, arg3, ret_payload);
> }
>
> static const struct udevice_id zynqmp_firmware_ids[] = {
> - { .compatible = "xlnx,zynqmp-firmware" },
> - { .compatible = "xlnx,versal-firmware"},
> - { .compatible = "xlnx,versal-net-firmware"},
> + { .compatible = "xlnx,zynqmp-firmware", .data = (ulong)smc_call_legacy },
> + { .compatible = "xlnx,versal-firmware", .data = (ulong)smc_call_legacy},
> + { .compatible = "xlnx,versal-net-firmware", .data = (ulong)smc_call_legacy },
> { }
> };
>
> @@ -490,6 +496,10 @@ static int zynqmp_firmware_bind(struct udevice *dev)
> int ret;
> struct udevice *child;
>
> + smc_call_handler = (smc_call_handler_t)dev_get_driver_data(dev);
> + if (!smc_call_handler)
> + return -EINVAL;
> +
> if ((IS_ENABLED(CONFIG_XPL_BUILD) &&
> IS_ENABLED(CONFIG_SPL_POWER_DOMAIN) &&
> IS_ENABLED(CONFIG_ZYNQMP_POWER_DOMAIN)) ||
> diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
> index dc06abc52fce..7ef8a58847f4 100644
> --- a/include/zynqmp_firmware.h
> +++ b/include/zynqmp_firmware.h
> @@ -8,6 +8,8 @@
> #ifndef _ZYNQMP_FIRMWARE_H_
> #define _ZYNQMP_FIRMWARE_H_
>
> +#include <compiler.h>
> +
> enum pm_api_id {
> PM_GET_API_VERSION = 1,
> PM_SET_CONFIGURATION = 2,
> @@ -512,4 +514,11 @@ struct zynqmp_ipi_msg {
> #define PM_REG_PMC_GLOBAL_NODE 0x30000004
> #define PMC_MULTI_BOOT_MODE_REG_OFFSET 0x4
>
> +#define __data __section(".data")
> +
> +typedef int (*smc_call_handler_t)(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
> + u32 arg3, u32 *ret_payload);
> +
> +extern smc_call_handler_t __data smc_call_handler;
> +
> #endif /* _ZYNQMP_FIRMWARE_H_ */
Applied.
M
More information about the U-Boot
mailing list