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