[U-Boot] [RFC 2/2] arm64: zynqmp: install a PMU firmware config object at runtime

Michal Simek michal.simek at xilinx.com
Wed Mar 6 12:17:20 UTC 2019


On 28. 02. 19 23:28, Luca Ceresoli wrote:
> Optionally allow U-Boot to load at the PMU firmware configuration
> object into the Power Management Unit (PMU) on Xilinx ZynqMP.
> 
> The configuration object is required by the PMU FW to use the SoC. So
> far the only way to boot using U-Boot SPL was to hard-code the
> configuration object in the PMU firmware. Allow a different boot
> process, where the PMU FW is equal for any ZynqMP chip and its
> configuration is passed at runtime by U-Boot proper.
> 
> Requires the PM_SET_CONFIGURATION command to be implemented by ARM
> Trusted Firmware.
> 
> Signed-off-by: Luca Ceresoli <luca at lucaceresoli.net>
> ---
>  arch/arm/mach-zynqmp/include/mach/sys_proto.h |  1 +
>  board/xilinx/zynqmp/Kconfig                   | 27 +++++++++++++++++++
>  board/xilinx/zynqmp/Makefile                  |  4 +++
>  board/xilinx/zynqmp/zynqmp.c                  | 23 ++++++++++++++++
>  4 files changed, 55 insertions(+)
> 
> diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
> index 385c8825f2f6..1f2c0476ce96 100644
> --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
> +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
> @@ -22,6 +22,7 @@
>  #define ZYNQMP_FPGA_AUTH_DDR	1
>  
>  #define ZYNQMP_SIP_SVC_GET_API_VERSION		0xC2000001
> +#define ZYNQMP_SIP_SVC_SET_CONFIGURATION	0xC2000002
>  
>  #define ZYNQMP_PM_VERSION_MAJOR		1
>  #define ZYNQMP_PM_VERSION_MINOR		0
> diff --git a/board/xilinx/zynqmp/Kconfig b/board/xilinx/zynqmp/Kconfig
> index 7d1f7398c3e9..e9cec5c95470 100644
> --- a/board/xilinx/zynqmp/Kconfig
> +++ b/board/xilinx/zynqmp/Kconfig
> @@ -15,4 +15,31 @@ config CMD_ZYNQMP
>  	  and authentication feature enabled while generating
>  	  BOOT.BIN using Xilinx bootgen tool.
>  
> +config ZYNQMP_LOAD_PM_CFG_OBJ_FILE
> +	string "PMU firmware configuration object to load at runtime"
> +	help
> +	  Path to a PMU firmware configuration object to be built into
> +	  U-Boot and loaded at runtime into the PMU firmware.
> +
> +	  The ZynqMP Power Management Unit (PMU) needs a configuration
> +	  object for most SoC peripherals to work. It can be either
> +	  hard-coded in the PMUFW or passed at runtime.
> +
> +	  U-Boot can load the configuration object loaded at
> +	  runtime. To enable this feature set here the file name
> +	  (absolute path or relative to board/xilinx/zynqmp/). It will
> +	  be loaded into the PMU firmware at the beginning of U-Boot
> +	  proper.
> +
> +	  Note: if your pm_cfg_obj.c is generated by the Xilinx tools,
> +	  you must remove any linking directives from the
> +	  XPm_ConfigObject declaration! E.g.:
> +
> +	    -const u32 XPm_ConfigObject[] __attribute__((used, section(".sys_cfg_data"))) = {
> +	    +const u32 XPm_ConfigObject[] = {
> +
> +	  Leave this option empty if your PMU firmware has a built-in
> +	  configuration object or you are loading it by any other
> +	  means.
> +
>  endif
> diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
> index 80f8ca7e1e4b..5965e3333ff3 100644
> --- a/board/xilinx/zynqmp/Makefile
> +++ b/board/xilinx/zynqmp/Makefile
> @@ -33,6 +33,10 @@ ifneq ($(call ifdef_any_of, CONFIG_ZYNQMP_PSU_INIT_ENABLED CONFIG_SPL_BUILD),)
>  obj-y += $(init-objs)
>  endif
>  
> +ifneq ($(CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE),"")
> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ -I$(srctree)/$(src)
> +endif
> +
>  obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
>  
>  ifndef CONFIG_SPL_BUILD
> diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
> index 5e1d2116bc32..84fecf5a347f 100644
> --- a/board/xilinx/zynqmp/zynqmp.c
> +++ b/board/xilinx/zynqmp/zynqmp.c
> @@ -302,6 +302,25 @@ static char *zynqmp_get_silicon_idcode_name(void)
>  }
>  #endif
>  
> +#ifdef ZYNQMP_LOAD_PM_CFG_OBJ
> +#include CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE
> +
> +void zynqmp_pmufw_load_config_object(void)
> +{
> +	u32 *ocm = (u32*) CONFIG_SPL_TEXT_BASE;
> +	int err;
> +
> +	printf("Loading PMUFW cfg obj using OCM @ %p (size %ld)\n",
> +	       ocm, sizeof(XPm_ConfigObject));
> +
> +	memcpy(ocm, XPm_ConfigObject, sizeof(XPm_ConfigObject));
> +	err = invoke_smc(ZYNQMP_SIP_SVC_SET_CONFIGURATION,
> +			 CONFIG_SPL_TEXT_BASE, 0, 0, 0, NULL);
> +	if (err)
> +		panic("Cannot load PMUFW configuration object (%d)\n", err);
> +}
> +#endif // ZYNQMP_LOAD_PM_CFG_OBJ
> +
>  int board_early_init_f(void)
>  {
>  	int ret = 0;
> @@ -316,6 +335,10 @@ int board_early_init_f(void)
>  	if (pm_api_version < ZYNQMP_PM_VERSION)
>  		panic("PMUFW version error. Expected: v%d.%d\n",
>  		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR);
> +
> +	#ifdef ZYNQMP_LOAD_PM_CFG_OBJ
> +	zynqmp_pmufw_load_config_object();
> +	#endif
>  #endif
>  
>  #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
> 

Definitely thanks for sharing this. I would convert this to zynqmp
pmufw(whatever) command that you can pass this any time.
It means you will get new pmufw config object to memory and push it to
pmufw. And you will handle that pmufw config object as binary data file.
It general it is - but it is composed via C.

Thanks,
Michal


More information about the U-Boot mailing list