From c1795f7cee026b066485de794cff4e5bb9475a98 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Wed, 11 Dec 2019 20:39:52 +0100 Subject: spi: spi-ti-qspi: Remove unused macro for fclk frequency The fclk and its rate are retrieved from DT. Signed-off-by: Jean Pihet Cc: Ryan Barnett Cc: Conrad Ratschan Cc: Arnout Vandecappelle Link: https://lore.kernel.org/r/20191211193954.747745-2-jean.pihet@newoldbits.com Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/spi/spi-ti-qspi.c') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 3cb65371ae3b..a18835128ad0 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -79,8 +79,6 @@ struct ti_qspi { #define QSPI_COMPLETION_TIMEOUT msecs_to_jiffies(2000) -#define QSPI_FCLK 192000000 - /* Clock Control */ #define QSPI_CLK_EN (1 << 31) #define QSPI_CLK_DIV_MAX 0xffff -- cgit From e97f491450805fe6cbfd482b97b5427b21dec575 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 14 Jan 2020 13:41:24 +0100 Subject: spi: spi-ti-qspi: support large flash devices The TI QSPI IP has limitations: - the MMIO region is 64MB in size - in non-MMIO mode, the transfer can handle 4096 words max. Add support for bigger devices. Use MMIO and DMA transfers below the 64MB boundary, use software generated transfers above. Signed-off-by: Jean Pihet Cc: Ryan Barnett Cc: Conrad Ratschan Cc: Arnout Vandecappelle Link: https://lore.kernel.org/r/20200114124125.361429-2-jean.pihet@newoldbits.com Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/spi/spi-ti-qspi.c') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index ad2942b3d0a9..0334e2926998 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -525,6 +525,35 @@ static void ti_qspi_setup_mmap_read(struct spi_device *spi, u8 opcode, QSPI_SPI_SETUP_REG(spi->chip_select)); } +static int ti_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) +{ + struct ti_qspi *qspi = spi_controller_get_devdata(mem->spi->master); + size_t max_len; + + if (op->data.dir == SPI_MEM_DATA_IN) { + if (op->addr.val < qspi->mmap_size) { + /* Limit MMIO to the mmaped region */ + if (op->addr.val + op->data.nbytes > qspi->mmap_size) { + max_len = qspi->mmap_size - op->addr.val; + op->data.nbytes = min((size_t) op->data.nbytes, + max_len); + } + } else { + /* + * Use fallback mode (SW generated transfers) above the + * mmaped region. + * Adjust size to comply with the QSPI max frame length. + */ + max_len = QSPI_FRAME; + max_len -= 1 + op->addr.nbytes + op->dummy.nbytes; + op->data.nbytes = min((size_t) op->data.nbytes, + max_len); + } + } + + return 0; +} + static int ti_qspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { @@ -575,6 +604,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem, static const struct spi_controller_mem_ops ti_qspi_mem_ops = { .exec_op = ti_qspi_exec_mem_op, + .adjust_op_size = ti_qspi_adjust_op_size, }; static int ti_qspi_start_transfer_one(struct spi_master *master, -- cgit From e7cc5cfbea4c9bd2c452cb81d0829e9259dd84d8 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Tue, 14 Jan 2020 13:41:25 +0100 Subject: 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 Cc: Ryan Barnett Cc: Conrad Ratschan Cc: Arnout Vandecappelle Link: https://lore.kernel.org/r/20200114124125.361429-3-jean.pihet@newoldbits.com Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 54 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) (limited to 'drivers/spi/spi-ti-qspi.c') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 0334e2926998..858fda8ac73e 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -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; -- cgit From 6925212f328bf2abde0c8f0d037fddd36751d489 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Wed, 15 Jan 2020 11:07:00 +0100 Subject: spi: spi-ti-qspi: fix warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/spi/spi-ti-qspi.c: In function ‘ti_qspi_start_transfer_one’: drivers/spi/spi-ti-qspi.c:392:8: warning: ‘rx_wlen’ may be used uninitialized in this function [-Wmaybe-uninitialized] 392 | if (rx_wlen >= 32) | ^ drivers/spi/spi-ti-qspi.c:318:12: note: ‘rx_wlen’ was declared here 318 | u8 rxlen, rx_wlen; | ^~~~~~~ The warning is a false positive; it is not thrown by all compiler versions, e.g. Red Hat Cross 9.2.1-1 but not Linaro GCC 7.5-2019.12. Signed-off-by: Jean Pihet Link: https://lore.kernel.org/r/20200115100700.3357-1-jean.pihet@newoldbits.com Signed-off-by: Mark Brown --- drivers/spi/spi-ti-qspi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/spi/spi-ti-qspi.c') diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 858fda8ac73e..366a3e5cca6b 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -332,6 +332,7 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, break; } wlen = t->bits_per_word >> 3; /* in bytes */ + rx_wlen = wlen; while (count) { dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc); -- cgit