From 5442dcaa0d90fc376bdfc179a018931a8f43dea4 Mon Sep 17 00:00:00 2001 From: Chris Lesiak Date: Thu, 7 Mar 2019 20:39:00 +0000 Subject: spi: Fix zero length xfer bug This fixes a bug for messages containing both zero length and unidirectional xfers. The function spi_map_msg will allocate dummy tx and/or rx buffers for use with unidirectional transfers when the hardware can only do a bidirectional transfer. That dummy buffer will be used in place of a NULL buffer even when the xfer length is 0. Then in the function __spi_map_msg, if he hardware can dma, the zero length xfer will have spi_map_buf called on the dummy buffer. Eventually, __sg_alloc_table is called and returns -EINVAL because nents == 0. This fix prevents the error by not using the dummy buffer when the xfer length is zero. Signed-off-by: Chris Lesiak Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 93986f879b09..2be394d3bc59 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1039,6 +1039,8 @@ static int spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) if (max_tx || max_rx) { list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (!xfer->len) + continue; if (!xfer->tx_buf) xfer->tx_buf = ctlr->dummy_tx; if (!xfer->rx_buf) -- cgit v1.2.3 From c842749ea1d32513f9e603c074d60d7aa07cb2ef Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 4 Mar 2019 20:18:49 +0000 Subject: spi: imx: stop buffer overflow in RX FIFO flush Commit 71abd29057cb ("spi: imx: Add support for SPI Slave mode") added an RX FIFO flush before start of a transfer. In slave mode, the master may have sent more data than expected and this data will still be in the RX FIFO at the start of the next transfer, and so needs to be flushed. However, the code to do the flush was accidentally saving this data into the previous transfer's RX buffer, clobbering the contents of whatever followed that buffer. Change it to empty the FIFO and throw away the data. Every one of the RX functions for the different eCSPI versions and modes reads the RX FIFO data using the same readl() call, so just use that, rather than using the spi_imx->rx function pointer and making sure all the different rx functions have a working "throw away" mode. There is another issue, which affects master mode when switching from DMA to PIO. There can be extra data in the RX FIFO which triggers this flush code, causing memory corruption in the same manner. I don't know why this data is unexpectedly in the FIFO. It's likely there is a different bug or erratum responsible for that. But regardless of that, I think this is proper fix the for bug at hand here. Fixes: 71abd29057cb ("spi: imx: Add support for SPI Slave mode") Cc: Jiada Wang Cc: Fabio Estevam Cc: Stefan Agner Cc: Shawn Guo Signed-off-by: Trent Piepho Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 6ec647bbba77..a81ae29aa68a 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1494,7 +1494,7 @@ static int spi_imx_transfer(struct spi_device *spi, /* flush rxfifo before transfer */ while (spi_imx->devtype_data->rx_available(spi_imx)) - spi_imx->rx(spi_imx); + readl(spi_imx->base + MXC_CSPIRXDATA); if (spi_imx->slave_mode) return spi_imx_pio_transfer_slave(spi, transfer); -- cgit v1.2.3 From 42bdaaece121b3bb50fd4d1203d6d0170279f9fa Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Mar 2019 19:43:31 +0100 Subject: spi: rspi: Fix register initialization while runtime-suspended The Renesas RSPI/QSPI driver performs SPI controller register initialization in its spi_operations.setup() callback, without calling pm_runtime_get_sync() first, which may cause spurious failures. So far this went unnoticed, as this SPI controller is typically used with a single SPI NOR FLASH containing the boot loader: 1. If the device's module clock is still enabled (left enabled by the bootloader, and not yet disabled by the clk_disable_unused() late initcall), register initialization succeeds, 2. If the device's module clock is disabled, register writes don't seem to cause lock-ups or crashes. Data received in the first SPI message may be corrupted, though. Subsequent SPI messages seem to be OK. E.g. on r8a7791/koelsch, one bit is lost while receiving the 6th byte of the JEDEC ID for the s25fl512s FLASH, corrupting that byte and all later bytes. But until commit a2126b0a010905e5 ("mtd: spi-nor: refine Spansion S25FL512S ID"), the 6th byte was not considered for FLASH identification. Fix this by moving all initialization from the .setup() to the .prepare_message() callback. The latter is always called after the device has been runtime-resumed by the SPI core. This also makes the driver follow the rule that .setup() must not change global driver state or register values, as that might break a transfer in progress. Fixes: 490c97747d5dc77d ("spi: rspi: Add runtime PM support, using spi core auto_runtime_pm") Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 556870dcdf79..b30fed824e66 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -868,28 +868,6 @@ static int qspi_transfer_one(struct spi_controller *ctlr, } } -static int rspi_setup(struct spi_device *spi) -{ - struct rspi_data *rspi = spi_controller_get_devdata(spi->controller); - - rspi->max_speed_hz = spi->max_speed_hz; - - rspi->spcmd = SPCMD_SSLKP; - if (spi->mode & SPI_CPOL) - rspi->spcmd |= SPCMD_CPOL; - if (spi->mode & SPI_CPHA) - rspi->spcmd |= SPCMD_CPHA; - - /* CMOS output mode and MOSI signal from previous transfer */ - rspi->sppcr = 0; - if (spi->mode & SPI_LOOP) - rspi->sppcr |= SPPCR_SPLP; - - set_config_register(rspi, 8); - - return 0; -} - static u16 qspi_transfer_mode(const struct spi_transfer *xfer) { if (xfer->tx_buf) @@ -959,8 +937,24 @@ static int rspi_prepare_message(struct spi_controller *ctlr, struct spi_message *msg) { struct rspi_data *rspi = spi_controller_get_devdata(ctlr); + struct spi_device *spi = msg->spi; int ret; + rspi->max_speed_hz = spi->max_speed_hz; + + rspi->spcmd = SPCMD_SSLKP; + if (spi->mode & SPI_CPOL) + rspi->spcmd |= SPCMD_CPOL; + if (spi->mode & SPI_CPHA) + rspi->spcmd |= SPCMD_CPHA; + + /* CMOS output mode and MOSI signal from previous transfer */ + rspi->sppcr = 0; + if (spi->mode & SPI_LOOP) + rspi->sppcr |= SPPCR_SPLP; + + set_config_register(rspi, 8); + if (msg->spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) { /* Setup sequencer for messages with multiple transfer modes */ @@ -1267,7 +1261,6 @@ static int rspi_probe(struct platform_device *pdev) init_waitqueue_head(&rspi->wait); ctlr->bus_num = pdev->id; - ctlr->setup = rspi_setup; ctlr->auto_runtime_pm = true; ctlr->transfer_one = ops->transfer_one; ctlr->prepare_message = rspi_prepare_message; -- cgit v1.2.3 From 26843bb128590edd7eba1ad7ce22e4b9f1066ce3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Mar 2019 19:45:13 +0100 Subject: spi: rspi: Fix sequencer reset during initialization While the sequencer is reset after each SPI message since commit 880c6d114fd79a69 ("spi: rspi: Add support for Quad and Dual SPI Transfers on QSPI"), it was never reset for the first message, thus relying on reset state or bootloader settings. Fix this by initializing it explicitly during configuration. Fixes: 0b2182ddac4b8837 ("spi: add support for Renesas RSPI") Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index b30fed824e66..3be8fbe80b08 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -271,7 +271,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size) /* Sets parity, interrupt mask */ rspi_write8(rspi, 0x00, RSPI_SPCR2); - /* Sets SPCMD */ + /* Resets sequencer */ + rspi_write8(rspi, 0, RSPI_SPSCR); rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); @@ -315,7 +316,8 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) rspi_write8(rspi, 0x00, RSPI_SSLND); rspi_write8(rspi, 0x00, RSPI_SPND); - /* Sets SPCMD */ + /* Resets sequencer */ + rspi_write8(rspi, 0, RSPI_SPSCR); rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); @@ -366,7 +368,8 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size) /* Sets buffer to allow normal operation */ rspi_write8(rspi, 0x00, QSPI_SPBFCR); - /* Sets SPCMD */ + /* Resets sequencer */ + rspi_write8(rspi, 0, RSPI_SPSCR); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); /* Sets RSPI mode */ -- cgit v1.2.3 From 5356c2c70e385198e1a753ee364323f2fc01f759 Mon Sep 17 00:00:00 2001 From: Ludovic Barre Date: Fri, 8 Mar 2019 14:12:20 +0100 Subject: spi: spi-mem: stm32-qspi: avoid memory corruption at low frequency This patch solves a memory corruption seen at 8 MHz. To avoid such issue, timeout counter is disabled. Signed-off-by: Ludovic Barre Signed-off-by: Mark Brown --- drivers/spi/spi-stm32-qspi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 3b2a9a6b990d..7354f9d68dba 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -76,7 +76,6 @@ #define QSPI_PSMAR 0x28 #define QSPI_PIR 0x2c #define QSPI_LPTR 0x30 -#define LPTR_DFT_TIMEOUT 0x10 #define STM32_QSPI_MAX_MMAP_SZ SZ_256M #define STM32_QSPI_MAX_NORCHIP 2 @@ -372,8 +371,7 @@ static int stm32_qspi_setup(struct spi_device *spi) flash->presc = presc; mutex_lock(&qspi->lock); - writel_relaxed(LPTR_DFT_TIMEOUT, qspi->io_base + QSPI_LPTR); - cr = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_TCEN | CR_SSHIFT | CR_EN; + cr = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN; writel_relaxed(cr, qspi->io_base + QSPI_CR); /* set dcr fsize to max address */ -- cgit v1.2.3 From f37d8e67f39e6d3eaf4cc5471e8a3d21209843c6 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Wed, 13 Mar 2019 11:55:41 -0500 Subject: spi : spi-topcliff-pch: Fix to handle empty DMA buffers pch_alloc_dma_buf allocated tx, rx DMA buffers which can fail. Further, these buffers are used without a check. The patch checks for these failures and sends the error upstream. Signed-off-by: Aditya Pakki Signed-off-by: Mark Brown --- drivers/spi/spi-topcliff-pch.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index e7e8ea1edcce..fa730a871d25 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1300,18 +1300,27 @@ static void pch_free_dma_buf(struct pch_spi_board_data *board_dat, dma->rx_buf_virt, dma->rx_buf_dma); } -static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat, +static int pch_alloc_dma_buf(struct pch_spi_board_data *board_dat, struct pch_spi_data *data) { struct pch_spi_dma_ctrl *dma; + int ret; dma = &data->dma; + ret = 0; /* Get Consistent memory for Tx DMA */ dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL); + if (!dma->tx_buf_virt) + ret = -ENOMEM; + /* Get Consistent memory for Rx DMA */ dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL); + if (!dma->rx_buf_virt) + ret = -ENOMEM; + + return ret; } static int pch_spi_pd_probe(struct platform_device *plat_dev) @@ -1388,7 +1397,9 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev) if (use_dma) { dev_info(&plat_dev->dev, "Use DMA for data transfers\n"); - pch_alloc_dma_buf(board_dat, data); + ret = pch_alloc_dma_buf(board_dat, data); + if (ret) + goto err_spi_register_master; } ret = spi_register_master(master); -- cgit v1.2.3 From 69c8a9bcb03222ad3b949064ac05de463c7c9aa3 Mon Sep 17 00:00:00 2001 From: Clark Wang Date: Thu, 21 Mar 2019 09:57:12 +0000 Subject: spi: lpspi: fix dataloss when SS is inactivated between every words If we don't use CONT to keep SS activated or use DMA mode without cs-gpio, SS will be inactivated between every words. The word here means the data sent once which length can be set as 1/2/4 bytes. In the isr function, we read the FSR_RXCOUNT just behind the fsl_lpspi_read_rx_fifo. This causes the value of FSR_RXCOUNT cannot reflect whether there is still data not sent timely. So do this judgement by FSR_TXCOUNT. Signed-off-by: Clark Wang Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-lpspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 391863914043..9e117c4635d8 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -62,7 +62,7 @@ #define CFGR1_PCSPOL BIT(8) #define CFGR1_NOSTALL BIT(3) #define CFGR1_MASTER BIT(0) -#define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18)) +#define FSR_TXCOUNT (0xFF) #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) #define TCR_CPHA BIT(30) @@ -452,7 +452,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) } if (temp_SR & SR_MBF || - readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) { + readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_TXCOUNT) { writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); return IRQ_HANDLED; -- cgit v1.2.3 From 0e694df356c0a24ca0de27cca8f70d900969988a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randolph=20Maa=C3=9Fen?= Date: Tue, 26 Mar 2019 15:30:50 +0100 Subject: spi: tegra20-slink: change chip select action order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To transfer via SPI the tegra20-slink driver first sets the command register, which contains the chip select value, and after that the command2 register, which contains the chip select line. This leads to a small spike in the chip selct 0 line between the set of the value and the selection of the chip select line. This commit changes the order of the register writes so that first the chip select line is chosen and then the value is set, removing the spike. Signed-off-by: Randolph Maaßen Reviewed-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra20-slink.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 1427f343b39a..6d4679126213 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -717,9 +717,6 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, command2 = tspi->command2_reg; command2 &= ~(SLINK_RXEN | SLINK_TXEN); - tegra_slink_writel(tspi, command, SLINK_COMMAND); - tspi->command_reg = command; - tspi->cur_direction = 0; if (t->rx_buf) { command2 |= SLINK_RXEN; @@ -729,9 +726,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, command2 |= SLINK_TXEN; tspi->cur_direction |= DATA_DIR_TX; } + + /* + * Writing to the command2 register bevore the command register prevents + * a spike in chip_select line 0. This selects the chip_select line + * before changing the chip_select value. + */ tegra_slink_writel(tspi, command2, SLINK_COMMAND2); tspi->command2_reg = command2; + tegra_slink_writel(tspi, command, SLINK_COMMAND); + tspi->command_reg = command; + if (total_fifo_words > SLINK_FIFO_DEPTH) ret = tegra_slink_start_dma_based_transfer(tspi, t); else -- cgit v1.2.3 From 94b18a86eb5c82c5778bfb1ce815651f0e331bb5 Mon Sep 17 00:00:00 2001 From: Cezary Gapinski Date: Tue, 26 Mar 2019 22:48:59 +0100 Subject: spi: pic32: fix dma channels termination When timeout occurs DMA TX and RX channels should be stopped instead of stopping RX channel twice time. Signed-off-by: Cezary Gapinski Signed-off-by: Mark Brown --- drivers/spi/spi-pic32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 131849adc570..d9f374c8b709 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -559,7 +559,7 @@ static int pic32_spi_one_transfer(struct spi_master *master, dev_err(&spi->dev, "wait error/timedout\n"); if (dma_issued) { dmaengine_terminate_all(master->dma_rx); - dmaengine_terminate_all(master->dma_rx); + dmaengine_terminate_all(master->dma_tx); } ret = -ETIMEDOUT; } else { -- cgit v1.2.3 From 7b3d10cdf54b8bc1dc0da21faed9789ac4da3684 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:23 -0700 Subject: spi: tegra114: clear packed bit for unpacked mode Fixes: Clear packed bit when not using packed mode. Packed bit is not cleared when not using packed mode. This results in transfer timeouts for the unpacked mode transfers followed by the packed mode transfers. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index a76acedd7e2f..1435792944c4 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -730,6 +730,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, if (tspi->is_packed) command1 |= SPI_PACKED; + else + command1 &= ~SPI_PACKED; command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN); tspi->cur_direction = 0; -- cgit v1.2.3 From 1a89ac5b91895127f7c586ec5075c3753ca25501 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:24 -0700 Subject: spi: tegra114: fix for unpacked mode transfers Fixes: computation of actual bytes to fill/receive in/from FIFO in unpacked mode when transfer length is not a multiple of requested bits per word. unpacked mode transfers fails when the transfer includes partial bytes in the last word. Total words to be written/read to/from FIFO is computed based on transfer length and bits per word. Unpacked mode includes 0 padding bytes for partial words to align with bits per word and these extra bytes are also accounted for calculating bytes left to transfer in the current driver. This causes extra bytes access of tx/rx buffers along with buffer index position crossing actual length where remain_len becomes negative and due to unsigned type, negative value is a 32 bit representation of signed value and transferred bytes never meets the actual transfer length resulting in transfer timeout and a hang. This patch fixes this with proper computation of the actual bytes to fill in FIFO during transmit and the actual bytes to read from FIFO during receive ignoring 0 padded bytes. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 1435792944c4..876eb2acdef1 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } + + tspi->cur_tx_pos += written_words * tspi->bytes_per_word; } else { + unsigned int write_bytes; max_n_32bit = min(tspi->curr_dma_words, tx_empty_count); written_words = max_n_32bit; nbytes = written_words * tspi->bytes_per_word; + if (nbytes > t->len - tspi->cur_pos) + nbytes = t->len - tspi->cur_pos; + write_bytes = nbytes; for (count = 0; count < max_n_32bit; count++) { u32 x = 0; @@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } + + tspi->cur_tx_pos += write_bytes; } - tspi->cur_tx_pos += written_words * tspi->bytes_per_word; + return written_words; } @@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( for (i = 0; len && (i < 4); i++, len--) *rx_buf++ = (x >> i*8) & 0xFF; } - tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; read_words += tspi->curr_dma_words; + tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; + u8 bytes_per_word = tspi->bytes_per_word; + unsigned int read_bytes; + len = rx_full_count * bytes_per_word; + if (len > t->len - tspi->cur_pos) + len = t->len - tspi->cur_pos; + read_bytes = len; for (count = 0; count < rx_full_count; count++) { u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask; - for (i = 0; (i < tspi->bytes_per_word); i++) + for (i = 0; len && (i < bytes_per_word); i++, len--) *rx_buf++ = (x >> (i*8)) & 0xFF; } - tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word; read_words += rx_full_count; + tspi->cur_rx_pos += read_bytes; } + return read_words; } @@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len); + tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; + unsigned int write_bytes; + if (consume > t->len - tspi->cur_pos) + consume = t->len - tspi->cur_pos; + write_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = 0; @@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tspi->tx_dma_buf[count] = x; } + + tspi->cur_tx_pos += write_bytes; } - tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys, @@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len); + tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; + unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; + unsigned int read_bytes; + if (consume > t->len - tspi->cur_pos) + consume = t->len - tspi->cur_pos; + read_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = tspi->rx_dma_buf[count] & rx_mask; - for (i = 0; (i < tspi->bytes_per_word); i++) + for (i = 0; consume && (i < tspi->bytes_per_word); + i++, consume--) *rx_buf++ = (x >> (i*8)) & 0xFF; } + + tspi->cur_rx_pos += read_bytes; } - tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, -- cgit v1.2.3 From 32bd1a9551cae34e6889afa235c7afdfede9aeac Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:27 -0700 Subject: spi: tegra114: terminate dma and reset on transfer timeout Fixes: terminate DMA and perform controller reset on transfer timeout to clear the FIFO's and errors. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 876eb2acdef1..a6153b905d1a 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -869,7 +869,16 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, if (WARN_ON(ret == 0)) { dev_err(tspi->dev, "spi transfer timeout, err %d\n", ret); + if (tspi->is_curr_dma_xfer && + (tspi->cur_direction & DATA_DIR_TX)) + dmaengine_terminate_all(tspi->tx_dma_chan); + if (tspi->is_curr_dma_xfer && + (tspi->cur_direction & DATA_DIR_RX)) + dmaengine_terminate_all(tspi->rx_dma_chan); ret = -EIO; + reset_control_assert(tspi->rst); + udelay(2); + reset_control_deassert(tspi->rst); goto complete_xfer; } -- cgit v1.2.3 From c4fc9e5b28ff787e35137c2cc13316bb11d7657b Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:28 -0700 Subject: spi: tegra114: flush fifos Fixes: Flush TX and RX FIFOs before start of new transfer and on FIFO overflow or underrun errors. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index a6153b905d1a..28aa080a94ff 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -499,22 +499,37 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len) return 0; } -static int tegra_spi_start_dma_based_transfer( - struct tegra_spi_data *tspi, struct spi_transfer *t) +static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi) { - u32 val; - unsigned int len; - int ret = 0; + unsigned long timeout = jiffies + HZ; u32 status; - /* Make sure that Rx and Tx fifo are empty */ status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { - dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", - (unsigned)status); - return -EIO; + status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH; + tegra_spi_writel(tspi, status, SPI_FIFO_STATUS); + while ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { + status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); + if (time_after(jiffies, timeout)) { + dev_err(tspi->dev, + "timeout waiting for fifo flush\n"); + return -EIO; + } + + udelay(1); + } } + return 0; +} + +static int tegra_spi_start_dma_based_transfer( + struct tegra_spi_data *tspi, struct spi_transfer *t) +{ + u32 val; + unsigned int len; + int ret = 0; + val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1); tegra_spi_writel(tspi, val, SPI_DMA_BLK); @@ -779,6 +794,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n", tspi->def_command1_reg, (unsigned)command1); + ret = tegra_spi_flush_fifos(tspi); + if (ret < 0) + return ret; if (total_fifo_words > SPI_FIFO_DEPTH) ret = tegra_spi_start_dma_based_transfer(tspi, t); else @@ -876,6 +894,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, (tspi->cur_direction & DATA_DIR_RX)) dmaengine_terminate_all(tspi->rx_dma_chan); ret = -EIO; + tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); @@ -929,6 +948,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); + tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); @@ -1001,6 +1021,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); + tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); -- cgit v1.2.3 From f4ce428c41fb22e3ed55496dded94df44cb920fa Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:29 -0700 Subject: spi: tegra114: configure dma burst size to fifo trig level Fixes: Configure DMA burst size to be same as SPI TX/RX trigger levels to avoid mismatch. SPI FIFO trigger levels are calculated based on the transfer length. So this patch moves DMA slave configuration to happen before start of DMAs. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 52 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 28aa080a94ff..05bb2f9bff3c 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -529,6 +529,8 @@ static int tegra_spi_start_dma_based_transfer( u32 val; unsigned int len; int ret = 0; + u8 dma_burst; + struct dma_slave_config dma_sconfig = {0}; val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1); tegra_spi_writel(tspi, val, SPI_DMA_BLK); @@ -540,12 +542,16 @@ static int tegra_spi_start_dma_based_transfer( len = tspi->curr_dma_words * 4; /* Set attention level based on length of transfer */ - if (len & 0xF) + if (len & 0xF) { val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1; - else if (((len) >> 4) & 0x1) + dma_burst = 1; + } else if (((len) >> 4) & 0x1) { val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4; - else + dma_burst = 4; + } else { val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8; + dma_burst = 8; + } if (tspi->cur_direction & DATA_DIR_TX) val |= SPI_IE_TX; @@ -556,7 +562,18 @@ static int tegra_spi_start_dma_based_transfer( tegra_spi_writel(tspi, val, SPI_DMA_CTL); tspi->dma_control_reg = val; + dma_sconfig.device_fc = true; if (tspi->cur_direction & DATA_DIR_TX) { + dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO; + dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_sconfig.dst_maxburst = dma_burst; + ret = dmaengine_slave_config(tspi->tx_dma_chan, &dma_sconfig); + if (ret < 0) { + dev_err(tspi->dev, + "DMA slave config failed: %d\n", ret); + return ret; + } + tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t); ret = tegra_spi_start_tx_dma(tspi, len); if (ret < 0) { @@ -567,6 +584,16 @@ static int tegra_spi_start_dma_based_transfer( } if (tspi->cur_direction & DATA_DIR_RX) { + dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO; + dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_sconfig.src_maxburst = dma_burst; + ret = dmaengine_slave_config(tspi->rx_dma_chan, &dma_sconfig); + if (ret < 0) { + dev_err(tspi->dev, + "DMA slave config failed: %d\n", ret); + return ret; + } + /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, tspi->dma_buf_size, DMA_FROM_DEVICE); @@ -626,7 +653,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, u32 *dma_buf; dma_addr_t dma_phys; int ret; - struct dma_slave_config dma_sconfig; dma_chan = dma_request_slave_channel_reason(tspi->dev, dma_to_memory ? "rx" : "tx"); @@ -646,19 +672,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, return -ENOMEM; } - if (dma_to_memory) { - dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO; - dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_sconfig.src_maxburst = 0; - } else { - dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO; - dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_sconfig.dst_maxburst = 0; - } - - ret = dmaengine_slave_config(dma_chan, &dma_sconfig); - if (ret) - goto scrub; if (dma_to_memory) { tspi->rx_dma_chan = dma_chan; tspi->rx_dma_buf = dma_buf; @@ -669,11 +682,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, tspi->tx_dma_phys = dma_phys; } return 0; - -scrub: - dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys); - dma_release_channel(dma_chan); - return ret; } static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, -- cgit v1.2.3 From 019194933339b3e9b486639c8cb3692020844d65 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:32 -0700 Subject: spi: tegra114: reset controller on probe Fixes: SPI driver can be built as module so perform SPI controller reset on probe to make sure it is in valid state before initiating transfer. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 05bb2f9bff3c..09cfae3abce2 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1136,27 +1136,19 @@ static int tegra_spi_probe(struct platform_device *pdev) spi_irq = platform_get_irq(pdev, 0); tspi->irq = spi_irq; - ret = request_threaded_irq(tspi->irq, tegra_spi_isr, - tegra_spi_isr_thread, IRQF_ONESHOT, - dev_name(&pdev->dev), tspi); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", - tspi->irq); - goto exit_free_master; - } tspi->clk = devm_clk_get(&pdev->dev, "spi"); if (IS_ERR(tspi->clk)) { dev_err(&pdev->dev, "can not get clock\n"); ret = PTR_ERR(tspi->clk); - goto exit_free_irq; + goto exit_free_master; } tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); if (IS_ERR(tspi->rst)) { dev_err(&pdev->dev, "can not get reset\n"); ret = PTR_ERR(tspi->rst); - goto exit_free_irq; + goto exit_free_master; } tspi->max_buf_size = SPI_FIFO_DEPTH << 2; @@ -1164,7 +1156,7 @@ static int tegra_spi_probe(struct platform_device *pdev) ret = tegra_spi_init_dma_param(tspi, true); if (ret < 0) - goto exit_free_irq; + goto exit_free_master; ret = tegra_spi_init_dma_param(tspi, false); if (ret < 0) goto exit_rx_dma_free; @@ -1186,18 +1178,32 @@ static int tegra_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret); goto exit_pm_disable; } + + reset_control_assert(tspi->rst); + udelay(2); + reset_control_deassert(tspi->rst); tspi->def_command1_reg = SPI_M_S; tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); pm_runtime_put(&pdev->dev); + ret = request_threaded_irq(tspi->irq, tegra_spi_isr, + tegra_spi_isr_thread, IRQF_ONESHOT, + dev_name(&pdev->dev), tspi); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", + tspi->irq); + goto exit_pm_disable; + } master->dev.of_node = pdev->dev.of_node; ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); - goto exit_pm_disable; + goto exit_free_irq; } return ret; +exit_free_irq: + free_irq(spi_irq, tspi); exit_pm_disable: pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) @@ -1205,8 +1211,6 @@ exit_pm_disable: tegra_spi_deinit_dma_param(tspi, false); exit_rx_dma_free: tegra_spi_deinit_dma_param(tspi, true); -exit_free_irq: - free_irq(spi_irq, tspi); exit_free_master: spi_master_put(master); return ret; -- cgit v1.2.3 From 807195f2103f8662f8c0f9baf71dd7bc1a6b745b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Apr 2019 16:46:02 +0200 Subject: spi: spi-gpio: Remove spi->controller_data comment The conversion from GPIO numbers to GPIO descriptors removed the use of spi->controller_data, but forgot to update a comment referring to it. Fixes: 9b00bc7b901ff672 ("spi: spi-gpio: Rewrite to use GPIO descriptors") Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 3e98c1a0ba6d..e89348d95817 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -35,7 +35,6 @@ * platform_device->driver_data ... points to spi_gpio * * spi->controller_state ... reserved for bitbang framework code - * spi->controller_data ... holds chipselect GPIO * * spi->master->dev.driver_data ... points to spi_gpio->bitbang */ -- cgit v1.2.3 From 1723fdec5fcbc4de3d26bbb23a9e1704ee258955 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Apr 2019 16:46:56 +0200 Subject: spi: Add missing error handling for CS GPIOs While devm_gpiod_get_index_optional() returns NULL if the GPIO is not present (i.e. -ENOENT), it may still return other error codes, like -EPROBE_DEFER. Currently these are not handled, leading to unrecoverable failures later in case of probe deferral: gpiod_set_consumer_name: invalid GPIO (errorpointer) gpiod_direction_output: invalid GPIO (errorpointer) gpiod_set_value_cansleep: invalid GPIO (errorpointer) gpiod_set_value_cansleep: invalid GPIO (errorpointer) gpiod_set_value_cansleep: invalid GPIO (errorpointer) Detect and propagate errors to fix this. Fixes: f3186dd876697e69 ("spi: Optionally use GPIO descriptors for CS GPIOs") Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2be394d3bc59..7b6494bd8a9b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2197,6 +2197,8 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) */ cs[i] = devm_gpiod_get_index_optional(dev, "cs", i, GPIOD_OUT_LOW); + if (IS_ERR(cs[i])) + return PTR_ERR(cs[i]); if (cs[i]) { /* -- cgit v1.2.3 From f3e182c33e534f4caeb255a3ab927debc0d222aa Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:02 -0700 Subject: spi: tegra114: de-assert CS before SPI mode change With SW CS, during the transfer completion CS is de-asserted by writing default command1 register value to SPI_COMMAND1 register. With this both mode and CS state are set at the same time and if current transfer mode is different to default SPI mode and if mode change happens prior to CS de-assert, clock polarity can change while CS is active before transfer finishes. This causes Slave to see spurious clock edges resulting in data mismatch. This patch fixes this by de-asserting CS before writing SPI_COMMAND1 to its default value so through out the transfer it will be in same SPI mode. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 09cfae3abce2..8de002fc6943 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -856,6 +856,19 @@ static void tegra_spi_transfer_delay(int delay) udelay(delay % 1000); } +static void tegra_spi_transfer_end(struct spi_device *spi) +{ + struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); + int cs_val = (spi->mode & SPI_CS_HIGH) ? 0 : 1; + + if (cs_val) + tspi->command1_reg |= SPI_CS_SW_VAL; + else + tspi->command1_reg &= ~SPI_CS_SW_VAL; + tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1); + tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); +} + static int tegra_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -918,8 +931,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, complete_xfer: if (ret < 0 || skip) { - tegra_spi_writel(tspi, tspi->def_command1_reg, - SPI_COMMAND1); + tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); goto exit; } else if (list_is_last(&xfer->transfer_list, @@ -927,13 +939,11 @@ complete_xfer: if (xfer->cs_change) tspi->cs_control = spi; else { - tegra_spi_writel(tspi, tspi->def_command1_reg, - SPI_COMMAND1); + tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } } else if (xfer->cs_change) { - tegra_spi_writel(tspi, tspi->def_command1_reg, - SPI_COMMAND1); + tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } -- cgit v1.2.3 From a026525d4e45e3d9690bffd0b05d018ff5638b5a Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:03 -0700 Subject: spi: tegra114: avoid reset call in atomic context This patch moves SPI controller reset out of spin lock. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 8de002fc6943..b57f10182fae 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -967,11 +967,12 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); tegra_spi_flush_fifos(tspi); + complete(&tspi->xfer_completion); + spin_unlock_irqrestore(&tspi->lock, flags); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); - complete(&tspi->xfer_completion); - goto exit; + return IRQ_HANDLED; } if (tspi->cur_direction & DATA_DIR_RX) @@ -1040,11 +1041,11 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); tegra_spi_flush_fifos(tspi); + complete(&tspi->xfer_completion); + spin_unlock_irqrestore(&tspi->lock, flags); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); - complete(&tspi->xfer_completion); - spin_unlock_irqrestore(&tspi->lock, flags); return IRQ_HANDLED; } -- cgit v1.2.3 From 29f2133717c527f492933b0622a4aafe0b3cbe9e Mon Sep 17 00:00:00 2001 From: Flavio Suligoi Date: Fri, 12 Apr 2019 09:32:19 +0200 Subject: spi: pxa2xx: fix SCR (divisor) calculation Calculate the divisor for the SCR (Serial Clock Rate), avoiding that the SSP transmission rate can be greater than the device rate. When the division between the SSP clock and the device rate generates a reminder, we have to increment by one the divisor. In this way the resulting SSP clock will never be greater than the device SPI max frequency. For example, with: - ssp_clk = 50 MHz - dev freq = 15 MHz without this patch the SSP clock will be greater than 15 MHz: - 25 MHz for PXA25x_SSP and CE4100_SSP - 16,56 MHz for the others Instead, with this patch, we have in both case an SSP clock of 12.5MHz, so the max rate of the SPI device clock is respected. Signed-off-by: Flavio Suligoi Reviewed-by: Jarkko Nikula Reviewed-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index b6ddba833d02..d2076f2f468f 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -884,10 +884,14 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) rate = min_t(int, ssp_clk, rate); + /* + * Calculate the divisor for the SCR (Serial Clock Rate), avoiding + * that the SSP transmission rate can be greater than the device rate + */ if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP) - return (ssp_clk / (2 * rate) - 1) & 0xff; + return (DIV_ROUND_UP(ssp_clk, 2 * rate) - 1) & 0xff; else - return (ssp_clk / rate - 1) & 0xfff; + return (DIV_ROUND_UP(ssp_clk, rate) - 1) & 0xfff; } static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, -- cgit v1.2.3 From cc1b69fc5f9f52cf18295db05cad57187cee1c1d Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 15 Apr 2019 14:30:26 -0700 Subject: spi: tegra114: fix PIO transfer This patch fixes PIO mode transfer to use PIO bit in SPI_COMMAND1 register. Current driver uses DMA_EN instead of PIO bit. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index b57f10182fae..21e4fdad013f 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -641,8 +641,9 @@ static int tegra_spi_start_cpu_based_transfer( tspi->is_curr_dma_xfer = false; - val |= SPI_DMA_EN; - tegra_spi_writel(tspi, val, SPI_DMA_CTL); + val = tspi->command1_reg; + val |= SPI_PIO; + tegra_spi_writel(tspi, val, SPI_COMMAND1); return 0; } -- cgit v1.2.3 From 8d1467a68426c61807c97163459b481ecb714523 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 24 Apr 2019 14:38:44 +0200 Subject: spi: stm32: return the get_irq error During probe, return the "get_irq" error value instead of -ENOENT. This allows the driver to be defer probed if needed. Signed-off-by: Fabien Dessenne Acked-by: Amelie Delaunay Signed-off-by: Mark Brown --- drivers/spi/spi-stm32.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 4186ed20d796..b222ce8d083e 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1839,8 +1839,9 @@ static int stm32_spi_probe(struct platform_device *pdev) spi->irq = platform_get_irq(pdev, 0); if (spi->irq <= 0) { - dev_err(&pdev->dev, "no irq: %d\n", spi->irq); - ret = -ENOENT; + ret = spi->irq; + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to get irq: %d\n", ret); goto err_master_put; } ret = devm_request_threaded_irq(&pdev->dev, spi->irq, -- cgit v1.2.3 From e5c27498a0403b270620b1a8a0a66e3efc222fb6 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 24 Apr 2019 09:17:59 +0000 Subject: spi: atmel-quadspi: fix crash while suspending atmel_qspi objects are kept in spi_controller objects, so, first get pointer to spi_controller object and then get atmel_qspi object from spi_controller object. Fixes: 2d30ac5ed633 ("mtd: spi-nor: atmel-quadspi: Use spi-mem interface for atmel-quadspi driver") Signed-off-by: Claudiu Beznea Reviewed-by: Tudor Ambarus Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index fffc21cd5f79..b3173ebddade 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -570,7 +570,8 @@ static int atmel_qspi_remove(struct platform_device *pdev) static int __maybe_unused atmel_qspi_suspend(struct device *dev) { - struct atmel_qspi *aq = dev_get_drvdata(dev); + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); clk_disable_unprepare(aq->qspick); clk_disable_unprepare(aq->pclk); @@ -580,7 +581,8 @@ static int __maybe_unused atmel_qspi_suspend(struct device *dev) static int __maybe_unused atmel_qspi_resume(struct device *dev) { - struct atmel_qspi *aq = dev_get_drvdata(dev); + struct spi_controller *ctrl = dev_get_drvdata(dev); + struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); clk_prepare_enable(aq->pclk); clk_prepare_enable(aq->qspick); -- cgit v1.2.3 From 7e95b16625a3659a75c0ba4d5b0802324d16be13 Mon Sep 17 00:00:00 2001 From: Hoan Nguyen An Date: Tue, 23 Apr 2019 18:19:21 +0900 Subject: spi: rspi: Fix handling of QSPI code when transmit and receive Process handling QSPI when transmit/receive at qspi_trigger_transfer_out_in() as follows: Setting the trigger, is the number of bytes in the FIFO buffer to determine when there is an interrupt. Then check if the value of triggering number is 32-bytes or 1-byte, there will be corresponding processing Handling (if (n == QSPI_BUFFER_SIZE) esle) this is unnecessary, leads to the same processing of data transmission or reception, The difference here are with ret = rspi_wait_for_tx_empty(rspi); ret = rspi_wait_for_rx_full(rspi); When the nummber trigger is 32 bytes, we only write into FIFO when the FIFO is completely empty (interrupt transmission), and only receive if FIFO is full of 32 bytes of data. In the case of a nummber trigger that is 1 byte, in principle we still need to process rspi_wait_for_tx_empty/full so that FIFO is empty only with the amount of data we need to write to or equal to the number of bytes we need to receive, There is currently no processing of this. And in the current case with this patch, at this time it only needs at least 1 byte received in FIFO that has interrupt received, or FIFO at least 1bytes free can be written into FIFO, This patch therefore does not affect this processing. So we need to eliminate unnecessary waste processing (if (n == QSPI_BUFFER_SIZE) esle), more precisely in waiting for FIFO status. The same with handling in qspi_transfer_out()/qspi_transfer_in(). Signed-off-by: Hoan Nguyen An Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 71 ++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 3be8fbe80b08..15f5723d9f95 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -739,27 +739,22 @@ static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, while (len > 0) { n = qspi_set_send_trigger(rspi, len); qspi_set_receive_trigger(rspi, len); - if (n == QSPI_BUFFER_SIZE) { - ret = rspi_wait_for_tx_empty(rspi); - if (ret < 0) { - dev_err(&rspi->ctlr->dev, "transmit timeout\n"); - return ret; - } - for (i = 0; i < n; i++) - rspi_write_data(rspi, *tx++); + ret = rspi_wait_for_tx_empty(rspi); + if (ret < 0) { + dev_err(&rspi->ctlr->dev, "transmit timeout\n"); + return ret; + } + for (i = 0; i < n; i++) + rspi_write_data(rspi, *tx++); - ret = rspi_wait_for_rx_full(rspi); - if (ret < 0) { - dev_err(&rspi->ctlr->dev, "receive timeout\n"); - return ret; - } - for (i = 0; i < n; i++) - *rx++ = rspi_read_data(rspi); - } else { - ret = rspi_pio_transfer(rspi, tx, rx, n); - if (ret < 0) - return ret; + ret = rspi_wait_for_rx_full(rspi); + if (ret < 0) { + dev_err(&rspi->ctlr->dev, "receive timeout\n"); + return ret; } + for (i = 0; i < n; i++) + *rx++ = rspi_read_data(rspi); + len -= n; } @@ -796,19 +791,14 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) 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->ctlr->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, len); - if (ret < 0) - return ret; + ret = rspi_wait_for_tx_empty(rspi); + if (ret < 0) { + dev_err(&rspi->ctlr->dev, "transmit timeout\n"); + return ret; } + for (i = 0; i < len; i++) + rspi_write_data(rspi, *tx++); + n -= len; } @@ -833,19 +823,14 @@ static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) 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->ctlr->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, len); - if (ret < 0) - return ret; + ret = rspi_wait_for_rx_full(rspi); + if (ret < 0) { + dev_err(&rspi->ctlr->dev, "receive timeout\n"); + return ret; } + for (i = 0; i < len; i++) + *rx++ = rspi_read_data(rspi); + n -= len; } -- cgit v1.2.3