All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] soc/board: decouple SoC identification reads from firmware calls
@ 2026-08-20 14:54 Akshay Belsare
  2026-08-20 14:54 ` [PATCH 1/3] soc: xilinx: decouple chip ID retrieval from direct " Akshay Belsare
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Akshay Belsare @ 2026-08-20 14:54 UTC (permalink / raw)
  To: u-boot, michal.simek; +Cc: git, padmarao.begari, Akshay Belsare

Chip ID, PMC TAP IDCODE/VERSION/USERCODE, and the PGGS boot index are
currently read either directly through MMIO or via firmware, depending
on the platform and configuration. This series introduces common helper
APIs with weak MMIO-based defaults for each platform and firmware-backed
overrides in firmware-zynqmp.c when CONFIG_ZYNQMP_FIRMWARE is enabled.
 
This removes firmware-specific conditionals from callers, centralizes
the access mechanism, and provides a consistent interface across
ZynqMP, Versal, Versal Net, and Versal Gen 2 platforms.

Akshay Belsare (3):
  soc: xilinx: decouple chip ID retrieval from direct firmware calls
  soc: xilinx: route PMC TAP register access through firmware
  board: xilinx: decouple PGGS boot index read from firmware

 arch/arm/mach-versal-net/cpu.c                | 34 ++++++++++-
 .../mach-versal-net/include/mach/sys_proto.h  |  6 ++
 arch/arm/mach-versal/cpu.c                    | 18 ++++++
 arch/arm/mach-versal/include/mach/sys_proto.h |  4 ++
 arch/arm/mach-versal2/cpu.c                   | 39 ++++++++++++-
 .../arm/mach-versal2/include/mach/sys_proto.h |  8 +++
 arch/arm/mach-zynqmp/cpu.c                    |  8 +++
 arch/arm/mach-zynqmp/include/mach/sys_proto.h |  2 +
 board/xilinx/common/board.c                   |  6 +-
 drivers/firmware/firmware-zynqmp.c            | 57 +++++++++++++++++++
 drivers/soc/soc_amd_versal2.c                 | 23 +++-----
 drivers/soc/soc_xilinx_versal.c               | 23 +++-----
 drivers/soc/soc_xilinx_versal_net.c           | 23 +++-----
 drivers/soc/soc_xilinx_zynqmp.c               | 21 +++----
 include/zynqmp_firmware.h                     |  5 +-
 15 files changed, 204 insertions(+), 73 deletions(-)

-- 
2.34.1


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

* [PATCH 1/3] soc: xilinx: decouple chip ID retrieval from direct firmware calls
  2026-08-20 14:54 [PATCH 0/3] soc/board: decouple SoC identification reads from firmware calls Akshay Belsare
@ 2026-08-20 14:54 ` Akshay Belsare
  2026-08-20 14:54 ` [PATCH 2/3] soc: xilinx: route PMC TAP register access through firmware Akshay Belsare
  2026-08-20 14:54 ` [PATCH 3/3] board: xilinx: decouple PGGS boot index read from firmware Akshay Belsare
  2 siblings, 0 replies; 4+ messages in thread
From: Akshay Belsare @ 2026-08-20 14:54 UTC (permalink / raw)
  To: u-boot, michal.simek
  Cc: git, padmarao.begari, Akshay Belsare, Tom Rini, Ilias Apalodimas,
	Simon Glass

All four Xilinx SoC drivers contain identical
IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE) conditionals to retrieve the
chip ID. Move this logic behind xilinx_pm_get_chipid(), using a
weak default implementation for each platform and a common override
in firmware-zynqmp.c.

As part of this refactoring, move the ZynqMP weak default
implementation to mach-zynqmp/cpu.c to align with the other supported
platforms. Also declare xilinx_pm_get_chipid() in sys_proto.h instead
of zynqmp_firmware.h, as the SoC drivers no longer require direct
dependencies on firmware-specific definitions.

Signed-off-by: Akshay Belsare <akshay.belsare@amd.com>
---
 arch/arm/mach-versal-net/cpu.c                | 13 +++++++++++
 .../mach-versal-net/include/mach/sys_proto.h  |  2 ++
 arch/arm/mach-versal/cpu.c                    | 13 +++++++++++
 arch/arm/mach-versal/include/mach/sys_proto.h |  2 ++
 arch/arm/mach-versal2/cpu.c                   | 13 +++++++++++
 .../arm/mach-versal2/include/mach/sys_proto.h |  2 ++
 arch/arm/mach-zynqmp/cpu.c                    |  8 +++++++
 arch/arm/mach-zynqmp/include/mach/sys_proto.h |  2 ++
 drivers/firmware/firmware-zynqmp.c            | 17 ++++++++++++++
 drivers/soc/soc_amd_versal2.c                 | 23 ++++++-------------
 drivers/soc/soc_xilinx_versal.c               | 23 ++++++-------------
 drivers/soc/soc_xilinx_versal_net.c           | 23 ++++++-------------
 drivers/soc/soc_xilinx_zynqmp.c               | 21 ++++++-----------
 13 files changed, 100 insertions(+), 62 deletions(-)

diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c
index 7df7c49ac71..54d8496a5e8 100644
--- a/arch/arm/mach-versal-net/cpu.c
+++ b/arch/arm/mach-versal-net/cpu.c
@@ -11,6 +11,7 @@
 #include <malloc.h>
 #include <time.h>
 #include <vsprintf.h>
+#include <linux/errno.h>
 #include <asm/armv8/mmu.h>
 #include <asm/cache.h>
 #include <asm/global_data.h>
@@ -237,6 +238,18 @@ bool soc_detection(void)
 	return true;
 }
 
+__weak int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
+{
+	if (idcode)
+		*idcode = 0;
+
+	*version = readl(PMC_TAP_VERSION);
+	if (!*version)
+		return -EINVAL;
+
+	return 0;
+}
+
 U_BOOT_DRVINFO(soc_xilinx_versal_net) = {
 	.name = "soc_xilinx_versal_net",
 };
diff --git a/arch/arm/mach-versal-net/include/mach/sys_proto.h b/arch/arm/mach-versal-net/include/mach/sys_proto.h
index 4907dae1108..bfe9df76b0b 100644
--- a/arch/arm/mach-versal-net/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal-net/include/mach/sys_proto.h
@@ -13,3 +13,5 @@ void versal_net_timer_setup(void);
 u8 versal_net_get_bootmode(void);
 /* Direct MMIO read of the bootmode register (EL3 / no-firmware path) */
 u32 versal_net_bootmode_reg(void);
+/* Overridable chip ID accessor: weak MMIO default, firmware override */
+int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c
index 7521d45bc1a..15b3303bd1c 100644
--- a/arch/arm/mach-versal/cpu.c
+++ b/arch/arm/mach-versal/cpu.c
@@ -9,6 +9,7 @@
 #include <init.h>
 #include <log.h>
 #include <time.h>
+#include <linux/errno.h>
 #include <asm/armv8/mmu.h>
 #include <asm/cache.h>
 #include <asm/global_data.h>
@@ -178,6 +179,18 @@ u8 __weak versal_get_bootmode(void)
 	return reg & BOOT_MODES_MASK;
 }
 
+__weak int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
+{
+	if (idcode)
+		*idcode = 0;
+
+	*version = readl(VERSAL_PS_PMC_VERSION);
+	if (!*version)
+		return -EINVAL;
+
+	return 0;
+}
+
 U_BOOT_DRVINFO(soc_xilinx_versal) = {
 	.name = "soc_xilinx_versal",
 };
diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h
index cb373e6fad9..bff4659eb8f 100644
--- a/arch/arm/mach-versal/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal/include/mach/sys_proto.h
@@ -27,5 +27,7 @@ u8 versal_get_bootmode(void);
 u32 versal_bootmode_reg(void);
 /* EL3 clock/timer register setup, called from board_early_init_r() */
 void versal_timer_setup(void);
+/* Overridable chip ID accessor: weak MMIO default, firmware override */
+int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
 
 #endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index d72f66f4fba..fc7cdbaaa65 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -12,6 +12,7 @@
 #include <time.h>
 #include <vsprintf.h>
 #include <wait_bit.h>
+#include <linux/errno.h>
 #include <asm/armv8/mmu.h>
 #include <asm/cache.h>
 #include <asm/global_data.h>
@@ -310,6 +311,18 @@ bool soc_detection(void)
 	return true;
 }
 
+__weak int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
+{
+	if (idcode)
+		*idcode = 0;
+
+	*version = readl(PMC_TAP_VERSION);
+	if (!*version)
+		return -EINVAL;
+
+	return 0;
+}
+
 U_BOOT_DRVINFO(soc_amd_versal2) = {
 	.name = "soc_amd_versal2",
 };
diff --git a/arch/arm/mach-versal2/include/mach/sys_proto.h b/arch/arm/mach-versal2/include/mach/sys_proto.h
index d678adf9c26..1a23f8dd425 100644
--- a/arch/arm/mach-versal2/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal2/include/mach/sys_proto.h
@@ -21,6 +21,8 @@ u32 versal2_multi_boot_reg(void);
 u8 versal2_get_bootmode(void);
 /* EL3 clock/timer register setup, called from board_early_init_r() */
 void versal2_timer_setup(void);
+/* Overridable chip ID accessor: weak MMIO default, firmware override */
+int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
 
 int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us);
 int zynqmp_pm_wait_sram_init_done(u32 timeout_us);
diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c
index 088cc962189..c7328970fe5 100644
--- a/arch/arm/mach-zynqmp/cpu.c
+++ b/arch/arm/mach-zynqmp/cpu.c
@@ -214,6 +214,14 @@ int __weak zynqmp_mmio_read(const u32 address, u32 *value)
 	return -EINVAL;
 }
 
+__weak int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
+{
+	if (idcode)
+		*idcode = 0;
+
+	return zynqmp_mmio_read(ZYNQMP_PS_VERSION, version);
+}
+
 void zynqmp_timer_setup(void)
 {
 	u32 val;
diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
index d2bb10ffcbb..e791c2da74f 100644
--- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h
@@ -59,5 +59,7 @@ void zynqmp_timer_setup(void);
 /* Direct MMIO accessors (EL3/SPL or no-firmware path) */
 int zynqmp_mmio_rawread(const u32 address, u32 *value);
 int zynqmp_mmio_rawwrite(const u32 address, const u32 mask, const u32 value);
+/* Overridable chip ID accessor: weak MMIO default, firmware override */
+int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
 
 #endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index fae66ccb3d8..ad759849fe4 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -175,6 +175,23 @@ unsigned int zynqmp_firmware_version(void)
 	return pm_api_version;
 };
 
+int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, 0, 0, ret_payload);
+	if (ret)
+		return ret;
+
+	if (idcode)
+		*idcode = ret_payload[1];
+	if (version)
+		*version = ret_payload[2];
+
+	return 0;
+}
+
 #if defined(CONFIG_ARCH_VERSAL2)
 /*
  * Poll the M-PHY TX/RX config-ready status until it settles or @timeout_us
diff --git a/drivers/soc/soc_amd_versal2.c b/drivers/soc/soc_amd_versal2.c
index 7f06c1e70bc..d31c6deec45 100644
--- a/drivers/soc/soc_amd_versal2.c
+++ b/drivers/soc/soc_amd_versal2.c
@@ -7,9 +7,8 @@
 
 #include <dm.h>
 #include <soc.h>
-#include <zynqmp_firmware.h>
-#include <asm/io.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 
 #include <linux/bitfield.h>
 
@@ -48,23 +47,15 @@ static const struct soc_ops soc_amd_versal2_ops = {
 static int soc_amd_versal2_probe(struct udevice *dev)
 {
 	struct soc_amd_versal2_priv *priv = dev_get_priv(dev);
-	u32 ret_payload[PAYLOAD_ARG_CNT];
+	u32 version;
 	int ret;
 
-	priv->family = versal2_family;
-
-	if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
-		ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
-					0, 0, ret_payload);
-		if (ret)
-			return ret;
-	} else {
-		ret_payload[2] = readl(PMC_TAP_VERSION);
-		if (!ret_payload[2])
-			return -EINVAL;
-	}
+	ret = xilinx_pm_get_chipid(NULL, &version);
+	if (ret)
+		return ret;
 
-	priv->revision = FIELD_GET(PS_VERSION_MASK, ret_payload[2]);
+	priv->family = versal2_family;
+	priv->revision = FIELD_GET(PS_VERSION_MASK, version);
 
 	return 0;
 }
diff --git a/drivers/soc/soc_xilinx_versal.c b/drivers/soc/soc_xilinx_versal.c
index c43a80df1fc..ff6eb873d8a 100644
--- a/drivers/soc/soc_xilinx_versal.c
+++ b/drivers/soc/soc_xilinx_versal.c
@@ -7,9 +7,8 @@
 
 #include <dm.h>
 #include <soc.h>
-#include <zynqmp_firmware.h>
-#include <asm/io.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 
 /*
  * v1 -> 0x10 - ES1
@@ -44,23 +43,15 @@ static const struct soc_ops soc_xilinx_versal_ops = {
 static int soc_xilinx_versal_probe(struct udevice *dev)
 {
 	struct soc_xilinx_versal_priv *priv = dev_get_priv(dev);
-	u32 ret_payload[PAYLOAD_ARG_CNT];
+	u32 version;
 	int ret;
 
-	priv->family = versal_family;
-
-	if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
-		ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
-					0, 0, ret_payload);
-		if (ret)
-			return ret;
-	} else {
-		ret_payload[2] = readl(VERSAL_PS_PMC_VERSION);
-		if (!ret_payload[2])
-			return -EINVAL;
-	}
+	ret = xilinx_pm_get_chipid(NULL, &version);
+	if (ret)
+		return ret;
 
-	priv->revision = ret_payload[2] >> VERSAL_PS_VER_SHIFT;
+	priv->family = versal_family;
+	priv->revision = version >> VERSAL_PS_VER_SHIFT;
 
 	return 0;
 }
diff --git a/drivers/soc/soc_xilinx_versal_net.c b/drivers/soc/soc_xilinx_versal_net.c
index 210f9f8f8fd..3218cc416f7 100644
--- a/drivers/soc/soc_xilinx_versal_net.c
+++ b/drivers/soc/soc_xilinx_versal_net.c
@@ -7,9 +7,8 @@
 
 #include <dm.h>
 #include <soc.h>
-#include <zynqmp_firmware.h>
-#include <asm/io.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 
 #include <linux/bitfield.h>
 
@@ -46,23 +45,15 @@ static const struct soc_ops soc_xilinx_versal_net_ops = {
 static int soc_xilinx_versal_net_probe(struct udevice *dev)
 {
 	struct soc_xilinx_versal_net_priv *priv = dev_get_priv(dev);
-	u32 ret_payload[PAYLOAD_ARG_CNT];
+	u32 version;
 	int ret;
 
-	priv->family = versal_family;
-
-	if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
-		ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
-					0, 0, ret_payload);
-		if (ret)
-			return ret;
-	} else {
-		ret_payload[2] = readl(PMC_TAP_VERSION);
-		if (!ret_payload[2])
-			return -EINVAL;
-	}
+	ret = xilinx_pm_get_chipid(NULL, &version);
+	if (ret)
+		return ret;
 
-	priv->revision = FIELD_GET(PS_VERSION_MASK, ret_payload[2]);
+	priv->family = versal_family;
+	priv->revision = FIELD_GET(PS_VERSION_MASK, version);
 
 	return 0;
 }
diff --git a/drivers/soc/soc_xilinx_zynqmp.c b/drivers/soc/soc_xilinx_zynqmp.c
index 0e13e230914..1dc0b05a1a3 100644
--- a/drivers/soc/soc_xilinx_zynqmp.c
+++ b/drivers/soc/soc_xilinx_zynqmp.c
@@ -13,7 +13,6 @@
 #include <dm/device_compat.h>
 #include <asm/cache.h>
 #include <soc.h>
-#include <zynqmp_firmware.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/hardware.h>
 
@@ -400,22 +399,17 @@ static const struct soc_ops soc_xilinx_zynqmp_ops = {
 static int soc_xilinx_zynqmp_probe(struct udevice *dev)
 {
 	struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
-	u32 ret_payload[PAYLOAD_ARG_CNT];
+	u32 idcode = 0, version;
 	int ret;
 
-	priv->family = zynqmp_family;
-
-	if (!IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
-		ret = zynqmp_mmio_read(ZYNQMP_PS_VERSION, &ret_payload[2]);
-	else
-		ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
-					0, 0, ret_payload);
+	ret = xilinx_pm_get_chipid(&idcode, &version);
 	if (ret < 0)
 		return ret;
 
-	priv->revision = ret_payload[2] & ZYNQMP_PS_VER_MASK;
+	priv->family = zynqmp_family;
+	priv->revision = version & ZYNQMP_PS_VER_MASK;
 
-	if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
+	if (idcode) {
 		/*
 		 * Firmware returns:
 		 * payload[0][31:0] = status of the operation
@@ -424,9 +418,8 @@ static int soc_xilinx_zynqmp_probe(struct udevice *dev)
 		 * payload[2][28:20] = EXTENDED_IDCODE
 		 * payload[2][29] = PL_INIT
 		 */
-		u32 idcode = ret_payload[1];
-		u32 idcode2 = ret_payload[2] >>
-				   ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
+		u32 idcode2 = version >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
+
 		dev_dbg(dev, "IDCODE: 0x%0x, IDCODE2: 0x%0x\n", idcode,
 			idcode2);
 
-- 
2.34.1


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

* [PATCH 2/3] soc: xilinx: route PMC TAP register access through firmware
  2026-08-20 14:54 [PATCH 0/3] soc/board: decouple SoC identification reads from firmware calls Akshay Belsare
  2026-08-20 14:54 ` [PATCH 1/3] soc: xilinx: decouple chip ID retrieval from direct " Akshay Belsare
@ 2026-08-20 14:54 ` Akshay Belsare
  2026-08-20 14:54 ` [PATCH 3/3] board: xilinx: decouple PGGS boot index read from firmware Akshay Belsare
  2 siblings, 0 replies; 4+ messages in thread
From: Akshay Belsare @ 2026-08-20 14:54 UTC (permalink / raw)
  To: u-boot, michal.simek
  Cc: git, padmarao.begari, Akshay Belsare, Tom Rini, Ilias Apalodimas

The Versal Net and Versal Gen 2 implementations of soc_detection()
currently access the PMC TAP IDCODE, VERSION, and USERCODE registers
directly without any firmware abstraction.
 
Introduce dedicated helpers for each register access:
zynqmp_pm_get_pmc_tap_idcode(),
zynqmp_pm_get_pmc_tap_version(), and
zynqmp_pm_get_pmc_tap_usercode().
 
Implement these helpers as weak platform defaults, with a common
firmware-backed override in firmware-zynqmp.c. The firmware
implementation accesses the registers through IOCTL_READ_REG using the
new PM_REGNODE_PMC_TAP register node, following the same mechanism used
by zynqmp_pm_get_pmc_multi_boot_reg() for PMC_GLOBAL register access.
 
This change removes direct PMC TAP register accesses from the SoC
detection path and provides a consistent firmware abstraction across
supported platforms.

Signed-off-by: Akshay Belsare <akshay.belsare@amd.com>
---
 arch/arm/mach-versal-net/cpu.c                | 21 ++++++++--
 .../mach-versal-net/include/mach/sys_proto.h  |  4 ++
 arch/arm/mach-versal2/cpu.c                   | 21 ++++++++--
 .../arm/mach-versal2/include/mach/sys_proto.h |  4 ++
 drivers/firmware/firmware-zynqmp.c            | 40 +++++++++++++++++++
 include/zynqmp_firmware.h                     |  4 ++
 6 files changed, 88 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c
index 54d8496a5e8..5ba2295e4f8 100644
--- a/arch/arm/mach-versal-net/cpu.c
+++ b/arch/arm/mach-versal-net/cpu.c
@@ -193,13 +193,13 @@ bool soc_detection(void)
 {
 	u32 version, ps_version;
 
-	version = readl(PMC_TAP_VERSION);
+	version = zynqmp_pm_get_pmc_tap_version();
 	platform_id = FIELD_GET(PLATFORM_MASK, version);
 	ps_version = FIELD_GET(PS_VERSION_MASK, version);
 
 	debug("idcode %x, version %x, usercode %x\n",
-	      readl(PMC_TAP_IDCODE), version,
-	      readl(PMC_TAP_USERCODE));
+	      zynqmp_pm_get_pmc_tap_idcode(), version,
+	      zynqmp_pm_get_pmc_tap_usercode());
 
 	debug("pmc_ver %lx, ps version %x, rtl version %lx\n",
 	      FIELD_GET(PMC_VERSION_MASK, version),
@@ -250,6 +250,21 @@ __weak int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
 	return 0;
 }
 
+__weak u32 zynqmp_pm_get_pmc_tap_idcode(void)
+{
+	return readl(PMC_TAP_IDCODE);
+}
+
+__weak u32 zynqmp_pm_get_pmc_tap_version(void)
+{
+	return readl(PMC_TAP_VERSION);
+}
+
+__weak u32 zynqmp_pm_get_pmc_tap_usercode(void)
+{
+	return readl(PMC_TAP_USERCODE);
+}
+
 U_BOOT_DRVINFO(soc_xilinx_versal_net) = {
 	.name = "soc_xilinx_versal_net",
 };
diff --git a/arch/arm/mach-versal-net/include/mach/sys_proto.h b/arch/arm/mach-versal-net/include/mach/sys_proto.h
index bfe9df76b0b..877a7e6a0c3 100644
--- a/arch/arm/mach-versal-net/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal-net/include/mach/sys_proto.h
@@ -15,3 +15,7 @@ u8 versal_net_get_bootmode(void);
 u32 versal_net_bootmode_reg(void);
 /* Overridable chip ID accessor: weak MMIO default, firmware override */
 int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
+/* Overridable PMC TAP register accessors: weak MMIO default, firmware override */
+u32 zynqmp_pm_get_pmc_tap_idcode(void);
+u32 zynqmp_pm_get_pmc_tap_version(void);
+u32 zynqmp_pm_get_pmc_tap_usercode(void);
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index fc7cdbaaa65..24a02c38462 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -290,13 +290,13 @@ bool soc_detection(void)
 {
 	u32 version, ps_version;
 
-	version = readl(PMC_TAP_VERSION);
+	version = zynqmp_pm_get_pmc_tap_version();
 	platform_id = FIELD_GET(PLATFORM_MASK, version);
 	ps_version = FIELD_GET(PS_VERSION_MASK, version);
 
 	debug("idcode %x, version %x, usercode %x\n",
-	      readl(PMC_TAP_IDCODE), version,
-	      readl(PMC_TAP_USERCODE));
+	      zynqmp_pm_get_pmc_tap_idcode(), version,
+	      zynqmp_pm_get_pmc_tap_usercode());
 
 	debug("pmc_ver %lx, ps version %x, rtl version %lx\n",
 	      FIELD_GET(PMC_VERSION_MASK, version),
@@ -323,6 +323,21 @@ __weak int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
 	return 0;
 }
 
+__weak u32 zynqmp_pm_get_pmc_tap_idcode(void)
+{
+	return readl(PMC_TAP_IDCODE);
+}
+
+__weak u32 zynqmp_pm_get_pmc_tap_version(void)
+{
+	return readl(PMC_TAP_VERSION);
+}
+
+__weak u32 zynqmp_pm_get_pmc_tap_usercode(void)
+{
+	return readl(PMC_TAP_USERCODE);
+}
+
 U_BOOT_DRVINFO(soc_amd_versal2) = {
 	.name = "soc_amd_versal2",
 };
diff --git a/arch/arm/mach-versal2/include/mach/sys_proto.h b/arch/arm/mach-versal2/include/mach/sys_proto.h
index 1a23f8dd425..fcc2e75c89a 100644
--- a/arch/arm/mach-versal2/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal2/include/mach/sys_proto.h
@@ -23,6 +23,10 @@ u8 versal2_get_bootmode(void);
 void versal2_timer_setup(void);
 /* Overridable chip ID accessor: weak MMIO default, firmware override */
 int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
+/* Overridable PMC TAP register accessors: weak MMIO default, firmware override */
+u32 zynqmp_pm_get_pmc_tap_idcode(void);
+u32 zynqmp_pm_get_pmc_tap_version(void);
+u32 zynqmp_pm_get_pmc_tap_usercode(void);
 
 int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us);
 int zynqmp_pm_wait_sram_init_done(u32 timeout_us);
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index ad759849fe4..7a922fe544b 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -510,6 +510,46 @@ u32 versal2_pmc_multi_boot(void)
 }
 #endif
 
+#if defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2)
+static u32 zynqmp_pm_get_pmc_tap_reg(u32 offset)
+{
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+
+	ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_REG);
+	if (ret) {
+		printf("%s: IOCTL_READ_REG is not supported failed with error code: %d\n"
+		       , __func__, ret);
+		return 0;
+	}
+
+	ret = xilinx_pm_request(PM_IOCTL, PM_REGNODE_PMC_TAP, IOCTL_READ_REG,
+				offset, 0, 0, 0, ret_payload);
+	if (ret) {
+		printf("%s: node 0x%x: pmc_tap offset 0x%x failed\n",
+		       __func__, PM_REGNODE_PMC_TAP, offset);
+		return 0;
+	}
+
+	return ret_payload[1];
+}
+
+u32 zynqmp_pm_get_pmc_tap_idcode(void)
+{
+	return zynqmp_pm_get_pmc_tap_reg(PMC_TAP_IDCODE_OFFSET);
+}
+
+u32 zynqmp_pm_get_pmc_tap_version(void)
+{
+	return zynqmp_pm_get_pmc_tap_reg(PMC_TAP_VERSION_OFFSET);
+}
+
+u32 zynqmp_pm_get_pmc_tap_usercode(void)
+{
+	return zynqmp_pm_get_pmc_tap_reg(PMC_TAP_USERCODE_OFFSET);
+}
+#endif
+
 int zynqmp_pm_feature(const u32 api_id)
 {
 	int ret;
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index f753a67ac27..0293bd15a2e 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -533,11 +533,15 @@ extern smc_call_handler_t __data smc_call_handler;
 
 #define PM_REGNODE_PMC_IOU_SLCR		0x30000002
 #define PM_REGNODE_EFUSE_CACHE		0x30000003
+#define PM_REGNODE_PMC_TAP		0x30000005
 #define PM_REG_PGGS3			0x30004003
 
 #define SRAM_CSR_OFFSET			0x104C
 #define TXRX_CFGRDY_OFFSET		0x1054
 #define UFS_CAL_1_OFFSET		0xBE8
+#define PMC_TAP_IDCODE_OFFSET		0x0
+#define PMC_TAP_VERSION_OFFSET		0x4
+#define PMC_TAP_USERCODE_OFFSET	0x8
 
 #define PMC_GLOBAL_PGGS3_REG_NODE	0x1824C005
 
-- 
2.34.1


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

* [PATCH 3/3] board: xilinx: decouple PGGS boot index read from firmware
  2026-08-20 14:54 [PATCH 0/3] soc/board: decouple SoC identification reads from firmware calls Akshay Belsare
  2026-08-20 14:54 ` [PATCH 1/3] soc: xilinx: decouple chip ID retrieval from direct " Akshay Belsare
  2026-08-20 14:54 ` [PATCH 2/3] soc: xilinx: route PMC TAP register access through firmware Akshay Belsare
@ 2026-08-20 14:54 ` Akshay Belsare
  2 siblings, 0 replies; 4+ messages in thread
From: Akshay Belsare @ 2026-08-20 14:54 UTC (permalink / raw)
  To: u-boot, michal.simek
  Cc: git, padmarao.begari, Akshay Belsare, Tom Rini, Ilias Apalodimas

Move PGGS boot index retrieval behind a platform-specific helper
instead of selecting between firmware and direct register access in
plat_get_boot_index().
 
Add weak default implementations for Versal and Versal Gen 2, and cast
the register address to (ulong) before readl() to ensure correct
handling on 64-bit targets.

Signed-off-by: Akshay Belsare <akshay.belsare@amd.com>
---
 arch/arm/mach-versal/cpu.c                     | 5 +++++
 arch/arm/mach-versal/include/mach/sys_proto.h  | 2 ++
 arch/arm/mach-versal2/cpu.c                    | 5 +++++
 arch/arm/mach-versal2/include/mach/sys_proto.h | 2 ++
 board/xilinx/common/board.c                    | 6 ++----
 include/zynqmp_firmware.h                      | 1 -
 6 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c
index 15b3303bd1c..a4ee51ef0d6 100644
--- a/arch/arm/mach-versal/cpu.c
+++ b/arch/arm/mach-versal/cpu.c
@@ -191,6 +191,11 @@ __weak int xilinx_pm_get_chipid(u32 *idcode, u32 *version)
 	return 0;
 }
 
+__weak u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr)
+{
+	return readl((ulong)reg_addr);
+}
+
 U_BOOT_DRVINFO(soc_xilinx_versal) = {
 	.name = "soc_xilinx_versal",
 };
diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h
index bff4659eb8f..771b8cd8cbc 100644
--- a/arch/arm/mach-versal/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal/include/mach/sys_proto.h
@@ -29,5 +29,7 @@ u32 versal_bootmode_reg(void);
 void versal_timer_setup(void);
 /* Overridable chip ID accessor: weak MMIO default, firmware override */
 int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
+/* Overridable PMC GLOBAL PGGS register accessor: weak MMIO default, firmware override */
+u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr);
 
 #endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index 24a02c38462..404250f2d44 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -338,6 +338,11 @@ __weak u32 zynqmp_pm_get_pmc_tap_usercode(void)
 	return readl(PMC_TAP_USERCODE);
 }
 
+__weak u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr)
+{
+	return readl((ulong)reg_addr);
+}
+
 U_BOOT_DRVINFO(soc_amd_versal2) = {
 	.name = "soc_amd_versal2",
 };
diff --git a/arch/arm/mach-versal2/include/mach/sys_proto.h b/arch/arm/mach-versal2/include/mach/sys_proto.h
index fcc2e75c89a..64626bac24e 100644
--- a/arch/arm/mach-versal2/include/mach/sys_proto.h
+++ b/arch/arm/mach-versal2/include/mach/sys_proto.h
@@ -27,6 +27,8 @@ int xilinx_pm_get_chipid(u32 *idcode, u32 *version);
 u32 zynqmp_pm_get_pmc_tap_idcode(void);
 u32 zynqmp_pm_get_pmc_tap_version(void);
 u32 zynqmp_pm_get_pmc_tap_usercode(void);
+/* Overridable PMC GLOBAL PGGS register accessor: weak MMIO default, firmware override */
+u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr);
 
 int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us);
 int zynqmp_pm_wait_sram_init_done(u32 timeout_us);
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index f45b879736e..ac309ae7336 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -21,6 +21,7 @@
 #include <asm/sections.h>
 #if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL2)
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 #endif
 #include <dm/uclass.h>
 #include <i2c.h>
@@ -752,10 +753,7 @@ static int plat_get_boot_index(void)
 {
 	u32 val;
 
-	if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
-		val = zynqmp_pm_get_pmc_global_pggs_reg(PMC_GLOBAL_PGGS4_REG);
-	else
-		val = readl(PMC_GLOBAL_PGGS4_REG);
+	val = zynqmp_pm_get_pmc_global_pggs_reg(PMC_GLOBAL_PGGS4_REG);
 
 	if (FIELD_GET(MAGIC_MASK, val) != MAGIC_NUM) {
 		log_err("FWU requires PMC magic number 0x%x\n", MAGIC_NUM);
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index 0293bd15a2e..a60d33b02ab 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -466,7 +466,6 @@ int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value);
 int zynqmp_pm_feature(const u32 api_id);
 u32 zynqmp_pm_get_bootmode_reg(void);
 u32 zynqmp_pm_get_pmc_multi_boot_reg(void);
-u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr);
 
 /* Type of Config Object */
 #define PM_CONFIG_OBJECT_TYPE_BASE	0x1U
-- 
2.34.1


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

end of thread, other threads:[~2026-08-20 15:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 14:54 [PATCH 0/3] soc/board: decouple SoC identification reads from firmware calls Akshay Belsare
2026-08-20 14:54 ` [PATCH 1/3] soc: xilinx: decouple chip ID retrieval from direct " Akshay Belsare
2026-08-20 14:54 ` [PATCH 2/3] soc: xilinx: route PMC TAP register access through firmware Akshay Belsare
2026-08-20 14:54 ` [PATCH 3/3] board: xilinx: decouple PGGS boot index read from firmware Akshay Belsare

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.