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: Jean 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.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Jean Pihet 2020-01-14 13:41:25 +01:00 committed by Mark Brown
parent e97f491450
commit e7cc5cfbea
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
1 changed files with 51 additions and 3 deletions

View File

@ -314,6 +314,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
{
int wlen;
unsigned int cmd;
u32 rx;
u8 rxlen, rx_wlen;
u8 *rxbuf;
rxbuf = t->rx_buf;
@ -336,14 +338,60 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
if (qspi_is_busy(qspi))
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);
if (ti_qspi_poll_wc(qspi)) {
dev_err(qspi->dev, "read timed out\n");
return -ETIMEDOUT;
}
switch (wlen) {
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;
case 2:
*((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,
*((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG);
break;
}
rxbuf += wlen;
count -= wlen;
rxbuf += rxlen;
count -= rxlen;
}
return 0;