From 3be09bec42a800d4f8ead8119c462f3eb4fad435 Mon Sep 17 00:00:00 2001 From: Hiep Cao Minh Date: Fri, 4 Nov 2016 17:38:54 +0900 Subject: [PATCH 1/5] spi: rspi: supports 32bytes buffer for DUAL and QUAD This patch supports 32bytes of buffer for DUAL and QUAD in QSPI by Using Transmit/Receive Buffer Data Triggering Number. In order to improve the DUAL and QUAD's performance of SPI while transferring data in PIO mode, it sends/receives each 32bytes data instead of each byte data as current situation. Signed-off-by: Hiep Cao Minh Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 52 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index a816f07e168e8..3bab75ab1b257 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -413,7 +413,7 @@ static unsigned int qspi_set_send_trigger(struct rspi_data *rspi, return n; } -static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) +static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) { unsigned int n; @@ -428,6 +428,7 @@ static void qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) qspi_update(rspi, SPBFCR_RXTRG_MASK, SPBFCR_RXTRG_1B, QSPI_SPBFCR); } + return n; } #define set_config_register(spi, n) spi->ops->set_config_register(spi, n) @@ -514,6 +515,51 @@ static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, return 0; } +static int rspi_pio_transfer_in_or_our(struct rspi_data *rspi, const u8 *tx, + u8 *rx, unsigned int n) +{ + unsigned int i, len; + int ret; + + while (n > 0) { + if (tx) { + len = qspi_set_send_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_tx_empty(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "transmit timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + rspi_write_data(rspi, *tx++); + } else { + ret = rspi_pio_transfer(rspi, tx, NULL, n); + if (ret < 0) + return ret; + } + } + if (rx) { + len = qspi_set_receive_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_rx_full(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "receive timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + *rx++ = rspi_read_data(rspi); + } else { + ret = rspi_pio_transfer(rspi, NULL, rx, n); + if (ret < 0) + return ret; + *rx++ = ret; + } + } + n -= len; + } + return 0; +} + static void rspi_dma_complete(void *arg) { struct rspi_data *rspi = arg; @@ -793,7 +839,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) return ret; } - ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len); + ret = rspi_pio_transfer_in_or_our(rspi, xfer->tx_buf, NULL, xfer->len); if (ret < 0) return ret; @@ -811,7 +857,7 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) return ret; } - return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len); + return rspi_pio_transfer_in_or_our(rspi, NULL, xfer->rx_buf, xfer->len); } static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, From db30083813b559e98e10ae26bd09d3dc69be7fb7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 8 Nov 2016 14:46:12 +0100 Subject: [PATCH 2/5] spi: rspi: avoid uninitialized variable access The newly introduced rspi_pio_transfer_in_or_our() function must take either a valid 'rx' or 'tx' pointer, and has undefined behavior if both are NULL, as found by 'gcc -Wmaybe-unintialized': drivers/spi/spi-rspi.c: In function 'rspi_pio_transfer_in_or_our': drivers/spi/spi-rspi.c:558:5: error: 'len' may be used uninitialized in this function [-Werror=maybe-uninitialized] The analysis of the function is correct in principle, but the code is currently safe because both callers always pass exactly one of the two pointers. Looking closer at this function shows that having a combined method for rx and tx here actually increases the complexity and the size of the file. This simplifies it again by keeping the two separate, which then ends up avoiding that warning. Fixes: 3be09bec42a8 ("spi: rspi: supports 32bytes buffer for DUAL and QUAD") Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 94 ++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 3bab75ab1b257..9daf500317376 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -515,51 +515,6 @@ static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, return 0; } -static int rspi_pio_transfer_in_or_our(struct rspi_data *rspi, const u8 *tx, - u8 *rx, unsigned int n) -{ - unsigned int i, len; - int ret; - - while (n > 0) { - if (tx) { - len = qspi_set_send_trigger(rspi, n); - if (len == QSPI_BUFFER_SIZE) { - ret = rspi_wait_for_tx_empty(rspi); - if (ret < 0) { - dev_err(&rspi->master->dev, "transmit timeout\n"); - return ret; - } - for (i = 0; i < len; i++) - rspi_write_data(rspi, *tx++); - } else { - ret = rspi_pio_transfer(rspi, tx, NULL, n); - if (ret < 0) - return ret; - } - } - if (rx) { - len = qspi_set_receive_trigger(rspi, n); - if (len == QSPI_BUFFER_SIZE) { - ret = rspi_wait_for_rx_full(rspi); - if (ret < 0) { - dev_err(&rspi->master->dev, "receive timeout\n"); - return ret; - } - for (i = 0; i < len; i++) - *rx++ = rspi_read_data(rspi); - } else { - ret = rspi_pio_transfer(rspi, NULL, rx, n); - if (ret < 0) - return ret; - *rx++ = ret; - } - } - n -= len; - } - return 0; -} - static void rspi_dma_complete(void *arg) { struct rspi_data *rspi = arg; @@ -831,6 +786,9 @@ static int qspi_transfer_out_in(struct rspi_data *rspi, static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) { + const u8 *tx = xfer->tx_buf; + unsigned int n = xfer->len; + unsigned int i, len; int ret; if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { @@ -839,9 +797,23 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) return ret; } - ret = rspi_pio_transfer_in_or_our(rspi, xfer->tx_buf, NULL, xfer->len); - if (ret < 0) - return ret; + while (n > 0) { + len = qspi_set_send_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_tx_empty(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "transmit timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + rspi_write_data(rspi, *tx++); + } else { + ret = rspi_pio_transfer(rspi, tx, NULL, n); + if (ret < 0) + return ret; + } + n -= len; + } /* Wait for the last transmission */ rspi_wait_for_tx_empty(rspi); @@ -851,13 +823,37 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) { + u8 *rx = xfer->rx_buf; + unsigned int n = xfer->len; + unsigned int i, len; + int ret; + if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); if (ret != -EAGAIN) return ret; } - return rspi_pio_transfer_in_or_our(rspi, NULL, xfer->rx_buf, xfer->len); + while (n > 0) { + len = qspi_set_receive_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_rx_full(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "receive timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + *rx++ = rspi_read_data(rspi); + } else { + ret = rspi_pio_transfer(rspi, NULL, rx, n); + if (ret < 0) + return ret; + *rx++ = ret; + } + n -= len; + } + + return 0; } static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, From b099b1319d581243402d8dc56b4237d9928d00ca Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 7 Nov 2016 17:46:52 -0300 Subject: [PATCH 3/5] spi: s3c64xx: Allow driver to build if COMPILE_TEST is enabled The driver only has runtime but no build time dependency with PLAT_SAMSUNG || ARCH_EXYNOS so it can be built for testing purposes if the COMPILE_TEST option is enabled. This is useful to have more build coverage and make sure that the driver is not affected by changes that could cause build regressions. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b7995474148c7..68910915ca49a 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -553,7 +553,7 @@ config SPI_S3C24XX_FIQ config SPI_S3C64XX tristate "Samsung S3C64XX series type SPI" - depends on (PLAT_SAMSUNG || ARCH_EXYNOS) + depends on (PLAT_SAMSUNG || ARCH_EXYNOS || COMPILE_TEST) help SPI driver for Samsung S3C64XX and newer SoCs. From 6906b0ec5cdef784102e7699807df140eeaba133 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 14 Nov 2016 13:24:20 +0200 Subject: [PATCH 4/5] spi: spi-pxa2xx: Remove unused macro IS_DMA_ALIGNED() became unused by the commit 6356437e65c2 ("spi: spi-pxa2xx: remove legacy PXA DMA bits"). Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index ce31b8199bb3b..2823a00a94059 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -109,7 +109,6 @@ static inline void pxa2xx_spi_write(const struct driver_data *drv_data, #define DONE_STATE ((void *)2) #define ERROR_STATE ((void *)-1) -#define IS_DMA_ALIGNED(x) IS_ALIGNED((unsigned long)(x), DMA_ALIGNMENT) #define DMA_ALIGNMENT 8 static inline int pxa25x_ssp_comp(struct driver_data *drv_data) From 73482910587444c5600c9d6851ec056fc2ad38c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 30 Nov 2016 11:47:44 +0100 Subject: [PATCH 5/5] spi: orion: fix comment to mention MVEBU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MVEBU chips (Armada XP, Armada 370 and others) are supported by this driver. Mention this in the help text to make more obvious what is already specified in the dependencies of this symbol. Signed-off-by: Uwe Kleine-König Acked-by: Gregory CLEMENT Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b7995474148c7..2b0119150bde0 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -451,7 +451,8 @@ config SPI_ORION tristate "Orion SPI master" depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST help - This enables using the SPI master controller on the Orion chips. + This enables using the SPI master controller on the Orion + and MVEBU chips. config SPI_PIC32 tristate "Microchip PIC32 series SPI"