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