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