1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020, 2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_flexio_spi_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_spi_edma"
18 #endif
19 
20 /*<! Structure definition for spi_edma_private_handle_t. The structure is private. */
21 typedef struct _flexio_spi_master_edma_private_handle
22 {
23     FLEXIO_SPI_Type *base;
24     flexio_spi_master_edma_handle_t *handle;
25 } flexio_spi_master_edma_private_handle_t;
26 
27 /*******************************************************************************
28  * Prototypes
29  ******************************************************************************/
30 
31 /*!
32  * @brief EDMA callback function for FLEXIO SPI send transfer.
33  *
34  * @param handle EDMA handle pointer.
35  * @param param Callback function parameter.
36  */
37 static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
38 
39 /*!
40  * @brief EDMA callback function for FLEXIO SPI receive transfer.
41  *
42  * @param handle EDMA handle pointer.
43  * @param param Callback function parameter.
44  */
45 static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
46 
47 /*!
48  * @brief EDMA config for FLEXIO SPI transfer.
49  *
50  * @param base pointer to FLEXIO_SPI_Type structure.
51  * @param handle pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
52  * @param xfer Pointer to flexio spi transfer structure.
53  * @retval kStatus_Success Successfully create the handle.
54  * @retval kStatus_InvalidArgument The transfer size is not supported.
55  */
56 static status_t FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
57                                       flexio_spi_master_edma_handle_t *handle,
58                                       flexio_spi_transfer_t *xfer);
59 
60 /*******************************************************************************
61  * Variables
62  ******************************************************************************/
63 
64 /* Dummy data used to send */
65 static const uint32_t s_dummyData = FLEXIO_SPI_DUMMYDATA;
66 
67 /*< @brief user configurable flexio spi handle count. */
68 #define FLEXIO_SPI_HANDLE_COUNT 2
69 
70 /*<! Private handle only used for internally. */
71 static flexio_spi_master_edma_private_handle_t s_edmaPrivateHandle[FLEXIO_SPI_HANDLE_COUNT];
72 
73 /*******************************************************************************
74  * Code
75  ******************************************************************************/
76 
FLEXIO_SPI_TxEDMACallback(edma_handle_t * handle,void * param,bool transferDone,uint32_t tcds)77 static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
78 {
79     tcds                                                      = tcds;
80     flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
81 
82     /* Disable Tx DMA */
83     if (transferDone)
84     {
85         FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, (uint32_t)kFLEXIO_SPI_TxDmaEnable, false);
86 
87         /* change the state */
88         spiPrivateHandle->handle->txInProgress = false;
89 
90         /* All finished, call the callback */
91         if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
92         {
93             if (spiPrivateHandle->handle->callback != NULL)
94             {
95                 (spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
96                                                      spiPrivateHandle->handle->userData);
97             }
98         }
99     }
100 }
101 
FLEXIO_SPI_RxEDMACallback(edma_handle_t * handle,void * param,bool transferDone,uint32_t tcds)102 static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
103 {
104     tcds                                                      = tcds;
105     flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
106 
107     if (transferDone)
108     {
109         /* Disable Rx dma */
110         FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, (uint32_t)kFLEXIO_SPI_RxDmaEnable, false);
111 
112         /* change the state */
113         spiPrivateHandle->handle->rxInProgress = false;
114 
115         /* All finished, call the callback */
116         if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
117         {
118             if (spiPrivateHandle->handle->callback != NULL)
119             {
120                 (spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
121                                                      spiPrivateHandle->handle->userData);
122             }
123         }
124     }
125 }
126 
FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type * base,flexio_spi_master_edma_handle_t * handle,flexio_spi_transfer_t * xfer)127 static status_t FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
128                                       flexio_spi_master_edma_handle_t *handle,
129                                       flexio_spi_transfer_t *xfer)
130 {
131     edma_transfer_config_t xferConfig      = {0};
132     flexio_spi_shift_direction_t direction = kFLEXIO_SPI_MsbFirst;
133     uint8_t bytesPerFrame;
134     uint8_t dataFormat = FLEXIO_SPI_XFER_DATA_FORMAT(xfer->flags);
135 
136     /* Configure the values in handle. */
137     switch (dataFormat)
138     {
139         case (uint8_t)kFLEXIO_SPI_8bitMsb:
140             bytesPerFrame = 1U;
141             direction     = kFLEXIO_SPI_MsbFirst;
142             break;
143         case (uint8_t)kFLEXIO_SPI_8bitLsb:
144             bytesPerFrame = 1U;
145             direction     = kFLEXIO_SPI_LsbFirst;
146             break;
147         case (uint8_t)kFLEXIO_SPI_16bitMsb:
148             bytesPerFrame = 2U;
149             direction     = kFLEXIO_SPI_MsbFirst;
150             break;
151         case (uint8_t)kFLEXIO_SPI_16bitLsb:
152             bytesPerFrame = 2U;
153             direction     = kFLEXIO_SPI_LsbFirst;
154             break;
155         case (uint8_t)kFLEXIO_SPI_32bitMsb:
156             bytesPerFrame = 4U;
157             direction     = kFLEXIO_SPI_MsbFirst;
158             break;
159         case (uint8_t)kFLEXIO_SPI_32bitLsb:
160             bytesPerFrame = 4U;
161             direction     = kFLEXIO_SPI_LsbFirst;
162             break;
163         default:
164             bytesPerFrame = 1U;
165             direction     = kFLEXIO_SPI_MsbFirst;
166             assert(true);
167             break;
168     }
169 
170     /* Transfer size should be bytesPerFrame divisible. */
171     if ((xfer->dataSize % bytesPerFrame) != 0U)
172     {
173         return kStatus_InvalidArgument;
174     }
175 
176     /* Save total transfer size. */
177     handle->transferSize = xfer->dataSize;
178 
179     /* Configure tx transfer EDMA. */
180     xferConfig.destAddr   = FLEXIO_SPI_GetTxDataRegisterAddress(base, direction);
181     xferConfig.destOffset = 0;
182     if (bytesPerFrame == 1U)
183     {
184         xferConfig.srcTransferSize  = kEDMA_TransferSize1Bytes;
185         xferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
186         xferConfig.minorLoopBytes   = 1U;
187     }
188     else if (bytesPerFrame == 2U)
189     {
190         if (direction == kFLEXIO_SPI_MsbFirst)
191         {
192             xferConfig.destAddr -= 1U;
193         }
194         xferConfig.srcTransferSize  = kEDMA_TransferSize2Bytes;
195         xferConfig.destTransferSize = kEDMA_TransferSize2Bytes;
196         xferConfig.minorLoopBytes   = 2U;
197     }
198     else
199     {
200         if (direction == kFLEXIO_SPI_MsbFirst)
201         {
202             xferConfig.destAddr -= 3U;
203         }
204         xferConfig.srcTransferSize  = kEDMA_TransferSize4Bytes;
205         xferConfig.destTransferSize = kEDMA_TransferSize4Bytes;
206         xferConfig.minorLoopBytes   = 4U;
207     }
208 
209     /* Configure DMA channel. */
210     if (xfer->txData != NULL)
211     {
212         xferConfig.srcOffset = (int16_t)bytesPerFrame;
213         xferConfig.srcAddr   = (uint32_t)(xfer->txData);
214     }
215     else
216     {
217         /* Disable the source increasement and source set to dummyData. */
218         xferConfig.srcOffset = 0;
219         xferConfig.srcAddr   = (uint32_t)(&s_dummyData);
220     }
221 
222     xferConfig.majorLoopCounts = (xfer->dataSize / xferConfig.minorLoopBytes);
223 
224     /* Store the initially configured eDMA minor byte transfer count into the FLEXIO SPI handle */
225     handle->nbytes = (uint8_t)xferConfig.minorLoopBytes;
226 
227     if (handle->txHandle != NULL)
228     {
229         (void)EDMA_SubmitTransfer(handle->txHandle, &xferConfig);
230     }
231 
232     /* Configure rx transfer EDMA. */
233     if (xfer->rxData != NULL)
234     {
235         xferConfig.srcAddr = FLEXIO_SPI_GetRxDataRegisterAddress(base, direction);
236         if (bytesPerFrame == 2U)
237         {
238             if (direction == kFLEXIO_SPI_LsbFirst)
239             {
240                 xferConfig.srcAddr -= 1U;
241             }
242         }
243         else if (bytesPerFrame == 4U)
244         {
245             if (direction == kFLEXIO_SPI_LsbFirst)
246             {
247                 xferConfig.srcAddr -= 3U;
248             }
249         }
250         else
251         {
252         }
253         xferConfig.srcOffset  = 0;
254         xferConfig.destAddr   = (uint32_t)(xfer->rxData);
255         xferConfig.destOffset = (int16_t)bytesPerFrame;
256         (void)EDMA_SubmitTransfer(handle->rxHandle, &xferConfig);
257         handle->rxInProgress = true;
258         FLEXIO_SPI_EnableDMA(base, (uint32_t)kFLEXIO_SPI_RxDmaEnable, true);
259         EDMA_StartTransfer(handle->rxHandle);
260     }
261 
262     /* Always start tx transfer. */
263     if (handle->txHandle != NULL)
264     {
265         handle->txInProgress = true;
266         FLEXIO_SPI_EnableDMA(base, (uint32_t)kFLEXIO_SPI_TxDmaEnable, true);
267         EDMA_StartTransfer(handle->txHandle);
268     }
269 
270     return kStatus_Success;
271 }
272 
273 /*!
274  * brief Initializes the FlexIO SPI master eDMA handle.
275  *
276  * This function initializes the FlexIO SPI master eDMA handle which can be used for other FlexIO SPI master
277  * transactional
278  * APIs.
279  * For a specified FlexIO SPI instance, call this API once to get the initialized handle.
280  *
281  * param base Pointer to FLEXIO_SPI_Type structure.
282  * param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
283  * param callback SPI callback, NULL means no callback.
284  * param userData callback function parameter.
285  * param txHandle User requested eDMA handle for FlexIO SPI RX eDMA transfer.
286  * param rxHandle User requested eDMA handle for FlexIO SPI TX eDMA transfer.
287  * retval kStatus_Success Successfully create the handle.
288  * retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
289  */
FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type * base,flexio_spi_master_edma_handle_t * handle,flexio_spi_master_edma_transfer_callback_t callback,void * userData,edma_handle_t * txHandle,edma_handle_t * rxHandle)290 status_t FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
291                                                    flexio_spi_master_edma_handle_t *handle,
292                                                    flexio_spi_master_edma_transfer_callback_t callback,
293                                                    void *userData,
294                                                    edma_handle_t *txHandle,
295                                                    edma_handle_t *rxHandle)
296 {
297     assert(handle != NULL);
298 
299     uint8_t index = 0;
300 
301     /* Find the an empty handle pointer to store the handle. */
302     for (index = 0U; index < (uint8_t)FLEXIO_SPI_HANDLE_COUNT; index++)
303     {
304         if (s_edmaPrivateHandle[index].base == NULL)
305         {
306             s_edmaPrivateHandle[index].base   = base;
307             s_edmaPrivateHandle[index].handle = handle;
308             break;
309         }
310     }
311 
312     if (index == (uint16_t)FLEXIO_SPI_HANDLE_COUNT)
313     {
314         return kStatus_OutOfRange;
315     }
316 
317     /* Set spi base to handle. */
318     handle->txHandle = txHandle;
319     handle->rxHandle = rxHandle;
320 
321     /* Register callback and userData. */
322     handle->callback = callback;
323     handle->userData = userData;
324 
325     /* Set SPI state to idle. */
326     handle->txInProgress = false;
327     handle->rxInProgress = false;
328 
329     /* Install callback for Tx/Rx dma channel. */
330     if (handle->txHandle != NULL)
331     {
332         EDMA_SetCallback(handle->txHandle, FLEXIO_SPI_TxEDMACallback, &s_edmaPrivateHandle[index]);
333     }
334     if (handle->rxHandle != NULL)
335     {
336         EDMA_SetCallback(handle->rxHandle, FLEXIO_SPI_RxEDMACallback, &s_edmaPrivateHandle[index]);
337     }
338 
339     return kStatus_Success;
340 }
341 
342 /*!
343  * brief Performs a non-blocking FlexIO SPI transfer using eDMA.
344  *
345  * note This interface returns immediately after transfer initiates. Call
346  * FLEXIO_SPI_MasterGetTransferCountEDMA to poll the transfer status and check
347  * whether the FlexIO SPI transfer is finished.
348  *
349  * param base Pointer to FLEXIO_SPI_Type structure.
350  * param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
351  * param xfer Pointer to FlexIO SPI transfer structure.
352  * retval kStatus_Success Successfully start a transfer.
353  * retval kStatus_InvalidArgument Input argument is invalid.
354  * retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
355  */
FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type * base,flexio_spi_master_edma_handle_t * handle,flexio_spi_transfer_t * xfer)356 status_t FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type *base,
357                                        flexio_spi_master_edma_handle_t *handle,
358                                        flexio_spi_transfer_t *xfer)
359 {
360     assert(handle != NULL);
361     assert(xfer != NULL);
362 
363     uint32_t dataMode  = 0;
364     uint16_t timerCmp  = (uint16_t)base->flexioBase->TIMCMP[base->timerIndex[0]];
365     uint8_t dataFormat = FLEXIO_SPI_XFER_DATA_FORMAT(xfer->flags);
366 
367     timerCmp &= 0x00FFU;
368 
369     /* Check if the device is busy. */
370     if ((handle->txInProgress) || (handle->rxInProgress))
371     {
372         return kStatus_FLEXIO_SPI_Busy;
373     }
374 
375     /* Check if input parameter invalid. */
376     if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
377     {
378         return kStatus_InvalidArgument;
379     }
380 
381     /* Timer1 controls the CS signal which enables/disables(asserts/deasserts) when timer0 enable/disable. Timer0
382        enables when tx shifter is written and disables when timer compare. The timer compare event causes the
383        transmit shift registers to load which generates a tx register empty event. Since when timer stop bit is
384        disabled, a timer enable condition can be detected in the same cycle as a timer disable condition, so if
385        software writes the tx register upon the detection of tx register empty event, the timer enable condition
386        is triggered again, then the CS signal can remain low until software no longer writes the tx register. */
387     if ((xfer->flags & (uint8_t)kFLEXIO_SPI_csContinuous) != 0U)
388     {
389         base->flexioBase->TIMCFG[base->timerIndex[0]] =
390             (base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TSTOP_MASK) |
391             FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitDisabled);
392     }
393     else
394     {
395         base->flexioBase->TIMCFG[base->timerIndex[0]] =
396             (base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TSTOP_MASK) |
397             FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitEnableOnTimerDisable);
398     }
399 
400     /* configure data mode. */
401     if ((dataFormat == (uint8_t)kFLEXIO_SPI_8bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_8bitLsb))
402     {
403         dataMode = (8UL * 2UL - 1UL) << 8U;
404     }
405     else if ((dataFormat == (uint8_t)kFLEXIO_SPI_16bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_16bitLsb))
406     {
407         dataMode = (16UL * 2UL - 1UL) << 8U;
408     }
409     else if ((dataFormat == (uint8_t)kFLEXIO_SPI_32bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_32bitLsb))
410     {
411         dataMode = (32UL * 2UL - 1UL) << 8U;
412     }
413     else
414     {
415         dataMode = (8UL * 2UL - 1UL) << 8U;
416     }
417 
418     dataMode |= timerCmp;
419 
420     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
421 
422     return FLEXIO_SPI_EDMAConfig(base, handle, xfer);
423 }
424 
425 /*!
426  * brief Gets the remaining bytes for FlexIO SPI eDMA transfer.
427  *
428  * param base Pointer to FLEXIO_SPI_Type structure.
429  * param handle FlexIO SPI eDMA handle pointer.
430  * param count Number of bytes transferred so far by the non-blocking transaction.
431  */
FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type * base,flexio_spi_master_edma_handle_t * handle,size_t * count)432 status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base,
433                                                flexio_spi_master_edma_handle_t *handle,
434                                                size_t *count)
435 {
436     assert(handle != NULL);
437 
438     if (NULL == count)
439     {
440         return kStatus_InvalidArgument;
441     }
442 
443     if (handle->rxInProgress)
444     {
445         *count =
446             (handle->transferSize - (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(
447                                                                    handle->rxHandle->base, handle->rxHandle->channel));
448     }
449     else
450     {
451         *count =
452             (handle->transferSize - (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(
453                                                                    handle->txHandle->base, handle->txHandle->channel));
454     }
455 
456     return kStatus_Success;
457 }
458 
459 /*!
460  * brief Aborts a FlexIO SPI transfer using eDMA.
461  *
462  * param base Pointer to FLEXIO_SPI_Type structure.
463  * param handle FlexIO SPI eDMA handle pointer.
464  */
FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type * base,flexio_spi_master_edma_handle_t * handle)465 void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master_edma_handle_t *handle)
466 {
467     assert(handle != NULL);
468 
469     /* Disable dma. */
470     EDMA_AbortTransfer(handle->txHandle);
471     EDMA_AbortTransfer(handle->rxHandle);
472 
473     /* Disable DMA enable bit. */
474     FLEXIO_SPI_EnableDMA(base, (uint32_t)kFLEXIO_SPI_DmaAllEnable, false);
475 
476     /* Set the handle state. */
477     handle->txInProgress = false;
478     handle->rxInProgress = false;
479 }
480 
481 /*!
482  * brief Performs a non-blocking FlexIO SPI transfer using eDMA.
483  *
484  * note This interface returns immediately after transfer initiates. Call
485  * FLEXIO_SPI_SlaveGetTransferCountEDMA to poll the transfer status and
486  * check whether the FlexIO SPI transfer is finished.
487  *
488  * param base Pointer to FLEXIO_SPI_Type structure.
489  * param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
490  * param xfer Pointer to FlexIO SPI transfer structure.
491  * retval kStatus_Success Successfully start a transfer.
492  * retval kStatus_InvalidArgument Input argument is invalid.
493  * retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
494  */
FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type * base,flexio_spi_slave_edma_handle_t * handle,flexio_spi_transfer_t * xfer)495 status_t FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type *base,
496                                       flexio_spi_slave_edma_handle_t *handle,
497                                       flexio_spi_transfer_t *xfer)
498 {
499     assert(handle != NULL);
500     assert(xfer != NULL);
501 
502     uint32_t dataMode  = 0U;
503     uint8_t dataFormat = FLEXIO_SPI_XFER_DATA_FORMAT(xfer->flags);
504 
505     /* Check if the device is busy. */
506     if ((handle->txInProgress) || (handle->rxInProgress))
507     {
508         return kStatus_FLEXIO_SPI_Busy;
509     }
510 
511     /* SCK timer use CS pin as inverted trigger so timer should be disbaled on trigger falling edge(CS re-asserts). */
512     /* However if CPHA is first edge mode, timer will restart each time right after timer compare event occur and
513        before CS pin re-asserts, which triggers another shifter load. To avoid this, when in CS dis-continuous mode,
514        timer should disable in timer compare rather than trigger falling edge(CS re-asserts), and in CS continuous mode,
515        tx/rx shifters should be flushed after transfer finishes and before next transfer starts. */
516     FLEXIO_SPI_FlushShifters(base);
517     if ((xfer->flags & (uint8_t)kFLEXIO_SPI_csContinuous) != 0U)
518     {
519         base->flexioBase->TIMCFG[base->timerIndex[0]] |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTriggerFallingEdge);
520     }
521     else
522     {
523         if ((base->flexioBase->SHIFTCTL[base->shifterIndex[0]] & FLEXIO_SHIFTCTL_TIMPOL_MASK) ==
524             FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnNegitive))
525         {
526             base->flexioBase->TIMCFG[base->timerIndex[0]] =
527                 (base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TIMDIS_MASK) |
528                 FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare);
529         }
530         else
531         {
532             base->flexioBase->TIMCFG[base->timerIndex[0]] =
533                 (base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TIMDIS_MASK) |
534                 FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTriggerFallingEdge);
535         }
536     }
537 
538     /* Check if input parameter invalid. */
539     if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
540     {
541         return kStatus_InvalidArgument;
542     }
543 
544     /* configure data mode. */
545     if ((dataFormat == (uint8_t)kFLEXIO_SPI_8bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_8bitLsb))
546     {
547         dataMode = 8U * 2U - 1U;
548     }
549     else if ((dataFormat == (uint8_t)kFLEXIO_SPI_16bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_16bitLsb))
550     {
551         dataMode = 16U * 2U - 1U;
552     }
553     else if ((dataFormat == (uint8_t)kFLEXIO_SPI_32bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_32bitLsb))
554     {
555         dataMode = 32UL * 2UL - 1UL;
556     }
557     else
558     {
559         dataMode = 8U * 2U - 1U;
560     }
561 
562     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
563 
564     return FLEXIO_SPI_EDMAConfig(base, handle, xfer);
565 }
566