Signed-off-by: Jiri Vlasak <[email protected]>
---
 arch/arm/src/kinetis/kinetis_spi.c | 267 ++++++++++-------------------
 1 file changed, 90 insertions(+), 177 deletions(-)

diff --git a/arch/arm/src/kinetis/kinetis_spi.c 
b/arch/arm/src/kinetis/kinetis_spi.c
index 5d06ee7c60..50a6890b78 100644
--- a/arch/arm/src/kinetis/kinetis_spi.c
+++ b/arch/arm/src/kinetis/kinetis_spi.c
@@ -133,9 +133,6 @@ static inline void     spi_putreg16(struct kinetis_spidev_s 
*priv,
                                     uint8_t offset, uint16_t value);
 static inline void     spi_putreg8(struct kinetis_spidev_s *priv,
                                    uint8_t offset, uint8_t value);
-static inline uint16_t spi_readword(struct kinetis_spidev_s *priv);
-static inline void     spi_writeword(struct kinetis_spidev_s *priv,
-                                     uint16_t word, bool first_word);
 
 static inline bool     spi_run(struct kinetis_spidev_s *priv,
                                bool enable);
@@ -145,8 +142,6 @@ static inline void     spi_write_status(struct 
kinetis_spidev_s *priv,
                                         uint32_t status);
 static inline void     spi_wait_status(struct kinetis_spidev_s *priv,
                                        uint32_t status);
-static uint16_t        spi_send_data(struct kinetis_spidev_s *priv,
-                                     uint16_t wd, bool last);
 
 /* DMA support */
 
@@ -573,65 +568,6 @@ static inline void spi_write_control(struct 
kinetis_spidev_s *priv,
               (uint16_t) (control >> 16));
 }
 
-/****************************************************************************
- * Name: spi_writeword
- *
- * Description:
- *   Write one word to SPI TX FIFO or single-entry buffer.
- *   In non-FIFO mode, performs 32-bit write including control bits.
- *   In FIFO-enabled mode, writes only the data (control handled separately).
- *
- * Input Parameters:
- *   priv - Device-specific state data
- *   word - word to send
- *   first_word - Flag to set control in case of FIFO disabled
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-
-static inline void spi_writeword(struct kinetis_spidev_s *priv,
-                                 uint16_t word, bool first_word)
-{
-  uint32_t mcr = spi_getreg(priv, KINETIS_SPI_MCR_OFFSET);
-  uint32_t pushr_val;
-
-  /* Wait until there is space in the fifo */
-
-  spi_wait_status(priv, SPI_SR_TFFF);
-
-  /* Write the data to transmitted to the SPI Data Register */
-
-  spi_putreg(priv, KINETIS_SPI_PUSHR_OFFSET,
-             (priv->cmd_info & 0xffff0000) | SPI_PUSHR_TXDATA(word));
-}
-
-/****************************************************************************
- * Name: spi_readword
- *
- * Description:
- *   Read one 16 bit word from SPI RX FIFO
- *
- * Input Parameters:
- *   priv - Device-specific state data
- *
- * Returned Value:
- *   The 8-bit value from the FIFO
- *
- ****************************************************************************/
-
-static inline uint16_t spi_readword(struct kinetis_spidev_s *priv)
-{
-  /* Wait until transfer completes and the data is in the RX FIFO */
-
-  spi_wait_status(priv, SPI_SR_RFDF | SPI_SR_TCF);
-
-  /* Return the data */
-
-  return spi_getreg16(priv, KINETIS_SPI_POPR_OFFSET);
-}
-
 /****************************************************************************
  * Name: spi_run
  *
@@ -1184,66 +1120,6 @@ static int spi_hwfeatures(struct spi_dev_s *dev,
 }
 #endif
 
-/****************************************************************************
- * Name: spi_send_data
- *
- * Description:
- *   Exchange one word on SPI
- *
- * Input Parameters:
- *   priv - Device-specific state data
- *   wd  - The word to send.  the size of the data is determined by the
- *         number of bits selected for the SPI interface.
- *
- * Returned Value:
- *   response
- *
- ****************************************************************************/
-
-static uint16_t spi_send_data(struct kinetis_spidev_s *priv, uint16_t wd,
-                              bool last)
-{
-  uint16_t ret;
-  uint32_t mcr = spi_getreg(priv, KINETIS_SPI_MCR_OFFSET);
-  bool first_word = false;
-
-  /* Start module and write control if FIFO enabled on first transfer */
-
-  if ((spi_getreg(priv, KINETIS_SPI_SR_OFFSET) & SPI_SR_TXRXS) == 0)
-    {
-      spi_run(priv, true);
-      first_word = true;
-
-      if ((mcr & SPI_MCR_DIS_TXF) == 0)
-        {
-          /* FIFO enabled: safe to write control separately */
-
-          spi_write_control(priv, SPI_PUSHR_CTAS_CTAR0 | SPI_PUSHR_CTCNT);
-        }
-
-      /* Non-FIFO mode: first_word flag used in spi_writeword() */
-    }
-
-  spi_writeword(priv, wd, first_word);
-  ret = spi_readword(priv);
-
-  if (!last)
-    {
-      /* Clear the Transfer complete and the RX FIFO RDY */
-
-      spi_write_status(priv, SPI_SR_TCF | SPI_SR_RFDF);
-    }
-  else
-    {
-      /* Clear all status */
-
-      spi_write_status(priv, spi_getreg(priv, KINETIS_SPI_SR_OFFSET));
-      spi_run(priv, false);
-    }
-
-  return ret;
-}
-
 /****************************************************************************
  * Name: spi_send
  *
@@ -1262,9 +1138,9 @@ static uint16_t spi_send_data(struct kinetis_spidev_s 
*priv, uint16_t wd,
 
 static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
 {
-  struct kinetis_spidev_s *priv = (struct kinetis_spidev_s *)dev;
-
-  return (uint32_t)spi_send_data(priv, (uint16_t)wd, true);
+  uint32_t rx = 0;
+  spi_exchange(dev, &wd, &rx, 1);
+  return rx;
 }
 
 /****************************************************************************
@@ -1298,74 +1174,111 @@ static void spi_exchange_nodma(struct spi_dev_s *dev,
 #endif
 {
   struct kinetis_spidev_s *priv = (struct kinetis_spidev_s *)dev;
-  uint8_t        *brxptr = (uint8_t *)rxbuffer;
-  const uint8_t  *btxptr = (uint8_t *)txbuffer;
-  uint16_t       *wrxptr = (uint16_t *)rxbuffer;
-  const uint16_t *wtxptr = (const uint16_t *)txbuffer;
-  uint8_t         byte;
-  uint16_t        word;
-
-  spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
+  uint32_t        word = 0;
+  size_t          nwords_original = nwords;
+  uint8_t        *brxptr = NULL;
+  const uint8_t  *btxptr = NULL;
+  uint16_t       *wrxptr = NULL;
+  const uint16_t *wtxptr = NULL;
 
   if (priv->nbits > 8)
     {
       /* 16-bit mode */
 
-      while (nwords-- > 0)
-        {
-          /* Get the next word to write.  Is there a source buffer? */
-
-          if (wtxptr)
-            {
-              word = *wtxptr++;
-            }
-          else
-            {
-              word = 0xffff;
-            }
-
-          /* Exchange one word */
-
-          word = spi_send_data(priv, word, nwords ? false : true);
-
-          /* Is there a buffer to receive the return value? */
-
-          if (wrxptr)
-            {
-              *wrxptr++ = word;
-            }
-        }
+      wrxptr = (uint16_t *)rxbuffer;
+      wtxptr = (uint16_t const *)txbuffer;
     }
   else
     {
       /* 8-bit mode */
 
-      while (nwords-- > 0)
+      brxptr = (uint8_t *)rxbuffer;
+      btxptr = (uint8_t const *)txbuffer;
+    }
+
+  spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
+
+  spi_run(priv, true);
+  spi_flush(dev);
+
+  while (nwords-- > 0)
+    {
+      word = priv->cmd_info & 0xffff0000;
+
+      if (nwords == nwords_original)
         {
-          /* Get the next word to write.  Is there a source buffer? */
+          /* This is the first frame. Clear CTCNT. */
 
-          if (btxptr)
-            {
-              byte = *btxptr++;
-            }
-          else
-            {
-              byte = 0xff;
-            }
+          word |= SPI_PUSHR_CTCNT;
+        }
 
-          /* Exchange one word */
+      if (nwords == 0)
+        {
+          /* This is the last frame. Set EOQ. */
 
-          byte = (uint8_t) spi_send_data(priv, (uint16_t)byte,
-                                         nwords ? false : true);
+          word |= SPI_PUSHR_EOQ;
+        }
 
-          /* Is there a buffer to receive the return value? */
+      if (btxptr)
+        {
+          word |= SPI_PUSHR_TXDATA(*btxptr++);
+        }
+      else if (wtxptr)
+        {
+          word |= SPI_PUSHR_TXDATA(*wtxptr++);
+        }
+      else
+        {
+          word |= 0xffff;
+        }
 
-          if (brxptr)
-            {
-              *brxptr++ = byte;
-            }
+      /* Wait until there is space in the TX FIFO. */
+
+      spi_wait_status(priv, SPI_SR_TFFF);
+
+      /* TCF remains set until cleared, so clear it. */
+
+      spi_write_status(priv, SPI_SR_TCF);
+
+      /* Write the data to be transmitted. */
+
+      spi_putreg(priv, KINETIS_SPI_PUSHR_OFFSET, word);
+
+      /* Wait until transfer completes and new data is in the RX FIFO. */
+
+      spi_wait_status(priv, SPI_SR_TCF | SPI_SR_RFDF);
+
+      /* Read new data from the RX FIFO. */
+
+      word = spi_getreg(priv, KINETIS_SPI_POPR_OFFSET);
+
+      /* There should be no data, because POPR read and SPI_MCR_DIS_RXF. */
+
+      DEBUGASSERT(0 == (spi_getreg(priv, KINETIS_SPI_SR_OFFSET)
+                        & SPI_SR_RXCTR_MASK));
+
+      /* Data taken from the RX FIFO, so clear the RFDF. */
+
+      spi_write_status(priv, SPI_SR_RFDF);
+
+      if (brxptr)
+        {
+          *brxptr++ = (uint8_t)word;
+        }
+      else if (wrxptr)
+        {
+          *wrxptr++ = (uint16_t)word;
+        }
+
+      if (nwords == 0)
+        {
+          /* Last frame. EOQF remains set until cleared, so clear it. */
+
+          spi_write_status(priv, SPI_SR_EOQF);
         }
     }
+
+  spi_run(priv, false);
 }
 
 /****************************************************************************
-- 
2.47.3

Reply via email to