cadence_qspi_apb_enable_linear_mode() currently selects between a
firmware request and direct register access based on
IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE).

Introduce zynqmp_pm_ospi_enable_linear_mode(bool enable) with weak
default implementations for Versal, Versal Net, and Versal Gen 2, and
a firmware-backed override in firmware-zynqmp.c, guarded to those
platforms since ZynqMP has no OSPI AXI mux to select. This removes the
firmware-specific conditional from the driver while preserving existing
behavior.

Use a boolean argument instead of PM_OSPI_MUX_SEL_* values so the weak
default implementations remain independent of zynqmp_firmware.h and
firmware-specific definitions.

zynqmp_pm_ospi_enable_linear_mode() only calls xilinx_pm_request(), so
it lives outside the CONFIG_ZYNQMP_IPI-guarded block, same as the
other wrapper functions above it.

Signed-off-by: Akshay Belsare <[email protected]>
---
 arch/arm/mach-versal-net/cpu.c                | 12 +++++++++
 .../mach-versal-net/include/mach/sys_proto.h  |  2 ++
 arch/arm/mach-versal/cpu.c                    | 12 +++++++++
 arch/arm/mach-versal/include/mach/sys_proto.h |  2 ++
 arch/arm/mach-versal2/cpu.c                   | 12 +++++++++
 .../arm/mach-versal2/include/mach/sys_proto.h |  2 ++
 drivers/firmware/firmware-zynqmp.c            | 11 ++++++++
 drivers/spi/cadence_ospi_versal.c             | 27 +++++--------------
 8 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-versal-net/cpu.c b/arch/arm/mach-versal-net/cpu.c
index 1555751da2e..f5c8e684dda 100644
--- a/arch/arm/mach-versal-net/cpu.c
+++ b/arch/arm/mach-versal-net/cpu.c
@@ -238,6 +238,18 @@ bool soc_detection(void)
        return true;
 }
 
+__weak int zynqmp_pm_ospi_enable_linear_mode(bool enable)
+{
+       if (enable)
+               writel(readl(VERSAL_AXI_MUX_SEL) |
+                      VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
+       else
+               writel(readl(VERSAL_AXI_MUX_SEL) &
+                      ~VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
+
+       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..2682b0faeea 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 OSPI AXI-mux select: weak MMIO default, firmware override */
+int zynqmp_pm_ospi_enable_linear_mode(bool enable);
diff --git a/arch/arm/mach-versal/cpu.c b/arch/arm/mach-versal/cpu.c
index 7521d45bc1a..3ec51bf560e 100644
--- a/arch/arm/mach-versal/cpu.c
+++ b/arch/arm/mach-versal/cpu.c
@@ -178,6 +178,18 @@ u8 __weak versal_get_bootmode(void)
        return reg & BOOT_MODES_MASK;
 }
 
+__weak int zynqmp_pm_ospi_enable_linear_mode(bool enable)
+{
+       if (enable)
+               writel(readl(VERSAL_AXI_MUX_SEL) |
+                      VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
+       else
+               writel(readl(VERSAL_AXI_MUX_SEL) &
+                      ~VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
+
+       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..da357abaaee 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 OSPI AXI-mux select: weak MMIO default, firmware override */
+int zynqmp_pm_ospi_enable_linear_mode(bool enable);
 
 #endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
index 19baa1331bd..c2173161fd7 100644
--- a/arch/arm/mach-versal2/cpu.c
+++ b/arch/arm/mach-versal2/cpu.c
@@ -311,6 +311,18 @@ bool soc_detection(void)
        return true;
 }
 
+__weak int zynqmp_pm_ospi_enable_linear_mode(bool enable)
+{
+       if (enable)
+               writel(readl(VERSAL_AXI_MUX_SEL) |
+                      VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
+       else
+               writel(readl(VERSAL_AXI_MUX_SEL) &
+                      ~VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
+
+       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..30db724bc2c 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 OSPI AXI-mux select: weak MMIO default, firmware override */
+int zynqmp_pm_ospi_enable_linear_mode(bool enable);
 
 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 dad7fd086bf..d09e92de1b0 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -858,6 +858,17 @@ int zynqmp_pm_ospi_init(void)
                                      ZYNQMP_PM_MAX_QOS, 
ZYNQMP_PM_REQUEST_ACK_NO);
 }
 
+#if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) || \
+       defined(CONFIG_ARCH_VERSAL2)
+int zynqmp_pm_ospi_enable_linear_mode(bool enable)
+{
+       u32 select = enable ? PM_OSPI_MUX_SEL_LINEAR : PM_OSPI_MUX_SEL_DMA;
+
+       return xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI, IOCTL_OSPI_MUX_SELECT,
+                                select, 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/drivers/spi/cadence_ospi_versal.c 
b/drivers/spi/cadence_ospi_versal.c
index e6f4ba49e77..602a7f4884c 100644
--- a/drivers/spi/cadence_ospi_versal.c
+++ b/drivers/spi/cadence_ospi_versal.c
@@ -12,8 +12,8 @@
 #include <asm/gpio.h>
 #include <asm/cache.h>
 #include <cpu_func.h>
-#include <zynqmp_firmware.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 #include "cadence_qspi.h"
 
 int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
@@ -200,25 +200,12 @@ int cadence_qspi_flash_reset(struct udevice *dev)
 
 void cadence_qspi_apb_enable_linear_mode(bool enable)
 {
-       if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
-               if (enable)
-                       /* ahb read mode */
-                       xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI,
-                                         IOCTL_OSPI_MUX_SELECT,
-                                         PM_OSPI_MUX_SEL_LINEAR, 0, 0, 0, 
NULL);
-               else
-                       /* DMA mode */
-                       xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI,
-                                         IOCTL_OSPI_MUX_SELECT,
-                                         PM_OSPI_MUX_SEL_DMA, 0, 0, 0, NULL);
-       } else {
-               if (enable)
-                       writel(readl(VERSAL_AXI_MUX_SEL) |
-                              VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
-               else
-                       writel(readl(VERSAL_AXI_MUX_SEL) &
-                              ~VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
-       }
+       int ret;
+
+       /* ahb read mode vs. DMA mode */
+       ret = zynqmp_pm_ospi_enable_linear_mode(enable);
+       if (ret)
+               printf("%s: failed to select OSPI mux mode: %d\n", __func__, 
ret);
 }
 
 int cadence_device_reset(struct udevice *bus)
-- 
2.25.1

Reply via email to