cadence_qspi_flash_reset() currently performs the OSPI flash GPIO reset sequence by directly accessing PLM/PSM-protected registers, bypassing the firmware interface.
Add zynqmp_pm_ospi_flash_reset() as a firmware abstraction, backed by zynqmp_pm_ospi_flash_reset_raw() (the same register sequence, added here as a weak default for Versal, Versal Net and Versal Gen 2) which the next patch switches cadence_qspi_flash_reset() to use. The firmware-backed override falls back to the raw sequence at EL3/SPL, where SMC is unavailable, matching zynqmp_mmio_read()/write(). CONFIG_CADENCE_OSPI_VERSAL covers Versal, Versal Net and Versal Gen 2 alike, so the wrapper needs a Gen 2 weak default too for amd_versal2_mini_ospi_defconfig to link. Versal Gen 2's actual flash reset still goes through cadence_device_reset() (see cadence_qspi.c's dispatcher) and never calls this wrapper at runtime - this addition resolves the build symbol only, with no functional Gen 2 coverage. zynqmp_pm_ospi_flash_reset() only calls zynqmp_pm_ospi_flash_reset_raw() or xilinx_pm_request(), neither needing CONFIG_ZYNQMP_IPI, so it lives outside that guard, like the other wrapper functions above it. Signed-off-by: Akshay Belsare <[email protected]> --- arch/arm/mach-versal-net/cpu.c | 51 +++++++++++++++++++ .../mach-versal-net/include/mach/sys_proto.h | 6 +++ arch/arm/mach-versal/cpu.c | 51 +++++++++++++++++++ arch/arm/mach-versal/include/mach/sys_proto.h | 6 +++ arch/arm/mach-versal2/cpu.c | 51 +++++++++++++++++++ .../arm/mach-versal2/include/mach/sys_proto.h | 6 +++ drivers/firmware/firmware-zynqmp.c | 14 +++++ include/zynqmp_firmware.h | 2 + 8 files changed, 187 insertions(+) diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c index f5c8e684dda..20a41d9ed97 100644 --- a/arch/arm/mach-versal-net/cpu.c +++ b/arch/arm/mach-versal-net/cpu.c @@ -20,6 +20,7 @@ #include <asm/cache.h> #include <dm/platdata.h> #include <linux/bitfield.h> +#include <linux/delay.h> #include <linux/string.h> #include "../../../board/xilinx/common/board.h" @@ -250,6 +251,56 @@ __weak int zynqmp_pm_ospi_enable_linear_mode(bool enable) return 0; } +#if !CONFIG_IS_ENABLED(DM_GPIO) +int zynqmp_pm_ospi_flash_reset_raw(void) +{ + /* CRP WPROT */ + writel(0, WPROT_CRP); + /* GPIO Reset */ + writel(0, RST_GPIO); + + /* disable IOU write protection */ + writel(0, WPROT_LPD_MIO); + + /* set direction as output */ + writel((readl(BOOT_MODE_DIR) | BIT(FLASH_RESET_GPIO)), + BOOT_MODE_DIR); + + /* Data output enable */ + writel((readl(BOOT_MODE_OUT) | BIT(FLASH_RESET_GPIO)), + BOOT_MODE_OUT); + + /* IOU SLCR write enable */ + writel(0, WPROT_PMC_MIO); + + /* set MIO as GPIO */ + writel(0x60, MIO_PIN_12); + + /* Set value 1 to pin */ + writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(10); + + /* Disable Tri-state */ + writel((readl(BANK0_TRI) & ~BIT(FLASH_RESET_GPIO)), BANK0_TRI); + udelay(5); + + /* Set value 0 to pin */ + writel((readl(BANK0_OUTPUT) & ~BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(150); + + /* Set value 1 to pin */ + writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(1200); + + return 0; +} + +__weak int zynqmp_pm_ospi_flash_reset(void) +{ + return zynqmp_pm_ospi_flash_reset_raw(); +} +#endif + 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 2682b0faeea..aa680baba89 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,9 @@ u8 versal_net_get_bootmode(void); u32 versal_net_bootmode_reg(void); /* Overridable OSPI AXI-mux select: weak MMIO default, firmware override */ int zynqmp_pm_ospi_enable_linear_mode(bool enable); +#if !CONFIG_IS_ENABLED(DM_GPIO) +/* Overridable OSPI flash GPIO reset sequence: weak MMIO default, firmware override */ +int zynqmp_pm_ospi_flash_reset(void); +/* Direct GPIO reset sequence (EL3 / no-firmware path) */ +int zynqmp_pm_ospi_flash_reset_raw(void); +#endif diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c index 3ec51bf560e..d0f23767662 100644 --- a/arch/arm/mach-versal/cpu.c +++ b/arch/arm/mach-versal/cpu.c @@ -17,6 +17,7 @@ #include <asm/arch/sys_proto.h> #include <asm/cache.h> #include <dm/platdata.h> +#include <linux/delay.h> DECLARE_GLOBAL_DATA_PTR; @@ -190,6 +191,56 @@ __weak int zynqmp_pm_ospi_enable_linear_mode(bool enable) return 0; } +#if !CONFIG_IS_ENABLED(DM_GPIO) +int zynqmp_pm_ospi_flash_reset_raw(void) +{ + /* CRP WPROT */ + writel(0, WPROT_CRP); + /* GPIO Reset */ + writel(0, RST_GPIO); + + /* disable IOU write protection */ + writel(0, WPROT_LPD_MIO); + + /* set direction as output */ + writel((readl(BOOT_MODE_DIR) | BIT(FLASH_RESET_GPIO)), + BOOT_MODE_DIR); + + /* Data output enable */ + writel((readl(BOOT_MODE_OUT) | BIT(FLASH_RESET_GPIO)), + BOOT_MODE_OUT); + + /* IOU SLCR write enable */ + writel(0, WPROT_PMC_MIO); + + /* set MIO as GPIO */ + writel(0x60, MIO_PIN_12); + + /* Set value 1 to pin */ + writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(10); + + /* Disable Tri-state */ + writel((readl(BANK0_TRI) & ~BIT(FLASH_RESET_GPIO)), BANK0_TRI); + udelay(5); + + /* Set value 0 to pin */ + writel((readl(BANK0_OUTPUT) & ~BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(150); + + /* Set value 1 to pin */ + writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(1200); + + return 0; +} + +__weak int zynqmp_pm_ospi_flash_reset(void) +{ + return zynqmp_pm_ospi_flash_reset_raw(); +} +#endif + 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 da357abaaee..83fc9b73b03 100644 --- a/arch/arm/mach-versal/include/mach/sys_proto.h +++ b/arch/arm/mach-versal/include/mach/sys_proto.h @@ -29,5 +29,11 @@ u32 versal_bootmode_reg(void); void versal_timer_setup(void); /* Overridable OSPI AXI-mux select: weak MMIO default, firmware override */ int zynqmp_pm_ospi_enable_linear_mode(bool enable); +#if !CONFIG_IS_ENABLED(DM_GPIO) +/* Overridable OSPI flash GPIO reset sequence: weak MMIO default, firmware override */ +int zynqmp_pm_ospi_flash_reset(void); +/* Direct GPIO reset sequence (EL3 / no-firmware path) */ +int zynqmp_pm_ospi_flash_reset_raw(void); +#endif #endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c index c2173161fd7..c1cd4aef508 100644 --- a/arch/arm/mach-versal2/cpu.c +++ b/arch/arm/mach-versal2/cpu.c @@ -22,6 +22,7 @@ #include <asm/cache.h> #include <dm/platdata.h> #include <linux/bitfield.h> +#include <linux/delay.h> #include <linux/string.h> #include "../../../board/xilinx/common/board.h" @@ -323,6 +324,56 @@ __weak int zynqmp_pm_ospi_enable_linear_mode(bool enable) return 0; } +#if !CONFIG_IS_ENABLED(DM_GPIO) +int zynqmp_pm_ospi_flash_reset_raw(void) +{ + /* CRP WPROT */ + writel(0, WPROT_CRP); + /* GPIO Reset */ + writel(0, RST_GPIO); + + /* disable IOU write protection */ + writel(0, WPROT_LPD_MIO); + + /* set direction as output */ + writel((readl(BOOT_MODE_DIR) | BIT(FLASH_RESET_GPIO)), + BOOT_MODE_DIR); + + /* Data output enable */ + writel((readl(BOOT_MODE_OUT) | BIT(FLASH_RESET_GPIO)), + BOOT_MODE_OUT); + + /* IOU SLCR write enable */ + writel(0, WPROT_PMC_MIO); + + /* set MIO as GPIO */ + writel(0x60, MIO_PIN_12); + + /* Set value 1 to pin */ + writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(10); + + /* Disable Tri-state */ + writel((readl(BANK0_TRI) & ~BIT(FLASH_RESET_GPIO)), BANK0_TRI); + udelay(5); + + /* Set value 0 to pin */ + writel((readl(BANK0_OUTPUT) & ~BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(150); + + /* Set value 1 to pin */ + writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); + udelay(1200); + + return 0; +} + +__weak int zynqmp_pm_ospi_flash_reset(void) +{ + return zynqmp_pm_ospi_flash_reset_raw(); +} +#endif + 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 30db724bc2c..5a903a0881a 100644 --- a/arch/arm/mach-versal2/include/mach/sys_proto.h +++ b/arch/arm/mach-versal2/include/mach/sys_proto.h @@ -23,6 +23,12 @@ u8 versal2_get_bootmode(void); void versal2_timer_setup(void); /* Overridable OSPI AXI-mux select: weak MMIO default, firmware override */ int zynqmp_pm_ospi_enable_linear_mode(bool enable); +#if !CONFIG_IS_ENABLED(DM_GPIO) +/* Overridable OSPI flash GPIO reset sequence: weak MMIO default, firmware override */ +int zynqmp_pm_ospi_flash_reset(void); +/* Direct GPIO reset sequence (EL3 / no-firmware path) */ +int zynqmp_pm_ospi_flash_reset_raw(void); +#endif 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 d09e92de1b0..6e6724653b7 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -869,6 +869,20 @@ int zynqmp_pm_ospi_enable_linear_mode(bool enable) } #endif +#if !CONFIG_IS_ENABLED(DM_GPIO) && \ + (defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) || \ + defined(CONFIG_ARCH_VERSAL2)) +int zynqmp_pm_ospi_flash_reset(void) +{ + /* At EL3 or in SPL the firmware (SMC) path is unavailable */ + if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) + return zynqmp_pm_ospi_flash_reset_raw(); + + return xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI, IOCTL_OSPI_FLASH_RESET, + 0, 0, 0, 0, NULL); +} +#endif + static const struct udevice_id zynqmp_firmware_ids[] = { { .compatible = "xlnx,zynqmp-firmware", .data = (ulong)smc_call_legacy }, { .compatible = "xlnx,versal-firmware", .data = (ulong)smc_call_legacy}, diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index 949ef5ec121..1270e061364 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -412,6 +412,8 @@ enum pm_ioctl_id { IOCTL_AIE_OPS = 33, /* IOCTL to get default/current QoS */ IOCTL_GET_QOS = 34, + /* IOCTL for OSPI flash GPIO reset sequence */ + IOCTL_OSPI_FLASH_RESET = 35, }; enum pm_sd_config_type { -- 2.25.1
