[PATCH 2/3] soc: xilinx: route PMC TAP register access through firmware
Akshay Belsare <[email protected]>
| Newsgroups | org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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