To modify Ixia port numbers and IP in pod.yaml
[kvmfornfv.git] / kernel / drivers / spi / spi-xilinx.c
index 133f53a..3009121 100644 (file)
@@ -249,23 +249,28 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
        xspi->tx_ptr = t->tx_buf;
        xspi->rx_ptr = t->rx_buf;
        remaining_words = t->len / xspi->bytes_per_word;
-       reinit_completion(&xspi->done);
 
        if (xspi->irq >= 0 &&  remaining_words > xspi->buffer_size) {
+               u32 isr;
                use_irq = true;
-               xspi->write_fn(XSPI_INTR_TX_EMPTY,
-                               xspi->regs + XIPIF_V123B_IISR_OFFSET);
-               /* Enable the global IPIF interrupt */
-               xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
-                               xspi->regs + XIPIF_V123B_DGIER_OFFSET);
                /* Inhibit irq to avoid spurious irqs on tx_empty*/
                cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
                xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
                               xspi->regs + XSPI_CR_OFFSET);
+               /* ACK old irqs (if any) */
+               isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+               if (isr)
+                       xspi->write_fn(isr,
+                                      xspi->regs + XIPIF_V123B_IISR_OFFSET);
+               /* Enable the global IPIF interrupt */
+               xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+                               xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+               reinit_completion(&xspi->done);
        }
 
        while (remaining_words) {
                int n_words, tx_words, rx_words;
+               u32 sr;
 
                n_words = min(remaining_words, xspi->buffer_size);
 
@@ -280,30 +285,41 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
                if (use_irq) {
                        xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
                        wait_for_completion(&xspi->done);
-               } else
-                       while (!(xspi->read_fn(xspi->regs + XSPI_SR_OFFSET) &
-                                               XSPI_SR_TX_EMPTY_MASK))
-                               ;
-
-               /* A transmit has just completed. Process received data and
-                * check for more data to transmit. Always inhibit the
-                * transmitter while the Isr refills the transmit register/FIFO,
-                * or make sure it is stopped if we're done.
-                */
-               if (use_irq)
+                       /* A transmit has just completed. Process received data
+                        * and check for more data to transmit. Always inhibit
+                        * the transmitter while the Isr refills the transmit
+                        * register/FIFO, or make sure it is stopped if we're
+                        * done.
+                        */
                        xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-                              xspi->regs + XSPI_CR_OFFSET);
+                                      xspi->regs + XSPI_CR_OFFSET);
+                       sr = XSPI_SR_TX_EMPTY_MASK;
+               } else
+                       sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
 
                /* Read out all the data from the Rx FIFO */
                rx_words = n_words;
-               while (rx_words--)
-                       xilinx_spi_rx(xspi);
+               while (rx_words) {
+                       if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) {
+                               xilinx_spi_rx(xspi);
+                               rx_words--;
+                               continue;
+                       }
+
+                       sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+                       if (!(sr & XSPI_SR_RX_EMPTY_MASK)) {
+                               xilinx_spi_rx(xspi);
+                               rx_words--;
+                       }
+               }
 
                remaining_words -= n_words;
        }
 
-       if (use_irq)
+       if (use_irq) {
                xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+               xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+       }
 
        return t->len;
 }