1 /*
2  * Copyright 2019-2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_flexspi_dma.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.flexspi_dma"
17 #endif
18 
19 /*<! Structure definition for flexspi_dma_private_handle_t. The structure is private. */
20 typedef struct _flexspi_dma_private_handle
21 {
22     FLEXSPI_Type *base;
23     flexspi_dma_handle_t *handle;
24 } flexspi_dma_private_handle_t;
25 
26 /* FLEXSPI DMA transfer handle, _flexspi_dma_tansfer_states. */
27 enum
28 {
29     kFLEXSPI_Idle, /* FLEXSPI Bus idle. */
30     kFLEXSPI_Busy  /* FLEXSPI Bus busy. */
31 };
32 
33 /*******************************************************************************
34  * Variables
35  ******************************************************************************/
36 
37 /*! @brief Pointers to flexspi bases for each instance. */
38 static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
39 
40 /*<! Private handle only used for internally. */
41 static flexspi_dma_private_handle_t s_dmaPrivateHandle[ARRAY_SIZE(s_flexspiBases)];
42 
43 #if defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES
44 /*<! Private DMA descriptor array used for internally to fix FLEXSPI+DMA ERRATA.
45 FLEXSPI.1: Using FLEXSPI register interface, TX buffer fill / RX buffer drain by DMA
46 with a single DMA descriptor cannot be performed. The link array consumes about
47 2K RAM consumption support FLEXSPI TX watermark starting from 8 bytes.*/
48 #define FLEXSPI_DMA_DES_COUNT 128U
49 #else
50 /*<! Private DMA descriptor array to support transfer size not multiple of watermark level byts.
51 The link array consumes 16 bytes consumption.*/
52 #define FLEXSPI_DMA_DES_COUNT 1U
53 #endif
54 
55 #if defined(__ICCARM__)
56 #pragma data_alignment = FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE
57 static dma_descriptor_t s_flexspiDes[FLEXSPI_DMA_DES_COUNT];
58 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
59 __attribute__((
60     aligned(FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE))) static dma_descriptor_t s_flexspiDes[FLEXSPI_DMA_DES_COUNT];
61 #elif defined(__GNUC__)
62 __attribute__((
63     aligned(FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE))) static dma_descriptor_t s_flexspiDes[FLEXSPI_DMA_DES_COUNT];
64 #endif
65 /*******************************************************************************
66  * Prototypes
67  ******************************************************************************/
68 
69 /*!
70  * @brief FLEXSPI DMA transfer finished callback function.
71  *
72  * This function is called when FLEXSPI DMA transfer finished. It disables the FLEXSPI
73  * TX/RX DMA request and sends status to FLEXSPI callback.
74  *
75  * @param handle The DMA handle.
76  * @param param Callback function parameter.
77  */
78 static void FLEXSPI_TransferDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
79 
80 /*!
81  * @brief FLEXSPI Write DMA data.
82  *
83  * This function is called in FLEXSPI DMA transfer. It configures Write DMA and prepare DMA data transfer.
84  *
85  * @param base FLEXSPI peripheral base address.
86  * @param handle The DMA handle.
87  * @param data pointer to data buffer which stores the transmit data
88  * @param dataSize size for transmit data buffer .
89  */
90 static status_t FLEXSPI_WriteDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize);
91 
92 /*!
93  * @brief FLEXSPI Read DMA data.
94  *
95  * This function is called in FLEXSPI DMA transfer. It configures Read DMA and prepare DMA data transfer.
96  *
97  * @param base FLEXSPI peripheral base address.
98  * @param handle The DMA handle.
99  * @param data pointer to data buffer which stores the receive data
100  * @param dataSize size for receive data buffer .
101  */
102 static status_t FLEXSPI_ReadDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize);
103 /*******************************************************************************
104  * Code
105  ******************************************************************************/
106 #if !(defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES)
FLEXSPI_CalculatePower(uint8_t value)107 static uint8_t FLEXSPI_CalculatePower(uint8_t value)
108 {
109     uint8_t power = 0;
110     while (value >> 1 != 0U)
111     {
112         power++;
113         value = value >> 1;
114     }
115 
116     return power;
117 }
118 #endif
119 
FLEXSPI_TransferDMACallback(dma_handle_t * handle,void * param,bool transferDone,uint32_t tcds)120 static void FLEXSPI_TransferDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
121 {
122     flexspi_dma_private_handle_t *flexspiPrivateHandle = (flexspi_dma_private_handle_t *)param;
123 
124     /* Avoid warning for unused parameters. */
125     handle = handle;
126     tcds   = tcds;
127 
128     if (transferDone)
129     {
130         /* Wait for bus idle. */
131         while (!FLEXSPI_GetBusIdleStatus(flexspiPrivateHandle->base))
132         {
133         }
134         /* Disable transfer. */
135         FLEXSPI_TransferAbortDMA(flexspiPrivateHandle->base, flexspiPrivateHandle->handle);
136 
137         if (flexspiPrivateHandle->handle->completionCallback != NULL)
138         {
139             flexspiPrivateHandle->handle->completionCallback(flexspiPrivateHandle->base, flexspiPrivateHandle->handle,
140                                                              kStatus_Success, flexspiPrivateHandle->handle->userData);
141         }
142     }
143 }
144 
FLEXSPI_WriteDataDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,uint32_t * data,size_t dataSize)145 static status_t FLEXSPI_WriteDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize)
146 {
147     void *txFifoBase = (void *)(uint32_t *)FLEXSPI_GetTxFifoAddress(base);
148     void *nextDesc   = NULL;
149     dma_channel_trigger_t dmaTxTriggerConfig;
150     dma_channel_config_t txChannelConfig;
151     uint32_t bytesPerDes;
152     uint8_t desCount;
153     uint8_t remains;
154     uint32_t srcInc;
155     uint32_t dstInc;
156 
157     /* Source address interleave size */
158     srcInc = kDMA_AddressInterleave1xWidth;
159     /* Destination address interleave size */
160     dstInc = kDMA_AddressInterleave1xWidth;
161 
162     /* Check the xfer->data start address follows the alignment */
163     if (((uint32_t)data & ((uint32_t)handle->nsize - 1U)) != 0U)
164     {
165         return kStatus_InvalidArgument;
166     }
167 
168     handle->count =
169         8U * ((uint8_t)(((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U));
170 
171     /* Check the handle->count is power of 2 */
172     if (((handle->count) & (handle->count - 1U)) != 0U)
173     {
174         return kStatus_InvalidArgument;
175     }
176 
177 #if defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES
178     if (dataSize < handle->count)
179     {
180         handle->nsize  = kFLEXPSI_DMAnSize1Bytes;
181         handle->nbytes = (uint8_t)dataSize;
182     }
183     else
184     {
185         /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
186         handle->nbytes = handle->count;
187     }
188 
189     handle->transferSize     = dataSize;
190     dmaTxTriggerConfig.burst = kDMA_SingleTransfer;
191     dmaTxTriggerConfig.type  = kDMA_HighLevelTrigger;
192     dmaTxTriggerConfig.wrap  = kDMA_NoWrap;
193 
194     /* Configure linked descriptors to start FLEXSPI Tx DMA transfer to provide software workaround for
195     ERRATA FLEXSPI.1: Using FLEXSPI register interface, TX buffer fill / RX buffer drain by DMA with a
196     single DMA descriptor cannot be performed. */
197     desCount    = (uint8_t)(dataSize / (uint32_t)handle->nbytes);
198     bytesPerDes = handle->nbytes;
199     remains     = (uint8_t)(dataSize - (uint32_t)desCount * (uint32_t)handle->nbytes);
200     if (remains > 0U)
201     {
202         uint32_t width = (uint32_t)kFLEXPSI_DMAnSize1Bytes;
203         DMA_SetupDescriptor(&s_flexspiDes[desCount - 1U],
204                             DMA_CHANNEL_XFER(false, true, true, false, width, srcInc, dstInc, remains),
205                             (void *)(uint64_t *)((uint32_t)data + desCount * bytesPerDes), txFifoBase, NULL);
206         nextDesc = &s_flexspiDes[desCount - 1U];
207     }
208 
209     remains = (uint8_t)bytesPerDes;
210 #else
211     uint32_t dmaTriggerBurst;
212     dmaTxTriggerConfig.type = kDMA_RisingEdgeTrigger;
213     bytesPerDes             = dataSize;
214 
215     if (dataSize < handle->count)
216     {
217         handle->nsize           = kFLEXPSI_DMAnSize1Bytes;
218         handle->nbytes          = (uint8_t)(dataSize / (uint32_t)handle->nsize);
219         dmaTxTriggerConfig.wrap = kDMA_NoWrap;
220 
221         /* Check the handle->nbytes is power of 2 */
222         if (((handle->nbytes) & (handle->nbytes - 1U)) != 0U)
223         {
224             handle->nbytes = 2U * ((handle->nbytes) & (handle->nbytes - 1U));
225         }
226 
227         desCount = 1U;
228     }
229     else
230     {
231         dmaTxTriggerConfig.wrap = kDMA_DstWrap;
232         remains                 = (uint8_t)(dataSize % (uint32_t)handle->count);
233         if (remains == 0U)
234         {
235             desCount = 1U;
236         }
237         else
238         {
239             desCount    = 2U;
240             bytesPerDes = dataSize - remains;
241             if ((remains & 3U) == 0U)
242             {
243                 handle->nsize = kFLEXPSI_DMAnSize4Bytes;
244             }
245             else if ((remains & 1U) == 0U)
246             {
247                 handle->nsize = kFLEXPSI_DMAnSize2Bytes;
248             }
249             else
250             {
251                 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
252             }
253         }
254         /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
255         handle->nbytes = handle->count / (uint8_t)handle->nsize;
256 
257         /* Check if dataSize exceeds the maximum transfer count supported by the driver. */
258         if ((dataSize - handle->count + 1U) / ((uint32_t)handle->nsize) > 1024U)
259         {
260             return kStatus_InvalidArgument;
261         }
262     }
263 
264     /* xfer->dataSize needs to be larger than 1 due to hardware limitation */
265     if (dataSize / (uint8_t)handle->nsize == 1U)
266     {
267         return kStatus_InvalidArgument;
268     }
269 
270     dmaTriggerBurst = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(FLEXSPI_CalculatePower(handle->nbytes));
271     dmaTxTriggerConfig.burst = (dma_trigger_burst_t)dmaTriggerBurst;
272     handle->transferSize     = dataSize;
273 #endif
274 
275     for (uint8_t i = desCount - 1U; i > 0U; i--)
276     {
277         DMA_SetupDescriptor(&s_flexspiDes[i - 1U],
278                             DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false,
279                                              false, (uint32_t)handle->nsize, srcInc, dstInc, remains),
280                             (void *)(uint64_t *)((uint32_t)data + i * bytesPerDes), txFifoBase, nextDesc);
281         nextDesc = &s_flexspiDes[i - 1U];
282     }
283 
284     DMA_PrepareChannelTransfer(
285         &txChannelConfig, (void *)data, txFifoBase,
286         DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false, false,
287                          (uint32_t)handle->nsize, srcInc, dstInc, bytesPerDes),
288         kDMA_MemoryToMemory, &dmaTxTriggerConfig, nextDesc);
289 
290     (void)DMA_SubmitChannelTransfer(handle->txDmaHandle, &txChannelConfig);
291 
292     DMA_SetCallback(handle->txDmaHandle, FLEXSPI_TransferDMACallback, &s_dmaPrivateHandle[FLEXSPI_GetInstance(base)]);
293     DMA_StartTransfer(handle->txDmaHandle);
294 
295     /* Enable FLEXSPI TX DMA. */
296     FLEXSPI_EnableTxDMA(base, true);
297 
298     /* Start Transfer. */
299     base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
300 
301     return kStatus_Success;
302 }
303 
FLEXSPI_ReadDataDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,uint32_t * data,size_t dataSize)304 static status_t FLEXSPI_ReadDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize)
305 {
306     dma_channel_trigger_t dmaRxTriggerConfig;
307     void *rxFifoBase = (void *)(uint32_t *)FLEXSPI_GetRxFifoAddress(base);
308     void *nextDesc   = NULL;
309     dma_channel_config_t rxChannelConfig;
310     uint32_t bytesPerDes;
311     uint8_t remains;
312     uint8_t desCount;
313     uint32_t srcInc;
314     uint32_t dstInc;
315 
316     /* Source address interleave size */
317     srcInc = kDMA_AddressInterleave1xWidth;
318     /* Destination address interleave size */
319     dstInc = kDMA_AddressInterleave1xWidth;
320 
321     handle->count =
322         8U * (uint8_t)(((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U);
323 
324     /* Check the watermark is power of 2U */
325     if ((handle->count & (handle->count - 1U)) != 0U)
326     {
327         return kStatus_InvalidArgument;
328     }
329 
330 #if defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES
331     if (dataSize < handle->count)
332     {
333         handle->nsize  = kFLEXPSI_DMAnSize1Bytes;
334         handle->nbytes = (uint8_t)dataSize;
335     }
336     else
337     {
338         /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
339         handle->nbytes = handle->count;
340     }
341 
342     dmaRxTriggerConfig.burst = kDMA_SingleTransfer;
343     dmaRxTriggerConfig.type  = kDMA_HighLevelTrigger;
344     dmaRxTriggerConfig.wrap  = kDMA_NoWrap;
345 
346     /* Configure linked descriptors to start FLEXSPI Tx DMA transfer to provide software workaround for
347     ERRATA FLEXSPI.1: Using FLEXSPI register interface, TX buffer fill / RX buffer drain by DMA with a
348     single DMA descriptor cannot be performed. */
349     desCount    = (uint8_t)(dataSize / (uint32_t)handle->nbytes);
350     bytesPerDes = handle->nbytes;
351     remains     = (uint8_t)(dataSize - (uint32_t)desCount * (uint32_t)handle->nbytes);
352 
353     if (remains > 0U)
354     {
355         uint32_t width = (uint32_t)kFLEXPSI_DMAnSize1Bytes;
356         DMA_SetupDescriptor(&s_flexspiDes[desCount - 1U],
357                             DMA_CHANNEL_XFER(false, true, true, false, width, srcInc, dstInc, remains), rxFifoBase,
358                             (void *)(uint64_t *)((uint32_t)data + desCount * bytesPerDes), NULL);
359         nextDesc = &s_flexspiDes[desCount - 1U];
360     }
361     remains = (uint8_t)bytesPerDes;
362 
363 #else
364     uint32_t dmaTriggerBurst;
365     dmaRxTriggerConfig.type = kDMA_RisingEdgeTrigger;
366     bytesPerDes             = dataSize;
367 
368     if (dataSize < handle->count)
369     {
370         handle->nsize           = kFLEXPSI_DMAnSize1Bytes;
371         handle->nbytes          = (uint8_t)(dataSize / (uint32_t)handle->nsize);
372         dmaRxTriggerConfig.wrap = kDMA_NoWrap;
373         /* Check the handle->nbytes is power of 2 */
374         if (((handle->nbytes) & (handle->nbytes - 1U)) != 0U)
375         {
376             handle->nbytes = 2U * ((handle->nbytes) & (handle->nbytes - 1U));
377         }
378         desCount = 1U;
379     }
380     else
381     {
382         dmaRxTriggerConfig.wrap = kDMA_SrcWrap;
383         remains                 = (uint8_t)(dataSize % (uint32_t)handle->count);
384         if (remains == 0U)
385         {
386             desCount = 1U;
387         }
388         else
389         {
390             desCount    = 2U;
391             bytesPerDes = dataSize - remains;
392             if ((remains & 3U) == 0U)
393             {
394                 handle->nsize = kFLEXPSI_DMAnSize4Bytes;
395             }
396             else if ((remains & 1U) == 0U)
397             {
398                 handle->nsize = kFLEXPSI_DMAnSize2Bytes;
399             }
400             else
401             {
402                 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
403             }
404         }
405         /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
406         handle->nbytes = handle->count / (uint8_t)handle->nsize;
407 
408         /* Check dataSize exceeds the maximum transfer count supported by the driver. */
409         if ((dataSize - handle->count + 1U) / ((uint32_t)handle->nsize) > 1024U)
410         {
411             return kStatus_InvalidArgument;
412         }
413     }
414 
415     dmaTriggerBurst =
416         DMA_CHANNEL_CFG_TRIGBURST(1U) | DMA_CHANNEL_CFG_BURSTPOWER(FLEXSPI_CalculatePower(handle->nbytes));
417     dmaRxTriggerConfig.burst = (dma_trigger_burst_t)(dmaTriggerBurst);
418 #endif
419 
420     for (uint8_t i = desCount - 1U; i > 0U; i--)
421     {
422         DMA_SetupDescriptor(&s_flexspiDes[i - 1U],
423                             DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false,
424                                              false, (uint32_t)handle->nsize, srcInc, dstInc, remains),
425                             rxFifoBase, (void *)(uint64_t *)((uint32_t)data + i * bytesPerDes), nextDesc);
426         nextDesc = &s_flexspiDes[i - 1U];
427     }
428 
429     DMA_PrepareChannelTransfer(
430         &rxChannelConfig, rxFifoBase, (void *)data,
431         DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false, false,
432                          (uint32_t)handle->nsize, srcInc, dstInc, bytesPerDes),
433         kDMA_MemoryToMemory, &dmaRxTriggerConfig, nextDesc);
434 
435     (void)DMA_SubmitChannelTransfer(handle->rxDmaHandle, &rxChannelConfig);
436 
437     DMA_SetCallback(handle->rxDmaHandle, FLEXSPI_TransferDMACallback, &s_dmaPrivateHandle[FLEXSPI_GetInstance(base)]);
438     DMA_StartTransfer(handle->rxDmaHandle);
439 
440     /* Enable FLEXSPI RX DMA. */
441     FLEXSPI_EnableRxDMA(base, true);
442 
443     /* Start Transfer. */
444     base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
445 
446     return kStatus_Success;
447 }
448 
449 /*!
450  * brief Initializes the FLEXSPI handle for transfer which is used in transactional functions and set the callback.
451  *
452  * param base FLEXSPI peripheral base address
453  * param handle Pointer to flexspi_dma_handle_t structure
454  * param callback FLEXSPI callback, NULL means no callback.
455  * param userData User callback function data.
456  * param txDmaHandle User requested DMA handle for TX DMA transfer.
457  * param rxDmaHandle User requested DMA handle for RX DMA transfer.
458  */
FLEXSPI_TransferCreateHandleDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,flexspi_dma_callback_t callback,void * userData,dma_handle_t * txDmaHandle,dma_handle_t * rxDmaHandle)459 void FLEXSPI_TransferCreateHandleDMA(FLEXSPI_Type *base,
460                                      flexspi_dma_handle_t *handle,
461                                      flexspi_dma_callback_t callback,
462                                      void *userData,
463                                      dma_handle_t *txDmaHandle,
464                                      dma_handle_t *rxDmaHandle)
465 {
466     assert(handle);
467 
468     uint32_t instance = FLEXSPI_GetInstance(base);
469 
470     s_dmaPrivateHandle[instance].base   = base;
471     s_dmaPrivateHandle[instance].handle = handle;
472 
473     (void)memset(handle, 0, sizeof(*handle));
474 
475     handle->state       = kFLEXSPI_Idle;
476     handle->txDmaHandle = txDmaHandle;
477     handle->rxDmaHandle = rxDmaHandle;
478     handle->nsize       = kFLEXPSI_DMAnSize4Bytes;
479 
480     handle->completionCallback = callback;
481     handle->userData           = userData;
482 }
483 
484 /*!
485  * brief Update FLEXSPI DMA transfer source data transfer size(SSIZE) and destination data transfer size(DSIZE).
486  *
487  * param base FLEXSPI peripheral base address
488  * param handle Pointer to flexspi_dma_handle_t structure
489  * param nsize FLEXSPI DMA transfer data transfer size(SSIZE/DSIZE), by default the size is
490  * kFLEXPSI_DMAnSize1Bytes(one byte).
491  * see flexspi_dma_transfer_nsize_t               .
492  */
FLEXSPI_TransferUpdateSizeDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,flexspi_dma_transfer_nsize_t nsize)493 void FLEXSPI_TransferUpdateSizeDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, flexspi_dma_transfer_nsize_t nsize)
494 {
495     handle->nsize = nsize;
496 }
497 
498 /*!
499  * brief Transfers FLEXSPI data using an dma non-blocking method.
500  *
501  * This function writes/receives data to/from the FLEXSPI transmit/receive FIFO. This function is non-blocking.
502  * param base FLEXSPI peripheral base address.
503  * param handle Pointer to flexspi_dma_handle_t structure
504  * param xfer FLEXSPI transfer structure.
505  * retval kStatus_FLEXSPI_Busy     FLEXSPI is busy transfer.
506  * retval kStatus_InvalidArgument  The watermark configuration is invalid, the watermark should be power of
507                                     2 to do successfully DMA transfer.
508  * retval kStatus_Success          FLEXSPI successfully start dma transfer.
509  */
FLEXSPI_TransferDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,flexspi_transfer_t * xfer)510 status_t FLEXSPI_TransferDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, flexspi_transfer_t *xfer)
511 {
512     uint32_t configValue = 0;
513     status_t result      = kStatus_Success;
514 
515     assert(handle);
516     assert(xfer);
517 
518     /* Check if the FLEXSPI bus is idle - if not return busy status. */
519     if (handle->state != (uint32_t)kFLEXSPI_Idle)
520     {
521         result = kStatus_FLEXSPI_Busy;
522     }
523     else
524     {
525         handle->transferSize = xfer->dataSize;
526 
527         /* Clear sequence pointer before sending data to external devices. */
528         base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
529 
530         /* Clear former pending status before start this transfer. */
531         base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
532                       FLEXSPI_INTR_IPCMDGE_MASK;
533 
534         /* Configure base address. */
535         base->IPCR0 = xfer->deviceAddress;
536 
537         /* Reset fifos. */
538         base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
539         base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
540 
541         /* Configure data size. */
542         if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
543         {
544             configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
545         }
546 
547         /* Configure sequence ID. */
548         configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
549         base->IPCR1 = configValue;
550 
551         if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
552         {
553             handle->state = kFLEXSPI_Busy;
554             result        = FLEXSPI_WriteDataDMA(base, handle, xfer->data, xfer->dataSize);
555         }
556         else if (xfer->cmdType == kFLEXSPI_Read)
557         {
558             handle->state = kFLEXSPI_Busy;
559             result        = FLEXSPI_ReadDataDMA(base, handle, xfer->data, xfer->dataSize);
560         }
561         else
562         {
563             /* Start Transfer. */
564             base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
565             /* Wait for bus idle. */
566             while (!FLEXSPI_GetBusIdleStatus(base))
567             {
568             }
569             result = FLEXSPI_CheckAndClearError(base, base->INTR);
570 
571             handle->state = kFLEXSPI_Idle;
572 
573             if (handle->completionCallback != NULL)
574             {
575                 handle->completionCallback(base, handle, result, handle->userData);
576             }
577         }
578     }
579 
580     return result;
581 }
582 
583 /*!
584  * brief Aborts the transfer data using dma.
585  *
586  * This function aborts the transfer data using dma.
587  *
588  * param base FLEXSPI peripheral base address.
589  * param handle Pointer to flexspi_dma_handle_t structure
590  */
FLEXSPI_TransferAbortDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle)591 void FLEXSPI_TransferAbortDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle)
592 {
593     assert(handle != NULL);
594 
595     if ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXDMAEN_MASK) != 0x00U)
596     {
597         FLEXSPI_EnableTxDMA(base, false);
598         DMA_AbortTransfer(handle->txDmaHandle);
599     }
600 
601     if ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXDMAEN_MASK) != 0x00U)
602     {
603         FLEXSPI_EnableRxDMA(base, false);
604         DMA_AbortTransfer(handle->rxDmaHandle);
605     }
606 
607     handle->state = kFLEXSPI_Idle;
608 }
609 
FLEXSPI_TransferGetTransferCountDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,size_t * count)610 status_t FLEXSPI_TransferGetTransferCountDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, size_t *count)
611 {
612     assert(handle);
613     assert(count);
614 
615     status_t result = kStatus_Success;
616 
617     if (handle->state != (uint32_t)kFLEXSPI_Busy)
618     {
619         result = kStatus_NoTransferInProgress;
620     }
621     else
622     {
623         if ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXDMAEN_MASK) != 0x00U)
624         {
625             *count =
626                 (handle->transferSize - DMA_GetRemainingBytes(handle->rxDmaHandle->base, handle->rxDmaHandle->channel));
627         }
628         else if ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXDMAEN_MASK) != 0x00U)
629         {
630             *count =
631                 (handle->transferSize - DMA_GetRemainingBytes(handle->txDmaHandle->base, handle->txDmaHandle->channel));
632         }
633         else
634         {
635             ; /* Intentional empty for MISRA C-2012 rule 15.7. */
636         }
637     }
638 
639     return result;
640 }
641