Skip to content

Commit 1c4351a

Browse files
mjchen0fabiobaltieri
authored andcommitted
drivers: mcux: spi and dma: add explicit dma channel type for SPI_TX
The spi_mcux_flexcomm driver uses a special last DMA blk_cfg to trigger a release of the SPI chip select. This transfer is always a 4-byte transfer, regardless of the width specified during dma_configure(). The way the spi_mcux_flexcomm driver communicated this special transfer was kind of a hack, where the dma_mcux_lpc driver would assume that when a blk_cfg with source_addr_adj and dest_addr_adj both set to NO_CHANGE was for this SPI_TX special case. However, this is an unsafe hack since it is perfectly valid to have dma use cases for both src/dest_addr_adj to be NO_CHANGE that is not for SPI_TX. One example is when transmitting a fixed/repeating value to a periperhal address (e.g. send 100 bytes of the same value from a single memory address over SPI). This CL introduces a dma_mcux_lpc specific dma channel_direction which the two drivers now use to cleary request this special transfer case. Signed-off-by: Mike J. Chen <[email protected]>
1 parent df46b30 commit 1c4351a

File tree

3 files changed

+15
-13
lines changed

3 files changed

+15
-13
lines changed

drivers/dma/dma_mcux_lpc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,9 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data,
224224
* address does not need to be change for these
225225
* transactions and the transfer width is 4 bytes
226226
*/
227-
if ((local_block.source_addr_adj == DMA_ADDR_ADJ_NO_CHANGE) &&
228-
(local_block.dest_addr_adj == DMA_ADDR_ADJ_NO_CHANGE)) {
227+
if ((data->dir == LPC_DMA_SPI_MCUX_FLEXCOMM_TX) &&
228+
(local_block.block_size == sizeof(uint32_t)) &&
229+
(local_block.next_block == NULL)) {
229230
src_inc = 0;
230231
dest_inc = 0;
231232
width = sizeof(uint32_t);
@@ -438,6 +439,7 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel,
438439
}
439440
}
440441
break;
442+
case LPC_DMA_SPI_MCUX_FLEXCOMM_TX:
441443
case MEMORY_TO_PERIPHERAL:
442444
/* Set the source increment value */
443445
if (block_config->source_gather_en) {

drivers/spi/spi_mcux_flexcomm.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <zephyr/logging/log.h>
1616
#ifdef CONFIG_SPI_MCUX_FLEXCOMM_DMA
1717
#include <zephyr/drivers/dma.h>
18+
#include <zephyr/drivers/dma/dma_mcux_lpc.h>
1819
#endif
1920
#include <zephyr/drivers/pinctrl.h>
2021
#include <zephyr/sys_clock.h>
@@ -398,15 +399,15 @@ static int spi_mcux_dma_tx_load(const struct device *dev, const struct spi_confi
398399
blk_cfg = &stream->dma_blk_cfg[dma_block_num];
399400
/* tx direction has memory as source and periph as dest. */
400401
blk_cfg->dest_address = (uint32_t)&base->FIFOWR;
402+
blk_cfg->dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
401403
blk_cfg->source_gather_en = 0;
402404
if (last_packet) {
403405
data->last_word = spi_mcux_get_last_tx_word(spi_cfg, buf, len, config->def_char,
404406
data->word_size_bits);
405407
blk_cfg->source_address = (uint32_t)&data->last_word;
408+
blk_cfg->source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
406409
blk_cfg->block_size = sizeof(uint32_t);
407410
blk_cfg->next_block = NULL;
408-
blk_cfg->source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
409-
blk_cfg->dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
410411
data->dma_tx.wait_for_dma_status = DMA_STATUS_COMPLETE;
411412
} else {
412413
blk_cfg->block_size = len;
@@ -418,14 +419,6 @@ static int spi_mcux_dma_tx_load(const struct device *dev, const struct spi_confi
418419
data->dummy_tx_buffer = 0;
419420
blk_cfg->source_address = (uint32_t)&data->dummy_tx_buffer;
420421
blk_cfg->source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
421-
/* The DMA driver uses the special case of source_addr_adj and dest_addr_adj
422-
* both set to DMA_ADDR_ADJ_NO_CHANGE to set the transfer width to 32 bits,
423-
* which is required on the last packet. To keep that case from being
424-
* inadvertantly triggered on a dummy transfer we must set the dest_addr_adj
425-
* to increment. This flag is ignored on the peripheral side of the
426-
* transfer, so this does not affect anything except the special case.
427-
*/
428-
blk_cfg->dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
429422
}
430423
data->dma_tx.wait_for_dma_status = DMA_STATUS_BLOCK;
431424
}
@@ -919,7 +912,7 @@ static DEVICE_API(spi, spi_mcux_driver_api) = {
919912
.channel = \
920913
DT_INST_DMAS_CELL_BY_NAME(id, tx, channel), \
921914
.dma_cfg = { \
922-
.channel_direction = MEMORY_TO_PERIPHERAL, \
915+
.channel_direction = LPC_DMA_SPI_MCUX_FLEXCOMM_TX, \
923916
.dma_callback = spi_mcux_dma_callback, \
924917
.complete_callback_en = true, \
925918
.block_count = 2, \

include/zephyr/drivers/dma/dma_mcux_lpc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,11 @@
5353
/* Used by driver to extract burstpower setting */
5454
#define LPC_DMA_GET_BURSTPOWER(slot) (((slot) & 0xE0) >> 5)
5555

56+
/*
57+
* Special channel_direction for SPI_MCUX_FLEXCOMM_TX so
58+
* that DMA driver can configure the last descriptor
59+
* to deassert CS.
60+
*/
61+
#define LPC_DMA_SPI_MCUX_FLEXCOMM_TX (DMA_CHANNEL_DIRECTION_PRIV_START)
62+
5663
#endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_DMA_MCUX_LPC_H_ */

0 commit comments

Comments
 (0)