[PATCH 2/7] firmware: zynqmp: Add PMC PGGS register read API

Padmarao Begari padmarao.begari at amd.com
Thu May 14 12:22:19 CEST 2026


Add zynqmp_pm_get_pmc_global_pggs_reg() to read PMC Global PGGS3
and PGGS4 registers via firmware IOCTL. Supports IOCTL_READ_PGGS
as the preferred path and falls back to IOCTL_READ_REG for older
PLM firmware versions that do not support IOCTL_READ_PGGS.

Signed-off-by: Padmarao Begari <padmarao.begari at amd.com>
---
 drivers/firmware/firmware-zynqmp.c | 54 +++++++++++++++++++++++++++++-
 include/zynqmp_firmware.h          |  4 +++
 2 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index fb583580ebe..ea14ed4ef95 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -3,7 +3,7 @@
  * Xilinx Zynq MPSoC Firmware driver
  *
  * Copyright (C) 2018-2019 Xilinx, Inc.
- * Copyright (C) 2022 - 2025, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022 - 2026, Advanced Micro Devices, Inc.
  */
 
 #include <asm/arch/hardware.h>
@@ -197,6 +197,58 @@ int zynqmp_pm_ufs_cal_reg(u32 *value)
 	*value = readl(PMXC_EFUSE_CACHE_BASE_ADDRESS + PMXC_UFS_CAL_1_OFFSET);
 	return 0;
 }
+#endif /* CONFIG_ARCH_VERSAL2 */
+
+#if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL2)
+u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr)
+{
+	int ret;
+	u32 value = 0;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+
+	if (reg_addr == PMC_GLOBAL_PGGS3_REG) {
+		value = 0;
+	} else if (reg_addr == PMC_GLOBAL_PGGS4_REG) {
+		value = 1;
+	} else {
+		printf("%s: not supported pggs register 0x%x\n",
+		       __func__, reg_addr);
+		return 0;
+	}
+
+	ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_PGGS);
+	if (ret) {
+		ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_REG);
+		if (ret) {
+			printf("%s: IOCTL_READ_REG is not supported : %d\n"
+				, __func__, ret);
+			return 0;
+		}
+
+		/* find node ID from the pggs3 offset */
+		value = PM_REG_PGGS3 + value;
+
+		ret = xilinx_pm_request(PM_IOCTL, value,
+					IOCTL_READ_REG, 0, 0, 0, 0,
+					ret_payload);
+		if (ret) {
+			printf("%s: node 0x%x get pggs register failed\n",
+			       __func__, value);
+			return 0;
+		}
+	} else {
+		ret = xilinx_pm_request(PM_IOCTL, PMC_GLOBAL_PGGS3_REG_NODE,
+					IOCTL_READ_PGGS, value, 0, 0, 0,
+					ret_payload);
+		if (ret) {
+			printf("%s: node 0x%x get pggs register failed\n",
+			       __func__, PMC_GLOBAL_PGGS3_REG_NODE);
+			return 0;
+		}
+	}
+
+	return ret_payload[1];
+}
 #endif
 
 int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value)
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index f5e72625e53..0e545e3db1b 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -470,6 +470,7 @@ int zynqmp_pm_ufs_sram_csr_read(u32 *value);
 int zynqmp_pm_ufs_sram_csr_write(u32 *value);
 int zynqmp_pm_ufs_cal_reg(u32 *value);
 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
@@ -534,4 +535,7 @@ extern smc_call_handler_t __data smc_call_handler;
 
 #define PM_DEV_OSPI		(0x1822402aU)
 
+#define PM_REG_PGGS3	0x30004003
+#define PMC_GLOBAL_PGGS3_REG_NODE	0x1824C005
+
 #endif /* _ZYNQMP_FIRMWARE_H_ */
-- 
2.34.1



More information about the U-Boot mailing list