Commit e7cc5cfb authored by Jean Pihet's avatar Jean Pihet Committed by Mark Brown

spi: spi-ti-qspi: optimize byte-transfers

Optimize the 8-bit based transfers, as used by the SPI flash
devices, by reading the data registers by 32 and 128 bits when
possible and copy the contents to the receive buffer.

The speed improvement is 4.9x using quad read.
Signed-off-by: default avatarJean Pihet <jean.pihet@newoldbits.com>
Cc: Ryan Barnett <ryan.barnett@rockwellcollins.com>
Cc: Conrad Ratschan <conrad.ratschan@rockwellcollins.com>
Cc: Arnout Vandecappelle <arnout.vandecappelle@essensium.com>
Link: https://lore.kernel.org/r/20200114124125.361429-3-jean.pihet@newoldbits.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent e97f4914
...@@ -314,6 +314,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, ...@@ -314,6 +314,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
{ {
int wlen; int wlen;
unsigned int cmd; unsigned int cmd;
u32 rx;
u8 rxlen, rx_wlen;
u8 *rxbuf; u8 *rxbuf;
rxbuf = t->rx_buf; rxbuf = t->rx_buf;
...@@ -336,14 +338,60 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, ...@@ -336,14 +338,60 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
if (qspi_is_busy(qspi)) if (qspi_is_busy(qspi))
return -EBUSY; return -EBUSY;
switch (wlen) {
case 1:
/*
* Optimize the 8-bit words transfers, as used by
* the SPI flash devices.
*/
if (count >= QSPI_WLEN_MAX_BYTES) {
rxlen = QSPI_WLEN_MAX_BYTES;
} else {
rxlen = min(count, 4);
}
rx_wlen = rxlen << 3;
cmd &= ~QSPI_WLEN_MASK;
cmd |= QSPI_WLEN(rx_wlen);
break;
default:
rxlen = wlen;
break;
}
ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG); ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
if (ti_qspi_poll_wc(qspi)) { if (ti_qspi_poll_wc(qspi)) {
dev_err(qspi->dev, "read timed out\n"); dev_err(qspi->dev, "read timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
switch (wlen) { switch (wlen) {
case 1: case 1:
*rxbuf = readb(qspi->base + QSPI_SPI_DATA_REG); /*
* Optimize the 8-bit words transfers, as used by
* the SPI flash devices.
*/
if (count >= QSPI_WLEN_MAX_BYTES) {
u32 *rxp = (u32 *) rxbuf;
rx = readl(qspi->base + QSPI_SPI_DATA_REG_3);
*rxp++ = be32_to_cpu(rx);
rx = readl(qspi->base + QSPI_SPI_DATA_REG_2);
*rxp++ = be32_to_cpu(rx);
rx = readl(qspi->base + QSPI_SPI_DATA_REG_1);
*rxp++ = be32_to_cpu(rx);
rx = readl(qspi->base + QSPI_SPI_DATA_REG);
*rxp++ = be32_to_cpu(rx);
} else {
u8 *rxp = rxbuf;
rx = readl(qspi->base + QSPI_SPI_DATA_REG);
if (rx_wlen >= 8)
*rxp++ = rx >> (rx_wlen - 8);
if (rx_wlen >= 16)
*rxp++ = rx >> (rx_wlen - 16);
if (rx_wlen >= 24)
*rxp++ = rx >> (rx_wlen - 24);
if (rx_wlen >= 32)
*rxp++ = rx;
}
break; break;
case 2: case 2:
*((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG); *((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG);
...@@ -352,8 +400,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, ...@@ -352,8 +400,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
*((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG); *((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG);
break; break;
} }
rxbuf += wlen; rxbuf += rxlen;
count -= wlen; count -= rxlen;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment