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