1 /*
2  * Copyright 2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_lpspi_edma.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.lpflexcomm_lpspi_edma"
17 #endif
18 
19 /*!
20  * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private.
21  */
22 typedef struct _lpspi_master_edma_private_handle
23 {
24     LPSPI_Type *base;                   /*!< LPSPI peripheral base address. */
25     lpspi_master_edma_handle_t *handle; /*!< lpspi_master_edma_handle_t handle */
26 } lpspi_master_edma_private_handle_t;
27 
28 /*!
29  * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private.
30  */
31 typedef struct _lpspi_slave_edma_private_handle
32 {
33     LPSPI_Type *base;                  /*!< LPSPI peripheral base address. */
34     lpspi_slave_edma_handle_t *handle; /*!< lpspi_slave_edma_handle_t handle */
35 } lpspi_slave_edma_private_handle_t;
36 
37 /***********************************************************************************************************************
38  * Prototypes
39  ***********************************************************************************************************************/
40 
41 /*!
42  * @brief EDMA_LpspiMasterCallback after the LPSPI master transfer completed by using EDMA.
43  * This is not a public API.
44  */
45 static void EDMA_LpspiMasterCallback(edma_handle_t *edmaHandle,
46                                      void *g_lpspiEdmaPrivateHandle,
47                                      bool transferDone,
48                                      uint32_t tcds);
49 
50 /*!
51  * @brief EDMA_LpspiSlaveCallback after the LPSPI slave transfer completed by using EDMA.
52  * This is not a public API.
53  */
54 static void EDMA_LpspiSlaveCallback(edma_handle_t *edmaHandle,
55                                     void *g_lpspiEdmaPrivateHandle,
56                                     bool transferDone,
57                                     uint32_t tcds);
58 
59 static void LPSPI_SeparateEdmaReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap);
60 
61 /***********************************************************************************************************************
62  * Variables
63  ***********************************************************************************************************************/
64 /*! @brief Pointers to lpspi bases for each instance. */
65 static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS;
66 
67 /*! @brief Pointers to lpspi edma handles for each instance. */
68 static lpspi_master_edma_private_handle_t s_lpspiMasterEdmaPrivateHandle[ARRAY_SIZE(s_lpspiBases)];
69 static lpspi_slave_edma_private_handle_t s_lpspiSlaveEdmaPrivateHandle[ARRAY_SIZE(s_lpspiBases)];
70 
71 /***********************************************************************************************************************
72  * Code
73  ***********************************************************************************************************************/
LPSPI_SeparateEdmaReadData(uint8_t * rxData,uint32_t readData,uint32_t bytesEachRead,bool isByteSwap)74 static void LPSPI_SeparateEdmaReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap)
75 {
76     assert(rxData != NULL);
77 
78     switch (bytesEachRead)
79     {
80         case 1:
81             if (!isByteSwap)
82             {
83                 *rxData = (uint8_t)readData;
84                 ++rxData;
85             }
86             else
87             {
88                 *rxData = (uint8_t)(readData >> 24);
89                 ++rxData;
90             }
91             break;
92 
93         case 2:
94             if (!isByteSwap)
95             {
96                 *rxData = (uint8_t)readData;
97                 ++rxData;
98                 *rxData = (uint8_t)(readData >> 8);
99                 ++rxData;
100             }
101             else
102             {
103                 *rxData = (uint8_t)(readData >> 16);
104                 ++rxData;
105                 *rxData = (uint8_t)(readData >> 24);
106                 ++rxData;
107             }
108             break;
109 
110         case 4:
111 
112             *rxData = (uint8_t)readData;
113             ++rxData;
114             *rxData = (uint8_t)(readData >> 8);
115             ++rxData;
116             *rxData = (uint8_t)(readData >> 16);
117             ++rxData;
118             *rxData = (uint8_t)(readData >> 24);
119             ++rxData;
120 
121             break;
122 
123         default:
124             assert(false);
125             break;
126     }
127 }
128 
129 /*!
130  * brief Initializes the LPSPI master eDMA handle.
131  *
132  * This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs.  Usually, for a
133  * specified LPSPI instance, call this API once to get the initialized handle.
134  *
135  * Note that the LPSPI eDMA has a separated (Rx and Rx as two sources) or shared (Rx  and Tx are the same source) DMA
136  * request source.
137  * (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
138  * Tx DMAMUX source for edmaIntermediaryToTxRegHandle.
139  * (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle.
140  *
141  * param base LPSPI peripheral base address.
142  * param handle LPSPI handle pointer to lpspi_master_edma_handle_t.
143  * param callback LPSPI callback.
144  * param userData callback function parameter.
145  * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
146  * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
147  */
LPSPI_MasterTransferCreateHandleEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,lpspi_master_edma_transfer_callback_t callback,void * userData,edma_handle_t * edmaRxRegToRxDataHandle,edma_handle_t * edmaTxDataToTxRegHandle)148 void LPSPI_MasterTransferCreateHandleEDMA(LPSPI_Type *base,
149                                           lpspi_master_edma_handle_t *handle,
150                                           lpspi_master_edma_transfer_callback_t callback,
151                                           void *userData,
152                                           edma_handle_t *edmaRxRegToRxDataHandle,
153                                           edma_handle_t *edmaTxDataToTxRegHandle)
154 {
155     assert(handle != NULL);
156     assert(edmaRxRegToRxDataHandle != NULL);
157     assert(edmaTxDataToTxRegHandle != NULL);
158 
159     /* Zero the handle. */
160     (void)memset(handle, 0, sizeof(*handle));
161 
162     uint32_t instance = LPSPI_GetInstance(base);
163 
164     s_lpspiMasterEdmaPrivateHandle[instance].base   = base;
165     s_lpspiMasterEdmaPrivateHandle[instance].handle = handle;
166 
167     handle->callback = callback;
168     handle->userData = userData;
169 
170     handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
171     handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
172 }
173 
LPSPI_PrepareTransferEDMA(LPSPI_Type * base)174 static void LPSPI_PrepareTransferEDMA(LPSPI_Type *base)
175 {
176     /* Flush FIFO, clear status, disable all the inerrupts and DMA requests. */
177     LPSPI_FlushFifo(base, true, true);
178     LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
179     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
180     LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
181 }
182 
183 /*!
184  * brief LPSPI master config transfer parameter using eDMA.
185  *
186  * This function is preparing to transfers data using eDMA.
187  *
188  * param base LPSPI peripheral base address.
189  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
190  * param configFlags transfer configuration flags. ref _lpspi_transfer_config_flag_for_master.
191  * return Indicates whether LPSPI master transfer was successful or not.
192  * retval kStatus_Success          Execution successfully.
193  * retval kStatus_LPSPI_Busy       The LPSPI device is busy.
194  */
LPSPI_MasterTransferPrepareEDMALite(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,uint32_t configFlags)195 status_t LPSPI_MasterTransferPrepareEDMALite(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, uint32_t configFlags)
196 {
197     assert(handle != NULL);
198 
199     /* Check that we're not busy.*/
200     if (handle->state == (uint8_t)kLPSPI_Busy)
201     {
202         return kStatus_LPSPI_Busy;
203     }
204 
205     /* Disable module before configuration */
206     LPSPI_Enable(base, false);
207 
208     LPSPI_PrepareTransferEDMA(base);
209 
210     bool isByteSwap      = ((configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
211     bool isPcsContinuous = ((configFlags & (uint32_t)kLPSPI_MasterPcsContinuous) != 0U);
212     uint32_t instance    = LPSPI_GetInstance(base);
213     uint8_t dummyData    = g_lpspiDummyData[instance];
214     /*Used for byte swap*/
215     uint32_t whichPcs      = (configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
216     uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
217 
218     handle->txBuffIfNull =
219         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
220     /*The TX and RX FIFO sizes are always the same*/
221     handle->fifoSize            = LPSPI_GetRxFifoSize(base);
222     handle->isPcsContinuous     = isPcsContinuous;
223     handle->isByteSwap          = isByteSwap;
224     handle->isThereExtraRxBytes = false;
225 
226     /*Because DMA is fast enough , so set the RX and TX watermarks to 0 .*/
227     LPSPI_SetFifoWatermarks(base, 0U, 0U);
228 
229     /* Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
230     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
231 
232     /* Enable module for following configuration of TCR to take effect. */
233     LPSPI_Enable(base, true);
234 
235     /* For DMA transfer , we'd better not masked the transmit data and receive data in TCR since the transfer flow is
236      * hard to controlled by software. */
237     base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_BYSW_MASK | LPSPI_TCR_PCS_MASK)) |
238                 LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_BYSW(isByteSwap) | LPSPI_TCR_PCS(whichPcs);
239     /*Calculate the bytes for write/read the TX/RX register each time*/
240     if (bytesPerFrame <= 4U)
241     {
242         handle->bytesEachWrite = (uint8_t)bytesPerFrame;
243         handle->bytesEachRead  = (uint8_t)bytesPerFrame;
244         handle->bytesLastRead  = (uint8_t)bytesPerFrame;
245     }
246     else
247     {
248         handle->bytesEachWrite = 4U;
249         handle->bytesEachRead  = 4U;
250 
251         handle->bytesLastRead = 4U;
252     }
253     return kStatus_Success;
254 }
255 
256 /*!
257  * brief LPSPI master transfer data using eDMA without configs.
258  *
259  * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
260  * is transferred, the callback function is called.
261  *
262  * Note:
263  * This API is only for transfer through DMA without configuration.
264  * Before calling this API, you must call LPSPI_MasterTransferPrepareEDMALite to configure it once.
265  * The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
266  * For bytesPerFrame greater than 4:
267  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
268  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
269  *
270  * param base LPSPI peripheral base address.
271  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
272  * param transfer pointer to lpspi_transfer_t structure, config field is not working.
273  * return Indicates whether LPSPI master transfer was successful or not.
274  * retval kStatus_Success          Execution successfully.
275  * retval kStatus_LPSPI_Busy       The LPSPI device is busy.
276  * retval kStatus_InvalidArgument  The transfer structure is invalid.
277  */
LPSPI_MasterTransferEDMALite(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,lpspi_transfer_t * transfer)278 status_t LPSPI_MasterTransferEDMALite(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, lpspi_transfer_t *transfer)
279 {
280     assert(handle != NULL);
281     assert(transfer != NULL);
282 
283     /* Check that we're not busy.*/
284     if (handle->state == (uint8_t)kLPSPI_Busy)
285     {
286         return kStatus_LPSPI_Busy;
287     }
288 
289     /* Check arguements */
290     if (!LPSPI_CheckTransferArgument(base, transfer, true))
291     {
292         return kStatus_InvalidArgument;
293     }
294 
295     /* Variables */
296     bool isThereExtraTxBytes = false;
297     uint8_t bytesLastWrite   = 0;
298     uint32_t instance        = LPSPI_GetInstance(base);
299     /*Used for byte swap*/
300     uint32_t addrOffset    = 0;
301     uint32_t rxAddr        = LPSPI_GetRxRegisterAddress(base);
302     uint32_t txAddr        = LPSPI_GetTxRegisterAddress(base);
303     uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
304     edma_transfer_config_t transferConfigRx = {0};
305     edma_transfer_config_t transferConfigTx = {0};
306     edma_tcd_t *softwareTCD_pcsContinuous   = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[2]) & (~0x1FU));
307     edma_tcd_t *softwareTCD_extraBytes      = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[1]) & (~0x1FU));
308 
309     handle->state                  = (uint8_t)kLPSPI_Busy;
310     handle->txData                 = transfer->txData;
311     handle->rxData                 = transfer->rxData;
312     handle->txRemainingByteCount   = transfer->dataSize;
313     handle->rxRemainingByteCount   = transfer->dataSize;
314     handle->totalByteCount         = transfer->dataSize;
315     handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
316     handle->readRegRemainingTimes  = handle->writeRegRemainingTimes;
317 
318     handle->isThereExtraRxBytes = false;
319 
320     /*Calculate the bytes for write/read the TX/RX register each time*/
321     if (bytesPerFrame > 4U)
322     {
323         if ((transfer->dataSize % 4U) != 0U)
324         {
325             bytesLastWrite        = (uint8_t)(transfer->dataSize % 4U);
326             handle->bytesLastRead = bytesLastWrite;
327 
328             isThereExtraTxBytes = true;
329 
330             --handle->writeRegRemainingTimes;
331 
332             --handle->readRegRemainingTimes;
333             handle->isThereExtraRxBytes = true;
334         }
335     }
336 
337     EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_LpspiMasterCallback,
338                      &s_lpspiMasterEdmaPrivateHandle[instance]);
339 
340     /* Configure rx EDMA transfer */
341     EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
342 
343     if (handle->rxData != NULL)
344     {
345         transferConfigRx.destAddr   = (uint32_t) & (handle->rxData[0]);
346         transferConfigRx.destOffset = 1;
347     }
348     else
349     {
350         transferConfigRx.destAddr   = (uint32_t) & (handle->rxBuffIfNull);
351         transferConfigRx.destOffset = 0;
352     }
353     transferConfigRx.destTransferSize = kEDMA_TransferSize1Bytes;
354 
355     addrOffset = 0;
356     switch (handle->bytesEachRead)
357     {
358         case (1U):
359             transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
360             transferConfigRx.minorLoopBytes  = 1;
361             if (handle->isByteSwap)
362             {
363                 addrOffset = 3;
364             }
365             break;
366 
367         case (2U):
368             transferConfigRx.srcTransferSize = kEDMA_TransferSize2Bytes;
369             transferConfigRx.minorLoopBytes  = 2;
370             if (handle->isByteSwap)
371             {
372                 addrOffset = 2;
373             }
374             break;
375 
376         case (4U):
377             transferConfigRx.srcTransferSize = kEDMA_TransferSize4Bytes;
378             transferConfigRx.minorLoopBytes  = 4;
379             break;
380 
381         default:
382             transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
383             transferConfigRx.minorLoopBytes  = 1;
384             assert(false);
385             break;
386     }
387 
388     transferConfigRx.srcAddr   = (uint32_t)rxAddr + addrOffset;
389     transferConfigRx.srcOffset = 0;
390 
391     transferConfigRx.majorLoopCounts = handle->readRegRemainingTimes;
392 
393     /* Store the initially configured eDMA minor byte transfer count into the LPSPI handle */
394     handle->nbytes = (uint8_t)transferConfigRx.minorLoopBytes;
395 
396     EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
397                            &transferConfigRx, NULL);
398     EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
399                                  (uint32_t)kEDMA_MajorInterruptEnable);
400 
401     /* Configure tx EDMA transfer */
402     EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
403 
404     if (isThereExtraTxBytes)
405     {
406         if (handle->txData != NULL)
407         {
408             transferConfigTx.srcAddr   = (uint32_t) & (transfer->txData[transfer->dataSize - bytesLastWrite]);
409             transferConfigTx.srcOffset = 1;
410         }
411         else
412         {
413             transferConfigTx.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
414             transferConfigTx.srcOffset = 0;
415         }
416 
417         transferConfigTx.destOffset = 0;
418 
419         transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
420 
421         addrOffset = 0;
422         switch (bytesLastWrite)
423         {
424             case (1U):
425                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
426                 transferConfigTx.minorLoopBytes   = 1;
427                 if (handle->isByteSwap)
428                 {
429                     addrOffset = 3;
430                 }
431                 break;
432 
433             case (2U):
434                 transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
435                 transferConfigTx.minorLoopBytes   = 2;
436                 if (handle->isByteSwap)
437                 {
438                     addrOffset = 2;
439                 }
440                 break;
441 
442             default:
443                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
444                 transferConfigTx.minorLoopBytes   = 1;
445                 assert(false);
446                 break;
447         }
448 
449         transferConfigTx.destAddr        = (uint32_t)txAddr + addrOffset;
450         transferConfigTx.majorLoopCounts = 1;
451 
452 #if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
453         EDMA_TcdResetExt(handle->edmaRxRegToRxDataHandle->base, softwareTCD_extraBytes);
454         if (handle->isPcsContinuous)
455         {
456             EDMA_TcdSetTransferConfigExt(handle->edmaRxRegToRxDataHandle->base, softwareTCD_extraBytes,
457                                          &transferConfigTx, softwareTCD_pcsContinuous);
458         }
459         else
460         {
461             EDMA_TcdSetTransferConfigExt(handle->edmaRxRegToRxDataHandle->base, softwareTCD_extraBytes,
462                                          &transferConfigTx, NULL);
463         }
464 #else
465         EDMA_TcdReset(softwareTCD_extraBytes);
466         if (handle->isPcsContinuous)
467         {
468             EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, softwareTCD_pcsContinuous);
469         }
470         else
471         {
472             EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, NULL);
473         }
474 #endif
475     }
476 
477     if (handle->isPcsContinuous)
478     {
479         handle->transmitCommand = base->TCR & ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK);
480 
481         transferConfigTx.srcAddr   = (uint32_t) & (handle->transmitCommand);
482         transferConfigTx.srcOffset = 0;
483 
484         transferConfigTx.destAddr   = (uint32_t) & (base->TCR);
485         transferConfigTx.destOffset = 0;
486 
487         transferConfigTx.srcTransferSize  = kEDMA_TransferSize4Bytes;
488         transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
489         transferConfigTx.minorLoopBytes   = 4;
490         transferConfigTx.majorLoopCounts  = 1;
491 
492 #if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
493         EDMA_TcdResetExt(handle->edmaRxRegToRxDataHandle->base, softwareTCD_pcsContinuous);
494         EDMA_TcdSetTransferConfigExt(handle->edmaRxRegToRxDataHandle->base, softwareTCD_pcsContinuous,
495                                      &transferConfigTx, NULL);
496 #else
497         EDMA_TcdReset(softwareTCD_pcsContinuous);
498         EDMA_TcdSetTransferConfig(softwareTCD_pcsContinuous, &transferConfigTx, NULL);
499 #endif
500     }
501 
502     if (handle->txData != NULL)
503     {
504         transferConfigTx.srcAddr   = (uint32_t)(handle->txData);
505         transferConfigTx.srcOffset = 1;
506     }
507     else
508     {
509         transferConfigTx.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
510         transferConfigTx.srcOffset = 0;
511     }
512 
513     transferConfigTx.destOffset = 0;
514 
515     transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
516 
517     addrOffset = 0U;
518     switch (handle->bytesEachRead)
519     {
520         case (1U):
521             transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
522             transferConfigTx.minorLoopBytes   = 1;
523             if (handle->isByteSwap)
524             {
525                 addrOffset = 3;
526             }
527             break;
528 
529         case (2U):
530             transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
531             transferConfigTx.minorLoopBytes   = 2;
532 
533             if (handle->isByteSwap)
534             {
535                 addrOffset = 2;
536             }
537             break;
538 
539         case (4U):
540             transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
541             transferConfigTx.minorLoopBytes   = 4;
542             break;
543 
544         default:
545             transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
546             transferConfigTx.minorLoopBytes   = 1;
547             assert(false);
548             break;
549     }
550 
551     transferConfigTx.destAddr = (uint32_t)txAddr + addrOffset;
552 
553     transferConfigTx.majorLoopCounts = handle->writeRegRemainingTimes;
554 
555     if (isThereExtraTxBytes)
556     {
557         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
558                                &transferConfigTx, softwareTCD_extraBytes);
559     }
560     else if (handle->isPcsContinuous)
561     {
562         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
563                                &transferConfigTx, softwareTCD_pcsContinuous);
564     }
565     else
566     {
567         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
568                                &transferConfigTx, NULL);
569     }
570 
571     EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
572     EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
573     LPSPI_EnableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
574 
575     return kStatus_Success;
576 }
577 
578 /*!
579  * brief LPSPI master transfer data using eDMA.
580  *
581  * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
582  * is transferred, the callback function is called.
583  *
584  * Note:
585  * The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
586  * For bytesPerFrame greater than 4:
587  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
588  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
589  *
590  * param base LPSPI peripheral base address.
591  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
592  * param transfer pointer to lpspi_transfer_t structure.
593  * return status of status_t.
594  */
LPSPI_MasterTransferEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,lpspi_transfer_t * transfer)595 status_t LPSPI_MasterTransferEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, lpspi_transfer_t *transfer)
596 {
597     status_t status = kStatus_Fail;
598     status          = LPSPI_MasterTransferPrepareEDMALite(base, handle, transfer->configFlags);
599     if (kStatus_Success != status)
600     {
601         return status;
602     }
603     return LPSPI_MasterTransferEDMALite(base, handle, transfer);
604 }
605 
EDMA_LpspiMasterCallback(edma_handle_t * edmaHandle,void * g_lpspiEdmaPrivateHandle,bool transferDone,uint32_t tcds)606 static void EDMA_LpspiMasterCallback(edma_handle_t *edmaHandle,
607                                      void *g_lpspiEdmaPrivateHandle,
608                                      bool transferDone,
609                                      uint32_t tcds)
610 {
611     assert(edmaHandle != NULL);
612     assert(g_lpspiEdmaPrivateHandle != NULL);
613 
614     uint32_t readData;
615 
616     lpspi_master_edma_private_handle_t *lpspiEdmaPrivateHandle;
617 
618     lpspiEdmaPrivateHandle = (lpspi_master_edma_private_handle_t *)g_lpspiEdmaPrivateHandle;
619 
620     size_t rxRemainingByteCount = lpspiEdmaPrivateHandle->handle->rxRemainingByteCount;
621     uint8_t bytesLastRead       = lpspiEdmaPrivateHandle->handle->bytesLastRead;
622     bool isByteSwap             = lpspiEdmaPrivateHandle->handle->isByteSwap;
623 
624     LPSPI_DisableDMA(lpspiEdmaPrivateHandle->base, (uint32_t)kLPSPI_TxDmaEnable | (uint32_t)kLPSPI_RxDmaEnable);
625 
626     if (lpspiEdmaPrivateHandle->handle->isThereExtraRxBytes)
627     {
628         while (LPSPI_GetRxFifoCount(lpspiEdmaPrivateHandle->base) == 0U)
629         {
630         }
631         readData = LPSPI_ReadData(lpspiEdmaPrivateHandle->base);
632 
633         if (lpspiEdmaPrivateHandle->handle->rxData != NULL)
634         {
635             LPSPI_SeparateEdmaReadData(&(lpspiEdmaPrivateHandle->handle->rxData[rxRemainingByteCount - bytesLastRead]),
636                                        readData, bytesLastRead, isByteSwap);
637         }
638     }
639 
640     lpspiEdmaPrivateHandle->handle->state = (uint8_t)kLPSPI_Idle;
641 
642     if (lpspiEdmaPrivateHandle->handle->callback != NULL)
643     {
644         lpspiEdmaPrivateHandle->handle->callback(lpspiEdmaPrivateHandle->base, lpspiEdmaPrivateHandle->handle,
645                                                  kStatus_Success, lpspiEdmaPrivateHandle->handle->userData);
646     }
647 }
648 
649 /*!
650  * brief LPSPI master aborts a transfer which is using eDMA.
651  *
652  * This function aborts a transfer which is using eDMA.
653  *
654  * param base LPSPI peripheral base address.
655  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
656  */
LPSPI_MasterTransferAbortEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle)657 void LPSPI_MasterTransferAbortEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle)
658 {
659     assert(handle != NULL);
660 
661     LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
662 
663     EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
664     EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
665 
666     handle->state = (uint8_t)kLPSPI_Idle;
667 }
668 
669 /*!
670  * brief Gets the master eDMA transfer remaining bytes.
671  *
672  * This function gets the master eDMA transfer remaining bytes.
673  *
674  * param base LPSPI peripheral base address.
675  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
676  * param count Number of bytes transferred so far by the EDMA transaction.
677  * return status of status_t.
678  */
LPSPI_MasterTransferGetCountEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,size_t * count)679 status_t LPSPI_MasterTransferGetCountEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, size_t *count)
680 {
681     assert(handle != NULL);
682 
683     if (NULL == count)
684     {
685         return kStatus_InvalidArgument;
686     }
687 
688     /* Catch when there is not an active transfer. */
689     if (handle->state != (uint8_t)kLPSPI_Busy)
690     {
691         *count = 0;
692         return kStatus_NoTransferInProgress;
693     }
694 
695     size_t remainingByte;
696 
697     remainingByte =
698         (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
699                                                                    handle->edmaRxRegToRxDataHandle->channel);
700 
701     *count = handle->totalByteCount - remainingByte;
702 
703     return kStatus_Success;
704 }
705 
706 /*!
707  * brief Initializes the LPSPI slave eDMA handle.
708  *
709  * This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs.  Usually, for a
710  * specified LPSPI instance, call this API once to get the initialized handle.
711  *
712  * Note that LPSPI eDMA has a separated (Rx and Tx as two sources) or shared (Rx  and Tx as the same source) DMA request
713  * source.
714  *
715  * (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
716  * Tx DMAMUX source for edmaTxDataToTxRegHandle.
717  * (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle .
718  *
719  * param base LPSPI peripheral base address.
720  * param handle LPSPI handle pointer to lpspi_slave_edma_handle_t.
721  * param callback LPSPI callback.
722  * param userData callback function parameter.
723  * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
724  * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
725  */
LPSPI_SlaveTransferCreateHandleEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle,lpspi_slave_edma_transfer_callback_t callback,void * userData,edma_handle_t * edmaRxRegToRxDataHandle,edma_handle_t * edmaTxDataToTxRegHandle)726 void LPSPI_SlaveTransferCreateHandleEDMA(LPSPI_Type *base,
727                                          lpspi_slave_edma_handle_t *handle,
728                                          lpspi_slave_edma_transfer_callback_t callback,
729                                          void *userData,
730                                          edma_handle_t *edmaRxRegToRxDataHandle,
731                                          edma_handle_t *edmaTxDataToTxRegHandle)
732 {
733     assert(handle != NULL);
734     assert(edmaRxRegToRxDataHandle != NULL);
735     assert(edmaTxDataToTxRegHandle != NULL);
736 
737     /* Zero the handle. */
738     (void)memset(handle, 0, sizeof(*handle));
739 
740     uint32_t instance = LPSPI_GetInstance(base);
741 
742     s_lpspiSlaveEdmaPrivateHandle[instance].base   = base;
743     s_lpspiSlaveEdmaPrivateHandle[instance].handle = handle;
744 
745     handle->callback = callback;
746     handle->userData = userData;
747 
748     handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
749     handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
750 }
751 
752 /*!
753  * brief LPSPI slave transfers data using eDMA.
754  *
755  * This function transfers data using eDMA. This is a non-blocking function, which return right away. When all data
756  * is transferred, the callback function is called.
757  *
758  * Note:
759  * The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
760  * For bytesPerFrame greater than 4:
761  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
762  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
763  *
764  * param base LPSPI peripheral base address.
765  * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
766  * param transfer pointer to lpspi_transfer_t structure.
767  * return status of status_t.
768  */
LPSPI_SlaveTransferEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle,lpspi_transfer_t * transfer)769 status_t LPSPI_SlaveTransferEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, lpspi_transfer_t *transfer)
770 {
771     assert(handle != NULL);
772     assert(transfer != NULL);
773 
774     /* Check that we're not busy.*/
775     if (handle->state == (uint8_t)kLPSPI_Busy)
776     {
777         return kStatus_LPSPI_Busy;
778     }
779     /* Disable module before configuration. */
780     LPSPI_Enable(base, false);
781     /* Check arguements, also dma transfer can not support 3 bytes */
782     if (!LPSPI_CheckTransferArgument(base, transfer, true))
783     {
784         return kStatus_InvalidArgument;
785     }
786 
787     LPSPI_PrepareTransferEDMA(base);
788 
789     /* Variables */
790     bool isThereExtraTxBytes = false;
791     bool isByteSwap          = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
792     uint8_t bytesLastWrite   = 0;
793     uint8_t dummyData        = g_lpspiDummyData[LPSPI_GetInstance(base)];
794     uint32_t mask            = (uint32_t)kLPSPI_RxDmaEnable;
795 
796     /* Used for byte swap */
797     uint32_t addrOffset    = 0;
798     uint32_t instance      = LPSPI_GetInstance(base);
799     uint32_t rxAddr        = LPSPI_GetRxRegisterAddress(base);
800     uint32_t txAddr        = LPSPI_GetTxRegisterAddress(base);
801     uint32_t whichPcs      = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
802     uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
803     edma_transfer_config_t transferConfigRx = {0};
804     edma_transfer_config_t transferConfigTx = {0};
805     edma_tcd_t *softwareTCD_extraBytes      = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[1]) & (~0x1FU));
806 
807     /* Assign the original value for members of transfer handle. */
808     handle->state                  = (uint8_t)kLPSPI_Busy;
809     handle->txData                 = transfer->txData;
810     handle->rxData                 = transfer->rxData;
811     handle->txRemainingByteCount   = transfer->dataSize;
812     handle->rxRemainingByteCount   = transfer->dataSize;
813     handle->totalByteCount         = transfer->dataSize;
814     handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
815     handle->readRegRemainingTimes  = handle->writeRegRemainingTimes;
816     handle->txBuffIfNull =
817         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
818     /*The TX and RX FIFO sizes are always the same*/
819     handle->fifoSize            = LPSPI_GetRxFifoSize(base);
820     handle->isByteSwap          = isByteSwap;
821     handle->isThereExtraRxBytes = false;
822 
823     /* Because DMA is fast enough, set the RX and TX watermarks to 0. */
824     LPSPI_SetFifoWatermarks(base, 0U, 0U);
825 
826     /* Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
827     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
828 
829     /* Enable module for following configuration of TCR to take effect. */
830     LPSPI_Enable(base, true);
831 
832     /* For DMA transfer, mask the transmit data if the tx data is null, for rx the receive data should not be masked at
833        any time since we use rx dma transfer finish cllback to indicate transfer finish. */
834     base->TCR =
835         (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_BYSW_MASK | LPSPI_TCR_TXMSK_MASK)) |
836         LPSPI_TCR_TXMSK(transfer->txData == NULL) | LPSPI_TCR_BYSW(isByteSwap) | LPSPI_TCR_PCS(whichPcs);
837 
838     /*Calculate the bytes for write/read the TX/RX register each time*/
839     if (bytesPerFrame <= 4U)
840     {
841         handle->bytesEachWrite = (uint8_t)bytesPerFrame;
842         handle->bytesEachRead  = (uint8_t)bytesPerFrame;
843 
844         handle->bytesLastRead = (uint8_t)bytesPerFrame;
845     }
846     else
847     {
848         handle->bytesEachWrite = 4U;
849         handle->bytesEachRead  = 4U;
850 
851         handle->bytesLastRead = 4U;
852 
853         if ((transfer->dataSize % 4U) != 0U)
854         {
855             bytesLastWrite        = (uint8_t)(transfer->dataSize % 4U);
856             handle->bytesLastRead = bytesLastWrite;
857 
858             isThereExtraTxBytes = true;
859             --handle->writeRegRemainingTimes;
860 
861             handle->isThereExtraRxBytes = true;
862             --handle->readRegRemainingTimes;
863         }
864     }
865 
866     EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_LpspiSlaveCallback,
867                      &s_lpspiSlaveEdmaPrivateHandle[instance]);
868 
869     /*Rx*/
870     if (handle->readRegRemainingTimes > 0U)
871     {
872         EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
873 
874         if (handle->rxData != NULL)
875         {
876             transferConfigRx.destAddr   = (uint32_t) & (handle->rxData[0]);
877             transferConfigRx.destOffset = 1;
878         }
879         else
880         {
881             transferConfigRx.destAddr   = (uint32_t) & (handle->rxBuffIfNull);
882             transferConfigRx.destOffset = 0;
883         }
884         transferConfigRx.destTransferSize = kEDMA_TransferSize1Bytes;
885 
886         addrOffset = 0;
887         switch (handle->bytesEachRead)
888         {
889             case (1U):
890                 transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
891                 transferConfigRx.minorLoopBytes  = 1;
892                 if (handle->isByteSwap)
893                 {
894                     addrOffset = 3;
895                 }
896                 break;
897 
898             case (2U):
899                 transferConfigRx.srcTransferSize = kEDMA_TransferSize2Bytes;
900                 transferConfigRx.minorLoopBytes  = 2;
901                 if (handle->isByteSwap)
902                 {
903                     addrOffset = 2;
904                 }
905                 break;
906 
907             case (4U):
908                 transferConfigRx.srcTransferSize = kEDMA_TransferSize4Bytes;
909                 transferConfigRx.minorLoopBytes  = 4;
910                 break;
911 
912             default:
913                 transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
914                 transferConfigRx.minorLoopBytes  = 1;
915                 assert(false);
916                 break;
917         }
918 
919         transferConfigRx.srcAddr   = (uint32_t)rxAddr + addrOffset;
920         transferConfigRx.srcOffset = 0;
921 
922         transferConfigRx.majorLoopCounts = handle->readRegRemainingTimes;
923 
924         /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
925         handle->nbytes = (uint8_t)transferConfigRx.minorLoopBytes;
926 
927         EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
928                                &transferConfigRx, NULL);
929         EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
930                                      (uint32_t)kEDMA_MajorInterruptEnable);
931         EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
932     }
933 
934     /*Tx*/
935     if (handle->txData != NULL)
936     {
937         EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
938         if (isThereExtraTxBytes)
939         {
940             transferConfigTx.srcAddr         = (uint32_t) & (transfer->txData[transfer->dataSize - bytesLastWrite]);
941             transferConfigTx.srcOffset       = 1;
942             transferConfigTx.destOffset      = 0;
943             transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
944             addrOffset                       = 0;
945             switch (bytesLastWrite)
946             {
947                 case (1U):
948                     transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
949                     transferConfigTx.minorLoopBytes   = 1;
950                     if (handle->isByteSwap)
951                     {
952                         addrOffset = 3;
953                     }
954                     break;
955 
956                 case (2U):
957                     transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
958                     transferConfigTx.minorLoopBytes   = 2;
959                     if (handle->isByteSwap)
960                     {
961                         addrOffset = 2;
962                     }
963                     break;
964 
965                 default:
966                     transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
967                     transferConfigTx.minorLoopBytes   = 1;
968                     assert(false);
969                     break;
970             }
971 
972             transferConfigTx.destAddr        = (uint32_t)txAddr + addrOffset;
973             transferConfigTx.majorLoopCounts = 1;
974 
975 #if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
976             EDMA_TcdResetExt(handle->edmaTxDataToTxRegHandle->base, softwareTCD_extraBytes);
977             EDMA_TcdSetTransferConfigExt(handle->edmaTxDataToTxRegHandle->base, softwareTCD_extraBytes,
978                                          &transferConfigTx, NULL);
979 #else
980             EDMA_TcdReset(softwareTCD_extraBytes);
981             EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, NULL);
982 #endif
983         }
984 
985         transferConfigTx.srcAddr         = (uint32_t)(handle->txData);
986         transferConfigTx.srcOffset       = 1;
987         transferConfigTx.destOffset      = 0;
988         transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
989         addrOffset                       = 0;
990         switch (handle->bytesEachRead)
991         {
992             case (1U):
993                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
994                 transferConfigTx.minorLoopBytes   = 1;
995                 if (handle->isByteSwap)
996                 {
997                     addrOffset = 3;
998                 }
999                 break;
1000 
1001             case (2U):
1002                 transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
1003                 transferConfigTx.minorLoopBytes   = 2;
1004 
1005                 if (handle->isByteSwap)
1006                 {
1007                     addrOffset = 2;
1008                 }
1009                 break;
1010 
1011             case (4U):
1012                 transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
1013                 transferConfigTx.minorLoopBytes   = 4;
1014                 break;
1015 
1016             default:
1017                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
1018                 transferConfigTx.minorLoopBytes   = 1;
1019                 assert(false);
1020                 break;
1021         }
1022 
1023         transferConfigTx.destAddr        = (uint32_t)txAddr + addrOffset;
1024         transferConfigTx.majorLoopCounts = handle->writeRegRemainingTimes;
1025 
1026         if (isThereExtraTxBytes)
1027         {
1028             EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
1029                                    &transferConfigTx, softwareTCD_extraBytes);
1030         }
1031         else
1032         {
1033             EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
1034                                    &transferConfigTx, NULL);
1035         }
1036         EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
1037         mask |= (uint32_t)kLPSPI_TxDmaEnable;
1038     }
1039 
1040     LPSPI_EnableDMA(base, mask);
1041 
1042     return kStatus_Success;
1043 }
1044 
EDMA_LpspiSlaveCallback(edma_handle_t * edmaHandle,void * g_lpspiEdmaPrivateHandle,bool transferDone,uint32_t tcds)1045 static void EDMA_LpspiSlaveCallback(edma_handle_t *edmaHandle,
1046                                     void *g_lpspiEdmaPrivateHandle,
1047                                     bool transferDone,
1048                                     uint32_t tcds)
1049 {
1050     assert(edmaHandle != NULL);
1051     assert(g_lpspiEdmaPrivateHandle != NULL);
1052 
1053     uint32_t readData;
1054 
1055     lpspi_slave_edma_private_handle_t *lpspiEdmaPrivateHandle;
1056 
1057     lpspiEdmaPrivateHandle = (lpspi_slave_edma_private_handle_t *)g_lpspiEdmaPrivateHandle;
1058 
1059     size_t rxRemainingByteCount = lpspiEdmaPrivateHandle->handle->rxRemainingByteCount;
1060     uint8_t bytesLastRead       = lpspiEdmaPrivateHandle->handle->bytesLastRead;
1061     bool isByteSwap             = lpspiEdmaPrivateHandle->handle->isByteSwap;
1062 
1063     LPSPI_DisableDMA(lpspiEdmaPrivateHandle->base, (uint32_t)kLPSPI_TxDmaEnable | (uint32_t)kLPSPI_RxDmaEnable);
1064 
1065     if (lpspiEdmaPrivateHandle->handle->isThereExtraRxBytes)
1066     {
1067         while (LPSPI_GetRxFifoCount(lpspiEdmaPrivateHandle->base) == 0U)
1068         {
1069         }
1070         readData = LPSPI_ReadData(lpspiEdmaPrivateHandle->base);
1071 
1072         if (lpspiEdmaPrivateHandle->handle->rxData != NULL)
1073         {
1074             LPSPI_SeparateEdmaReadData(&(lpspiEdmaPrivateHandle->handle->rxData[rxRemainingByteCount - bytesLastRead]),
1075                                        readData, bytesLastRead, isByteSwap);
1076         }
1077     }
1078 
1079     lpspiEdmaPrivateHandle->handle->state = (uint8_t)kLPSPI_Idle;
1080 
1081     if (lpspiEdmaPrivateHandle->handle->callback != NULL)
1082     {
1083         lpspiEdmaPrivateHandle->handle->callback(lpspiEdmaPrivateHandle->base, lpspiEdmaPrivateHandle->handle,
1084                                                  kStatus_Success, lpspiEdmaPrivateHandle->handle->userData);
1085     }
1086 }
1087 
1088 /*!
1089  * brief LPSPI slave aborts a transfer which is using eDMA.
1090  *
1091  * This function aborts a transfer which is using eDMA.
1092  *
1093  * param base LPSPI peripheral base address.
1094  * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
1095  */
LPSPI_SlaveTransferAbortEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle)1096 void LPSPI_SlaveTransferAbortEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle)
1097 {
1098     assert(handle != NULL);
1099 
1100     LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
1101 
1102     EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
1103     EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
1104 
1105     handle->state = (uint8_t)kLPSPI_Idle;
1106 }
1107 
1108 /*!
1109  * brief Gets the slave eDMA transfer remaining bytes.
1110  *
1111  * This function gets the slave eDMA transfer remaining bytes.
1112  *
1113  * param base LPSPI peripheral base address.
1114  * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
1115  * param count Number of bytes transferred so far by the eDMA transaction.
1116  * return status of status_t.
1117  */
LPSPI_SlaveTransferGetCountEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle,size_t * count)1118 status_t LPSPI_SlaveTransferGetCountEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, size_t *count)
1119 {
1120     assert(handle != NULL);
1121 
1122     if (NULL == count)
1123     {
1124         return kStatus_InvalidArgument;
1125     }
1126 
1127     /* Catch when there is not an active transfer. */
1128     if (handle->state != (uint8_t)kLPSPI_Busy)
1129     {
1130         *count = 0;
1131         return kStatus_NoTransferInProgress;
1132     }
1133 
1134     size_t remainingByte;
1135 
1136     remainingByte =
1137         (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
1138                                                                    handle->edmaRxRegToRxDataHandle->channel);
1139 
1140     *count = handle->totalByteCount - remainingByte;
1141 
1142     return kStatus_Success;
1143 }
1144