Signed-off-by: Jiri Vlasak <[email protected]>
---
arch/arm/src/kinetis/kinetis_spi.c | 53 +++++++++++++++++++++---------
1 file changed, 38 insertions(+), 15 deletions(-)
diff --git a/arch/arm/src/kinetis/kinetis_spi.c
b/arch/arm/src/kinetis/kinetis_spi.c
index 430b3e7bc9..fde628c5b1 100644
--- a/arch/arm/src/kinetis/kinetis_spi.c
+++ b/arch/arm/src/kinetis/kinetis_spi.c
@@ -1293,9 +1293,21 @@ static void spi_exchange_nodma(struct spi_dev_s *dev,
* Description:
* Exchange a block of data on SPI using DMA
*
+ * DMA maps developer's user-space memory txbuffer directly to SPI's PUSHR
+ * register. 8- and 16-bit writes and reads to the PUSHR are bad (8-bit 0xff
+ * write to the PUSHR results in 0xfcffffff in the TX FIFO, effectively
+ * re-using data (low 16 bits of PUSHR) as command information (high 16 bits
+ * of PUSHR), see K60 Reference Manual K60P144M150SF3RM.pdf, 53.3.7.)
+ * Therefore, txbuffer, when not NULL, MUST be 32-bit pointer that includes
+ * both, data and command information.
+ *
+ * When txbuffer != NULL && rxbuffer != NULL, then rxbuffer needs to be
+ * 32-bit pointer, too. If txbuffer == NULL, decide based on the number of
+ * bits transferred over SPI.
+ *
* Input Parameters:
* dev - Device-specific state data
- * txbuffer - A pointer to the buffer of data to be sent
+ * txbuffer - A 32-bit pointer to the buffer of cmd info and data to be sent
* rxbuffer - A pointer to a buffer in which to receive data
* nwords - the length of data to be exchanged in units of words.
* The wordsize is determined by the number of bits-per-word
@@ -1316,7 +1328,7 @@ static void spi_exchange(struct spi_dev_s *dev, const
void *txbuffer,
size_t adjust;
ssize_t nbytes;
static uint8_t rxdummy[4] aligned_data(4);
- static const uint16_t txdummy = 0xffff;
+ static const uint32_t txdummy = 0x0000ffff;
struct kinetis_spidev_s *priv = (struct kinetis_spidev_s *)dev;
DEBUGASSERT(priv != NULL);
@@ -1374,11 +1386,15 @@ static void spi_exchange(struct spi_dev_s *dev, const
void *txbuffer,
config.daddr = (uint32_t) (rxbuffer ? rxbuffer : rxdummy);
config.soff = 0;
config.doff = rxbuffer ? adjust : 0;
- config.iter = nbytes;
+ config.iter = txbuffer ? nwords : nbytes;
config.flags = EDMA_CONFIG_LINKTYPE_LINKNONE;
- config.ssize = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
- config.dsize = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
- config.nbytes = adjust;
+ config.ssize = txbuffer
+ ? EDMA_32BIT
+ : (adjust == 1 ? EDMA_8BIT : EDMA_16BIT);
+ config.dsize = txbuffer
+ ? EDMA_32BIT
+ : (adjust == 1 ? EDMA_8BIT : EDMA_16BIT);
+ config.nbytes = txbuffer ? 4 : adjust;
#ifdef CONFIG_KINETIS_EDMA_ELINK
config.linkch = NULL;
#endif
@@ -1390,13 +1406,17 @@ static void spi_exchange(struct spi_dev_s *dev, const
void *txbuffer,
config.saddr = (uint32_t) (txbuffer ? txbuffer : &txdummy);
config.daddr = priv->spibase + KINETIS_SPI_PUSHR_OFFSET;
- config.soff = txbuffer ? adjust : 0;
+ config.soff = txbuffer ? 4 : 0;
config.doff = 0;
- config.iter = nbytes;
+ config.iter = txbuffer ? nwords : nbytes;
config.flags = EDMA_CONFIG_LINKTYPE_LINKNONE;
- config.ssize = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
- config.dsize = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
- config.nbytes = adjust;
+ config.ssize = txbuffer
+ ? EDMA_32BIT
+ : (adjust == 1 ? EDMA_8BIT : EDMA_16BIT);
+ config.dsize = txbuffer
+ ? EDMA_32BIT
+ : (adjust == 1 ? EDMA_8BIT : EDMA_16BIT);
+ config.nbytes = txbuffer ? 4 : adjust;
#ifdef CONFIG_KINETIS_EDMA_ELINK
config.linkch = NULL;
#endif
@@ -1410,14 +1430,17 @@ static void spi_exchange(struct spi_dev_s *dev, const
void *txbuffer,
SPI_RSER_RFDF_RE | SPI_RSER_TFFF_RE |
SPI_RSER_RFDF_DIRS | SPI_RSER_TFFF_DIRS);
+ /* Reset TCR to zero. It can also be reset using CTCNT field in the upper 16
+ * bits (command info) of the PUSHR register. Do not write the TCR when the
+ * module is in the Running state.
+ */
+
+ spi_putreg(priv, KINETIS_SPI_TCR_OFFSET, 0);
+
/* Start the DMAs */
spi_dmarxstart(priv);
spi_run(priv, true);
-
- spi_putreg(priv, KINETIS_SPI_TCR_OFFSET, 0);
- spi_write_control(priv, SPI_PUSHR_CTAS_CTAR0);
-
spi_dmatxstart(priv);
/* Then wait for each to complete */
--
2.47.3