All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 0/2] arm64: zynqmp: pass a PMUFW config object
@ 2019-04-15 16:47 Luca Ceresoli
  2019-04-15 16:47 ` [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime Luca Ceresoli
  2019-04-15 16:47 ` [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary Luca Ceresoli
  0 siblings, 2 replies; 13+ messages in thread
From: Luca Ceresoli @ 2019-04-15 16:47 UTC (permalink / raw)
  To: u-boot

Hi,

This patchset aims at solving a long-standing issue in the ZynqMP users
community: the management of the PMU firmware configuration object when
U-Boot SPL is used.

History and status
==================

First non-RFC version. The code is now clean and I consider it OK for
mainline inclusion.

Since RFC v2 the cfg obj is now passed as a binary blob. The code to
compile it in the C form has been removed and replaced by a Python tool to
convert C to bin. The loading has been fixed and cleaned up according to
comments.

TODO: move the PMU IPC code to a mailbox uclass driver.

Description
===========

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.

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-bsp/pmu-firmware/pmu-firmware/0001-Load-XPm_ConfigObject-at-boot.patch
RFCv1: https://lists.denx.de/pipermail/u-boot/2019-February/360450.html
RFCv2: https://lists.denx.de/pipermail/u-boot/2019-March/362464.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                  |  17 +
 arch/arm/mach-zynqmp/Makefile                 |   4 +
 arch/arm/mach-zynqmp/include/mach/sys_proto.h |   4 +
 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py    | 302 ++++++++++++++++++
 arch/arm/mach-zynqmp/pmu_ipc.c                | 112 +++++++
 board/xilinx/zynqmp/Makefile                  |  12 +
 board/xilinx/zynqmp/pm_cfg_obj.S              |  17 +
 board/xilinx/zynqmp/zynqmp.c                  |   8 +
 8 files changed, 476 insertions(+)
 create mode 100755 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
 create mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c
 create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.S

-- 
2.21.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-04-15 16:47 [U-Boot] [PATCH v3 0/2] arm64: zynqmp: pass a PMUFW config object Luca Ceresoli
@ 2019-04-15 16:47 ` Luca Ceresoli
  2019-05-03 22:38   ` Michal Simek
  2019-04-15 16:47 ` [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary Luca Ceresoli
  1 sibling, 1 reply; 13+ messages in thread
From: Luca Ceresoli @ 2019-04-15 16:47 UTC (permalink / raw)
  To: u-boot

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 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/fb647e6b4c00f5154eba52a88b948195b6f1dc2b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.c#L295
 * https://github.com/ARM-software/arm-trusted-firmware/blob/c48d02bade88b07fa7f43aa44e5217f68e5d047f/plat/xilinx/zynqmp/pm_service/pm_api_sys.c#L357

SPL logs on the console before loading the configuration object:

  U-Boot SPL 2018.01 (Mar 20 2019 - 08:12:21)
  Loading PMUFW cfg obj (2008 bytes)
  EL Level:	EL3
  ...

Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>

---

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                  |  17 +++
 arch/arm/mach-zynqmp/Makefile                 |   4 +
 arch/arm/mach-zynqmp/include/mach/sys_proto.h |   4 +
 arch/arm/mach-zynqmp/pmu_ipc.c                | 112 ++++++++++++++++++
 board/xilinx/zynqmp/Makefile                  |  12 ++
 board/xilinx/zynqmp/pm_cfg_obj.S              |  17 +++
 board/xilinx/zynqmp/zynqmp.c                  |   8 ++
 7 files changed, 174 insertions(+)
 create mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c
 create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.S

diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig
index 9bb5a5c20201..b88d1d313839 100644
--- a/arch/arm/mach-zynqmp/Kconfig
+++ b/arch/arm/mach-zynqmp/Kconfig
@@ -65,6 +65,23 @@ config PMUFW_INIT_FILE
 	  Include external PMUFW (Platform Management Unit FirmWare) to
 	  a Xilinx bootable image (boot.bin).
 
+config ZYNQMP_LOAD_PM_CFG_OBJ_FILE
+	string "PMU firmware configuration object to load at runtime"
+	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
+	  board/xilinx/zynqmp/) 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..d391b7c1d54e 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_LOAD_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..e2b9a79ed539 100644
--- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
@@ -72,4 +72,8 @@ int chip_id(unsigned char id);
 void tcm_init(u8 mode);
 #endif
 
+#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
+void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
+#endif
+
 #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..5feb8568f8de
--- /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 = 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 = 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,
+		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..d7a3cb244521 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -33,6 +33,18 @@ 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),"")
+PM_CFG_OBJ_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE))
+
+$(obj)/pm_cfg_obj.bin: $(PM_CFG_OBJ_FILE) FORCE
+	$(call if_changed,shipped)
+
+$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
+
+CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ
+obj-$(CONFIG_SPL_BUILD) += pm_cfg_obj.o
+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..72ca0fb785dc
--- /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 "spl/board/xilinx/zynqmp/pm_cfg_obj.bin"
+
+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/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index db272478506f..7fcb3e120688 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -327,6 +327,14 @@ int board_early_init_f(void)
 
 int board_init(void)
 {
+#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
+	extern const u32 zynqmp_pm_cfg_obj[];
+	extern const int zynqmp_pm_cfg_obj_size;
+
+	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) && \
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary
  2019-04-15 16:47 [U-Boot] [PATCH v3 0/2] arm64: zynqmp: pass a PMUFW config object Luca Ceresoli
  2019-04-15 16:47 ` [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime Luca Ceresoli
@ 2019-04-15 16:47 ` Luca Ceresoli
  2019-05-03 22:31   ` Michal Simek
  1 sibling, 1 reply; 13+ messages in thread
From: Luca Ceresoli @ 2019-04-15 16:47 UTC (permalink / raw)
  To: u-boot

The recently-added ZYNQMP_LOAD_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>
---
 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py | 302 +++++++++++++++++++++
 1 file changed, 302 insertions(+)
 create mode 100755 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py

diff --git a/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py b/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
new file mode 100755
index 000000000000..5aea15860319
--- /dev/null
+++ b/arch/arm/mach-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.strip())
+
+print("Wrote %d bytes" % out_file.tell())
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary
  2019-04-15 16:47 ` [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary Luca Ceresoli
@ 2019-05-03 22:31   ` Michal Simek
  2019-05-04  6:14     ` Luca Ceresoli
  0 siblings, 1 reply; 13+ messages in thread
From: Michal Simek @ 2019-05-03 22:31 UTC (permalink / raw)
  To: u-boot

Hi,

On 15. 04. 19 9:47, Luca Ceresoli wrote:
> The recently-added ZYNQMP_LOAD_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>
> ---
>  arch/arm/mach-zynqmp/pm_cfg_obj_convert.py | 302 +++++++++++++++++++++
>  1 file changed, 302 insertions(+)
>  create mode 100755 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
> 
> diff --git a/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py b/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
> new file mode 100755
> index 000000000000..5aea15860319
> --- /dev/null
> +++ b/arch/arm/mach-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.strip())
> +
> +print("Wrote %d bytes" % out_file.tell())
> 


I have created simple script for extracting this object also from fsbl
elf file. Maybe we should also publish it when this is out.
For your reference.

#!/bin/bash
# Written by Michal Simek

FSBL=zynqmp_fsbl
PMCFG=pmcfg.bin

PM_END=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
'/XPm_ConfigObject/,/^$/p' | head -n -2 | tail -n 1 | cut -c 5-12 | awk
'{printf ("0x%s",$1)}'`
PM_START=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
'/XPm_ConfigObject/,/^$/p' | head -n 1 | awk '{printf ("0x%s",$1)}'`

FSBL_START=`aarch64-linux-gnu-readelf -a ${FSBL}.elf | grep "Entry point
address" | awk '{print $4}'`

PM_OBJECT_START=`echo $((${PM_START} - ${FSBL_START}))`
PM_OBJECT_SIZE=`echo $((${PM_END} - ${PM_START}))`

echo "FSBL starting address ${FSBL_START}"
echo "FSBL object addresses ${PM_START} ${PM_END}"
echo "OBJECT start ${PM_OBJECT_START} size ${PM_OBJECT_SIZE}"

aarch64-linux-gnu-objcopy -O binary ${FSBL}.elf ${FSBL}.bin

# Extracting config object
dd if=${FSBL}.bin of=${PMCFG} bs=1 skip=${PM_OBJECT_START}
count=${PM_OBJECT_SIZE} > /dev/null 2>&1

echo "Your object ${PMCFG} is ready"

rm -f ${FSBL}.bin *~

Anyway this patch is good. I didn't test it but it looks ok.

M

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-04-15 16:47 ` [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime Luca Ceresoli
@ 2019-05-03 22:38   ` Michal Simek
  2019-05-04 16:54     ` Luca Ceresoli
  0 siblings, 1 reply; 13+ messages in thread
From: Michal Simek @ 2019-05-03 22:38 UTC (permalink / raw)
  To: u-boot

On 15. 04. 19 9:47, 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 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/fb647e6b4c00f5154eba52a88b948195b6f1dc2b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.c#L295
>  * https://github.com/ARM-software/arm-trusted-firmware/blob/c48d02bade88b07fa7f43aa44e5217f68e5d047f/plat/xilinx/zynqmp/pm_service/pm_api_sys.c#L357
> 
> SPL logs on the console before loading the configuration object:
> 
>   U-Boot SPL 2018.01 (Mar 20 2019 - 08:12:21)
>   Loading PMUFW cfg obj (2008 bytes)
>   EL Level:	EL3
>   ...
> 
> Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
> 
> ---
> 
> 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                  |  17 +++
>  arch/arm/mach-zynqmp/Makefile                 |   4 +
>  arch/arm/mach-zynqmp/include/mach/sys_proto.h |   4 +
>  arch/arm/mach-zynqmp/pmu_ipc.c                | 112 ++++++++++++++++++
>  board/xilinx/zynqmp/Makefile                  |  12 ++
>  board/xilinx/zynqmp/pm_cfg_obj.S              |  17 +++
>  board/xilinx/zynqmp/zynqmp.c                  |   8 ++
>  7 files changed, 174 insertions(+)
>  create mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c
>  create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.S
> 
> diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig
> index 9bb5a5c20201..b88d1d313839 100644
> --- a/arch/arm/mach-zynqmp/Kconfig
> +++ b/arch/arm/mach-zynqmp/Kconfig
> @@ -65,6 +65,23 @@ config PMUFW_INIT_FILE
>  	  Include external PMUFW (Platform Management Unit FirmWare) to
>  	  a Xilinx bootable image (boot.bin).
>  
> +config ZYNQMP_LOAD_PM_CFG_OBJ_FILE
> +	string "PMU firmware configuration object to load at runtime"
> +	help
> +

remove this empty line.

> +	  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
> +	  board/xilinx/zynqmp/) 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..d391b7c1d54e 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_LOAD_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..e2b9a79ed539 100644
> --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
> +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
> @@ -72,4 +72,8 @@ int chip_id(unsigned char id);
>  void tcm_init(u8 mode);
>  #endif
>  
> +#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
> +void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
> +#endif

nit: you can remove that if/endif to open a way to also pass different
configuration object from full u-boot.

> +
>  #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..5feb8568f8de
> --- /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 = 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 = 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]);
> +}
> +
> +/**

This suggest kernel-doc format but it is not. Please run kernel-doc and
check this file.

> + * 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;
> +}
> +
> +/**

ditto.

> + * 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,
> +		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..d7a3cb244521 100644
> --- a/board/xilinx/zynqmp/Makefile
> +++ b/board/xilinx/zynqmp/Makefile
> @@ -33,6 +33,18 @@ 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),"")
> +PM_CFG_OBJ_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE))
> +
> +$(obj)/pm_cfg_obj.bin: $(PM_CFG_OBJ_FILE) FORCE
> +	$(call if_changed,shipped)

What's the reason to copying it?

> +
> +$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
> +
> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ

I am no fan of passing another object. you have
CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE already and this can be used instead.

> +obj-$(CONFIG_SPL_BUILD) += pm_cfg_obj.o
> +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..72ca0fb785dc
> --- /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 "spl/board/xilinx/zynqmp/pm_cfg_obj.bin"
> +
> +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/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
> index db272478506f..7fcb3e120688 100644
> --- a/board/xilinx/zynqmp/zynqmp.c
> +++ b/board/xilinx/zynqmp/zynqmp.c
> @@ -327,6 +327,14 @@ int board_early_init_f(void)
>  
>  int board_init(void)
>  {
> +#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
> +	extern const u32 zynqmp_pm_cfg_obj[];
> +	extern const int zynqmp_pm_cfg_obj_size;

please put these two to header instead.

> +
> +	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) && \
> 

Anyway we are almost there. I have tested it on HW and it works.
When this is cleanup I think this should also go to zynqmp pmufw command
to be able to change it at run time directly from u-boot prompt.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary
  2019-05-03 22:31   ` Michal Simek
@ 2019-05-04  6:14     ` Luca Ceresoli
  2019-05-04 22:21       ` Michal Simek
  0 siblings, 1 reply; 13+ messages in thread
From: Luca Ceresoli @ 2019-05-04  6:14 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On 04/05/19 00:31, Michal Simek wrote:
> Hi,
> 
> On 15. 04. 19 9:47, Luca Ceresoli wrote:
>> The recently-added ZYNQMP_LOAD_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>
>> ---
>>  arch/arm/mach-zynqmp/pm_cfg_obj_convert.py | 302 +++++++++++++++++++++
>>  1 file changed, 302 insertions(+)
>>  create mode 100755 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
>>
>> diff --git a/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py b/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
>> new file mode 100755
>> index 000000000000..5aea15860319
>> --- /dev/null
>> +++ b/arch/arm/mach-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.strip())
>> +
>> +print("Wrote %d bytes" % out_file.tell())
>>
> 
> 
> I have created simple script for extracting this object also from fsbl
> elf file. Maybe we should also publish it when this is out.
> For your reference.
> 
> #!/bin/bash
> # Written by Michal Simek
> 
> FSBL=zynqmp_fsbl
> PMCFG=pmcfg.bin
> 
> PM_END=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
> '/XPm_ConfigObject/,/^$/p' | head -n -2 | tail -n 1 | cut -c 5-12 | awk
> '{printf ("0x%s",$1)}'`
> PM_START=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
> '/XPm_ConfigObject/,/^$/p' | head -n 1 | awk '{printf ("0x%s",$1)}'`
> 
> FSBL_START=`aarch64-linux-gnu-readelf -a ${FSBL}.elf | grep "Entry point
> address" | awk '{print $4}'`
> 
> PM_OBJECT_START=`echo $((${PM_START} - ${FSBL_START}))`
> PM_OBJECT_SIZE=`echo $((${PM_END} - ${PM_START}))`
> 
> echo "FSBL starting address ${FSBL_START}"
> echo "FSBL object addresses ${PM_START} ${PM_END}"
> echo "OBJECT start ${PM_OBJECT_START} size ${PM_OBJECT_SIZE}"
> 
> aarch64-linux-gnu-objcopy -O binary ${FSBL}.elf ${FSBL}.bin
> 
> # Extracting config object
> dd if=${FSBL}.bin of=${PMCFG} bs=1 skip=${PM_OBJECT_START}
> count=${PM_OBJECT_SIZE} > /dev/null 2>&1
> 
> echo "Your object ${PMCFG} is ready"
> 
> rm -f ${FSBL}.bin *~
> 
> Anyway this patch is good. I didn't test it but it looks ok.

Ok, thanks.

In the meantime I have been wondering whether it should be moved from
arch/arm/mach-zynqmp/pm_cfg_obj_convert.py to tools/ (and prefixed with
zynqmp_), where other tools are.

-- 
Luca

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-05-03 22:38   ` Michal Simek
@ 2019-05-04 16:54     ` Luca Ceresoli
  2019-05-06 15:56       ` Michal Simek
  0 siblings, 1 reply; 13+ messages in thread
From: Luca Ceresoli @ 2019-05-04 16:54 UTC (permalink / raw)
  To: u-boot

Hi Michal,

thanks for your review. See my replies below.

On 04/05/19 00:38, Michal Simek wrote:
> On 15. 04. 19 9:47, 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 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/fb647e6b4c00f5154eba52a88b948195b6f1dc2b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_misc_drivers.c#L295
>>  * https://github.com/ARM-software/arm-trusted-firmware/blob/c48d02bade88b07fa7f43aa44e5217f68e5d047f/plat/xilinx/zynqmp/pm_service/pm_api_sys.c#L357
>>
>> SPL logs on the console before loading the configuration object:
>>
>>   U-Boot SPL 2018.01 (Mar 20 2019 - 08:12:21)
>>   Loading PMUFW cfg obj (2008 bytes)
>>   EL Level:	EL3
>>   ...
>>
>> Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
>>
>> ---
>>
>> 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                  |  17 +++
>>  arch/arm/mach-zynqmp/Makefile                 |   4 +
>>  arch/arm/mach-zynqmp/include/mach/sys_proto.h |   4 +
>>  arch/arm/mach-zynqmp/pmu_ipc.c                | 112 ++++++++++++++++++
>>  board/xilinx/zynqmp/Makefile                  |  12 ++
>>  board/xilinx/zynqmp/pm_cfg_obj.S              |  17 +++
>>  board/xilinx/zynqmp/zynqmp.c                  |   8 ++
>>  7 files changed, 174 insertions(+)
>>  create mode 100644 arch/arm/mach-zynqmp/pmu_ipc.c
>>  create mode 100644 board/xilinx/zynqmp/pm_cfg_obj.S
>>
>> diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig
>> index 9bb5a5c20201..b88d1d313839 100644
>> --- a/arch/arm/mach-zynqmp/Kconfig
>> +++ b/arch/arm/mach-zynqmp/Kconfig
>> @@ -65,6 +65,23 @@ config PMUFW_INIT_FILE
>>  	  Include external PMUFW (Platform Management Unit FirmWare) to
>>  	  a Xilinx bootable image (boot.bin).
>>  
>> +config ZYNQMP_LOAD_PM_CFG_OBJ_FILE
>> +	string "PMU firmware configuration object to load at runtime"
>> +	help
>> +
> 
> remove this empty line.

OK.

>> diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
>> index 385c8825f2f6..e2b9a79ed539 100644
>> --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
>> +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
>> @@ -72,4 +72,8 @@ int chip_id(unsigned char id);
>>  void tcm_init(u8 mode);
>>  #endif
>>  
>> +#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
>> +void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size);
>> +#endif
> 
> nit: you can remove that if/endif to open a way to also pass different
> configuration object from full u-boot.

Good idea. Less #ifdefs is always good as well.

>> diff --git a/arch/arm/mach-zynqmp/pmu_ipc.c b/arch/arm/mach-zynqmp/pmu_ipc.c
>> new file mode 100644
>> index 000000000000..5feb8568f8de
>> --- /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 = 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 = 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]);
>> +}
>> +
>> +/**
> 
> This suggest kernel-doc format but it is not. Please run kernel-doc and
> check this file.

Will do.

>> diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
>> index 80f8ca7e1e4b..d7a3cb244521 100644
>> --- a/board/xilinx/zynqmp/Makefile
>> +++ b/board/xilinx/zynqmp/Makefile
>> @@ -33,6 +33,18 @@ 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),"")
>> +PM_CFG_OBJ_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE))
>> +
>> +$(obj)/pm_cfg_obj.bin: $(PM_CFG_OBJ_FILE) FORCE
>> +	$(call if_changed,shipped)
> 
> What's the reason to copying it?

Perhaps none. Will check and fix.

>> +$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
>> +
>> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ
> 
> I am no fan of passing another object. you have
> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE already and this can be used instead.

Not sure I got your point here. I'm not passing an object, just setting
a define (without value). This is used to enable code under #ifdef in C
files.

>> +obj-$(CONFIG_SPL_BUILD) += pm_cfg_obj.o
>> +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 db272478506f..7fcb3e120688 100644
>> --- a/board/xilinx/zynqmp/zynqmp.c
>> +++ b/board/xilinx/zynqmp/zynqmp.c
>> @@ -327,6 +327,14 @@ int board_early_init_f(void)
>>  
>>  int board_init(void)
>>  {
>> +#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
>> +	extern const u32 zynqmp_pm_cfg_obj[];
>> +	extern const int zynqmp_pm_cfg_obj_size;
> 
> please put these two to header instead.

This was done on purpose to reduce the amount of #ifdefs, and also to
not pollute the namespace with two symbols that are not needed outside
this function. I don't see the added value of moving them in a .h, but I
might be wrong.

> Anyway we are almost there. I have tested it on HW and it works.
> When this is cleanup I think this should also go to zynqmp pmufw command
> to be able to change it at run time directly from u-boot prompt.

Sure. Also moving to a mailbox uclass driver is on my todo list. But
this is progressing in spare time, so it's all probably going to happen
after this patch is accepted. Ok for you?

-- 
Luca

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary
  2019-05-04  6:14     ` Luca Ceresoli
@ 2019-05-04 22:21       ` Michal Simek
  0 siblings, 0 replies; 13+ messages in thread
From: Michal Simek @ 2019-05-04 22:21 UTC (permalink / raw)
  To: u-boot

Hi,

pá 3. 5. 2019 v 23:15 odesílatel Luca Ceresoli <luca@lucaceresoli.net>
napsal:

> Hi Michal,
>
> On 04/05/19 00:31, Michal Simek wrote:
> > Hi,
> >
> > On 15. 04. 19 9:47, Luca Ceresoli wrote:
> >> The recently-added ZYNQMP_LOAD_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>
> >> ---
> >>  arch/arm/mach-zynqmp/pm_cfg_obj_convert.py | 302 +++++++++++++++++++++
> >>  1 file changed, 302 insertions(+)
> >>  create mode 100755 arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
> >>
> >> diff --git a/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
> b/arch/arm/mach-zynqmp/pm_cfg_obj_convert.py
> >> new file mode 100755
> >> index 000000000000..5aea15860319
> >> --- /dev/null
> >> +++ b/arch/arm/mach-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.strip())
> >> +
> >> +print("Wrote %d bytes" % out_file.tell())
> >>
> >
> >
> > I have created simple script for extracting this object also from fsbl
> > elf file. Maybe we should also publish it when this is out.
> > For your reference.
> >
> > #!/bin/bash
> > # Written by Michal Simek
> >
> > FSBL=zynqmp_fsbl
> > PMCFG=pmcfg.bin
> >
> > PM_END=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
> > '/XPm_ConfigObject/,/^$/p' | head -n -2 | tail -n 1 | cut -c 5-12 | awk
> > '{printf ("0x%s",$1)}'`
> > PM_START=`aarch64-linux-gnu-objdump -D ${FSBL}.elf | sed -n
> > '/XPm_ConfigObject/,/^$/p' | head -n 1 | awk '{printf ("0x%s",$1)}'`
> >
> > FSBL_START=`aarch64-linux-gnu-readelf -a ${FSBL}.elf | grep "Entry point
> > address" | awk '{print $4}'`
> >
> > PM_OBJECT_START=`echo $((${PM_START} - ${FSBL_START}))`
> > PM_OBJECT_SIZE=`echo $((${PM_END} - ${PM_START}))`
> >
> > echo "FSBL starting address ${FSBL_START}"
> > echo "FSBL object addresses ${PM_START} ${PM_END}"
> > echo "OBJECT start ${PM_OBJECT_START} size ${PM_OBJECT_SIZE}"
> >
> > aarch64-linux-gnu-objcopy -O binary ${FSBL}.elf ${FSBL}.bin
> >
> > # Extracting config object
> > dd if=${FSBL}.bin of=${PMCFG} bs=1 skip=${PM_OBJECT_START}
> > count=${PM_OBJECT_SIZE} > /dev/null 2>&1
> >
> > echo "Your object ${PMCFG} is ready"
> >
> > rm -f ${FSBL}.bin *~
> >
> > Anyway this patch is good. I didn't test it but it looks ok.
>
> Ok, thanks.
>
> In the meantime I have been wondering whether it should be moved from
> arch/arm/mach-zynqmp/pm_cfg_obj_convert.py to tools/ (and prefixed with
> zynqmp_), where other tools are.
>
>
Not a problem with it.

M



-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-05-04 16:54     ` Luca Ceresoli
@ 2019-05-06 15:56       ` Michal Simek
  2019-05-07 14:11         ` Luca Ceresoli
  0 siblings, 1 reply; 13+ messages in thread
From: Michal Simek @ 2019-05-06 15:56 UTC (permalink / raw)
  To: u-boot

Hi,

snip.

>>> +$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
>>> +
>>> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ
>>
>> I am no fan of passing another object. you have
>> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE already and this can be used instead.
> 
> Not sure I got your point here. I'm not passing an object, just setting
> a define (without value). This is used to enable code under #ifdef in C
> files.

Sorry I meant new config option. It should be enough to use CFG_OBJ_FILE
everywhere and not create another config option which is just used the
same way.

> 
>>> +obj-$(CONFIG_SPL_BUILD) += pm_cfg_obj.o
>>> +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 db272478506f..7fcb3e120688 100644
>>> --- a/board/xilinx/zynqmp/zynqmp.c
>>> +++ b/board/xilinx/zynqmp/zynqmp.c
>>> @@ -327,6 +327,14 @@ int board_early_init_f(void)
>>>  
>>>  int board_init(void)
>>>  {
>>> +#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
>>> +	extern const u32 zynqmp_pm_cfg_obj[];
>>> +	extern const int zynqmp_pm_cfg_obj_size;
>>
>> please put these two to header instead.
> 
> This was done on purpose to reduce the amount of #ifdefs, and also to
> not pollute the namespace with two symbols that are not needed outside
> this function. I don't see the added value of moving them in a .h, but I
> might be wrong.

Is checkpatch ok with this? I think that it should error out that you
shouldn't put externs to .c files.

> 
>> Anyway we are almost there. I have tested it on HW and it works.
>> When this is cleanup I think this should also go to zynqmp pmufw command
>> to be able to change it at run time directly from u-boot prompt.
> 
> Sure. Also moving to a mailbox uclass driver is on my todo list. But
> this is progressing in spare time, so it's all probably going to happen
> after this patch is accepted. Ok for you?

Definitely. As I told you I am ok with current approach and these things
should come later.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-05-06 15:56       ` Michal Simek
@ 2019-05-07 14:11         ` Luca Ceresoli
  2019-05-14 15:06           ` Luca Ceresoli
  0 siblings, 1 reply; 13+ messages in thread
From: Luca Ceresoli @ 2019-05-07 14:11 UTC (permalink / raw)
  To: u-boot

Hi,

On 06/05/19 17:56, Michal Simek wrote:
> Hi,
> 
> snip.
> 
>>>> +$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
>>>> +
>>>> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ
>>>
>>> I am no fan of passing another object. you have
>>> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE already and this can be used instead.
>>
>> Not sure I got your point here. I'm not passing an object, just setting
>> a define (without value). This is used to enable code under #ifdef in C
>> files.
> 
> Sorry I meant new config option. It should be enough to use CFG_OBJ_FILE
> everywhere and not create another config option which is just used the
> same way.

I totally agree. But I would need to check whether
CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE is empty or not, and I don't think
the C preprocessor can do that.

>>>> diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
>>>> index db272478506f..7fcb3e120688 100644
>>>> --- a/board/xilinx/zynqmp/zynqmp.c
>>>> +++ b/board/xilinx/zynqmp/zynqmp.c
>>>> @@ -327,6 +327,14 @@ int board_early_init_f(void)
>>>>  
>>>>  int board_init(void)
>>>>  {
>>>> +#if defined(CONFIG_SPL_BUILD) && defined(ZYNQMP_LOAD_PM_CFG_OBJ)
>>>> +	extern const u32 zynqmp_pm_cfg_obj[];
>>>> +	extern const int zynqmp_pm_cfg_obj_size;
>>>
>>> please put these two to header instead.
>>
>> This was done on purpose to reduce the amount of #ifdefs, and also to
>> not pollute the namespace with two symbols that are not needed outside
>> this function. I don't see the added value of moving them in a .h, but I
>> might be wrong.
> 
> Is checkpatch ok with this? I think that it should error out that you
> shouldn't put externs to .c files.

Uhm, no, checkpatch is not ok with this. I disagree, but for sake of
peace in the world I'll move it to a .h file.

-- 
Luca

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-05-07 14:11         ` Luca Ceresoli
@ 2019-05-14 15:06           ` Luca Ceresoli
  2019-05-14 15:45             ` Michal Simek
  0 siblings, 1 reply; 13+ messages in thread
From: Luca Ceresoli @ 2019-05-14 15:06 UTC (permalink / raw)
  To: u-boot

Hi Michal, All,

On 07/05/19 16:11, Luca Ceresoli wrote:
> Hi,
> 
> On 06/05/19 17:56, Michal Simek wrote:
>> Hi,
>>
>> snip.
>>
>>>>> +$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
>>>>> +
>>>>> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ
>>>>
>>>> I am no fan of passing another object. you have
>>>> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE already and this can be used instead.
>>>
>>> Not sure I got your point here. I'm not passing an object, just setting
>>> a define (without value). This is used to enable code under #ifdef in C
>>> files.
>>
>> Sorry I meant new config option. It should be enough to use CFG_OBJ_FILE
>> everywhere and not create another config option which is just used the
>> same way.
> 
> I totally agree. But I would need to check whether
> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE is empty or not, and I don't think
> the C preprocessor can do that.

Any news on this issue? It's the only issue still open on this series,
and as said, I don't think there's a way to avoid the extra define. As
such, unless a smart solution emerges suddenly, I'm sending v4 in one or
two days with all the other issues fixed.

Thanks,
-- 
Luca

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-05-14 15:06           ` Luca Ceresoli
@ 2019-05-14 15:45             ` Michal Simek
  2019-05-15  8:19               ` Luca Ceresoli
  0 siblings, 1 reply; 13+ messages in thread
From: Michal Simek @ 2019-05-14 15:45 UTC (permalink / raw)
  To: u-boot

On 14. 05. 19 8:06, Luca Ceresoli wrote:
> Hi Michal, All,
> 
> On 07/05/19 16:11, Luca Ceresoli wrote:
>> Hi,
>>
>> On 06/05/19 17:56, Michal Simek wrote:
>>> Hi,
>>>
>>> snip.
>>>
>>>>>> +$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
>>>>>> +
>>>>>> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ
>>>>>
>>>>> I am no fan of passing another object. you have
>>>>> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE already and this can be used instead.
>>>>
>>>> Not sure I got your point here. I'm not passing an object, just setting
>>>> a define (without value). This is used to enable code under #ifdef in C
>>>> files.
>>>
>>> Sorry I meant new config option. It should be enough to use CFG_OBJ_FILE
>>> everywhere and not create another config option which is just used the
>>> same way.
>>
>> I totally agree. But I would need to check whether
>> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE is empty or not, and I don't think
>> the C preprocessor can do that.
> 
> Any news on this issue? It's the only issue still open on this series,
> and as said, I don't think there's a way to avoid the extra define. As
> such, unless a smart solution emerges suddenly, I'm sending v4 in one or
> two days with all the other issues fixed.

I didn't spend any time on this. Try to grep it. If you don't file
anything please add there TODO and let's fix it in future.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime
  2019-05-14 15:45             ` Michal Simek
@ 2019-05-15  8:19               ` Luca Ceresoli
  0 siblings, 0 replies; 13+ messages in thread
From: Luca Ceresoli @ 2019-05-15  8:19 UTC (permalink / raw)
  To: u-boot

Hi,

On 14/05/19 17:45, Michal Simek wrote:
>>>>>>> +$(obj)/pm_cfg_obj.o: $(obj)/pm_cfg_obj.bin
>>>>>>> +
>>>>>>> +CFLAGS_zynqmp.o += -DZYNQMP_LOAD_PM_CFG_OBJ
>>>>>>
>>>>>> I am no fan of passing another object. you have
>>>>>> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE already and this can be used instead.
>>>>>
>>>>> Not sure I got your point here. I'm not passing an object, just setting
>>>>> a define (without value). This is used to enable code under #ifdef in C
>>>>> files.
>>>>
>>>> Sorry I meant new config option. It should be enough to use CFG_OBJ_FILE
>>>> everywhere and not create another config option which is just used the
>>>> same way.
>>>
>>> I totally agree. But I would need to check whether
>>> CONFIG_ZYNQMP_LOAD_PM_CFG_OBJ_FILE is empty or not, and I don't think
>>> the C preprocessor can do that.
>>
>> Any news on this issue? It's the only issue still open on this series,
>> and as said, I don't think there's a way to avoid the extra define. As
>> such, unless a smart solution emerges suddenly, I'm sending v4 in one or
>> two days with all the other issues fixed.
> 
> I didn't spend any time on this. Try to grep it. If you don't file
> anything please add there TODO and let's fix it in future.

I did grep and searched, but the core problem is that the preprocessor
cannot compare strings.

But now I found a way out. Looks a bit of a hack to me, but it works,
will be in v4. If that's not OK, I'll do v5 with the current solution
and a TODO.

-- 
Luca

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-05-15  8:19 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-15 16:47 [U-Boot] [PATCH v3 0/2] arm64: zynqmp: pass a PMUFW config object Luca Ceresoli
2019-04-15 16:47 ` [U-Boot] [PATCH v3 1/2] arm64: zynqmp: spl: install a PMU firmware config object at runtime Luca Ceresoli
2019-05-03 22:38   ` Michal Simek
2019-05-04 16:54     ` Luca Ceresoli
2019-05-06 15:56       ` Michal Simek
2019-05-07 14:11         ` Luca Ceresoli
2019-05-14 15:06           ` Luca Ceresoli
2019-05-14 15:45             ` Michal Simek
2019-05-15  8:19               ` Luca Ceresoli
2019-04-15 16:47 ` [U-Boot] [PATCH v3 2/2] arm64: zynqmp: add tool to convert PMU config object .c to binary Luca Ceresoli
2019-05-03 22:31   ` Michal Simek
2019-05-04  6:14     ` Luca Ceresoli
2019-05-04 22:21       ` Michal Simek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.