|
12 | 12 | #include <linux/gpio/consumer.h> |
13 | 13 | #include <linux/interrupt.h> |
14 | 14 | #include <linux/io.h> |
| 15 | +#include <linux/kernel.h> |
15 | 16 | #include <linux/module.h> |
16 | 17 | #include <linux/of_irq.h> |
17 | 18 | #include <linux/of_address.h> |
@@ -302,49 +303,43 @@ static int cdns_spi_setup_transfer(struct spi_device *spi, |
302 | 303 | } |
303 | 304 |
|
304 | 305 | /** |
305 | | - * cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible |
| 306 | + * cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO |
306 | 307 | * @xspi: Pointer to the cdns_spi structure |
| 308 | + * @ntx: Number of bytes to pack into the TX FIFO |
| 309 | + * @nrx: Number of bytes to drain from the RX FIFO |
307 | 310 | */ |
308 | | -static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) |
| 311 | +static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx) |
309 | 312 | { |
310 | | - unsigned long trans_cnt = 0; |
| 313 | + ntx = clamp(ntx, 0, xspi->tx_bytes); |
| 314 | + nrx = clamp(nrx, 0, xspi->rx_bytes); |
311 | 315 |
|
312 | | - while ((trans_cnt < xspi->tx_fifo_depth) && |
313 | | - (xspi->tx_bytes > 0)) { |
| 316 | + xspi->tx_bytes -= ntx; |
| 317 | + xspi->rx_bytes -= nrx; |
314 | 318 |
|
| 319 | + while (ntx || nrx) { |
315 | 320 | /* When xspi in busy condition, bytes may send failed, |
316 | 321 | * then spi control did't work thoroughly, add one byte delay |
317 | 322 | */ |
318 | | - if (cdns_spi_read(xspi, CDNS_SPI_ISR) & |
319 | | - CDNS_SPI_IXR_TXFULL) |
| 323 | + if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL) |
320 | 324 | udelay(10); |
321 | 325 |
|
322 | | - if (xspi->txbuf) |
323 | | - cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); |
324 | | - else |
325 | | - cdns_spi_write(xspi, CDNS_SPI_TXD, 0); |
| 326 | + if (ntx) { |
| 327 | + if (xspi->txbuf) |
| 328 | + cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); |
| 329 | + else |
| 330 | + cdns_spi_write(xspi, CDNS_SPI_TXD, 0); |
326 | 331 |
|
327 | | - xspi->tx_bytes--; |
328 | | - trans_cnt++; |
329 | | - } |
330 | | -} |
| 332 | + ntx--; |
| 333 | + } |
331 | 334 |
|
332 | | -/** |
333 | | - * cdns_spi_read_rx_fifo - Reads the RX FIFO with as many bytes as possible |
334 | | - * @xspi: Pointer to the cdns_spi structure |
335 | | - * @count: Read byte count |
336 | | - */ |
337 | | -static void cdns_spi_read_rx_fifo(struct cdns_spi *xspi, unsigned long count) |
338 | | -{ |
339 | | - u8 data; |
340 | | - |
341 | | - /* Read out the data from the RX FIFO */ |
342 | | - while (count > 0) { |
343 | | - data = cdns_spi_read(xspi, CDNS_SPI_RXD); |
344 | | - if (xspi->rxbuf) |
345 | | - *xspi->rxbuf++ = data; |
346 | | - xspi->rx_bytes--; |
347 | | - count--; |
| 335 | + if (nrx) { |
| 336 | + u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD); |
| 337 | + |
| 338 | + if (xspi->rxbuf) |
| 339 | + *xspi->rxbuf++ = data; |
| 340 | + |
| 341 | + nrx--; |
| 342 | + } |
348 | 343 | } |
349 | 344 | } |
350 | 345 |
|
@@ -382,33 +377,22 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) |
382 | 377 | spi_finalize_current_transfer(ctlr); |
383 | 378 | status = IRQ_HANDLED; |
384 | 379 | } else if (intr_status & CDNS_SPI_IXR_TXOW) { |
385 | | - int trans_cnt = cdns_spi_read(xspi, CDNS_SPI_THLD); |
| 380 | + int threshold = cdns_spi_read(xspi, CDNS_SPI_THLD); |
| 381 | + int trans_cnt = xspi->rx_bytes - xspi->tx_bytes; |
| 382 | + |
| 383 | + if (threshold > 1) |
| 384 | + trans_cnt -= threshold; |
| 385 | + |
386 | 386 | /* Set threshold to one if number of pending are |
387 | 387 | * less than half fifo |
388 | 388 | */ |
389 | 389 | if (xspi->tx_bytes < xspi->tx_fifo_depth >> 1) |
390 | 390 | cdns_spi_write(xspi, CDNS_SPI_THLD, 1); |
391 | 391 |
|
392 | | - while (trans_cnt) { |
393 | | - cdns_spi_read_rx_fifo(xspi, 1); |
394 | | - |
395 | | - if (xspi->tx_bytes) { |
396 | | - if (xspi->txbuf) |
397 | | - cdns_spi_write(xspi, CDNS_SPI_TXD, |
398 | | - *xspi->txbuf++); |
399 | | - else |
400 | | - cdns_spi_write(xspi, CDNS_SPI_TXD, 0); |
401 | | - xspi->tx_bytes--; |
402 | | - } |
403 | | - trans_cnt--; |
404 | | - } |
405 | | - if (!xspi->tx_bytes) { |
406 | | - /* Fixed delay due to controller limitation with |
407 | | - * RX_NEMPTY incorrect status |
408 | | - * Xilinx AR:65885 contains more details |
409 | | - */ |
410 | | - udelay(10); |
411 | | - cdns_spi_read_rx_fifo(xspi, xspi->rx_bytes); |
| 392 | + if (xspi->tx_bytes) { |
| 393 | + cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt); |
| 394 | + } else { |
| 395 | + cdns_spi_process_fifo(xspi, 0, trans_cnt); |
412 | 396 | cdns_spi_write(xspi, CDNS_SPI_IDR, |
413 | 397 | CDNS_SPI_IXR_DEFAULT); |
414 | 398 | spi_finalize_current_transfer(ctlr); |
@@ -451,16 +435,17 @@ static int cdns_transfer_one(struct spi_controller *ctlr, |
451 | 435 | xspi->tx_bytes = transfer->len; |
452 | 436 | xspi->rx_bytes = transfer->len; |
453 | 437 |
|
454 | | - if (!spi_controller_is_slave(ctlr)) |
| 438 | + if (!spi_controller_is_slave(ctlr)) { |
455 | 439 | cdns_spi_setup_transfer(spi, transfer); |
| 440 | + } else { |
| 441 | + /* Set TX empty threshold to half of FIFO depth |
| 442 | + * only if TX bytes are more than half FIFO depth. |
| 443 | + */ |
| 444 | + if (xspi->tx_bytes > xspi->tx_fifo_depth) |
| 445 | + cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1); |
| 446 | + } |
456 | 447 |
|
457 | | - /* Set TX empty threshold to half of FIFO depth |
458 | | - * only if TX bytes are more than half FIFO depth. |
459 | | - */ |
460 | | - if (xspi->tx_bytes > (xspi->tx_fifo_depth >> 1)) |
461 | | - cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1); |
462 | | - |
463 | | - cdns_spi_fill_tx_fifo(xspi); |
| 448 | + cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0); |
464 | 449 | spi_transfer_delay_exec(transfer); |
465 | 450 |
|
466 | 451 | cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT); |
|
0 commit comments