@@ -248,6 +248,8 @@ static int spi_mcux_configure(const struct device *dev,
248248}
249249
250250#ifdef CONFIG_SPI_MCUX_LPSPI_DMA
251+ static int spi_mcux_dma_rxtx_load (const struct device * dev ,
252+ size_t * dma_size );
251253
252254/* This function is executed in the interrupt context */
253255static void spi_mcux_dma_callback (const struct device * dev , void * arg ,
@@ -276,6 +278,26 @@ static void spi_mcux_dma_callback(const struct device *dev, void *arg,
276278 data -> status_flags |= SPI_MCUX_LPSPI_DMA_ERROR_FLAG ;
277279 }
278280 }
281+ #if CONFIG_SPI_ASYNC
282+ if (data -> ctx .asynchronous &&
283+ ((data -> status_flags & SPI_MCUX_LPSPI_DMA_DONE_FLAG ) ==
284+ SPI_MCUX_LPSPI_DMA_DONE_FLAG )) {
285+ /* Load dma blocks of equal length */
286+ size_t dma_size = MIN (data -> ctx .tx_len , data -> ctx .rx_len );
287+
288+ if (dma_size == 0 ) {
289+ dma_size = MAX (data -> ctx .tx_len , data -> ctx .rx_len );
290+ }
291+
292+ spi_context_update_tx (& data -> ctx , 1 , dma_size );
293+ spi_context_update_rx (& data -> ctx , 1 , dma_size );
294+
295+ if (data -> ctx .tx_len == 0 && data -> ctx .rx_len == 0 ) {
296+ spi_context_complete (& data -> ctx , spi_dev , 0 );
297+ }
298+ return ;
299+ }
300+ #endif
279301 spi_context_complete (& data -> ctx , spi_dev , 0 );
280302}
281303
@@ -386,6 +408,45 @@ static int wait_dma_rx_tx_done(const struct device *dev)
386408 }
387409}
388410
411+ static inline int spi_mcux_dma_rxtx_load (const struct device * dev ,
412+ size_t * dma_size )
413+ {
414+ struct spi_mcux_data * lpspi_data = dev -> data ;
415+ int ret = 0 ;
416+
417+ /* Clear status flags */
418+ lpspi_data -> status_flags = 0U ;
419+ /* Load dma blocks of equal length */
420+ * dma_size = MIN (lpspi_data -> ctx .tx_len , lpspi_data -> ctx .rx_len );
421+ if (* dma_size == 0 ) {
422+ * dma_size = MAX (lpspi_data -> ctx .tx_len , lpspi_data -> ctx .rx_len );
423+ }
424+
425+ ret = spi_mcux_dma_tx_load (dev , lpspi_data -> ctx .tx_buf ,
426+ * dma_size );
427+ if (ret != 0 ) {
428+ return ret ;
429+ }
430+
431+ ret = spi_mcux_dma_rx_load (dev , lpspi_data -> ctx .rx_buf ,
432+ * dma_size );
433+ if (ret != 0 ) {
434+ return ret ;
435+ }
436+
437+ /* Start DMA */
438+ ret = dma_start (lpspi_data -> dma_tx .dma_dev ,
439+ lpspi_data -> dma_tx .channel );
440+ if (ret != 0 ) {
441+ return ret ;
442+ }
443+
444+ ret = dma_start (lpspi_data -> dma_rx .dma_dev ,
445+ lpspi_data -> dma_rx .channel );
446+ return ret ;
447+
448+ }
449+
389450static int transceive_dma (const struct device * dev ,
390451 const struct spi_config * spi_cfg ,
391452 const struct spi_buf_set * tx_bufs ,
@@ -400,78 +461,74 @@ static int transceive_dma(const struct device *dev,
400461 int ret ;
401462 size_t dma_size ;
402463
403- spi_context_lock (& data -> ctx , asynchronous , cb , userdata , spi_cfg );
464+ if (!asynchronous ) {
465+ spi_context_lock (& data -> ctx , asynchronous , cb , userdata , spi_cfg );
466+ }
404467
405468 ret = spi_mcux_configure (dev , spi_cfg );
406469 if (ret ) {
407- goto out ;
470+ if (!asynchronous ) {
471+ spi_context_release (& data -> ctx , ret );
472+ }
473+ return ret ;
408474 }
409475
410- spi_context_buffers_setup (& data -> ctx , tx_bufs , rx_bufs , 1 );
411-
412- spi_context_cs_control (& data -> ctx , true);
413-
414476 /* DMA is fast enough watermarks are not required */
415477 LPSPI_SetFifoWatermarks (base , 0U , 0U );
416478
417- /* Send each spi buf via DMA, updating context as DMA completes */
418- while (data -> ctx .rx_len > 0 || data -> ctx .tx_len > 0 ) {
419- /* Clear status flags */
420- data -> status_flags = 0U ;
421- /* Load dma blocks of equal length */
422- dma_size = MIN (data -> ctx .tx_len , data -> ctx .rx_len );
423- if (dma_size == 0 ) {
424- dma_size = MAX (data -> ctx .tx_len , data -> ctx .rx_len );
425- }
426- ret = spi_mcux_dma_tx_load (dev , data -> ctx .tx_buf , dma_size );
427- if (ret != 0 ) {
428- goto out ;
479+ if (!asynchronous ) {
480+ spi_context_buffers_setup (& data -> ctx , tx_bufs , rx_bufs , 1 );
481+ spi_context_cs_control (& data -> ctx , true);
482+
483+ /* Send each spi buf via DMA, updating context as DMA completes */
484+ while (data -> ctx .rx_len > 0 || data -> ctx .tx_len > 0 ) {
485+ /* Load dma block */
486+ ret = spi_mcux_dma_rxtx_load (dev , & dma_size );
487+ if (ret != 0 ) {
488+ goto out ;
489+ }
490+ /* Enable DMA Requests */
491+ LPSPI_EnableDMA (base , kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable );
492+
493+ /* Wait for DMA to finish */
494+ ret = wait_dma_rx_tx_done (dev );
495+ if (ret != 0 ) {
496+ goto out ;
497+ }
498+ while ((LPSPI_GetStatusFlags (base ) & kLPSPI_ModuleBusyFlag )) {
499+ /* wait until module is idle */
500+ }
501+
502+ /* Disable DMA */
503+ LPSPI_DisableDMA (base , kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable );
504+
505+ /* Update SPI contexts with amount of data we just sent */
506+ spi_context_update_tx (& data -> ctx , 1 , dma_size );
507+ spi_context_update_rx (& data -> ctx , 1 , dma_size );
429508 }
509+ spi_context_cs_control (& data -> ctx , false);
430510
431- ret = spi_mcux_dma_rx_load (dev , data -> ctx .rx_buf , dma_size );
432- if (ret != 0 ) {
433- goto out ;
434- }
511+ out :
512+ spi_context_release (& data -> ctx , ret );
513+ }
514+ #if CONFIG_SPI_ASYNC
515+ else {
516+ data -> ctx .asynchronous = asynchronous ;
517+ data -> ctx .callback = cb ;
518+ data -> ctx .callback_data = userdata ;
435519
436- /* Start DMA */
437- ret = dma_start (data -> dma_tx .dma_dev , data -> dma_tx .channel );
438- if (ret != 0 ) {
439- goto out ;
440- }
441- ret = dma_start (data -> dma_rx .dma_dev , data -> dma_rx .channel );
520+ ret = spi_mcux_dma_rxtx_load (dev , & dma_size );
442521 if (ret != 0 ) {
443522 goto out ;
444523 }
445524
446525 /* Enable DMA Requests */
447526 LPSPI_EnableDMA (base , kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable );
448-
449- /* Wait for DMA to finish */
450- ret = wait_dma_rx_tx_done (dev );
451- if (ret != 0 ) {
452- goto out ;
453- }
454-
455- while ((LPSPI_GetStatusFlags (base ) & kLPSPI_ModuleBusyFlag )) {
456- /* wait until module is idle */
457- }
458-
459- /* Disable DMA */
460- LPSPI_DisableDMA (base , kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable );
461-
462- /* Update SPI contexts with amount of data we just sent */
463- spi_context_update_tx (& data -> ctx , 1 , dma_size );
464- spi_context_update_rx (& data -> ctx , 1 , dma_size );
465527 }
466-
467- spi_context_cs_control (& data -> ctx , false);
468-
469- out :
470- spi_context_release (& data -> ctx , ret );
528+ #endif
471529
472530 return ret ;
473531}
474-
475532#endif
476533
477534static int transceive (const struct device * dev ,
@@ -530,7 +587,17 @@ static int spi_mcux_transceive_async(const struct device *dev,
530587 spi_callback_t cb ,
531588 void * userdata )
532589{
590+ #ifdef CONFIG_SPI_MCUX_LPSPI_DMA
591+ struct spi_mcux_data * data = dev -> data ;
592+
593+ if (data -> dma_rx .dma_dev && data -> dma_tx .dma_dev ) {
594+ spi_context_buffers_setup (& data -> ctx , tx_bufs , rx_bufs , 1 );
595+ }
596+
597+ return transceive_dma (dev , spi_cfg , tx_bufs , rx_bufs , true, cb , userdata );
598+ #else
533599 return transceive (dev , spi_cfg , tx_bufs , rx_bufs , true, cb , userdata );
600+ #endif /* CONFIG_SPI_MCUX_LPSPI_DMA */
534601}
535602#endif /* CONFIG_SPI_ASYNC */
536603
0 commit comments