Message ID | 1440066659-5356-1-git-send-email-vigneshr@ti.com (mailing list archive) |
---|---|
State | Accepted |
Commit | f682c4ffd25a19594d21987c19a69fa123242eb7 |
Headers | show |
On Thu, Aug 20, 2015 at 04:00:59PM +0530, Vignesh R wrote: > - writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); > + if (count >= QSPI_WLEN_MAX_BYTES) { > + u32 *txp = (u32 *)txbuf; > + > + data = cpu_to_be32(*txp++); > + writel(data, qspi->base + > + QSPI_SPI_DATA_REG_3); > + data = cpu_to_be32(*txp++); > + writel(data, qspi->base + > + QSPI_SPI_DATA_REG_2); > + data = cpu_to_be32(*txp++); > + writel(data, qspi->base + > + QSPI_SPI_DATA_REG_1); > + data = cpu_to_be32(*txp++); > + writel(data, qspi->base + > + QSPI_SPI_DATA_REG); > + xfer_len = QSPI_WLEN_MAX_BYTES; > + cmd |= QSPI_WLEN(QSPI_WLEN_MAX_BITS); > + } else { > + writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); > + cmd = qspi->cmd | QSPI_WR_SNGL; > + xfer_len = wlen; > + cmd |= QSPI_WLEN(wlen); > + } It's a bit sad that this isn't able to do a Duff's device type thing and only kicks in for the full 128 bit FIFO size, it looks like it could do any number of words.
On 08/20/2015 11:25 PM, Mark Brown wrote: > On Thu, Aug 20, 2015 at 04:00:59PM +0530, Vignesh R wrote: > >> - writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); >> + if (count >= QSPI_WLEN_MAX_BYTES) { >> + u32 *txp = (u32 *)txbuf; >> + >> + data = cpu_to_be32(*txp++); >> + writel(data, qspi->base + >> + QSPI_SPI_DATA_REG_3); >> + data = cpu_to_be32(*txp++); >> + writel(data, qspi->base + >> + QSPI_SPI_DATA_REG_2); >> + data = cpu_to_be32(*txp++); >> + writel(data, qspi->base + >> + QSPI_SPI_DATA_REG_1); >> + data = cpu_to_be32(*txp++); >> + writel(data, qspi->base + >> + QSPI_SPI_DATA_REG); >> + xfer_len = QSPI_WLEN_MAX_BYTES; >> + cmd |= QSPI_WLEN(QSPI_WLEN_MAX_BITS); >> + } else { >> + writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); >> + cmd = qspi->cmd | QSPI_WR_SNGL; >> + xfer_len = wlen; >> + cmd |= QSPI_WLEN(wlen); >> + } > > It's a bit sad that this isn't able to do a Duff's device type thing and > only kicks in for the full 128 bit FIFO size, it looks like it could do > any number of words. > Yes, any number of bytes can be transfered (max 16 bytes). I will try to work on your suggestion. Thanks!
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 45844a227c5e..f4cea6834fad 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -96,6 +96,8 @@ struct ti_qspi { #define QSPI_INVAL (4 << 16) #define QSPI_WC_CMD_INT_EN (1 << 14) #define QSPI_FLEN(n) ((n - 1) << 0) +#define QSPI_WLEN_MAX_BITS 128 +#define QSPI_WLEN_MAX_BYTES 16 /* STATUS REGISTER */ #define BUSY 0x01 @@ -224,14 +226,16 @@ static inline u32 qspi_is_busy(struct ti_qspi *qspi) static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) { - int wlen, count; + int wlen, count, xfer_len; unsigned int cmd; const u8 *txbuf; + u32 data; txbuf = t->tx_buf; cmd = qspi->cmd | QSPI_WR_SNGL; count = t->len; wlen = t->bits_per_word >> 3; /* in bytes */ + xfer_len = wlen; while (count) { if (qspi_is_busy(qspi)) @@ -241,7 +245,29 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) case 1: dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n", cmd, qspi->dc, *txbuf); - writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); + if (count >= QSPI_WLEN_MAX_BYTES) { + u32 *txp = (u32 *)txbuf; + + data = cpu_to_be32(*txp++); + writel(data, qspi->base + + QSPI_SPI_DATA_REG_3); + data = cpu_to_be32(*txp++); + writel(data, qspi->base + + QSPI_SPI_DATA_REG_2); + data = cpu_to_be32(*txp++); + writel(data, qspi->base + + QSPI_SPI_DATA_REG_1); + data = cpu_to_be32(*txp++); + writel(data, qspi->base + + QSPI_SPI_DATA_REG); + xfer_len = QSPI_WLEN_MAX_BYTES; + cmd |= QSPI_WLEN(QSPI_WLEN_MAX_BITS); + } else { + writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); + cmd = qspi->cmd | QSPI_WR_SNGL; + xfer_len = wlen; + cmd |= QSPI_WLEN(wlen); + } break; case 2: dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n", @@ -261,8 +287,8 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) dev_err(qspi->dev, "write timed out\n"); return -ETIMEDOUT; } - txbuf += wlen; - count -= wlen; + txbuf += xfer_len; + count -= xfer_len; } return 0;
TI QSPI has four 32 bit data regsiters which can be used to transfer 16 bytes of data at once. The register group QSPI_SPI_DATA_REG_3, QSPI_SPI_DATA_REG_2, QSPI_SPI_DATA_REG_1 and QSPI_SPI_DATA_REG is treated as a single 128-bit word for shifting data in and out. The bit at QSPI_SPI_DATA_REG_3[31] position is the first bit to be shifted out in case of 128 bit transfer mode. Therefore the first byte to be written to flash should be at QSPI_SPI_DATA_REG_3[31-25] position. Instead of writing 1 byte at a time when interacting with spi-nor flash, make use of all the four registers so that 16 bytes can be transferred in one go. This reduces number of register writes and Word Complete interrupts for a given transfer message size, thereby increasing the write performance. Without this patch the raw flash write speed is ~100KB/s, with this patch the write speed increases to ~400 kB/s on DRA74 EVM. Signed-off-by: Vignesh R <vigneshr@ti.com> --- drivers/spi/spi-ti-qspi.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-)