summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrice Chotard <patrice.chotard@foss.st.com>2025-12-08 10:29:09 +0300
committerMark Brown <broonie@kernel.org>2025-12-14 13:39:04 +0300
commitcfe58ffc95a601988702df6f3462cb54dde467e9 (patch)
tree93a1463a5e6cfd0d9b6965cda7d7fe77bf1664cb
parente35a7607e05d59d35e937b80532ae93d1dd2493f (diff)
downloadlinux-cfe58ffc95a601988702df6f3462cb54dde467e9.tar.xz
spi: stm32-ospi: Optimize FIFO accesses using u16 or u32
FIFO accesses uses u8 only for read/write. In order to optimize throughput, add u16 or u32 read/write accesses when possible. Running mtd_speedtest on a 4MB sNOR partition using a stm32mp257f-ev1 board gives the following results: before after gain Read : 5693 KiB/s 21139 KiB/s 371% Write: 765 KiB/s 910 KiB/s 19% Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> Link: https://patch.msgid.link/20251208-upstream_qspi_ospi_updates-v2-2-62526c9467dc@foss.st.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-stm32-ospi.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
index d733e37f0435..a6f53f06200e 100644
--- a/drivers/spi/spi-stm32-ospi.c
+++ b/drivers/spi/spi-stm32-ospi.c
@@ -142,14 +142,32 @@ struct stm32_ospi {
struct mutex lock;
};
-static void stm32_ospi_read_fifo(u8 *val, void __iomem *addr)
+static void stm32_ospi_read_fifo(void *val, void __iomem *addr, u8 len)
{
- *val = readb_relaxed(addr);
+ switch (len) {
+ case sizeof(u32):
+ *((u32 *)val) = readl_relaxed(addr);
+ break;
+ case sizeof(u16):
+ *((u16 *)val) = readw_relaxed(addr);
+ break;
+ case sizeof(u8):
+ *((u8 *)val) = readb_relaxed(addr);
+ };
}
-static void stm32_ospi_write_fifo(u8 *val, void __iomem *addr)
+static void stm32_ospi_write_fifo(void *val, void __iomem *addr, u8 len)
{
- writeb_relaxed(*val, addr);
+ switch (len) {
+ case sizeof(u32):
+ writel_relaxed(*((u32 *)val), addr);
+ break;
+ case sizeof(u16):
+ writew_relaxed(*((u16 *)val), addr);
+ break;
+ case sizeof(u8):
+ writeb_relaxed(*((u8 *)val), addr);
+ };
}
static int stm32_ospi_abort(struct stm32_ospi *ospi)
@@ -172,19 +190,20 @@ static int stm32_ospi_abort(struct stm32_ospi *ospi)
return timeout;
}
-static int stm32_ospi_poll(struct stm32_ospi *ospi, u8 *buf, u32 len, bool read)
+static int stm32_ospi_poll(struct stm32_ospi *ospi, void *buf, u32 len, bool read)
{
void __iomem *regs_base = ospi->regs_base;
- void (*fifo)(u8 *val, void __iomem *addr);
+ void (*fifo)(void *val, void __iomem *addr, u8 len);
u32 sr;
int ret;
+ u8 step;
if (read)
fifo = stm32_ospi_read_fifo;
else
fifo = stm32_ospi_write_fifo;
- while (len--) {
+ while (len) {
ret = readl_relaxed_poll_timeout_atomic(regs_base + OSPI_SR,
sr, sr & SR_FTF, 1,
STM32_FIFO_TIMEOUT_US);
@@ -193,7 +212,17 @@ static int stm32_ospi_poll(struct stm32_ospi *ospi, u8 *buf, u32 len, bool read)
len, sr);
return ret;
}
- fifo(buf++, regs_base + OSPI_DR);
+
+ if (len >= sizeof(u32))
+ step = sizeof(u32);
+ else if (len >= sizeof(u16))
+ step = sizeof(u16);
+ else
+ step = sizeof(u8);
+
+ fifo(buf, regs_base + OSPI_DR, step);
+ len -= step;
+ buf += step;
}
return 0;
@@ -408,7 +437,7 @@ static int stm32_ospi_xfer(struct stm32_ospi *ospi, const struct spi_mem_op *op)
if (op->data.dir == SPI_MEM_DATA_IN)
buf = op->data.buf.in;
else
- buf = (u8 *)op->data.buf.out;
+ buf = (void *)op->data.buf.out;
return stm32_ospi_poll(ospi, buf, op->data.nbytes,
op->data.dir == SPI_MEM_DATA_IN);