From e93e5ac0719cd31e7e78e590e76b7be88519716a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 4 Aug 2026 17:02:31 +0200 Subject: firmware: xilinx: ufs: move PHY/SRAM ready polling into the firmware backend The Versal Gen 2 UFS driver polls the firmware for M-PHY TX/RX configuration readiness and SRAM initialisation completion with two open-coded do/while loops. Each iteration is a full firmware round-trip (PM_IOCTL/IOCTL_READ_REG of a protected PMC_IOU_SLCR register), so the loop can issue up to a million EEMI calls, and it hard-codes the wait policy inside the controller driver. Introduce coarse blocking helpers, zynqmp_pm_wait_mphy_tx_rx_config_ready() and zynqmp_pm_wait_sram_init_done(), that take a caller-supplied timeout budget and contain the poll loop. The loop is EEMI-specific (legacy firmware only exposes the per-read status primitive) so it lives in the firmware driver, keeping the UFS driver backend-agnostic: a future backend can offload the wait to the platform in a single call without touching the controller driver again. The existing per-read primitives stay exported, so the current EEMI interface is unchanged. The timeout budget remains owned by the UFS driver (the consumer that knows the hardware) and is passed down, so EEMI and any future backend stay consistent. Reviewed-by: Sai Krishna Potthuri Link: https://patch.msgid.link/eaeaaea8ed76069943e0706a0917139ff6569929.1785855749.git.michal.simek@amd.com Signed-off-by: Michal Simek --- include/linux/firmware/xlnx-zynqmp-ufs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/firmware/xlnx-zynqmp-ufs.h b/include/linux/firmware/xlnx-zynqmp-ufs.h index d3538dd5822a..00383dd835f2 100644 --- a/include/linux/firmware/xlnx-zynqmp-ufs.h +++ b/include/linux/firmware/xlnx-zynqmp-ufs.h @@ -9,17 +9,17 @@ #define __FIRMWARE_XLNX_ZYNQMP_UFS_H__ #if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE) -int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready); -int zynqmp_pm_is_sram_init_done(bool *is_done); +int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us); +int zynqmp_pm_wait_sram_init_done(u32 timeout_us); int zynqmp_pm_set_sram_bypass(void); int zynqmp_pm_get_ufs_calibration_values(u32 *val); #else -static inline int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready) +static inline int zynqmp_pm_wait_mphy_tx_rx_config_ready(u32 timeout_us) { return -ENODEV; } -static inline int zynqmp_pm_is_sram_init_done(bool *is_done) +static inline int zynqmp_pm_wait_sram_init_done(u32 timeout_us) { return -ENODEV; } -- cgit v1.2.3 From 118be086595e8f98b19e8fa8e24276466a8e9483 Mon Sep 17 00:00:00 2001 From: Tanmay Shah Date: Mon, 3 Aug 2026 13:05:02 -0700 Subject: firmware: xilinx: support RPU boot from DDR Cortex-R52 cores can boot from DDR. In such case, elf's boot address will be in the ddr, and it should be passed to the PLM via EEMI call. Add ddr boot config EEMI call before starting RPU to configure the boot address. Also make sure TCM-Boot is support for old platforms as well. Remove HIVEC & LOVEC enum, as now PLM supports boot address directly. Signed-off-by: Tanmay Shah Link: https://patch.msgid.link/20260803200502.209361-1-tanmay.shah@amd.com Signed-off-by: Michal Simek --- drivers/firmware/xilinx/zynqmp.c | 44 +++++++++++++++++++++++++++++++----- include/linux/firmware/xlnx-zynqmp.h | 5 ---- 2 files changed, 38 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index fe650747ac91..d76660c55354 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -1527,7 +1527,6 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake); */ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) { - enum rpu_boot_mem bootmem; int ret; /* @@ -1536,22 +1535,55 @@ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) * starts at the base-address and subsequent vectors are on 4-byte * boundaries. * + * The Cortex-R5 cores can boot from TCM and OCM memories. * Exception vectors can start either from 0x0000_0000 (LOVEC) or * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory) * * Usually firmware will put Exception vectors at LOVEC. * + * The Cortex-R52 cores can boot from DDR and TCM. + * That means vector table can be at address 0x0 or at any DDR address + * that is in the 32-bit address range. Note that booting from DDR + * address 0x0 is not supported and the user must always assume that if + * 0x0 address is passed, then it will be TCM boot. + * * It is not recommend that you change the exception vector. * Changing the EVP to HIVEC will result in increased interrupt latency * and jitter. Also, if the OCM is secured and the Cortex-R5F processor * is non-secured, then the Cortex-R5F processor cannot access the * HIVEC exception vectors in the OCM. */ - bootmem = (bootaddr >= 0xFFFC0000) ? - PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC; + if (upper_32_bits(bootaddr)) { + pr_err("invalid bootaddr = 0x%llx\n", bootaddr); + return -EINVAL; + } - pr_debug("RPU boot addr 0x%llx from %s.", bootaddr, - bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM"); + /* + * New platforms can boot from DDR and require the DDR address + * to be configured explicitly. If the correct version of the + * IOCTL_RPU_BOOT_ADDR_CONFIG ioctl is not supported, do not + * treat it as a failure. If a DDR address is passed on other + * platforms, the PM request wake EEMI call will still fail and + * the RPU won't boot. + */ + ret = zynqmp_pm_is_function_supported(PM_IOCTL, + IOCTL_RPU_BOOT_ADDR_CONFIG); + if (!ret) { + /* config ddr boot address */ + ret = zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, + node, + IOCTL_RPU_BOOT_ADDR_CONFIG, + bootaddr); + if (ret < 0) { + pr_err("failed to set RPU Boot address 0x%llx\n", + bootaddr); + return ret; + } + } else if (ret != -EOPNOTSUPP && ret != -ENODATA) { + pr_err("ioctl rpu boot addr config ver check failed %d\n", + ret); + return ret; + } /* Request node before starting RPU core if new version of API is supported */ if (zynqmp_pm_feature(PM_REQUEST_NODE) > PM_API_VERSION_1) { @@ -1565,7 +1597,7 @@ int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) } ret = zynqmp_pm_request_wake(node, true, - bootmem, ZYNQMP_PM_REQUEST_ACK_NO); + bootaddr, ZYNQMP_PM_REQUEST_ACK_NO); if (ret) pr_err("failed to start RPU = 0x%x\n", node); return ret; diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index f4b3df614c77..41a1cd810bda 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -277,11 +277,6 @@ enum rpu_oper_mode { PM_RPU_MODE_SPLIT = 1, }; -enum rpu_boot_mem { - PM_RPU_BOOTMEM_LOVEC = 0, - PM_RPU_BOOTMEM_HIVEC = 1, -}; - enum rpu_tcm_comb { PM_RPU_TCM_SPLIT = 0, PM_RPU_TCM_COMB = 1, -- cgit v1.2.3