Unverified Commit cfe58ffc authored by Patrice Chotard's avatar Patrice Chotard Committed by Mark Brown
Browse files

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: default avatarPatrice 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: default avatarMark Brown <broonie@kernel.org>
parent e35a7607
Loading
Loading
Loading
Loading
+38 −9
Original line number Diff line number Diff line
@@ -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);