1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019,2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_flexio_mculcd_edma.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.flexio_mculcd_edma"
18 #endif
19 
20 #define EDMA_MAX_MAJOR_COUNT (DMA_CITER_ELINKNO_CITER_MASK >> DMA_CITER_ELINKNO_CITER_SHIFT)
21 
22 enum
23 {
24     kFLEXIO_MCULCD_StateIdle,           /*!< No transfer in progress. */
25     kFLEXIO_MCULCD_StateReadArray,      /*!< Reading array in progress. */
26     kFLEXIO_MCULCD_StateWriteArray,     /*!< Writing array in progress. */
27     kFLEXIO_MCULCD_StateWriteSameValue, /*!< Writing the same value in progress.
28                                          */
29 };
30 
31 /*******************************************************************************
32  * Prototypes
33  ******************************************************************************/
34 
35 /*!
36  * @brief EDMA callback function for FLEXIO MCULCD TX.
37  *
38  * For details, see @ref edma_callback.
39  */
40 static void FLEXIO_MCULCD_TxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds);
41 
42 /*!
43  * @brief EDMA callback function for FLEXIO MCULCD RX.
44  *
45  * For details, see @ref edma_callback.
46  */
47 static void FLEXIO_MCULCD_RxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds);
48 
49 /*!
50  * @brief Set EDMA config for FLEXIO MCULCD transfer.
51  *
52  * @param base pointer to FLEXIO_MCULCD_Type structure.
53  * @param handle pointer to flexio_mculcd_edma_handle_t structure to store the
54  * transfer state.
55  */
56 static void FLEXIO_MCULCD_EDMAConfig(FLEXIO_MCULCD_Type *base, flexio_mculcd_edma_handle_t *handle);
57 
58 /*!
59  * @brief Convert the FlexIO shifter number to eDMA modulo.
60  *
61  * @param shifterNum The FlexIO shifter number.
62  * @param modulo The modulo number.
63  * @retval Get the modulo successfully.
64  * @retval Could not get the modulo for the shifter number.
65  */
66 static bool FLEXIO_MCULCD_GetEDMAModulo(uint8_t shifterNum, edma_modulo_t *modulo);
67 
68 /*******************************************************************************
69  * Variables
70  ******************************************************************************/
71 
72 /*******************************************************************************
73  * Code
74  ******************************************************************************/
75 
FLEXIO_MCULCD_TxEDMACallback(edma_handle_t * DmaHandle,void * param,bool transferDone,uint32_t tcds)76 static void FLEXIO_MCULCD_TxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds)
77 {
78     tcds                                            = tcds;
79     flexio_mculcd_edma_handle_t *flexioLcdMcuHandle = (flexio_mculcd_edma_handle_t *)param;
80     FLEXIO_MCULCD_Type *flexioLcdMcuBase            = flexioLcdMcuHandle->base;
81 
82     if (transferDone)
83     {
84         if (flexioLcdMcuHandle->remainingCount >= flexioLcdMcuHandle->minorLoopBytes)
85         {
86             FLEXIO_MCULCD_EDMAConfig(flexioLcdMcuBase, flexioLcdMcuHandle);
87             EDMA_StartTransfer(flexioLcdMcuHandle->txDmaHandle);
88         }
89         else
90         {
91             FLEXIO_MCULCD_EnableTxDMA(flexioLcdMcuBase, false);
92 
93             /* Now the data are in shifter, wait for the data send out from the shifter. */
94             FLEXIO_MCULCD_WaitTransmitComplete();
95 
96             /* Disable the TX shifter and the timer. */
97             FLEXIO_MCULCD_ClearMultiBeatsWriteConfig(flexioLcdMcuBase);
98 
99             /* Send the remaining data. */
100             if (0U != flexioLcdMcuHandle->remainingCount)
101             {
102                 if ((uint32_t)kFLEXIO_MCULCD_StateWriteSameValue == flexioLcdMcuHandle->state)
103                 {
104                     FLEXIO_MCULCD_WriteSameValueBlocking(flexioLcdMcuBase, flexioLcdMcuHandle->dataAddrOrSameValue,
105                                                          flexioLcdMcuHandle->remainingCount);
106                 }
107                 else
108                 {
109                     FLEXIO_MCULCD_WriteDataArrayBlocking(flexioLcdMcuBase,
110                                                          (uint8_t *)flexioLcdMcuHandle->dataAddrOrSameValue,
111                                                          flexioLcdMcuHandle->remainingCount);
112                 }
113             }
114 
115             /* De-assert nCS. */
116             FLEXIO_MCULCD_StopTransfer(flexioLcdMcuBase);
117 
118             /* Change the state. */
119             flexioLcdMcuHandle->state          = (uint32_t)kFLEXIO_MCULCD_StateIdle;
120             flexioLcdMcuHandle->dataCount      = 0;
121             flexioLcdMcuHandle->remainingCount = 0;
122 
123             /* Callback to inform upper layer. */
124             if (NULL != flexioLcdMcuHandle->completionCallback)
125             {
126                 flexioLcdMcuHandle->completionCallback(flexioLcdMcuBase, flexioLcdMcuHandle, kStatus_FLEXIO_MCULCD_Idle,
127                                                        flexioLcdMcuHandle->userData);
128             }
129         }
130     }
131 }
132 
FLEXIO_MCULCD_RxEDMACallback(edma_handle_t * DmaHandle,void * param,bool transferDone,uint32_t tcds)133 static void FLEXIO_MCULCD_RxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds)
134 {
135     tcds = tcds;
136     uint32_t i;
137     uint32_t rxBufAddr;
138     flexio_mculcd_edma_handle_t *flexioLcdMcuHandle = (flexio_mculcd_edma_handle_t *)param;
139     FLEXIO_MCULCD_Type *flexioLcdMcuBase            = flexioLcdMcuHandle->base;
140     FLEXIO_Type *flexioBase                         = flexioLcdMcuBase->flexioBase;
141 
142     if (transferDone)
143     {
144         if (flexioLcdMcuHandle->remainingCount >= (2U * flexioLcdMcuHandle->minorLoopBytes))
145         {
146             FLEXIO_MCULCD_EDMAConfig(flexioLcdMcuBase, flexioLcdMcuHandle);
147             EDMA_StartTransfer(flexioLcdMcuHandle->rxDmaHandle);
148         }
149         else
150         {
151             FLEXIO_MCULCD_EnableRxDMA(flexioLcdMcuBase, false);
152 
153             /* Wait the data saved to the shifter buffer. */
154             while (0U == ((1UL << flexioLcdMcuBase->rxShifterEndIndex) & FLEXIO_GetShifterStatusFlags(flexioBase)))
155             {
156             }
157 
158             /* Disable the RX shifter and the timer. */
159             FLEXIO_MCULCD_ClearMultiBeatsReadConfig(flexioLcdMcuBase);
160 
161             rxBufAddr = FLEXIO_MCULCD_GetRxDataRegisterAddress(flexioLcdMcuBase);
162 
163 /* Read out the data. */
164 #if (defined(__CORTEX_M) && (__CORTEX_M == 0))
165             /* Cortex M0 and M0+ only support aligned access. */
166             for (i = 0; i < flexioLcdMcuHandle->rxShifterNum * 4; i++)
167             {
168                 ((uint8_t *)(flexioLcdMcuHandle->dataAddrOrSameValue))[i] = ((volatile uint8_t *)rxBufAddr)[i];
169             }
170 #else
171             for (i = 0; i < flexioLcdMcuHandle->rxShifterNum; i++)
172             {
173                 ((uint32_t *)(flexioLcdMcuHandle->dataAddrOrSameValue))[i] = ((volatile uint32_t *)rxBufAddr)[i];
174             }
175 #endif
176             flexioLcdMcuHandle->remainingCount -= flexioLcdMcuHandle->minorLoopBytes;
177 
178             if (0U != flexioLcdMcuHandle->remainingCount)
179             {
180                 FLEXIO_MCULCD_ReadDataArrayBlocking(
181                     flexioLcdMcuBase,
182                     (uint8_t *)(flexioLcdMcuHandle->dataAddrOrSameValue + flexioLcdMcuHandle->minorLoopBytes),
183                     flexioLcdMcuHandle->remainingCount);
184             }
185 
186             /* De-assert nCS. */
187             FLEXIO_MCULCD_StopTransfer(flexioLcdMcuBase);
188 
189             /* Change the state. */
190             flexioLcdMcuHandle->state          = (uint32_t)kFLEXIO_MCULCD_StateIdle;
191             flexioLcdMcuHandle->dataCount      = 0;
192             flexioLcdMcuHandle->remainingCount = 0;
193 
194             /* Callback to inform upper layer. */
195             if (NULL != flexioLcdMcuHandle->completionCallback)
196             {
197                 flexioLcdMcuHandle->completionCallback(flexioLcdMcuBase, flexioLcdMcuHandle, kStatus_FLEXIO_MCULCD_Idle,
198                                                        flexioLcdMcuHandle->userData);
199             }
200         }
201     }
202 }
203 
FLEXIO_MCULCD_EDMAConfig(FLEXIO_MCULCD_Type * base,flexio_mculcd_edma_handle_t * handle)204 static void FLEXIO_MCULCD_EDMAConfig(FLEXIO_MCULCD_Type *base, flexio_mculcd_edma_handle_t *handle)
205 {
206     edma_transfer_config_t xferConfig = {0};
207     edma_transfer_size_t transferSize = kEDMA_TransferSize1Bytes;
208     int16_t offset;
209     uint32_t majorLoopCounts;
210     uint32_t transferCount;
211 
212 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
213     transferSize = kEDMA_TransferSize1Bytes;
214     offset       = 1;
215 #else
216     transferSize = kEDMA_TransferSize2Bytes;
217     offset = 2;
218 #endif
219 
220     majorLoopCounts = handle->remainingCount / handle->minorLoopBytes;
221 
222     /* For reading, the last minor loop data is not tranfered by DMA. */
223     if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == handle->state)
224     {
225         majorLoopCounts--;
226     }
227 
228     if (majorLoopCounts > EDMA_MAX_MAJOR_COUNT)
229     {
230         majorLoopCounts = EDMA_MAX_MAJOR_COUNT;
231     }
232 
233     transferCount = majorLoopCounts * handle->minorLoopBytes;
234 
235     if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == handle->state)
236     {
237         xferConfig.srcAddr          = FLEXIO_MCULCD_GetRxDataRegisterAddress(base);
238         xferConfig.destAddr         = handle->dataAddrOrSameValue;
239         xferConfig.srcTransferSize  = kEDMA_TransferSize4Bytes;
240         xferConfig.destTransferSize = transferSize;
241         xferConfig.srcOffset        = 4;
242         xferConfig.destOffset       = offset;
243         xferConfig.minorLoopBytes   = handle->minorLoopBytes;
244         xferConfig.majorLoopCounts  = majorLoopCounts;
245         handle->remainingCount -= transferCount;
246         handle->dataAddrOrSameValue += transferCount;
247         (void)EDMA_SubmitTransfer(handle->rxDmaHandle, &xferConfig);
248         EDMA_SetModulo(handle->rxDmaHandle->base, handle->rxDmaHandle->channel, handle->rxEdmaModulo,
249                        kEDMA_ModuloDisable);
250     }
251     else
252     {
253         if ((uint32_t)kFLEXIO_MCULCD_StateWriteArray == handle->state)
254         {
255             xferConfig.srcAddr   = handle->dataAddrOrSameValue;
256             xferConfig.srcOffset = offset;
257             handle->dataAddrOrSameValue += transferCount;
258         }
259         else
260         {
261             xferConfig.srcAddr   = (uint32_t)(&(handle->dataAddrOrSameValue));
262             xferConfig.srcOffset = 0;
263         }
264         xferConfig.destAddr         = FLEXIO_MCULCD_GetTxDataRegisterAddress(base);
265         xferConfig.srcTransferSize  = transferSize;
266         xferConfig.destTransferSize = kEDMA_TransferSize4Bytes;
267         xferConfig.destOffset       = 4;
268         xferConfig.minorLoopBytes   = handle->minorLoopBytes;
269         xferConfig.majorLoopCounts  = majorLoopCounts;
270         handle->remainingCount -= transferCount;
271         (void)EDMA_SubmitTransfer(handle->txDmaHandle, &xferConfig);
272         EDMA_SetModulo(handle->txDmaHandle->base, handle->txDmaHandle->channel, kEDMA_ModuloDisable,
273                        handle->txEdmaModulo);
274     }
275 }
276 
FLEXIO_MCULCD_GetEDMAModulo(uint8_t shifterNum,edma_modulo_t * modulo)277 static bool FLEXIO_MCULCD_GetEDMAModulo(uint8_t shifterNum, edma_modulo_t *modulo)
278 {
279     bool ret = true;
280 
281     switch (shifterNum)
282     {
283         case 1U:
284             *modulo = kEDMA_Modulo4bytes;
285             break;
286         case 2U:
287             *modulo = kEDMA_Modulo8bytes;
288             break;
289         case 4U:
290             *modulo = kEDMA_Modulo16bytes;
291             break;
292         case 8U:
293             *modulo = kEDMA_Modulo32bytes;
294             break;
295         default:
296             ret = false;
297             break;
298     }
299 
300     return ret;
301 }
302 
303 /*!
304  * brief Initializes the FLEXO MCULCD master eDMA handle.
305  *
306  * This function initializes the FLEXO MCULCD master eDMA handle which can be
307  * used for other FLEXO MCULCD transactional APIs. For a specified FLEXO MCULCD
308  * instance, call this API once to get the initialized handle.
309  *
310  * param base Pointer to FLEXIO_MCULCD_Type structure.
311  * param handle Pointer to flexio_mculcd_edma_handle_t structure to store the
312  * transfer state.
313  * param callback MCULCD transfer complete callback, NULL means no callback.
314  * param userData callback function parameter.
315  * param txDmaHandle User requested eDMA handle for FlexIO MCULCD eDMA TX,
316  * the DMA request source of this handle should be the first of TX shifters.
317  * param rxDmaHandle User requested eDMA handle for FlexIO MCULCD eDMA RX,
318  * the DMA request source of this handle should be the last of RX shifters.
319  * retval kStatus_Success Successfully create the handle.
320  */
FLEXIO_MCULCD_TransferCreateHandleEDMA(FLEXIO_MCULCD_Type * base,flexio_mculcd_edma_handle_t * handle,flexio_mculcd_edma_transfer_callback_t callback,void * userData,edma_handle_t * txDmaHandle,edma_handle_t * rxDmaHandle)321 status_t FLEXIO_MCULCD_TransferCreateHandleEDMA(FLEXIO_MCULCD_Type *base,
322                                                 flexio_mculcd_edma_handle_t *handle,
323                                                 flexio_mculcd_edma_transfer_callback_t callback,
324                                                 void *userData,
325                                                 edma_handle_t *txDmaHandle,
326                                                 edma_handle_t *rxDmaHandle)
327 {
328     assert(NULL != handle);
329 
330     /* Zero the handle. */
331     (void)memset(handle, 0, sizeof(*handle));
332 
333     /* Initialize the state. */
334     handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
335 
336     /* Register callback and userData. */
337     handle->completionCallback = callback;
338     handle->userData           = userData;
339 
340     handle->base         = base;
341     handle->txShifterNum = base->txShifterEndIndex - base->txShifterStartIndex + 1U;
342     handle->rxShifterNum = base->rxShifterEndIndex - base->rxShifterStartIndex + 1U;
343 
344     if (NULL != rxDmaHandle)
345     {
346         if (!FLEXIO_MCULCD_GetEDMAModulo(handle->rxShifterNum, &handle->rxEdmaModulo))
347         {
348             return kStatus_InvalidArgument;
349         }
350 
351         handle->rxDmaHandle = rxDmaHandle;
352         EDMA_SetCallback(rxDmaHandle, FLEXIO_MCULCD_RxEDMACallback, handle);
353     }
354 
355     if (NULL != txDmaHandle)
356     {
357         if (!FLEXIO_MCULCD_GetEDMAModulo(handle->txShifterNum, &handle->txEdmaModulo))
358         {
359             return kStatus_InvalidArgument;
360         }
361 
362         handle->txDmaHandle = txDmaHandle;
363         EDMA_SetCallback(txDmaHandle, FLEXIO_MCULCD_TxEDMACallback, handle);
364     }
365 
366     return kStatus_Success;
367 }
368 
369 /*!
370  * brief Performs a non-blocking FlexIO MCULCD transfer using eDMA.
371  *
372  * This function returns immediately after transfer initiates. To check whether
373  * the transfer is completed, user could:
374  * 1. Use the transfer completed callback;
375  * 2. Polling function ref FLEXIO_MCULCD_GetTransferCountEDMA
376  *
377  * param base pointer to FLEXIO_MCULCD_Type structure.
378  * param handle pointer to flexio_mculcd_edma_handle_t structure to store the
379  * transfer state.
380  * param xfer Pointer to FlexIO MCULCD transfer structure.
381  * retval kStatus_Success Successfully start a transfer.
382  * retval kStatus_InvalidArgument Input argument is invalid.
383  * retval kStatus_FLEXIO_MCULCD_Busy FlexIO MCULCD is not idle, it is running another
384  * transfer.
385  */
FLEXIO_MCULCD_TransferEDMA(FLEXIO_MCULCD_Type * base,flexio_mculcd_edma_handle_t * handle,flexio_mculcd_transfer_t * xfer)386 status_t FLEXIO_MCULCD_TransferEDMA(FLEXIO_MCULCD_Type *base,
387                                     flexio_mculcd_edma_handle_t *handle,
388                                     flexio_mculcd_transfer_t *xfer)
389 {
390     assert(NULL != handle);
391     assert(NULL != xfer);
392 
393     /*
394      * The data transfer mechanism:
395      *
396      * Read:
397      * Assume the data length is Lr = (n1 * minorLoopBytes + n2), where
398      * n2 < minorLoopBytes.
399      * If (n1 <= 1), then all data are sent using blocking method.
400      * If (n1 > 1), then the beginning ((n1-1) * minorLoopBytes) are read
401      * using DMA, the left (minorLoopBytes + n2) are read using blocking method.
402      *
403      * Write:
404      * Assume the data length is Lw = (n1 * minorLoopBytes + n2), where
405      * n2 < minorLoopBytes.
406      * If (n1 = 0), then all data are sent using blocking method.
407      * If (n1 >= 1), then the beginning (n1 * minorLoopBytes) are sent
408      * using DMA, the left n2 are sent using blocking method.
409      */
410 
411     /* Check if the device is busy. */
412     if ((uint32_t)kFLEXIO_MCULCD_StateIdle != handle->state)
413     {
414         return kStatus_FLEXIO_MCULCD_Busy;
415     }
416 
417     /* Set the state in handle. */
418     if (kFLEXIO_MCULCD_ReadArray == xfer->mode)
419     {
420         handle->state          = (uint32_t)kFLEXIO_MCULCD_StateReadArray;
421         handle->minorLoopBytes = handle->rxShifterNum * 4UL;
422     }
423     else
424     {
425         handle->minorLoopBytes = handle->txShifterNum * 4UL;
426 
427         if (kFLEXIO_MCULCD_WriteArray == xfer->mode)
428         {
429             handle->state = (uint32_t)kFLEXIO_MCULCD_StateWriteArray;
430         }
431         else
432         {
433             handle->state = (uint32_t)kFLEXIO_MCULCD_StateWriteSameValue;
434         }
435     }
436 
437     /*
438      * For TX, if data is less than one minor loop, then use polling method.
439      * For RX, if data is less than two minor loop, then use polling method.
440      */
441     if ((xfer->dataSize < handle->minorLoopBytes) ||
442         ((kFLEXIO_MCULCD_ReadArray == xfer->mode) && (xfer->dataSize < 2U * (handle->minorLoopBytes))))
443     {
444         FLEXIO_MCULCD_TransferBlocking(base, xfer);
445 
446         handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
447 
448         /* Callback to inform upper layer. */
449         if (NULL != handle->completionCallback)
450         {
451             handle->completionCallback(base, handle, kStatus_FLEXIO_MCULCD_Idle, handle->userData);
452         }
453     }
454     else
455     {
456         handle->dataCount           = xfer->dataSize;
457         handle->remainingCount      = xfer->dataSize;
458         handle->dataAddrOrSameValue = xfer->dataAddrOrSameValue;
459 
460         /* Setup DMA to transfer data.  */
461         /* Assert the nCS. */
462         FLEXIO_MCULCD_StartTransfer(base);
463 
464         if (!xfer->dataOnly)
465         {
466             /* Send the command. */
467             FLEXIO_MCULCD_WriteCommandBlocking(base, xfer->command);
468         }
469 
470         /* Setup the DMA configuration. */
471         FLEXIO_MCULCD_EDMAConfig(base, handle);
472 
473         /* Start the transfer. */
474         if (kFLEXIO_MCULCD_ReadArray == xfer->mode)
475         {
476             /* For 6800, assert the RDWR pin. */
477             if (kFLEXIO_MCULCD_6800 == base->busType)
478             {
479                 base->setRDWRPin(true);
480             }
481             FLEXIO_MCULCD_SetMultiBeatsReadConfig(base);
482             FLEXIO_MCULCD_EnableRxDMA(base, true);
483             EDMA_StartTransfer(handle->rxDmaHandle);
484         }
485         else
486         {
487             /* For 6800, de-assert the RDWR pin. */
488             if (kFLEXIO_MCULCD_6800 == base->busType)
489             {
490                 base->setRDWRPin(false);
491             }
492             FLEXIO_MCULCD_SetMultiBeatsWriteConfig(base);
493             FLEXIO_MCULCD_EnableTxDMA(base, true);
494             EDMA_StartTransfer(handle->txDmaHandle);
495         }
496     }
497 
498     return kStatus_Success;
499 }
500 
501 /*!
502  * brief Aborts a FlexIO MCULCD transfer using eDMA.
503  *
504  * param base pointer to FLEXIO_MCULCD_Type structure.
505  * param handle FlexIO MCULCD eDMA handle pointer.
506  */
FLEXIO_MCULCD_TransferAbortEDMA(FLEXIO_MCULCD_Type * base,flexio_mculcd_edma_handle_t * handle)507 void FLEXIO_MCULCD_TransferAbortEDMA(FLEXIO_MCULCD_Type *base, flexio_mculcd_edma_handle_t *handle)
508 {
509     assert(NULL != handle);
510 
511     /* Disable dma. */
512     if (NULL != handle->txDmaHandle)
513     {
514         EDMA_AbortTransfer(handle->txDmaHandle);
515     }
516     if (NULL != handle->rxDmaHandle)
517     {
518         EDMA_AbortTransfer(handle->rxDmaHandle);
519     }
520 
521     /* Disable DMA enable bit. */
522     FLEXIO_MCULCD_EnableTxDMA(handle->base, false);
523     FLEXIO_MCULCD_EnableRxDMA(handle->base, false);
524 
525     /* Set the handle state. */
526     handle->state     = (uint32_t)kFLEXIO_MCULCD_StateIdle;
527     handle->dataCount = 0;
528 }
529 
530 /*!
531  * brief Gets the remaining bytes for FlexIO MCULCD eDMA transfer.
532  *
533  * param base pointer to FLEXIO_MCULCD_Type structure.
534  * param handle FlexIO MCULCD eDMA handle pointer.
535  * param count Number of count transferred so far by the eDMA transaction.
536  * retval kStatus_Success Get the transferred count Successfully.
537  * retval kStatus_NoTransferInProgress No transfer in process.
538  */
FLEXIO_MCULCD_TransferGetCountEDMA(FLEXIO_MCULCD_Type * base,flexio_mculcd_edma_handle_t * handle,size_t * count)539 status_t FLEXIO_MCULCD_TransferGetCountEDMA(FLEXIO_MCULCD_Type *base,
540                                             flexio_mculcd_edma_handle_t *handle,
541                                             size_t *count)
542 {
543     assert(NULL != handle);
544     assert(NULL != count);
545     uint32_t state = handle->state;
546 
547     if ((uint32_t)kFLEXIO_MCULCD_StateIdle == state)
548     {
549         return kStatus_NoTransferInProgress;
550     }
551     else
552     {
553         *count = handle->dataCount - handle->remainingCount;
554 
555         if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == state)
556         {
557             *count -= handle->minorLoopBytes *
558                       EDMA_GetRemainingMajorLoopCount(handle->rxDmaHandle->base, handle->rxDmaHandle->channel);
559         }
560         else
561         {
562             *count -= handle->minorLoopBytes *
563                       EDMA_GetRemainingMajorLoopCount(handle->txDmaHandle->base, handle->txDmaHandle->channel);
564         }
565     }
566 
567     return kStatus_Success;
568 }
569