From: Patrice Chotard Date: Mon, 8 Dec 2025 07:29:09 +0000 (+0100) Subject: spi: stm32-ospi: Optimize FIFO accesses using u16 or u32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cfe58ffc95a601988702df6f3462cb54dde467e9;p=thirdparty%2Fkernel%2Flinux.git 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 Link: https://patch.msgid.link/20251208-upstream_qspi_ospi_updates-v2-2-62526c9467dc@foss.st.com Signed-off-by: Mark Brown --- diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c index d733e37f0435f..a6f53f06200e7 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);