diff options
author | T Karthik Reddy <t.karthik.reddy@xilinx.com> | 2022-05-12 04:05:34 -0600 |
---|---|---|
committer | Michal Simek <michal.simek@amd.com> | 2022-06-29 16:00:31 +0200 |
commit | 248fe9f302df5f20d75a7d88b793db017262d750 (patch) | |
tree | 642dc7f671ce7af7deca3a61857a43c5c60e38f5 /drivers | |
parent | bf8dae5fcf400a593d56d5847d8ee62bc4c27855 (diff) |
spi: cadence_qspi: Enable apb linear mode for apb read & write operations
On versal platform, enable apb linear mode for apb read and write
execute operations amd disable it when using dma reads. This is done by
xilinx_pm_request() secure calls when CONFIG_ZYNQMP_FIRMWARE is enabled,
else we use direct raw reads and writes in case of mini U-Boot.
Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Link: https://lore.kernel.org/r/20220512100535.16364-5-ashok.reddy.soma@xilinx.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/cadence_ospi_versal.c | 24 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi.c | 7 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi.h | 1 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi_apb.c | 11 |
4 files changed, 43 insertions, 0 deletions
diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c index 0caf250203..52bcad053f 100644 --- a/drivers/spi/cadence_ospi_versal.c +++ b/drivers/spi/cadence_ospi_versal.c @@ -33,6 +33,7 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, bytes_to_dma = n_rx - rx_rem; if (bytes_to_dma) { + cadence_qspi_apb_enable_linear_mode(false); reg = readl(plat->regbase + CQSPI_REG_CONFIG); reg |= CQSPI_REG_CONFIG_ENBL_DMA; writel(reg, plat->regbase + CQSPI_REG_CONFIG); @@ -211,3 +212,26 @@ int cadence_spi_versal_flash_reset(struct udevice *dev) return 0; } #endif + +void cadence_qspi_apb_enable_linear_mode(bool enable) +{ + if (CONFIG_IS_ENABLED(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, NULL); + else + /* DMA mode */ + xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI, + IOCTL_OSPI_MUX_SELECT, + PM_OSPI_MUX_SEL_DMA, 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); + } +} diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 923c5f5318..5fb4d2ff03 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -18,7 +18,9 @@ #include <linux/err.h> #include <linux/errno.h> #include <linux/sizes.h> +#include <zynqmp_firmware.h> #include "cadence_qspi.h" +#include <dt-bindings/power/xlnx-versal-power.h> #define NSEC_PER_SEC 1000000000L @@ -196,6 +198,11 @@ static int cadence_spi_probe(struct udevice *bus) priv->regbase = plat->regbase; priv->ahbbase = plat->ahbbase; + if (CONFIG_IS_ENABLED(ZYNQMP_FIRMWARE)) + xilinx_pm_request(PM_REQUEST_NODE, PM_DEV_OSPI, + ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS, + ZYNQMP_PM_REQUEST_ACK_NO, NULL); + if (plat->ref_clk_hz == 0) { ret = clk_get_by_index(bus, 0, &clk); if (ret) { diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index 9d89e24ba4..c8d16bb0e4 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -284,5 +284,6 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat); int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg); int cadence_qspi_versal_flash_reset(struct udevice *dev); +void cadence_qspi_apb_enable_linear_mode(bool enable); #endif /* __CADENCE_QSPI_H__ */ diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index b11bd2d2c6..c00755050e 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -38,6 +38,11 @@ #include <malloc.h> #include "cadence_qspi.h" +__weak void cadence_qspi_apb_enable_linear_mode(bool enable) +{ + return; +} + void cadence_qspi_apb_controller_enable(void *reg_base) { unsigned int reg; @@ -730,6 +735,9 @@ int cadence_qspi_apb_read_execute(struct cadence_spi_plat *plat, void *buf = op->data.buf.in; size_t len = op->data.nbytes; + if (CONFIG_IS_ENABLED(ARCH_VERSAL)) + cadence_qspi_apb_enable_linear_mode(true); + if (plat->use_dac_mode && (from + len < plat->ahbsize)) { if (len < 256 || dma_memcpy(buf, plat->ahbbase + from, len) < 0) { @@ -897,6 +905,9 @@ int cadence_qspi_apb_write_execute(struct cadence_spi_plat *plat, const void *buf = op->data.buf.out; size_t len = op->data.nbytes; + if (CONFIG_IS_ENABLED(ARCH_VERSAL)) + cadence_qspi_apb_enable_linear_mode(true); + /* * Some flashes like the Cypress Semper flash expect a dummy 4-byte * address (all 0s) with the read status register command in DTR mode. |