This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 9be93addea mpfs/mpfs_corespi: Several speed optimizations to the FPGA 
driver
9be93addea is described below

commit 9be93addea69850defa8fbba77416efb363f8b46
Author: Ville Juven <[email protected]>
AuthorDate: Fri Sep 22 14:34:22 2023 +0300

    mpfs/mpfs_corespi: Several speed optimizations to the FPGA driver
    
    This is a collection of tweaks / optimizations to the driver to limit
    CPU usage as well as interrupt processing times.
    
    The changes are as follows:
    - setfrequency is now no-op if the frequency does not change. Accessing
      MPFS_SPI_CONTROL requires synchronization to the FIC domain, which
      takes unnecessary time if nothing changes
    - load/unload FIFO loops optimized so !buffer, priv->nbits and i==last are
      only tested once (instead of for every word written in loop).
    - Disable the RX interrupt only once (again, FIC domain access is slow)
    - In case a spurious MPFS_SPI_DATA_RX interrupt arrives, just wipe the
      whole RX FIFO, instead of trying to read it byte-by-byte
---
 arch/risc-v/src/mpfs/mpfs_corespi.c | 139 +++++++++++++++---------------------
 1 file changed, 57 insertions(+), 82 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_corespi.c 
b/arch/risc-v/src/mpfs/mpfs_corespi.c
index a14b5cb634..65c566a6d5 100644
--- a/arch/risc-v/src/mpfs/mpfs_corespi.c
+++ b/arch/risc-v/src/mpfs/mpfs_corespi.c
@@ -529,6 +529,13 @@ static uint32_t mpfs_spi_setfrequency(struct spi_dev_s 
*dev,
 
   DEBUGASSERT(frequency > 0);
 
+  if (priv->frequency == frequency)
+    {
+      /* Nothing changes */
+
+      return priv->actual;
+    }
+
   if (priv->enabled)
     {
       modifyreg32(MPFS_SPI_CONTROL, MPFS_SPI_ENABLE, 0);
@@ -739,54 +746,38 @@ static void mpfs_spi_load_tx_fifo(struct mpfs_spi_priv_s 
*priv,
 {
   uint16_t *data16;
   uint8_t *data8;
-  int last;
   int i;
 
   DEBUGASSERT(nwords > 0);
   data16 = (uint16_t *)txbuffer;
   data8 = (uint8_t *)txbuffer;
-  last = nwords - 1;
 
-  for (i = 0; i < nwords; i++)
+  if (!txbuffer)
     {
-      if (txbuffer)
+      for (i = 0; i < nwords - 1; i++)
         {
-          if (priv->nbits == 8)
-            {
-              if (i == last)
-                {
-                  putreg32((uint32_t)data8[priv->tx_pos], MPFS_SPI_TX_LAST);
-                }
-              else
-                {
-                  putreg32((uint32_t)data8[priv->tx_pos], MPFS_SPI_TX_DATA);
-                }
-            }
-          else
-            {
-              if (i == last)
-                {
-                  putreg32((uint32_t)data16[priv->tx_pos], MPFS_SPI_TX_LAST);
-                }
-              else
-                {
-                  putreg32((uint32_t)data16[priv->tx_pos], MPFS_SPI_TX_DATA);
-                }
-            }
+          putreg32(0, MPFS_SPI_TX_DATA);
         }
-      else
+
+      putreg32(0, MPFS_SPI_TX_LAST);
+    }
+  else if (priv->nbits == 8)
+    {
+      for (i = 0; i < nwords - 1; i++)
         {
-          if (i == last)
-            {
-              putreg32(0, MPFS_SPI_TX_LAST);
-            }
-          else
-            {
-              putreg32(0, MPFS_SPI_TX_DATA);
-            }
+          putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_DATA);
+        }
+
+      putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_LAST);
+    }
+  else
+    {
+      for (i = 0; i < nwords - 1; i++)
+        {
+          putreg32((uint32_t)data16[priv->tx_pos++], MPFS_SPI_TX_DATA);
         }
 
-      priv->tx_pos++;
+      putreg32((uint32_t)data16[priv->tx_pos++], MPFS_SPI_TX_LAST);
     }
 }
 
@@ -813,48 +804,40 @@ static void mpfs_spi_unload_rx_fifo(struct 
mpfs_spi_priv_s *priv,
 {
   uint16_t *data16;
   uint8_t *data8;
-  int last;
   int i;
 
   DEBUGASSERT(nwords > 0);
 
   data16 = (uint16_t *)rxbuffer;
   data8 = (uint8_t *)rxbuffer;
-  last = nwords - 1;
 
-  for (i = 0; i < nwords; i++)
+  if (!rxbuffer)
     {
-      /* The last character might not be available yet due to bus delays */
-
-      if (i == last)
+      modifyreg32(MPFS_SPI_COMMAND, 0, MPFS_SPI_RXFIFORST);
+    }
+  else if (priv->nbits == 8)
+    {
+      for (i = 0; i < nwords - 1; i++)
         {
-          if (mpfs_rx_wait_last_frame(priv) < 0)
-            {
-              /* Nothing came, get out */
-
-              return;
-            }
+          data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
         }
 
-      if (rxbuffer)
+      if (mpfs_rx_wait_last_frame(priv) == 0)
         {
-          if (priv->nbits == 8)
-            {
-              data8[priv->rx_pos] = getreg32(MPFS_SPI_RX_DATA);
-            }
-          else
-            {
-              data16[priv->rx_pos] = getreg32(MPFS_SPI_RX_DATA);
-            }
+          data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
         }
-      else
+    }
+  else if (priv->nbits == 16)
+    {
+      for (i = 0; i < nwords - 1; i++)
         {
-          getreg32(MPFS_SPI_RX_DATA);
+          data16[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
         }
 
-      priv->rx_pos++;
-
-      DEBUGASSERT(priv->rx_pos <= priv->rxwords);
+      if (mpfs_rx_wait_last_frame(priv) == 0)
+        {
+          data16[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
+        }
     }
 }
 
@@ -935,10 +918,6 @@ static void mpfs_spi_irq_exchange(struct mpfs_spi_priv_s 
*priv,
                                    MPFS_SPI_INTRXOVRFLOW |
                                    MPFS_SPI_INTTXDONE);
 
-  /* Make sure the RX interrupt is disabled */
-
-  modifyreg32(MPFS_SPI_CONTROL2, MPFS_SPI_INTEN_DATA_RX, 0);
-
   if (mpfs_spi_sem_waitdone(priv) < 0)
     {
       spiinfo("Message timed out\n");
@@ -1304,22 +1283,6 @@ static int mpfs_spi_irq(int cpuint, void *context, void 
*arg)
 
   spiinfo("irq status=%x\n", status);
 
-  if (status & MPFS_SPI_DATA_RX)
-    {
-      remaining = priv->rxwords - priv->rx_pos;
-
-      if (remaining <= priv->fifosize)
-        {
-          mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, remaining);
-        }
-      else
-        {
-          mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, priv->fifolevel);
-        }
-
-      putreg32(MPFS_SPI_DATA_RX, MPFS_SPI_INT_CLEAR);
-    }
-
   if (status & MPFS_SPI_TXDONE)
     {
       /* TX is done, we know RX is done too -> offload the RX FIFO */
@@ -1357,6 +1320,14 @@ static int mpfs_spi_irq(int cpuint, void *context, void 
*arg)
         }
     }
 
+  if (status & MPFS_SPI_DATA_RX)
+    {
+      /* We don't expect data RX interrupts, just reset RX FIFO */
+
+      modifyreg32(MPFS_SPI_COMMAND, 0, MPFS_SPI_RXFIFORST);
+      putreg32(MPFS_SPI_DATA_RX, MPFS_SPI_INT_CLEAR);
+    }
+
   if (status & MPFS_SPI_RXCHOVRFLW)
     {
       /* Handle receive overflow */
@@ -1449,6 +1420,10 @@ static void mpfs_spi_init(struct spi_dev_s *dev)
               0);
   modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, MPFS_SYSREG_SUBBLK_CORESPI);
 
+  /* Make sure the RX interrupt is disabled (we don't use it) */
+
+  modifyreg32(MPFS_SPI_CONTROL2, MPFS_SPI_INTEN_DATA_RX, 0);
+
   /* Install some default values, mode and nbits for read back */
 
   mpfs_spi_setfrequency(dev, config->clk_freq);

Reply via email to