Skip to content

Commit a84c11e

Browse files
charleskeepaxbroonie
authored andcommitted
spi: spi-cadence: Avoid read of RX FIFO before its ready
Recent changes to cdns_spi_irq introduced some issues. Firstly, when writing the end of a longer transaction, the code in cdns_spi_irq will write data into the TX FIFO, then immediately fall into the if (!xspi->tx_bytes) path and attempt to read data from the RX FIFO. However this required waiting for the TX FIFO to empty before the RX data was ready. Secondly, the variable trans_cnt is now rather inaccurately named since in cases, where the watermark is set to 1, trans_cnt will be 1 but the count of bytes transferred would be much longer. Finally, when setting up the transaction we set the watermark to 50% of the FIFO if the transaction is great than 50% of the FIFO. However, there is no need to split a tranaction that is smaller than the whole FIFO, so anything up to the FIFO size can be done in a single transaction. Tidy up the code a little, to avoid repeatedly calling cdns_spi_read_rx_fifo with a count of 1, and correct the three issues noted above. Fixes: b1b9051 ("spi: spi-cadence: Add support for Slave mode") Signed-off-by: Charles Keepax <[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]
1 parent 4c329f5 commit a84c11e

File tree

1 file changed

+15
-27
lines changed

1 file changed

+15
-27
lines changed

drivers/spi/spi-cadence.c

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -304,13 +304,11 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,
304304
* cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
305305
* @xspi: Pointer to the cdns_spi structure
306306
*/
307-
static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
307+
static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi, unsigned int avail)
308308
{
309309
unsigned long trans_cnt = 0;
310310

311-
while ((trans_cnt < xspi->tx_fifo_depth) &&
312-
(xspi->tx_bytes > 0)) {
313-
311+
while ((trans_cnt < avail) && (xspi->tx_bytes > 0)) {
314312
/* When xspi in busy condition, bytes may send failed,
315313
* then spi control did't work thoroughly, add one byte delay
316314
*/
@@ -381,33 +379,23 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
381379
spi_finalize_current_transfer(ctlr);
382380
status = IRQ_HANDLED;
383381
} else if (intr_status & CDNS_SPI_IXR_TXOW) {
384-
int trans_cnt = cdns_spi_read(xspi, CDNS_SPI_THLD);
382+
int threshold = cdns_spi_read(xspi, CDNS_SPI_THLD);
383+
int trans_cnt = xspi->rx_bytes - xspi->tx_bytes;
384+
385+
if (threshold > 1)
386+
trans_cnt -= threshold;
387+
385388
/* Set threshold to one if number of pending are
386389
* less than half fifo
387390
*/
388391
if (xspi->tx_bytes < xspi->tx_fifo_depth >> 1)
389392
cdns_spi_write(xspi, CDNS_SPI_THLD, 1);
390393

391-
while (trans_cnt) {
392-
cdns_spi_read_rx_fifo(xspi, 1);
393-
394-
if (xspi->tx_bytes) {
395-
if (xspi->txbuf)
396-
cdns_spi_write(xspi, CDNS_SPI_TXD,
397-
*xspi->txbuf++);
398-
else
399-
cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
400-
xspi->tx_bytes--;
401-
}
402-
trans_cnt--;
403-
}
404-
if (!xspi->tx_bytes) {
405-
/* Fixed delay due to controller limitation with
406-
* RX_NEMPTY incorrect status
407-
* Xilinx AR:65885 contains more details
408-
*/
409-
udelay(10);
410-
cdns_spi_read_rx_fifo(xspi, xspi->rx_bytes);
394+
cdns_spi_read_rx_fifo(xspi, trans_cnt);
395+
396+
if (xspi->tx_bytes) {
397+
cdns_spi_fill_tx_fifo(xspi, trans_cnt);
398+
} else {
411399
cdns_spi_write(xspi, CDNS_SPI_IDR,
412400
CDNS_SPI_IXR_DEFAULT);
413401
spi_finalize_current_transfer(ctlr);
@@ -456,10 +444,10 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
456444
/* Set TX empty threshold to half of FIFO depth
457445
* only if TX bytes are more than half FIFO depth.
458446
*/
459-
if (xspi->tx_bytes > (xspi->tx_fifo_depth >> 1))
447+
if (xspi->tx_bytes > xspi->tx_fifo_depth)
460448
cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
461449

462-
cdns_spi_fill_tx_fifo(xspi);
450+
cdns_spi_fill_tx_fifo(xspi, xspi->tx_fifo_depth);
463451
spi_transfer_delay_exec(transfer);
464452

465453
cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);

0 commit comments

Comments
 (0)