[U-Boot] [PATCH v4 0/2] arm64: zynqmp: pass a PMUFW config object

Hi,
this v4 has several small improvements over v3, addressing all the comments received. No major changes.
This patchset aims at solving a long-standing issue in the ZynqMP users community: loading a PMU firmware configuration object when U-Boot SPL is used.
The Platform Management Unit (PMU) needs a configuration object (cfg obj) to know how to operate the SoC. When using the "Xilinx workflow", the Xilinx FSBL (First Stage Bootloader) has the SPL role. FSBL has a built-in cfg obj and passes it to the PMUFW at runtime before jumping to U-Boot proper.
This is just not implemented in the U-Boot code. The best workaround for U-Boot SPL users is to patch [0] the PMUFW itself to have the cfg obj built-in and self-load it. This approach has some drawbacks: among others, it forces to use a different PMUFW binary for each hardware and hardware configuation. It also makes it impossible to change the configuration after boot.
The first patch fills the gap by allowing U-Boot SPL to load the cfg obj firmware at runtime. It adds a Kconfig string option to point to the cfg obj in the form of a binary blob. If the option is non-empty, code is enabled to link that file in U-Boot SPL and send the configuration to PMUFW.
Patch 2 adds a tool to convert the cfg obj C file (as produced by the Xilinx XSDK proprietary tool) in a binary blob suitable for loading. As suggested by Mike Looijmans it has been implemented as a Python script to make it easily usable.
These patches are tested on the UltraZed EV board, on u-boot/master and microblaze/master, using the defconfig I submitted a few days ago [1].
Future work on this topic include moving the PMU IPC code to a mailbox uclass driver and adding a command in U-Boot proper to load a config object blob (e.g. from a file based on a script).
Many thanks to Michal Simek for his many suggestions on how to improve this work.
[0] https://github.com/topic-embedded-products/meta-topic/blob/master/recipes-bs... [1] https://lists.denx.de/pipermail/u-boot/2019-May/368957.html RFCv1: https://lists.denx.de/pipermail/u-boot/2019-February/360450.html RFCv2: https://lists.denx.de/pipermail/u-boot/2019-March/362464.html v3: https://lists.denx.de/pipermail/u-boot/2019-April/365410.html
Luca
Luca Ceresoli (2): arm64: zynqmp: spl: install a PMU firmware config object at runtime arm64: zynqmp: add tool to convert PMU config object .c to binary
arch/arm/mach-zynqmp/Kconfig | 18 ++ arch/arm/mach-zynqmp/Makefile | 4 + arch/arm/mach-zynqmp/include/mach/sys_proto.h | 2 + arch/arm/mach-zynqmp/pmu_ipc.c | 112 +++++++ board/xilinx/zynqmp/Makefile | 5 + board/xilinx/zynqmp/pm_cfg_obj.S | 17 + board/xilinx/zynqmp/pm_cfg_obj.h | 9 + board/xilinx/zynqmp/zynqmp.c | 9 + tools/zynqmp_pm_cfg_obj_convert.py | 302 ++++++++++++++++++ 9 files changed, 478 insertions(+) create mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.S create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.h create mode 100755 tools/zynqmp_pm_cfg_obj_convert.py

Optionally allow U-Boot to load a configuration object into the Power Management Unit (PMU) firmware on Xilinx ZynqMP.
The configuration object is required by the PMU FW to enable most SoC peripherals. 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 SPL.
All the code for Inter-processor communication with the PMU is isolated in a new file (pmu_ipc.c). The code is inspired by the same feature as implemented in the Xilinx First Stage Bootloader (FSBL) and Arm Trusted Firmware:
* https://github.com/Xilinx/embeddedsw/blob/fb647e6b4c00f5154eba52a88b948195b6... * https://github.com/ARM-software/arm-trusted-firmware/blob/c48d02bade88b07fa7...
SPL logs on the console before loading the configuration object:
U-Boot SPL 2019.07-rc1-00511-gaec224515c87 (May 15 2019 - 08:43:41 +0200) Loading PMUFW cfg obj (2008 bytes) EL Level: EL3 ...
Signed-off-by: Luca Ceresoli luca@lucaceresoli.net
---
Changes v3 -> v4: - fix pointer-to-integer typecast warning - fix integer-to-pointer typecast warning with proper typecasting and add parentheses to avoid ambiguity - fix kerneldoc syntax (Michal) - remove empty line in Kconfig (Michal) - remove #ifdefs around function declaration (Michal) - remove unneeded file copy (Michal) - move externs to a new .h file (Michal) - avoid passing the extra -DZYNQMP_LOAD_PM_CFG_OBJ (using sizeof(), it looks a bit of a hack but seems to be working) - rename CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE to CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE and clarify in menuconfig that it's SPL-related
Changes RFC v2 -> v3: - don't compile pm_cfg_obj.c from source, load it from a binary file (suggested by Michal) - move IPC code to arch/arm/mach-zynqmp/ and sys_proto.h (Michal)
Changes RFC v1 -> RFC v2: - Load the cfg_obj in SPL, not U-Boot proper: this required a complete reimplementation since we cannot rely on ATF now - Update and refine the Kconfig option help --- arch/arm/mach-zynqmp/Kconfig | 18 +++ arch/arm/mach-zynqmp/Makefile | 4 + arch/arm/mach-zynqmp/include/mach/sys_proto.h | 2 + arch/arm/mach-zynqmp/pmu_ipc.c | 112 ++++++++++++++++++ board/xilinx/zynqmp/Makefile | 5 + board/xilinx/zynqmp/pm_cfg_obj.S | 17 +++ board/xilinx/zynqmp/pm_cfg_obj.h | 9 ++ board/xilinx/zynqmp/zynqmp.c | 9 ++ 8 files changed, 176 insertions(+) create mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.S create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.h
diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig index 9bb5a5c20201..6cf17eb94e11 100644 --- a/arch/arm/mach-zynqmp/Kconfig +++ b/arch/arm/mach-zynqmp/Kconfig @@ -65,6 +65,24 @@ config PMUFW_INIT_FILE Include external PMUFW (Platform Management Unit FirmWare) to a Xilinx bootable image (boot.bin).
+config ZYNQMP_SPL_PM_CFG_OBJ_FILE + string "PMU firmware configuration object to load at runtime by SPL" + depends on SPL + help + Path to a binary PMU firmware configuration object to be linked + into U-Boot SPL and loaded at runtime into the PMU firmware. + + The ZynqMP Power Management Unit (PMU) needs a configuration + object for most SoC peripherals to work. To have it loaded by + U-Boot SPL set here the file name (absolute path or relative to + the top source tree) of your configuration, which must be a + binary blob. It will be linked in the SPL binary and loaded + into the PMU firmware by U-Boot SPL during board + initialization. + + Leave this option empty if your PMU firmware has a hard-coded + configuration object or you are loading it by any other means. + config ZYNQMP_USB bool "Configure ZynqMP USB"
diff --git a/arch/arm/mach-zynqmp/Makefile b/arch/arm/mach-zynqmp/Makefile index 8a3b0747244a..f3765e45b1b9 100644 --- a/arch/arm/mach-zynqmp/Makefile +++ b/arch/arm/mach-zynqmp/Makefile @@ -8,3 +8,7 @@ obj-y += cpu.o obj-$(CONFIG_MP) += mp.o obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED) += psu_spl_init.o + +ifneq ($(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE),"") +obj-$(CONFIG_SPL_BUILD) += pmu_ipc.o +endif diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h index 385c8825f2f6..915badc6fbee 100644 --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h @@ -72,4 +72,6 @@ int chip_id(unsigned char id); void tcm_init(u8 mode); #endif
+void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size); + #endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/arch/arm/mach-zynqmp/pmu_ipc.c b/arch/arm/mach-zynqmp/pmu_ipc.c new file mode 100644 index 000000000000..d8858ea3ff99 --- /dev/null +++ b/arch/arm/mach-zynqmp/pmu_ipc.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Inter-Processor Communication with the Platform Management Unit (PMU) + * firmware. + * + * (C) Copyright 2019 Luca Ceresoli + * Luca Ceresoli luca@lucaceresoli.net + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> + +/* IPI bitmasks, register base and register offsets */ +#define IPI_BIT_MASK_APU 0x00001 +#define IPI_BIT_MASK_PMU0 0x10000 +#define IPI_REG_BASE_APU 0xFF300000 +#define IPI_REG_BASE_PMU0 0xFF330000 +#define IPI_REG_OFFSET_TRIG 0x00 +#define IPI_REG_OFFSET_OBR 0x04 + +/* IPI mailbox buffer offsets */ +#define IPI_BUF_BASE_APU 0xFF990400 +#define IPI_BUF_OFFSET_TARGET_PMU 0x1C0 +#define IPI_BUF_OFFSET_REQ 0x00 +#define IPI_BUF_OFFSET_RESP 0x20 + +#define PMUFW_PAYLOAD_ARG_CNT 8 + +/* PMUFW commands */ +#define PMUFW_CMD_SET_CONFIGURATION 2 + +static void pmu_ipc_send_request(const u32 *req, size_t req_len) +{ + u32 *mbx = (u32 *)(IPI_BUF_BASE_APU + + IPI_BUF_OFFSET_TARGET_PMU + + IPI_BUF_OFFSET_REQ); + size_t i; + + for (i = 0; i < req_len; i++) + writel(req[i], &mbx[i]); +} + +static void pmu_ipc_read_response(unsigned int *value, size_t count) +{ + u32 *mbx = (u32 *)(IPI_BUF_BASE_APU + + IPI_BUF_OFFSET_TARGET_PMU + + IPI_BUF_OFFSET_RESP); + size_t i; + + for (i = 0; i < count; i++) + value[i] = readl(&mbx[i]); +} + +/** + * Send request to PMU and get the response. + * + * @req: Request buffer. Byte 0 is the API ID, other bytes are optional + * parameters. + * @req_len: Request length in number of 32-bit words. + * @res: Response buffer. Byte 0 is the error code, other bytes are + * optional parameters. Optional, if @res_maxlen==0 the parameters + * will not be read. + * @res_maxlen: Space allocated for the response in number of 32-bit words. + * + * @return Error code returned by the PMU (i.e. the first word of the response) + */ +static int pmu_ipc_request(const u32 *req, size_t req_len, + u32 *res, size_t res_maxlen) +{ + u32 status; + + if (req_len > PMUFW_PAYLOAD_ARG_CNT || + res_maxlen > PMUFW_PAYLOAD_ARG_CNT) + return -EINVAL; + + pmu_ipc_send_request(req, req_len); + + /* Raise Inter-Processor Interrupt to PMU and wait for response */ + writel(IPI_BIT_MASK_PMU0, IPI_REG_BASE_APU + IPI_REG_OFFSET_TRIG); + do { + status = readl(IPI_REG_BASE_APU + IPI_REG_OFFSET_OBR); + } while (status & IPI_BIT_MASK_PMU0); + + pmu_ipc_read_response(res, res_maxlen); + + return 0; +} + +/** + * Send a configuration object to the PMU firmware. + * + * @cfg_obj: Pointer to the configuration object + * @size: Size of @cfg_obj in bytes + */ +void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) +{ + const u32 request[] = { + PMUFW_CMD_SET_CONFIGURATION, + (u32)((u64)cfg_obj) + }; + u32 response; + int err; + + printf("Loading PMUFW cfg obj (%ld bytes)\n", size); + + err = pmu_ipc_request(request, ARRAY_SIZE(request), &response, 1); + if (err) + panic("Cannot load PMUFW configuration object (%d)\n", err); + if (response != 0) + panic("PMUFW returned 0x%08x status!\n", response); +} diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 80f8ca7e1e4b..b4d39edc118f 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -33,6 +33,11 @@ ifneq ($(call ifdef_any_of, CONFIG_ZYNQMP_PSU_INIT_ENABLED CONFIG_SPL_BUILD),) obj-y += $(init-objs) endif
+ifneq ($(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE),"") +obj-$(CONFIG_SPL_BUILD) += pm_cfg_obj.o +$(obj)/pm_cfg_obj.o: $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE)) FORCE +endif + obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
ifndef CONFIG_SPL_BUILD diff --git a/board/xilinx/zynqmp/pm_cfg_obj.S b/board/xilinx/zynqmp/pm_cfg_obj.S new file mode 100644 index 000000000000..c4ca77e396ce --- /dev/null +++ b/board/xilinx/zynqmp/pm_cfg_obj.S @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +.section .rodata + +.global zynqmp_pm_cfg_obj +.type zynqmp_pm_cfg_obj, @object +.global zynqmp_pm_cfg_obj_size +.type zynqmp_pm_cfg_obj_size, @object + +zynqmp_pm_cfg_obj: +.align 4 +.incbin CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE + +zynqmp_pm_cfg_obj_end: + +zynqmp_pm_cfg_obj_size: +.int zynqmp_pm_cfg_obj_end - zynqmp_pm_cfg_obj diff --git a/board/xilinx/zynqmp/pm_cfg_obj.h b/board/xilinx/zynqmp/pm_cfg_obj.h new file mode 100644 index 000000000000..86e785490ced --- /dev/null +++ b/board/xilinx/zynqmp/pm_cfg_obj.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2019 Luca Ceresoli luca@lucaceresoli.net + * + * Declaration of PMU config object binary blob linked in at build time. + */ + +extern const u32 zynqmp_pm_cfg_obj[]; +extern const int zynqmp_pm_cfg_obj_size; diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 5189925beb3a..c16bdb724c39 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -22,6 +22,8 @@ #include <zynqmppl.h> #include <g_dnl.h>
+#include "pm_cfg_obj.h" + DECLARE_GLOBAL_DATA_PTR;
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) @@ -331,6 +333,13 @@ int board_early_init_f(void)
int board_init(void) { +#if defined(CONFIG_SPL_BUILD) + /* Check *at build time* if the filename is an non-empty string */ + if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1) + zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj, + zynqmp_pm_cfg_obj_size); +#endif + printf("EL Level:\tEL%d\n", current_el());
#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \

On 15. 05. 19 10:56, Luca Ceresoli wrote:
Optionally allow U-Boot to load a configuration object into the Power Management Unit (PMU) firmware on Xilinx ZynqMP.
The configuration object is required by the PMU FW to enable most SoC peripherals. 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 SPL.
All the code for Inter-processor communication with the PMU is isolated in a new file (pmu_ipc.c). The code is inspired by the same feature as implemented in the Xilinx First Stage Bootloader (FSBL) and Arm Trusted Firmware:
- https://github.com/Xilinx/embeddedsw/blob/fb647e6b4c00f5154eba52a88b948195b6...
- https://github.com/ARM-software/arm-trusted-firmware/blob/c48d02bade88b07fa7...
SPL logs on the console before loading the configuration object:
U-Boot SPL 2019.07-rc1-00511-gaec224515c87 (May 15 2019 - 08:43:41 +0200) Loading PMUFW cfg obj (2008 bytes) EL Level: EL3 ...
Signed-off-by: Luca Ceresoli luca@lucaceresoli.net
Changes v3 -> v4:
- fix pointer-to-integer typecast warning
- fix integer-to-pointer typecast warning with proper typecasting and add parentheses to avoid ambiguity
- fix kerneldoc syntax (Michal)
- remove empty line in Kconfig (Michal)
- remove #ifdefs around function declaration (Michal)
- remove unneeded file copy (Michal)
- move externs to a new .h file (Michal)
- avoid passing the extra -DZYNQMP_LOAD_PM_CFG_OBJ (using sizeof(), it looks a bit of a hack but seems to be working)
- rename CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE to CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE and clarify in menuconfig that it's SPL-related
Changes RFC v2 -> v3:
- don't compile pm_cfg_obj.c from source, load it from a binary file (suggested by Michal)
- move IPC code to arch/arm/mach-zynqmp/ and sys_proto.h (Michal)
Changes RFC v1 -> RFC v2:
- Load the cfg_obj in SPL, not U-Boot proper: this required a complete reimplementation since we cannot rely on ATF now
- Update and refine the Kconfig option help
arch/arm/mach-zynqmp/Kconfig | 18 +++ arch/arm/mach-zynqmp/Makefile | 4 + arch/arm/mach-zynqmp/include/mach/sys_proto.h | 2 + arch/arm/mach-zynqmp/pmu_ipc.c | 112 ++++++++++++++++++ board/xilinx/zynqmp/Makefile | 5 + board/xilinx/zynqmp/pm_cfg_obj.S | 17 +++ board/xilinx/zynqmp/pm_cfg_obj.h | 9 ++ board/xilinx/zynqmp/zynqmp.c | 9 ++ 8 files changed, 176 insertions(+) create mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.S create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.h
diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig index 9bb5a5c20201..6cf17eb94e11 100644 --- a/arch/arm/mach-zynqmp/Kconfig +++ b/arch/arm/mach-zynqmp/Kconfig @@ -65,6 +65,24 @@ config PMUFW_INIT_FILE Include external PMUFW (Platform Management Unit FirmWare) to a Xilinx bootable image (boot.bin).
+config ZYNQMP_SPL_PM_CFG_OBJ_FILE
- string "PMU firmware configuration object to load at runtime by SPL"
- depends on SPL
- help
Path to a binary PMU firmware configuration object to be linked
into U-Boot SPL and loaded at runtime into the PMU firmware.
The ZynqMP Power Management Unit (PMU) needs a configuration
object for most SoC peripherals to work. To have it loaded by
U-Boot SPL set here the file name (absolute path or relative to
the top source tree) of your configuration, which must be a
binary blob. It will be linked in the SPL binary and loaded
into the PMU firmware by U-Boot SPL during board
initialization.
Leave this option empty if your PMU firmware has a hard-coded
configuration object or you are loading it by any other means.
config ZYNQMP_USB bool "Configure ZynqMP USB"
diff --git a/arch/arm/mach-zynqmp/Makefile b/arch/arm/mach-zynqmp/Makefile index 8a3b0747244a..f3765e45b1b9 100644 --- a/arch/arm/mach-zynqmp/Makefile +++ b/arch/arm/mach-zynqmp/Makefile @@ -8,3 +8,7 @@ obj-y += cpu.o obj-$(CONFIG_MP) += mp.o obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED) += psu_spl_init.o
+ifneq ($(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE),"") +obj-$(CONFIG_SPL_BUILD) += pmu_ipc.o +endif diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h index 385c8825f2f6..915badc6fbee 100644 --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h @@ -72,4 +72,6 @@ int chip_id(unsigned char id); void tcm_init(u8 mode); #endif
+void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
#endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/arch/arm/mach-zynqmp/pmu_ipc.c b/arch/arm/mach-zynqmp/pmu_ipc.c new file mode 100644 index 000000000000..d8858ea3ff99 --- /dev/null +++ b/arch/arm/mach-zynqmp/pmu_ipc.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Inter-Processor Communication with the Platform Management Unit (PMU)
- firmware.
- (C) Copyright 2019 Luca Ceresoli
- Luca Ceresoli luca@lucaceresoli.net
- */
+#include <common.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h>
+/* IPI bitmasks, register base and register offsets */ +#define IPI_BIT_MASK_APU 0x00001 +#define IPI_BIT_MASK_PMU0 0x10000 +#define IPI_REG_BASE_APU 0xFF300000 +#define IPI_REG_BASE_PMU0 0xFF330000 +#define IPI_REG_OFFSET_TRIG 0x00 +#define IPI_REG_OFFSET_OBR 0x04
+/* IPI mailbox buffer offsets */ +#define IPI_BUF_BASE_APU 0xFF990400 +#define IPI_BUF_OFFSET_TARGET_PMU 0x1C0 +#define IPI_BUF_OFFSET_REQ 0x00 +#define IPI_BUF_OFFSET_RESP 0x20
+#define PMUFW_PAYLOAD_ARG_CNT 8
+/* PMUFW commands */ +#define PMUFW_CMD_SET_CONFIGURATION 2
+static void pmu_ipc_send_request(const u32 *req, size_t req_len) +{
- u32 *mbx = (u32 *)(IPI_BUF_BASE_APU +
IPI_BUF_OFFSET_TARGET_PMU +
IPI_BUF_OFFSET_REQ);
- size_t i;
- for (i = 0; i < req_len; i++)
writel(req[i], &mbx[i]);
+}
+static void pmu_ipc_read_response(unsigned int *value, size_t count) +{
- u32 *mbx = (u32 *)(IPI_BUF_BASE_APU +
IPI_BUF_OFFSET_TARGET_PMU +
IPI_BUF_OFFSET_RESP);
- size_t i;
- for (i = 0; i < count; i++)
value[i] = readl(&mbx[i]);
+}
+/**
- Send request to PMU and get the response.
- @req: Request buffer. Byte 0 is the API ID, other bytes are optional
parameters.
- @req_len: Request length in number of 32-bit words.
- @res: Response buffer. Byte 0 is the error code, other bytes are
optional parameters. Optional, if @res_maxlen==0 the parameters
will not be read.
- @res_maxlen: Space allocated for the response in number of 32-bit words.
- @return Error code returned by the PMU (i.e. the first word of the response)
- */
+static int pmu_ipc_request(const u32 *req, size_t req_len,
u32 *res, size_t res_maxlen)
+{
- u32 status;
- if (req_len > PMUFW_PAYLOAD_ARG_CNT ||
res_maxlen > PMUFW_PAYLOAD_ARG_CNT)
return -EINVAL;
- pmu_ipc_send_request(req, req_len);
- /* Raise Inter-Processor Interrupt to PMU and wait for response */
- writel(IPI_BIT_MASK_PMU0, IPI_REG_BASE_APU + IPI_REG_OFFSET_TRIG);
- do {
status = readl(IPI_REG_BASE_APU + IPI_REG_OFFSET_OBR);
- } while (status & IPI_BIT_MASK_PMU0);
- pmu_ipc_read_response(res, res_maxlen);
- return 0;
+}
+/**
- Send a configuration object to the PMU firmware.
- @cfg_obj: Pointer to the configuration object
- @size: Size of @cfg_obj in bytes
- */
+void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) +{
- const u32 request[] = {
PMUFW_CMD_SET_CONFIGURATION,
(u32)((u64)cfg_obj)
- };
- u32 response;
- int err;
- printf("Loading PMUFW cfg obj (%ld bytes)\n", size);
- err = pmu_ipc_request(request, ARRAY_SIZE(request), &response, 1);
- if (err)
panic("Cannot load PMUFW configuration object (%d)\n", err);
- if (response != 0)
panic("PMUFW returned 0x%08x status!\n", response);
+} diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 80f8ca7e1e4b..b4d39edc118f 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -33,6 +33,11 @@ ifneq ($(call ifdef_any_of, CONFIG_ZYNQMP_PSU_INIT_ENABLED CONFIG_SPL_BUILD),) obj-y += $(init-objs) endif
+ifneq ($(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE),"") +obj-$(CONFIG_SPL_BUILD) += pm_cfg_obj.o +$(obj)/pm_cfg_obj.o: $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE)) FORCE +endif
obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
ifndef CONFIG_SPL_BUILD diff --git a/board/xilinx/zynqmp/pm_cfg_obj.S b/board/xilinx/zynqmp/pm_cfg_obj.S new file mode 100644 index 000000000000..c4ca77e396ce --- /dev/null +++ b/board/xilinx/zynqmp/pm_cfg_obj.S @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */
+.section .rodata
+.global zynqmp_pm_cfg_obj +.type zynqmp_pm_cfg_obj, @object +.global zynqmp_pm_cfg_obj_size +.type zynqmp_pm_cfg_obj_size, @object
+zynqmp_pm_cfg_obj: +.align 4 +.incbin CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE
+zynqmp_pm_cfg_obj_end:
+zynqmp_pm_cfg_obj_size: +.int zynqmp_pm_cfg_obj_end - zynqmp_pm_cfg_obj diff --git a/board/xilinx/zynqmp/pm_cfg_obj.h b/board/xilinx/zynqmp/pm_cfg_obj.h new file mode 100644 index 000000000000..86e785490ced --- /dev/null +++ b/board/xilinx/zynqmp/pm_cfg_obj.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- (C) Copyright 2019 Luca Ceresoli luca@lucaceresoli.net
- Declaration of PMU config object binary blob linked in at build time.
- */
+extern const u32 zynqmp_pm_cfg_obj[]; +extern const int zynqmp_pm_cfg_obj_size; diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 5189925beb3a..c16bdb724c39 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -22,6 +22,8 @@ #include <zynqmppl.h> #include <g_dnl.h>
+#include "pm_cfg_obj.h"
DECLARE_GLOBAL_DATA_PTR;
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) @@ -331,6 +333,13 @@ int board_early_init_f(void)
int board_init(void) { +#if defined(CONFIG_SPL_BUILD)
- /* Check *at build time* if the filename is an non-empty string */
- if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
zynqmp_pm_cfg_obj_size);
+#endif
- printf("EL Level:\tEL%d\n", current_el());
#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
This is good step forward that's why even some stuff can be done better I have not a problem with applying this.
Thanks, Michal

The recently-added ZYNQMP_SPL_PM_CFG_OBJ_FILE option allows SPL to load a PMUFW configuration object from a binary blob. However the configuration object is produced by Xilinx proprietary tools as a C source file and no tool exists to easily convert it to a binary blob in an embedded Linux build system for U-Boot to use.
Add a simple Python script to do the conversion.
It is definitely not a complete C language parser, but it is enough to parse the known patterns generated by Xilinx tools, including:
- defines - literal integers, optionally with a 'U' suffix - bitwise OR between them
Signed-off-by: Luca Ceresoli luca@lucaceresoli.net
---
Changes v3 -> v4: - move to tools/ directory - remove double item.strip() call --- tools/zynqmp_pm_cfg_obj_convert.py | 302 +++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100755 tools/zynqmp_pm_cfg_obj_convert.py
diff --git a/tools/zynqmp_pm_cfg_obj_convert.py b/tools/zynqmp_pm_cfg_obj_convert.py new file mode 100755 index 000000000000..bb4959877df7 --- /dev/null +++ b/tools/zynqmp_pm_cfg_obj_convert.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2019 Luca Ceresoli luca@lucaceresoli.net + +import sys +import re +import struct +import logging +import argparse + +parser = argparse.ArgumentParser( + description='Convert a PMU configuration object from C source to a binary blob.', + allow_abbrev=False) +parser.add_argument('-D', '--debug', action="store_true") +parser.add_argument( + "in_file", metavar='INPUT_FILE', + help='PMU configuration object (C source as produced by Xilinx XSDK)') +parser.add_argument( + "out_file", metavar='OUTPUT_FILE', + help='PMU configuration object binary blob') +args = parser.parse_args() + +logging.basicConfig(format='%(levelname)s:%(message)s', + level=(logging.DEBUG if args.debug else logging.WARNING)) + +pm_define = { + 'PM_CAP_ACCESS' : 0x1, + 'PM_CAP_CONTEXT' : 0x2, + 'PM_CAP_WAKEUP' : 0x4, + + 'NODE_UNKNOWN' : 0, + 'NODE_APU' : 1, + 'NODE_APU_0' : 2, + 'NODE_APU_1' : 3, + 'NODE_APU_2' : 4, + 'NODE_APU_3' : 5, + 'NODE_RPU' : 6, + 'NODE_RPU_0' : 7, + 'NODE_RPU_1' : 8, + 'NODE_PLD' : 9, + 'NODE_FPD' : 10, + 'NODE_OCM_BANK_0' : 11, + 'NODE_OCM_BANK_1' : 12, + 'NODE_OCM_BANK_2' : 13, + 'NODE_OCM_BANK_3' : 14, + 'NODE_TCM_0_A' : 15, + 'NODE_TCM_0_B' : 16, + 'NODE_TCM_1_A' : 17, + 'NODE_TCM_1_B' : 18, + 'NODE_L2' : 19, + 'NODE_GPU_PP_0' : 20, + 'NODE_GPU_PP_1' : 21, + 'NODE_USB_0' : 22, + 'NODE_USB_1' : 23, + 'NODE_TTC_0' : 24, + 'NODE_TTC_1' : 25, + 'NODE_TTC_2' : 26, + 'NODE_TTC_3' : 27, + 'NODE_SATA' : 28, + 'NODE_ETH_0' : 29, + 'NODE_ETH_1' : 30, + 'NODE_ETH_2' : 31, + 'NODE_ETH_3' : 32, + 'NODE_UART_0' : 33, + 'NODE_UART_1' : 34, + 'NODE_SPI_0' : 35, + 'NODE_SPI_1' : 36, + 'NODE_I2C_0' : 37, + 'NODE_I2C_1' : 38, + 'NODE_SD_0' : 39, + 'NODE_SD_1' : 40, + 'NODE_DP' : 41, + 'NODE_GDMA' : 42, + 'NODE_ADMA' : 43, + 'NODE_NAND' : 44, + 'NODE_QSPI' : 45, + 'NODE_GPIO' : 46, + 'NODE_CAN_0' : 47, + 'NODE_CAN_1' : 48, + 'NODE_EXTERN' : 49, + 'NODE_APLL' : 50, + 'NODE_VPLL' : 51, + 'NODE_DPLL' : 52, + 'NODE_RPLL' : 53, + 'NODE_IOPLL' : 54, + 'NODE_DDR' : 55, + 'NODE_IPI_APU' : 56, + 'NODE_IPI_RPU_0' : 57, + 'NODE_GPU' : 58, + 'NODE_PCIE' : 59, + 'NODE_PCAP' : 60, + 'NODE_RTC' : 61, + 'NODE_LPD' : 62, + 'NODE_VCU' : 63, + 'NODE_IPI_RPU_1' : 64, + 'NODE_IPI_PL_0' : 65, + 'NODE_IPI_PL_1' : 66, + 'NODE_IPI_PL_2' : 67, + 'NODE_IPI_PL_3' : 68, + 'NODE_PL' : 69, + 'NODE_ID_MA' : 70, + + 'XILPM_RESET_PCIE_CFG' : 1000, + 'XILPM_RESET_PCIE_BRIDGE' : 1001, + 'XILPM_RESET_PCIE_CTRL' : 1002, + 'XILPM_RESET_DP' : 1003, + 'XILPM_RESET_SWDT_CRF' : 1004, + 'XILPM_RESET_AFI_FM5' : 1005, + 'XILPM_RESET_AFI_FM4' : 1006, + 'XILPM_RESET_AFI_FM3' : 1007, + 'XILPM_RESET_AFI_FM2' : 1008, + 'XILPM_RESET_AFI_FM1' : 1009, + 'XILPM_RESET_AFI_FM0' : 1010, + 'XILPM_RESET_GDMA' : 1011, + 'XILPM_RESET_GPU_PP1' : 1012, + 'XILPM_RESET_GPU_PP0' : 1013, + 'XILPM_RESET_GPU' : 1014, + 'XILPM_RESET_GT' : 1015, + 'XILPM_RESET_SATA' : 1016, + 'XILPM_RESET_ACPU3_PWRON' : 1017, + 'XILPM_RESET_ACPU2_PWRON' : 1018, + 'XILPM_RESET_ACPU1_PWRON' : 1019, + 'XILPM_RESET_ACPU0_PWRON' : 1020, + 'XILPM_RESET_APU_L2' : 1021, + 'XILPM_RESET_ACPU3' : 1022, + 'XILPM_RESET_ACPU2' : 1023, + 'XILPM_RESET_ACPU1' : 1024, + 'XILPM_RESET_ACPU0' : 1025, + 'XILPM_RESET_DDR' : 1026, + 'XILPM_RESET_APM_FPD' : 1027, + 'XILPM_RESET_SOFT' : 1028, + 'XILPM_RESET_GEM0' : 1029, + 'XILPM_RESET_GEM1' : 1030, + 'XILPM_RESET_GEM2' : 1031, + 'XILPM_RESET_GEM3' : 1032, + 'XILPM_RESET_QSPI' : 1033, + 'XILPM_RESET_UART0' : 1034, + 'XILPM_RESET_UART1' : 1035, + 'XILPM_RESET_SPI0' : 1036, + 'XILPM_RESET_SPI1' : 1037, + 'XILPM_RESET_SDIO0' : 1038, + 'XILPM_RESET_SDIO1' : 1039, + 'XILPM_RESET_CAN0' : 1040, + 'XILPM_RESET_CAN1' : 1041, + 'XILPM_RESET_I2C0' : 1042, + 'XILPM_RESET_I2C1' : 1043, + 'XILPM_RESET_TTC0' : 1044, + 'XILPM_RESET_TTC1' : 1045, + 'XILPM_RESET_TTC2' : 1046, + 'XILPM_RESET_TTC3' : 1047, + 'XILPM_RESET_SWDT_CRL' : 1048, + 'XILPM_RESET_NAND' : 1049, + 'XILPM_RESET_ADMA' : 1050, + 'XILPM_RESET_GPIO' : 1051, + 'XILPM_RESET_IOU_CC' : 1052, + 'XILPM_RESET_TIMESTAMP' : 1053, + 'XILPM_RESET_RPU_R50' : 1054, + 'XILPM_RESET_RPU_R51' : 1055, + 'XILPM_RESET_RPU_AMBA' : 1056, + 'XILPM_RESET_OCM' : 1057, + 'XILPM_RESET_RPU_PGE' : 1058, + 'XILPM_RESET_USB0_CORERESET' : 1059, + 'XILPM_RESET_USB1_CORERESET' : 1060, + 'XILPM_RESET_USB0_HIBERRESET' : 1061, + 'XILPM_RESET_USB1_HIBERRESET' : 1062, + 'XILPM_RESET_USB0_APB' : 1063, + 'XILPM_RESET_USB1_APB' : 1064, + 'XILPM_RESET_IPI' : 1065, + 'XILPM_RESET_APM_LPD' : 1066, + 'XILPM_RESET_RTC' : 1067, + 'XILPM_RESET_SYSMON' : 1068, + 'XILPM_RESET_AFI_FM6' : 1069, + 'XILPM_RESET_LPD_SWDT' : 1070, + 'XILPM_RESET_FPD' : 1071, + 'XILPM_RESET_RPU_DBG1' : 1072, + 'XILPM_RESET_RPU_DBG0' : 1073, + 'XILPM_RESET_DBG_LPD' : 1074, + 'XILPM_RESET_DBG_FPD' : 1075, + 'XILPM_RESET_APLL' : 1076, + 'XILPM_RESET_DPLL' : 1077, + 'XILPM_RESET_VPLL' : 1078, + 'XILPM_RESET_IOPLL' : 1079, + 'XILPM_RESET_RPLL' : 1080, + 'XILPM_RESET_GPO3_PL_0' : 1081, + 'XILPM_RESET_GPO3_PL_1' : 1082, + 'XILPM_RESET_GPO3_PL_2' : 1083, + 'XILPM_RESET_GPO3_PL_3' : 1084, + 'XILPM_RESET_GPO3_PL_4' : 1085, + 'XILPM_RESET_GPO3_PL_5' : 1086, + 'XILPM_RESET_GPO3_PL_6' : 1087, + 'XILPM_RESET_GPO3_PL_7' : 1088, + 'XILPM_RESET_GPO3_PL_8' : 1089, + 'XILPM_RESET_GPO3_PL_9' : 1090, + 'XILPM_RESET_GPO3_PL_10' : 1091, + 'XILPM_RESET_GPO3_PL_11' : 1092, + 'XILPM_RESET_GPO3_PL_12' : 1093, + 'XILPM_RESET_GPO3_PL_13' : 1094, + 'XILPM_RESET_GPO3_PL_14' : 1095, + 'XILPM_RESET_GPO3_PL_15' : 1096, + 'XILPM_RESET_GPO3_PL_16' : 1097, + 'XILPM_RESET_GPO3_PL_17' : 1098, + 'XILPM_RESET_GPO3_PL_18' : 1099, + 'XILPM_RESET_GPO3_PL_19' : 1100, + 'XILPM_RESET_GPO3_PL_20' : 1101, + 'XILPM_RESET_GPO3_PL_21' : 1102, + 'XILPM_RESET_GPO3_PL_22' : 1103, + 'XILPM_RESET_GPO3_PL_23' : 1104, + 'XILPM_RESET_GPO3_PL_24' : 1105, + 'XILPM_RESET_GPO3_PL_25' : 1106, + 'XILPM_RESET_GPO3_PL_26' : 1107, + 'XILPM_RESET_GPO3_PL_27' : 1108, + 'XILPM_RESET_GPO3_PL_28' : 1109, + 'XILPM_RESET_GPO3_PL_29' : 1110, + 'XILPM_RESET_GPO3_PL_30' : 1111, + 'XILPM_RESET_GPO3_PL_31' : 1112, + 'XILPM_RESET_RPU_LS' : 1113, + 'XILPM_RESET_PS_ONLY' : 1114, + 'XILPM_RESET_PL' : 1115, + 'XILPM_RESET_GPIO5_EMIO_92' : 1116, + 'XILPM_RESET_GPIO5_EMIO_93' : 1117, + 'XILPM_RESET_GPIO5_EMIO_94' : 1118, + 'XILPM_RESET_GPIO5_EMIO_95' : 1119, + + 'PM_CONFIG_MASTER_SECTION_ID' : 0x101, + 'PM_CONFIG_SLAVE_SECTION_ID' : 0x102, + 'PM_CONFIG_PREALLOC_SECTION_ID' : 0x103, + 'PM_CONFIG_POWER_SECTION_ID' : 0x104, + 'PM_CONFIG_RESET_SECTION_ID' : 0x105, + 'PM_CONFIG_SHUTDOWN_SECTION_ID' : 0x106, + 'PM_CONFIG_SET_CONFIG_SECTION_ID' : 0x107, + 'PM_CONFIG_GPO_SECTION_ID' : 0x108, + + 'PM_SLAVE_FLAG_IS_SHAREABLE' : 0x1, + 'PM_MASTER_USING_SLAVE_MASK' : 0x2, + + 'PM_CONFIG_GPO1_MIO_PIN_34_MAP' : (1 << 10), + 'PM_CONFIG_GPO1_MIO_PIN_35_MAP' : (1 << 11), + 'PM_CONFIG_GPO1_MIO_PIN_36_MAP' : (1 << 12), + 'PM_CONFIG_GPO1_MIO_PIN_37_MAP' : (1 << 13), + + 'PM_CONFIG_GPO1_BIT_2_MASK' : (1 << 2), + 'PM_CONFIG_GPO1_BIT_3_MASK' : (1 << 3), + 'PM_CONFIG_GPO1_BIT_4_MASK' : (1 << 4), + 'PM_CONFIG_GPO1_BIT_5_MASK' : (1 << 5), + + 'SUSPEND_TIMEOUT' : 0xFFFFFFFF, + + 'PM_CONFIG_IPI_PSU_CORTEXA53_0_MASK' : 0x00000001, + 'PM_CONFIG_IPI_PSU_CORTEXR5_0_MASK' : 0x00000100, + 'PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK' : 0x00000200, +} + +in_file = open(args.in_file, mode='r') +out_file = open(args.out_file, mode='wb') + +num_re = re.compile(r"^([0-9]+)U?$") +const_re = re.compile(r"^([A-Z_][A-Z0-9_]*)$") + +def process_item(item): + logging.debug("* ITEM " + item) + + value = 0 + for item in item.split('|'): + item = item.strip() + + num_match = num_re .match(item) + const_match = const_re.match(item) + + if num_match: + num = int(num_match.group(1)) + logging.debug(" - num " + str(num)) + value |= num + elif const_match: + name = const_match.group(1) + if not name in pm_define: + sys.stderr.write("Unknown define " + name + "!\n") + exit(1) + num = pm_define[name] + logging.debug(" - def " + hex(num)) + value |= num + + logging.debug(" = res " + hex(value)) + out_file.write(struct.pack('<L', value)) + + +# Read all code +code = in_file.read() + +# remove comments +code = re.sub('//.*?\n|/*.*?*/', '', code, flags=re.DOTALL) + +# remove everything outside the XPm_ConfigObject array definition +code = re.search('const u32 XPm_ConfigObject.*= {\n(.*)};', + code, flags=re.DOTALL).group(1) + +# Process each comma-separated array item +for item in code.split(','): + item = item.strip() + if item: + process_item(item) + +print("Wrote %d bytes" % out_file.tell())

On 15. 05. 19 10:56, Luca Ceresoli wrote:
The recently-added ZYNQMP_SPL_PM_CFG_OBJ_FILE option allows SPL to load a PMUFW configuration object from a binary blob. However the configuration object is produced by Xilinx proprietary tools as a C source file and no tool exists to easily convert it to a binary blob in an embedded Linux build system for U-Boot to use.
Add a simple Python script to do the conversion.
It is definitely not a complete C language parser, but it is enough to parse the known patterns generated by Xilinx tools, including:
- defines
- literal integers, optionally with a 'U' suffix
- bitwise OR between them
Signed-off-by: Luca Ceresoli luca@lucaceresoli.net
Changes v3 -> v4:
- move to tools/ directory
- remove double item.strip() call
tools/zynqmp_pm_cfg_obj_convert.py | 302 +++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100755 tools/zynqmp_pm_cfg_obj_convert.py
diff --git a/tools/zynqmp_pm_cfg_obj_convert.py b/tools/zynqmp_pm_cfg_obj_convert.py new file mode 100755 index 000000000000..bb4959877df7 --- /dev/null +++ b/tools/zynqmp_pm_cfg_obj_convert.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2019 Luca Ceresoli luca@lucaceresoli.net
+import sys +import re +import struct +import logging +import argparse
+parser = argparse.ArgumentParser(
- description='Convert a PMU configuration object from C source to a binary blob.',
- allow_abbrev=False)
I tried this tool on ubuntu 14.04 and found that allow_abbrev is not working with python 3.4.3
https://docs.python.org/3/library/argparse.html Changed in version 3.5: allow_abbrev parameter was added.
I think it would be good to remove this or apply patch below.
diff --git a/tools/zynqmp_pm_cfg_obj_convert.py b/tools/zynqmp_pm_cfg_obj_convert.py index bb4959877df7..556df249b893 100755 --- a/tools/zynqmp_pm_cfg_obj_convert.py +++ b/tools/zynqmp_pm_cfg_obj_convert.py @@ -8,9 +8,15 @@ import struct import logging import argparse
-parser = argparse.ArgumentParser( - description='Convert a PMU configuration object from C source to a binary blob.', - allow_abbrev=False) +try: + parser = argparse.ArgumentParser( + description='Convert a PMU configuration object from C source to a binary blob.', + allow_abbrev=False) + +except: + parser = argparse.ArgumentParser( + description='Convert a PMU configuration object from C source to a binary blob.') + parser.add_argument('-D', '--debug', action="store_true") parser.add_argument( "in_file", metavar='INPUT_FILE',
+parser.add_argument('-D', '--debug', action="store_true") +parser.add_argument(
- "in_file", metavar='INPUT_FILE',
- help='PMU configuration object (C source as produced by Xilinx XSDK)')
+parser.add_argument(
- "out_file", metavar='OUTPUT_FILE',
- help='PMU configuration object binary blob')
+args = parser.parse_args()
+logging.basicConfig(format='%(levelname)s:%(message)s',
level=(logging.DEBUG if args.debug else logging.WARNING))
+pm_define = {
- 'PM_CAP_ACCESS' : 0x1,
- 'PM_CAP_CONTEXT' : 0x2,
- 'PM_CAP_WAKEUP' : 0x4,
- 'NODE_UNKNOWN' : 0,
- 'NODE_APU' : 1,
- 'NODE_APU_0' : 2,
- 'NODE_APU_1' : 3,
- 'NODE_APU_2' : 4,
- 'NODE_APU_3' : 5,
- 'NODE_RPU' : 6,
- 'NODE_RPU_0' : 7,
- 'NODE_RPU_1' : 8,
- 'NODE_PLD' : 9,
- 'NODE_FPD' : 10,
- 'NODE_OCM_BANK_0' : 11,
- 'NODE_OCM_BANK_1' : 12,
- 'NODE_OCM_BANK_2' : 13,
- 'NODE_OCM_BANK_3' : 14,
- 'NODE_TCM_0_A' : 15,
- 'NODE_TCM_0_B' : 16,
- 'NODE_TCM_1_A' : 17,
- 'NODE_TCM_1_B' : 18,
- 'NODE_L2' : 19,
- 'NODE_GPU_PP_0' : 20,
- 'NODE_GPU_PP_1' : 21,
- 'NODE_USB_0' : 22,
- 'NODE_USB_1' : 23,
- 'NODE_TTC_0' : 24,
- 'NODE_TTC_1' : 25,
- 'NODE_TTC_2' : 26,
- 'NODE_TTC_3' : 27,
- 'NODE_SATA' : 28,
- 'NODE_ETH_0' : 29,
- 'NODE_ETH_1' : 30,
- 'NODE_ETH_2' : 31,
- 'NODE_ETH_3' : 32,
- 'NODE_UART_0' : 33,
- 'NODE_UART_1' : 34,
- 'NODE_SPI_0' : 35,
- 'NODE_SPI_1' : 36,
- 'NODE_I2C_0' : 37,
- 'NODE_I2C_1' : 38,
- 'NODE_SD_0' : 39,
- 'NODE_SD_1' : 40,
- 'NODE_DP' : 41,
- 'NODE_GDMA' : 42,
- 'NODE_ADMA' : 43,
- 'NODE_NAND' : 44,
- 'NODE_QSPI' : 45,
- 'NODE_GPIO' : 46,
- 'NODE_CAN_0' : 47,
- 'NODE_CAN_1' : 48,
- 'NODE_EXTERN' : 49,
- 'NODE_APLL' : 50,
- 'NODE_VPLL' : 51,
- 'NODE_DPLL' : 52,
- 'NODE_RPLL' : 53,
- 'NODE_IOPLL' : 54,
- 'NODE_DDR' : 55,
- 'NODE_IPI_APU' : 56,
- 'NODE_IPI_RPU_0' : 57,
- 'NODE_GPU' : 58,
- 'NODE_PCIE' : 59,
- 'NODE_PCAP' : 60,
- 'NODE_RTC' : 61,
- 'NODE_LPD' : 62,
- 'NODE_VCU' : 63,
- 'NODE_IPI_RPU_1' : 64,
- 'NODE_IPI_PL_0' : 65,
- 'NODE_IPI_PL_1' : 66,
- 'NODE_IPI_PL_2' : 67,
- 'NODE_IPI_PL_3' : 68,
- 'NODE_PL' : 69,
- 'NODE_ID_MA' : 70,
- 'XILPM_RESET_PCIE_CFG' : 1000,
- 'XILPM_RESET_PCIE_BRIDGE' : 1001,
- 'XILPM_RESET_PCIE_CTRL' : 1002,
- 'XILPM_RESET_DP' : 1003,
- 'XILPM_RESET_SWDT_CRF' : 1004,
- 'XILPM_RESET_AFI_FM5' : 1005,
- 'XILPM_RESET_AFI_FM4' : 1006,
- 'XILPM_RESET_AFI_FM3' : 1007,
- 'XILPM_RESET_AFI_FM2' : 1008,
- 'XILPM_RESET_AFI_FM1' : 1009,
- 'XILPM_RESET_AFI_FM0' : 1010,
- 'XILPM_RESET_GDMA' : 1011,
- 'XILPM_RESET_GPU_PP1' : 1012,
- 'XILPM_RESET_GPU_PP0' : 1013,
- 'XILPM_RESET_GPU' : 1014,
- 'XILPM_RESET_GT' : 1015,
- 'XILPM_RESET_SATA' : 1016,
- 'XILPM_RESET_ACPU3_PWRON' : 1017,
- 'XILPM_RESET_ACPU2_PWRON' : 1018,
- 'XILPM_RESET_ACPU1_PWRON' : 1019,
- 'XILPM_RESET_ACPU0_PWRON' : 1020,
- 'XILPM_RESET_APU_L2' : 1021,
- 'XILPM_RESET_ACPU3' : 1022,
- 'XILPM_RESET_ACPU2' : 1023,
- 'XILPM_RESET_ACPU1' : 1024,
- 'XILPM_RESET_ACPU0' : 1025,
- 'XILPM_RESET_DDR' : 1026,
- 'XILPM_RESET_APM_FPD' : 1027,
- 'XILPM_RESET_SOFT' : 1028,
- 'XILPM_RESET_GEM0' : 1029,
- 'XILPM_RESET_GEM1' : 1030,
- 'XILPM_RESET_GEM2' : 1031,
- 'XILPM_RESET_GEM3' : 1032,
- 'XILPM_RESET_QSPI' : 1033,
- 'XILPM_RESET_UART0' : 1034,
- 'XILPM_RESET_UART1' : 1035,
- 'XILPM_RESET_SPI0' : 1036,
- 'XILPM_RESET_SPI1' : 1037,
- 'XILPM_RESET_SDIO0' : 1038,
- 'XILPM_RESET_SDIO1' : 1039,
- 'XILPM_RESET_CAN0' : 1040,
- 'XILPM_RESET_CAN1' : 1041,
- 'XILPM_RESET_I2C0' : 1042,
- 'XILPM_RESET_I2C1' : 1043,
- 'XILPM_RESET_TTC0' : 1044,
- 'XILPM_RESET_TTC1' : 1045,
- 'XILPM_RESET_TTC2' : 1046,
- 'XILPM_RESET_TTC3' : 1047,
- 'XILPM_RESET_SWDT_CRL' : 1048,
- 'XILPM_RESET_NAND' : 1049,
- 'XILPM_RESET_ADMA' : 1050,
- 'XILPM_RESET_GPIO' : 1051,
- 'XILPM_RESET_IOU_CC' : 1052,
- 'XILPM_RESET_TIMESTAMP' : 1053,
- 'XILPM_RESET_RPU_R50' : 1054,
- 'XILPM_RESET_RPU_R51' : 1055,
- 'XILPM_RESET_RPU_AMBA' : 1056,
- 'XILPM_RESET_OCM' : 1057,
- 'XILPM_RESET_RPU_PGE' : 1058,
- 'XILPM_RESET_USB0_CORERESET' : 1059,
- 'XILPM_RESET_USB1_CORERESET' : 1060,
- 'XILPM_RESET_USB0_HIBERRESET' : 1061,
- 'XILPM_RESET_USB1_HIBERRESET' : 1062,
- 'XILPM_RESET_USB0_APB' : 1063,
- 'XILPM_RESET_USB1_APB' : 1064,
- 'XILPM_RESET_IPI' : 1065,
- 'XILPM_RESET_APM_LPD' : 1066,
- 'XILPM_RESET_RTC' : 1067,
- 'XILPM_RESET_SYSMON' : 1068,
- 'XILPM_RESET_AFI_FM6' : 1069,
- 'XILPM_RESET_LPD_SWDT' : 1070,
- 'XILPM_RESET_FPD' : 1071,
- 'XILPM_RESET_RPU_DBG1' : 1072,
- 'XILPM_RESET_RPU_DBG0' : 1073,
- 'XILPM_RESET_DBG_LPD' : 1074,
- 'XILPM_RESET_DBG_FPD' : 1075,
- 'XILPM_RESET_APLL' : 1076,
- 'XILPM_RESET_DPLL' : 1077,
- 'XILPM_RESET_VPLL' : 1078,
- 'XILPM_RESET_IOPLL' : 1079,
- 'XILPM_RESET_RPLL' : 1080,
- 'XILPM_RESET_GPO3_PL_0' : 1081,
- 'XILPM_RESET_GPO3_PL_1' : 1082,
- 'XILPM_RESET_GPO3_PL_2' : 1083,
- 'XILPM_RESET_GPO3_PL_3' : 1084,
- 'XILPM_RESET_GPO3_PL_4' : 1085,
- 'XILPM_RESET_GPO3_PL_5' : 1086,
- 'XILPM_RESET_GPO3_PL_6' : 1087,
- 'XILPM_RESET_GPO3_PL_7' : 1088,
- 'XILPM_RESET_GPO3_PL_8' : 1089,
- 'XILPM_RESET_GPO3_PL_9' : 1090,
- 'XILPM_RESET_GPO3_PL_10' : 1091,
- 'XILPM_RESET_GPO3_PL_11' : 1092,
- 'XILPM_RESET_GPO3_PL_12' : 1093,
- 'XILPM_RESET_GPO3_PL_13' : 1094,
- 'XILPM_RESET_GPO3_PL_14' : 1095,
- 'XILPM_RESET_GPO3_PL_15' : 1096,
- 'XILPM_RESET_GPO3_PL_16' : 1097,
- 'XILPM_RESET_GPO3_PL_17' : 1098,
- 'XILPM_RESET_GPO3_PL_18' : 1099,
- 'XILPM_RESET_GPO3_PL_19' : 1100,
- 'XILPM_RESET_GPO3_PL_20' : 1101,
- 'XILPM_RESET_GPO3_PL_21' : 1102,
- 'XILPM_RESET_GPO3_PL_22' : 1103,
- 'XILPM_RESET_GPO3_PL_23' : 1104,
- 'XILPM_RESET_GPO3_PL_24' : 1105,
- 'XILPM_RESET_GPO3_PL_25' : 1106,
- 'XILPM_RESET_GPO3_PL_26' : 1107,
- 'XILPM_RESET_GPO3_PL_27' : 1108,
- 'XILPM_RESET_GPO3_PL_28' : 1109,
- 'XILPM_RESET_GPO3_PL_29' : 1110,
- 'XILPM_RESET_GPO3_PL_30' : 1111,
- 'XILPM_RESET_GPO3_PL_31' : 1112,
- 'XILPM_RESET_RPU_LS' : 1113,
- 'XILPM_RESET_PS_ONLY' : 1114,
- 'XILPM_RESET_PL' : 1115,
- 'XILPM_RESET_GPIO5_EMIO_92' : 1116,
- 'XILPM_RESET_GPIO5_EMIO_93' : 1117,
- 'XILPM_RESET_GPIO5_EMIO_94' : 1118,
- 'XILPM_RESET_GPIO5_EMIO_95' : 1119,
- 'PM_CONFIG_MASTER_SECTION_ID' : 0x101,
- 'PM_CONFIG_SLAVE_SECTION_ID' : 0x102,
- 'PM_CONFIG_PREALLOC_SECTION_ID' : 0x103,
- 'PM_CONFIG_POWER_SECTION_ID' : 0x104,
- 'PM_CONFIG_RESET_SECTION_ID' : 0x105,
- 'PM_CONFIG_SHUTDOWN_SECTION_ID' : 0x106,
- 'PM_CONFIG_SET_CONFIG_SECTION_ID' : 0x107,
- 'PM_CONFIG_GPO_SECTION_ID' : 0x108,
- 'PM_SLAVE_FLAG_IS_SHAREABLE' : 0x1,
- 'PM_MASTER_USING_SLAVE_MASK' : 0x2,
- 'PM_CONFIG_GPO1_MIO_PIN_34_MAP' : (1 << 10),
- 'PM_CONFIG_GPO1_MIO_PIN_35_MAP' : (1 << 11),
- 'PM_CONFIG_GPO1_MIO_PIN_36_MAP' : (1 << 12),
- 'PM_CONFIG_GPO1_MIO_PIN_37_MAP' : (1 << 13),
- 'PM_CONFIG_GPO1_BIT_2_MASK' : (1 << 2),
- 'PM_CONFIG_GPO1_BIT_3_MASK' : (1 << 3),
- 'PM_CONFIG_GPO1_BIT_4_MASK' : (1 << 4),
- 'PM_CONFIG_GPO1_BIT_5_MASK' : (1 << 5),
- 'SUSPEND_TIMEOUT' : 0xFFFFFFFF,
- 'PM_CONFIG_IPI_PSU_CORTEXA53_0_MASK' : 0x00000001,
- 'PM_CONFIG_IPI_PSU_CORTEXR5_0_MASK' : 0x00000100,
- 'PM_CONFIG_IPI_PSU_CORTEXR5_1_MASK' : 0x00000200,
+}
+in_file = open(args.in_file, mode='r') +out_file = open(args.out_file, mode='wb')
+num_re = re.compile(r"^([0-9]+)U?$") +const_re = re.compile(r"^([A-Z_][A-Z0-9_]*)$")
+def process_item(item):
- logging.debug("* ITEM " + item)
- value = 0
- for item in item.split('|'):
item = item.strip()
num_match = num_re .match(item)
const_match = const_re.match(item)
if num_match:
num = int(num_match.group(1))
logging.debug(" - num " + str(num))
value |= num
elif const_match:
name = const_match.group(1)
if not name in pm_define:
sys.stderr.write("Unknown define " + name + "!\n")
exit(1)
num = pm_define[name]
logging.debug(" - def " + hex(num))
value |= num
- logging.debug(" = res " + hex(value))
- out_file.write(struct.pack('<L', value))
+# Read all code +code = in_file.read()
+# remove comments +code = re.sub('//.*?\n|/*.*?*/', '', code, flags=re.DOTALL)
+# remove everything outside the XPm_ConfigObject array definition +code = re.search('const u32 XPm_ConfigObject.*= {\n(.*)};',
code, flags=re.DOTALL).group(1)
+# Process each comma-separated array item +for item in code.split(','):
- item = item.strip()
- if item:
process_item(item)
+print("Wrote %d bytes" % out_file.tell())
Other then this one thing all look good. Please let me know if you want to include it or I will send a patch on the top of this patch.
Thanks, Michal
participants (2)
-
Luca Ceresoli
-
Michal Simek