1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2021 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_i2c_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.i2c_edma"
18 #endif
19 
20 /*<! @breif Structure definition for i2c_master_edma_private_handle_t. The structure is private. */
21 typedef struct _i2c_master_edma_private_handle
22 {
23     I2C_Type *base;
24     i2c_master_edma_handle_t *handle;
25 } i2c_master_edma_private_handle_t;
26 
27 /*! @brief i2c master DMA transfer state. */
28 enum _i2c_master_dma_transfer_states
29 {
30     kIdleState         = 0x0U, /*!< I2C bus idle. */
31     kTransferDataState = 0x1U, /*!< 7-bit address check state. */
32 };
33 
34 /*******************************************************************************
35  * Prototypes
36  ******************************************************************************/
37 
38 /*!
39  * @brief EDMA callback for I2C master EDMA driver.
40  *
41  * @param handle EDMA handler for I2C master EDMA driver
42  * @param userData user param passed to the callback function
43  */
44 static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds);
45 
46 /*!
47  * @brief Check and clear status operation.
48  *
49  * @param base I2C peripheral base address.
50  * @param status current i2c hardware status.
51  * @retval kStatus_Success No error found.
52  * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
53  * @retval kStatus_I2C_Nak Received Nak error.
54  */
55 static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status);
56 
57 /*!
58  * @brief EDMA config for I2C master driver.
59  *
60  * @param base I2C peripheral base address.
61  * @param handle pointer to i2c_master_edma_handle_t structure which stores the transfer state
62  */
63 static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_t *handle);
64 
65 /*!
66  * @brief Set up master transfer, send slave address and sub address(if any), wait until the
67  * wait until address sent status return.
68  *
69  * @param base I2C peripheral base address.
70  * @param handle pointer to i2c_master_edma_handle_t structure which stores the transfer state
71  * @param xfer pointer to i2c_master_transfer_t structure
72  */
73 static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
74                                                  i2c_master_edma_handle_t *handle,
75                                                  i2c_master_transfer_t *xfer);
76 
77 /*******************************************************************************
78  * Variables
79  ******************************************************************************/
80 
81 /*<! Private handle only used for internally. */
82 static i2c_master_edma_private_handle_t s_i2cEdmaPrivateHandle[FSL_FEATURE_SOC_I2C_COUNT];
83 
84 /*******************************************************************************
85  * Codes
86  ******************************************************************************/
87 
I2C_MasterTransferCallbackEDMA(edma_handle_t * handle,void * userData,bool transferDone,uint32_t tcds)88 static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
89 {
90     i2c_master_edma_private_handle_t *i2cPrivateHandle = (i2c_master_edma_private_handle_t *)userData;
91     status_t result                                    = kStatus_Success;
92     uint8_t tmpReg;
93     size_t tmpdataSize;
94 
95     /* Disable DMA. */
96     I2C_EnableDMA(i2cPrivateHandle->base, false);
97 
98     /* Send stop if kI2C_TransferNoStop flag is not asserted. */
99     if (0U == (i2cPrivateHandle->handle->transfer.flags & (uint32_t)kI2C_TransferNoStopFlag))
100     {
101         if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read)
102         {
103             /* Change to send NAK at the last byte. */
104             i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK;
105 
106             /* Wait the last data to be received. */
107             while (0U == (i2cPrivateHandle->base->S & (uint8_t)kI2C_TransferCompleteFlag))
108             {
109             }
110 
111             /* Send stop signal. */
112             result = I2C_MasterStop(i2cPrivateHandle->base);
113 
114             /* Read the last data byte. */
115             tmpReg                                                        = i2cPrivateHandle->base->D;
116             tmpdataSize                                                   = i2cPrivateHandle->handle->transfer.dataSize;
117             *(i2cPrivateHandle->handle->transfer.data + tmpdataSize - 1U) = tmpReg;
118         }
119         else
120         {
121             /* Wait the last data to be sent. */
122             while (0U == (i2cPrivateHandle->base->S & (uint8_t)kI2C_TransferCompleteFlag))
123             {
124             }
125 
126             /* Send stop signal. */
127             result = I2C_MasterStop(i2cPrivateHandle->base);
128         }
129     }
130     else
131     {
132         if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read)
133         {
134             /* Change to send NAK at the last byte. */
135             i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK;
136 
137             /* Wait the last data to be received. */
138             while (0U == (i2cPrivateHandle->base->S & (uint8_t)kI2C_TransferCompleteFlag))
139             {
140             }
141 
142             /* Change direction to send. */
143             i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK;
144 
145             /* Read the last data byte. */
146             tmpReg                                                        = i2cPrivateHandle->base->D;
147             tmpdataSize                                                   = i2cPrivateHandle->handle->transfer.dataSize;
148             *(i2cPrivateHandle->handle->transfer.data + tmpdataSize - 1U) = tmpReg;
149         }
150     }
151 
152     i2cPrivateHandle->handle->state = (uint8_t)kIdleState;
153 
154     if (NULL != i2cPrivateHandle->handle->completionCallback)
155     {
156         i2cPrivateHandle->handle->completionCallback(i2cPrivateHandle->base, i2cPrivateHandle->handle, result,
157                                                      i2cPrivateHandle->handle->userData);
158     }
159 }
160 
I2C_CheckAndClearError(I2C_Type * base,uint32_t status)161 static status_t I2C_CheckAndClearError(I2C_Type *base, uint32_t status)
162 {
163     status_t result = kStatus_Success;
164 
165     /* Check arbitration lost. */
166     if (0U != (status & (uint32_t)kI2C_ArbitrationLostFlag))
167     {
168         /* Clear arbitration lost flag. */
169         base->S = (uint8_t)kI2C_ArbitrationLostFlag;
170         result  = kStatus_I2C_ArbitrationLost;
171     }
172     /* Check NAK */
173     else if (0U != (status & (uint32_t)kI2C_ReceiveNakFlag))
174     {
175         result = kStatus_I2C_Nak;
176     }
177     else
178     {
179         /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */
180     }
181 
182     return result;
183 }
184 
I2C_InitTransferStateMachineEDMA(I2C_Type * base,i2c_master_edma_handle_t * handle,i2c_master_transfer_t * xfer)185 static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
186                                                  i2c_master_edma_handle_t *handle,
187                                                  i2c_master_transfer_t *xfer)
188 {
189     assert(NULL != handle);
190     assert(NULL != xfer);
191 
192     status_t result = kStatus_Success;
193 
194     if (handle->state != (uint8_t)kIdleState)
195     {
196         return kStatus_I2C_Busy;
197     }
198     else
199     {
200         i2c_direction_t direction = xfer->direction;
201 
202         /* Init the handle member. */
203         handle->transfer = *xfer;
204 
205         /* Save total transfer size. */
206         handle->transferSize = xfer->dataSize;
207 
208         handle->state = (uint8_t)kTransferDataState;
209 
210         /* Clear all status before transfer. */
211         I2C_MasterClearStatusFlags(base, (uint32_t)kClearFlags);
212 
213         /* Change to send write address when it's a read operation with command. */
214         if ((xfer->subaddressSize > 0U) && (0U != (uint8_t)(xfer->direction == kI2C_Read)))
215         {
216             direction = kI2C_Write;
217         }
218 
219         /* If repeated start is requested, send repeated start. */
220         if (0U != (handle->transfer.flags & (uint32_t)kI2C_TransferRepeatedStartFlag))
221         {
222             result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, direction);
223         }
224         else /* For normal transfer, send start. */
225         {
226             result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
227         }
228 
229         if (kStatus_Success != result)
230         {
231             return result;
232         }
233 
234 #if I2C_RETRY_TIMES != 0U
235         uint32_t waitTimes = I2C_RETRY_TIMES;
236         while ((0U == (base->S & (uint8_t)kI2C_IntPendingFlag)) && (0U != waitTimes))
237         {
238             waitTimes--;
239         }
240         if (waitTimes == 0U)
241         {
242             return kStatus_I2C_Timeout;
243         }
244 #else
245         while (0U == (base->S & (uint8_t)kI2C_IntPendingFlag))
246         {
247         }
248 #endif
249 
250         /* Check if there's transfer error. */
251         result = I2C_CheckAndClearError(base, base->S);
252 
253         /* Return if error. */
254         if (kStatus_Success != result)
255         {
256             if (result == kStatus_I2C_Nak)
257             {
258                 result = kStatus_I2C_Addr_Nak;
259 
260                 if (I2C_MasterStop(base) != kStatus_Success)
261                 {
262                     result = kStatus_I2C_Timeout;
263                 }
264 
265                 if (NULL != handle->completionCallback)
266                 {
267                     (handle->completionCallback)(base, handle, result, handle->userData);
268                 }
269             }
270 
271             return result;
272         }
273 
274         /* Send subaddress. */
275         if (0U != handle->transfer.subaddressSize)
276         {
277             do
278             {
279                 /* Clear interrupt pending flag. */
280                 base->S = (uint8_t)kI2C_IntPendingFlag;
281 
282                 handle->transfer.subaddressSize--;
283                 base->D = (uint8_t)((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize));
284 
285                 /* Wait until data transfer complete. */
286 #if I2C_RETRY_TIMES != 0U
287                 waitTimes = I2C_RETRY_TIMES;
288                 while ((0U == (base->S & (uint8_t)kI2C_IntPendingFlag)) && (0U != waitTimes))
289                 {
290                     waitTimes--;
291                 }
292                 if (waitTimes == 0U)
293                 {
294                     return kStatus_I2C_Timeout;
295                 }
296 #else
297                 while (0U == (base->S & (uint8_t)kI2C_IntPendingFlag))
298                 {
299                 }
300 #endif
301 
302                 /* Check if there's transfer error. */
303                 result = I2C_CheckAndClearError(base, base->S);
304 
305                 if (0 != result)
306                 {
307                     return result;
308                 }
309 
310             } while (handle->transfer.subaddressSize > 0U);
311 
312             if (handle->transfer.direction == kI2C_Read)
313             {
314                 /* Clear pending flag. */
315                 base->S = (uint8_t)kI2C_IntPendingFlag;
316 
317                 /* Send repeated start and slave address. */
318                 result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
319 
320                 if (0 != result)
321                 {
322                     return result;
323                 }
324 
325                 /* Wait until data transfer complete. */
326 #if I2C_RETRY_TIMES != 0U
327                 waitTimes = I2C_RETRY_TIMES;
328                 while ((0U == (base->S & (uint8_t)kI2C_IntPendingFlag)) && (0U != waitTimes))
329                 {
330                     waitTimes--;
331                 }
332                 if (waitTimes == 0U)
333                 {
334                     return kStatus_I2C_Timeout;
335                 }
336 #else
337                 while (0U == (base->S & (uint8_t)kI2C_IntPendingFlag))
338                 {
339                 }
340 #endif
341 
342                 /* Check if there's transfer error. */
343                 result = I2C_CheckAndClearError(base, base->S);
344 
345                 if (0 != result)
346                 {
347                     return result;
348                 }
349             }
350         }
351 
352         /* Clear pending flag. */
353         base->S = (uint8_t)kI2C_IntPendingFlag;
354     }
355 
356     return result;
357 }
358 
I2C_MasterTransferEDMAConfig(I2C_Type * base,i2c_master_edma_handle_t * handle)359 static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_t *handle)
360 {
361     edma_transfer_config_t transfer_config = {0};
362 
363     if (handle->transfer.direction == kI2C_Read)
364     {
365         transfer_config.srcAddr          = (uint32_t)I2C_GetDataRegAddr(base);
366         transfer_config.destAddr         = (uint32_t)(handle->transfer.data);
367         transfer_config.majorLoopCounts  = (handle->transfer.dataSize - 1U);
368         transfer_config.srcTransferSize  = kEDMA_TransferSize1Bytes;
369         transfer_config.srcOffset        = 0;
370         transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
371         transfer_config.destOffset       = 1;
372         transfer_config.minorLoopBytes   = 1;
373     }
374     else
375     {
376         transfer_config.srcAddr          = ((uint32_t)handle->transfer.data + 1U);
377         transfer_config.destAddr         = (uint32_t)I2C_GetDataRegAddr(base);
378         transfer_config.majorLoopCounts  = (handle->transfer.dataSize - 1U);
379         transfer_config.srcTransferSize  = kEDMA_TransferSize1Bytes;
380         transfer_config.srcOffset        = 1;
381         transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
382         transfer_config.destOffset       = 0;
383         transfer_config.minorLoopBytes   = 1;
384     }
385 
386     /* Store the initially configured eDMA minor byte transfer count into the I2C handle */
387     handle->nbytes = (uint8_t)(transfer_config.minorLoopBytes);
388 
389     (void)EDMA_SubmitTransfer(handle->dmaHandle, (const edma_transfer_config_t *)(uint32_t)&transfer_config);
390 
391     EDMA_StartTransfer(handle->dmaHandle);
392 }
393 
394 /*!
395  * brief Initializes the I2C handle which is used in transactional functions.
396  *
397  * param base I2C peripheral base address.
398  * param handle A pointer to the i2c_master_edma_handle_t structure.
399  * param callback A pointer to the user callback function.
400  * param userData A user parameter passed to the callback function.
401  * param edmaHandle eDMA handle pointer.
402  */
I2C_MasterCreateEDMAHandle(I2C_Type * base,i2c_master_edma_handle_t * handle,i2c_master_edma_transfer_callback_t callback,void * userData,edma_handle_t * edmaHandle)403 void I2C_MasterCreateEDMAHandle(I2C_Type *base,
404                                 i2c_master_edma_handle_t *handle,
405                                 i2c_master_edma_transfer_callback_t callback,
406                                 void *userData,
407                                 edma_handle_t *edmaHandle)
408 {
409     assert(NULL != handle);
410     assert(NULL != edmaHandle);
411 
412     uint32_t instance = I2C_GetInstance(base);
413 
414     /* Zero handle. */
415     (void)memset(handle, 0, sizeof(*handle));
416 
417     /* Set the user callback and userData. */
418     handle->completionCallback = callback;
419     handle->userData           = userData;
420 
421     /* Set the handle for EDMA. */
422     handle->dmaHandle = edmaHandle;
423 
424     s_i2cEdmaPrivateHandle[instance].base   = base;
425     s_i2cEdmaPrivateHandle[instance].handle = handle;
426 
427     EDMA_SetCallback(edmaHandle, (edma_callback)I2C_MasterTransferCallbackEDMA, &s_i2cEdmaPrivateHandle[instance]);
428 }
429 
430 /*!
431  * brief Performs a master eDMA non-blocking transfer on the I2C bus.
432  *
433  * param base I2C peripheral base address.
434  * param handle A pointer to the i2c_master_edma_handle_t structure.
435  * param xfer A pointer to the transfer structure of i2c_master_transfer_t.
436  * retval kStatus_Success Successfully completed the data transmission.
437  * retval kStatus_I2C_Busy A previous transmission is still not finished.
438  * retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
439  * retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
440  * retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
441  */
I2C_MasterTransferEDMA(I2C_Type * base,i2c_master_edma_handle_t * handle,i2c_master_transfer_t * xfer)442 status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer)
443 {
444     assert(NULL != handle);
445     assert(NULL != xfer);
446 
447     status_t result;
448     uint8_t tmpReg;
449 
450     /* Disable dma xfer. */
451     I2C_EnableDMA(base, false);
452 
453     /* Send address and command buffer(if there is), until senddata phase or receive data phase. */
454     result = I2C_InitTransferStateMachineEDMA(base, handle, xfer);
455 
456     if (0 != result)
457     {
458         /* Send stop if received Nak. */
459         if (result == kStatus_I2C_Nak)
460         {
461             if (I2C_MasterStop(base) != kStatus_Success)
462             {
463                 result = kStatus_I2C_Timeout;
464             }
465         }
466 
467         /* Reset the state to idle state. */
468         handle->state = (uint8_t)kIdleState;
469 
470         return result;
471     }
472 
473     /* Configure dma transfer. */
474     /* For i2c send, need to send 1 byte first to trigger the dma, for i2c read,
475     need to send stop before reading the last byte, so the dma transfer size should
476     be (xSize - 1). */
477     if (handle->transfer.dataSize > 1U)
478     {
479         I2C_MasterTransferEDMAConfig(base, handle);
480         if (handle->transfer.direction == kI2C_Read)
481         {
482             /* Change direction for receive. */
483             base->C1 &= ~(uint8_t)(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
484 
485             /* Read dummy to release the bus. */
486             (void)base->D;
487 
488             /* Enabe dma transfer. */
489             I2C_EnableDMA(base, true);
490         }
491         else
492         {
493             /* Enabe dma transfer. */
494             I2C_EnableDMA(base, true);
495 
496             /* Send the first data. */
497             base->D = *handle->transfer.data;
498         }
499     }
500     else /* If transfer size is 1, use polling method. */
501     {
502         if (handle->transfer.direction == kI2C_Read)
503         {
504             tmpReg = base->C1;
505 
506             /* Change direction to Rx. */
507             tmpReg &= ~(uint8_t)I2C_C1_TX_MASK;
508 
509             /* Configure send NAK */
510             tmpReg |= I2C_C1_TXAK_MASK;
511 
512             base->C1 = tmpReg;
513 
514             /* Read dummy to release the bus. */
515             (void)base->D;
516         }
517         else
518         {
519             base->D = *handle->transfer.data;
520         }
521 
522         /* Wait until data transfer complete. */
523 #if I2C_RETRY_TIMES != 0U
524         uint32_t waitTimes = I2C_RETRY_TIMES;
525         while ((0U == (base->S & (uint8_t)kI2C_IntPendingFlag)) && (0U != waitTimes))
526         {
527             waitTimes--;
528         }
529         if (waitTimes == 0U)
530         {
531             return kStatus_I2C_Timeout;
532         }
533 #else
534         while (0U == (base->S & (uint8_t)kI2C_IntPendingFlag))
535         {
536         }
537 #endif
538 
539         /* Clear pending flag. */
540         base->S = (uint8_t)kI2C_IntPendingFlag;
541 
542         /* Send stop if kI2C_TransferNoStop flag is not asserted. */
543         if (0U == (handle->transfer.flags & (uint32_t)kI2C_TransferNoStopFlag))
544         {
545             result = I2C_MasterStop(base);
546         }
547         else
548         {
549             /* Change direction to send. */
550             base->C1 |= I2C_C1_TX_MASK;
551         }
552 
553         /* Read the last byte of data. */
554         if (handle->transfer.direction == kI2C_Read)
555         {
556             tmpReg                 = base->D;
557             *handle->transfer.data = tmpReg;
558         }
559 
560         /* Reset the state to idle. */
561         handle->state = (uint8_t)kIdleState;
562     }
563 
564     return result;
565 }
566 
567 /*!
568  * brief Gets a master transfer status during the eDMA non-blocking transfer.
569  *
570  * param base I2C peripheral base address.
571  * param handle A pointer to the i2c_master_edma_handle_t structure.
572  * param count A number of bytes transferred by the non-blocking transaction.
573  */
I2C_MasterTransferGetCountEDMA(I2C_Type * base,i2c_master_edma_handle_t * handle,size_t * count)574 status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count)
575 {
576     assert(NULL != handle->dmaHandle);
577 
578     if (NULL == count)
579     {
580         return kStatus_InvalidArgument;
581     }
582 
583     if ((uint8_t)kIdleState != handle->state)
584     {
585         *count = (handle->transferSize -
586                   (uint32_t)handle->nbytes *
587                       EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel));
588     }
589     else
590     {
591         *count = handle->transferSize;
592     }
593 
594     return kStatus_Success;
595 }
596 
597 /*!
598  * brief Aborts a master eDMA non-blocking transfer early.
599  *
600  * param base I2C peripheral base address.
601  * param handle A pointer to the i2c_master_edma_handle_t structure.
602  */
I2C_MasterTransferAbortEDMA(I2C_Type * base,i2c_master_edma_handle_t * handle)603 void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle)
604 {
605     EDMA_AbortTransfer(handle->dmaHandle);
606 
607     /* Disable dma transfer. */
608     I2C_EnableDMA(base, false);
609 
610     /* Reset the state to idle. */
611     handle->state = (uint8_t)kIdleState;
612 }
613