By reading the 32 bits data register and copy the contents to the receive buffer, according to the single/dual/quad read mode and the data length to read. The speed improvement is 3.5x using quad read. --- drivers/spi/spi-ti-qspi.c | 48 ++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 13916232a959..65ec3bcb25ae 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -313,24 +313,25 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t, static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, int count) { - int wlen; unsigned int cmd; + u32 rx; u8 *rxbuf; + u8 xfer_len; rxbuf = t->rx_buf; cmd = qspi->cmd; + /* Optimize the transfers for dual and quad read */ switch (t->rx_nbits) { - case SPI_NBITS_DUAL: - cmd |= QSPI_RD_DUAL; - break; case SPI_NBITS_QUAD: - cmd |= QSPI_RD_QUAD; + cmd |= QSPI_RD_QUAD | QSPI_WLEN(32); + break; + case SPI_NBITS_DUAL: + cmd |= QSPI_RD_DUAL | QSPI_WLEN(16); break; default: - cmd |= QSPI_RD_SNGL; + cmd |= QSPI_RD_SNGL | QSPI_WLEN(8); break; } - wlen = t->bits_per_word >> 3; /* in bytes */ while (count) { dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc); @@ -342,19 +343,34 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, dev_err(qspi->dev, "read timed out\n"); return -ETIMEDOUT; } - switch (wlen) { - case 1: - *rxbuf = readb(qspi->base + QSPI_SPI_DATA_REG); + + /* Optimize the transfers for dual and quad read */ + rx = readl(qspi->base + QSPI_SPI_DATA_REG); + switch (t->rx_nbits) { + case SPI_NBITS_QUAD: + if (count >= 1) + *rxbuf++ = rx >> 24; + if (count >= 2) + *rxbuf++ = rx >> 16; + if (count >= 3) + *rxbuf++ = rx >> 8; + if (count >= 4) + *rxbuf++ = rx; + xfer_len = min(count, 4); break; - case 2: - *((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG); + case SPI_NBITS_DUAL: + if (count >= 1) + *rxbuf++ = rx >> 8; + if (count >= 2) + *rxbuf++ = rx; + xfer_len = min(count, 2); break; - case 4: - *((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG); + default: + *rxbuf++ = rx; + xfer_len = 1; break; } - rxbuf += wlen; - count -= wlen; + count -= xfer_len; } return 0; -- 2.23.0