1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_flexio_i2c_master.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.flexio_i2c_master"
18 #endif
19 
20 /*! @brief  FLEXIO I2C transfer state */
21 enum _flexio_i2c_master_transfer_states
22 {
23     kFLEXIO_I2C_Idle             = 0x0U, /*!< I2C bus idle */
24     kFLEXIO_I2C_Start            = 0x1U, /*!< I2C start phase */
25     kFLEXIO_I2C_SendCommand      = 0x2U, /*!< Send command byte phase */
26     kFLEXIO_I2C_SendData         = 0x3U, /*!< Send data transfer phase*/
27     kFLEXIO_I2C_ReceiveDataBegin = 0x4U, /*!< Receive data begin transfer phase*/
28     kFLEXIO_I2C_ReceiveData      = 0x5U, /*!< Receive data transfer phase*/
29 };
30 
31 /*******************************************************************************
32  * Prototypes
33  ******************************************************************************/
34 
35 /*!
36  * @brief Set up master transfer, send slave address and decide the initial
37  * transfer state.
38  *
39  * @param base pointer to FLEXIO_I2C_Type structure
40  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
41  * @param transfer pointer to flexio_i2c_master_transfer_t structure
42  */
43 static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
44                                                           flexio_i2c_master_handle_t *handle,
45                                                           flexio_i2c_master_transfer_t *xfer);
46 
47 /*!
48  * @brief Master run transfer state machine to perform a byte of transfer.
49  *
50  * @param base pointer to FLEXIO_I2C_Type structure
51  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
52  * @param statusFlags flexio i2c hardware status
53  * @retval kStatus_Success Successfully run state machine
54  * @retval kStatus_FLEXIO_I2C_Nak Receive Nak during transfer
55  */
56 static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
57                                                          flexio_i2c_master_handle_t *handle,
58                                                          uint32_t statusFlags);
59 
60 /*!
61  * @brief Complete transfer, disable interrupt and call callback.
62  *
63  * @param base pointer to FLEXIO_I2C_Type structure
64  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
65  * @param status flexio transfer status
66  */
67 static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
68                                               flexio_i2c_master_handle_t *handle,
69                                               status_t status);
70 
71 /*!
72  * @brief introduce function FLEXIO_I2C_MasterTransferStateMachineStart.
73  * This function was deal with Initial state, i2c start state.
74  *
75  * @param base pointer to FLEXIO_I2C_Type structure
76  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
77  */
78 static void FLEXIO_I2C_MasterTransferStateMachineStart(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle);
79 
80 /*!
81  * @brief introduce function FLEXIO_I2C_MasterTransferStateMachineSendCommand.
82  * This function was deal with Check address only needed for transfer with subaddress .
83  *
84  * @param base pointer to FLEXIO_I2C_Type structure
85  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
86  * @param statusFlags flexio i2c hardware status
87  *
88  * @return default is true when No abnormality.
89  * @return false when time out.
90  */
91 static bool FLEXIO_I2C_MasterTransferStateMachineSendCommand(FLEXIO_I2C_Type *base,
92                                                              flexio_i2c_master_handle_t *handle,
93                                                              uint32_t statusFlags);
94 
95 /*!
96  * @brief introduce function FLEXIO_I2C_MasterTransferStateMachineSendData.
97  * This function was deal with Send command byte.
98  *
99  * @param base pointer to FLEXIO_I2C_Type structure
100  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
101  * @param statusFlags flexio i2c hardware status
102  *
103  * @return default is true when No abnormality.
104  * @return false when time out.
105  */
106 static bool FLEXIO_I2C_MasterTransferStateMachineSendData(FLEXIO_I2C_Type *base,
107                                                           flexio_i2c_master_handle_t *handle,
108                                                           uint32_t statusFlags);
109 
110 /*!
111  * @brief introduce function FLEXIO_I2C_MasterTransferStateMachineReceiveDataBegin.
112  * This function was deal with Receive Data Begin.
113  *
114  * @param base pointer to FLEXIO_I2C_Type structure
115  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
116  * @param statusFlags flexio i2c hardware status
117  *
118  * @return default is true when No abnormality.
119  * @return false when time out.
120  */
121 static bool FLEXIO_I2C_MasterTransferStateMachineReceiveDataBegin(FLEXIO_I2C_Type *base,
122                                                                   flexio_i2c_master_handle_t *handle,
123                                                                   uint32_t statusFlags);
124 
125 /*!
126  * @brief introduce function Case_kFLEXIO_I2C_ReceiveDataBegin.
127  * This function was deal with Receive Data.
128  *
129  * @param base pointer to FLEXIO_I2C_Type structure
130  * @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
131  * @param statusFlags flexio i2c hardware status
132  *
133  * @return default is kStatus_Success when No abnormality.
134  * @return kStatus_FLEXIO_I2C_Nak when ReceiveNakFlag is not set.
135  * @return kStatus_FLEXIO_I2C_Timeout when time out.
136  */
137 static status_t FLEXIO_I2C_MasterTransferStateMachineReceiveData(FLEXIO_I2C_Type *base,
138                                                                  flexio_i2c_master_handle_t *handle,
139                                                                  uint32_t statusFlags);
140 
141 /*******************************************************************************
142  * Codes
143  ******************************************************************************/
144 
FLEXIO_I2C_GetInstance(FLEXIO_I2C_Type * base)145 static uint32_t FLEXIO_I2C_GetInstance(FLEXIO_I2C_Type *base)
146 {
147     return FLEXIO_GetInstance(base->flexioBase);
148 }
149 
FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,flexio_i2c_master_transfer_t * xfer)150 static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
151                                                           flexio_i2c_master_handle_t *handle,
152                                                           flexio_i2c_master_transfer_t *xfer)
153 {
154     bool needRestart;
155     uint32_t byteCount;
156 
157     /* Init the handle member. */
158     handle->transfer.slaveAddress   = xfer->slaveAddress;
159     handle->transfer.direction      = xfer->direction;
160     handle->transfer.subaddress     = xfer->subaddress;
161     handle->transfer.subaddressSize = xfer->subaddressSize;
162     handle->transfer.data           = xfer->data;
163     handle->transfer.dataSize       = xfer->dataSize;
164     handle->transfer.flags          = xfer->flags;
165     handle->transferSize            = xfer->dataSize;
166 
167     /* Initial state, i2c start state. */
168     handle->state = (uint8_t)kFLEXIO_I2C_Start;
169 
170     /* Clear all status before transfer. */
171     FLEXIO_I2C_MasterClearStatusFlags(base, (uint32_t)kFLEXIO_I2C_ReceiveNakFlag);
172 
173     /* Calculate whether need to send re-start. */
174     needRestart         = (handle->transfer.subaddressSize != 0U) && (handle->transfer.direction == kFLEXIO_I2C_Read);
175     handle->needRestart = needRestart;
176 
177     /* Calculate total byte count in a frame. */
178     byteCount = 1U;
179 
180     if (!needRestart)
181     {
182         byteCount += handle->transfer.dataSize;
183     }
184 
185     if (handle->transfer.subaddressSize != 0U)
186     {
187         byteCount += handle->transfer.subaddressSize;
188     }
189 
190     /* Configure data count. */
191     if (FLEXIO_I2C_MasterSetTransferCount(base, (uint16_t)byteCount) != kStatus_Success)
192     {
193         return kStatus_InvalidArgument;
194     }
195 
196     /* Configure timer1 disable condition. */
197     uint32_t tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[1]];
198     tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
199     tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPreTimerDisable);
200     base->flexioBase->TIMCFG[base->timerIndex[1]] = tmpConfig;
201 
202 #if I2C_RETRY_TIMES
203     uint32_t waitTimes = I2C_RETRY_TIMES;
204     while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
205            (0U != --waitTimes))
206     {
207     }
208     if (0U == waitTimes)
209     {
210         return kStatus_FLEXIO_I2C_Timeout;
211     }
212 #else
213     while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
214     {
215     }
216 #endif
217 
218     return kStatus_Success;
219 }
220 
FLEXIO_I2C_MasterTransferStateMachineStart(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle)221 static void FLEXIO_I2C_MasterTransferStateMachineStart(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle)
222 {
223     if (handle->needRestart)
224     {
225         FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Write);
226     }
227     else
228     {
229         FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, handle->transfer.direction);
230     }
231     if (handle->transfer.subaddressSize == 0U)
232     {
233         if (handle->transfer.direction == kFLEXIO_I2C_Write)
234         {
235             /* Next state, send data. */
236             handle->state = (uint8_t)kFLEXIO_I2C_SendData;
237         }
238         else
239         {
240             /* Next state, receive data begin. */
241             handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
242         }
243     }
244     else
245     {
246         /* Next state, send command byte. */
247         handle->state = (uint8_t)kFLEXIO_I2C_SendCommand;
248     }
249 }
250 
FLEXIO_I2C_MasterTransferStateMachineSendCommand(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,uint32_t statusFlags)251 static bool FLEXIO_I2C_MasterTransferStateMachineSendCommand(FLEXIO_I2C_Type *base,
252                                                              flexio_i2c_master_handle_t *handle,
253                                                              uint32_t statusFlags)
254 {
255     if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
256     {
257         if (handle->transfer.subaddressSize > 0U)
258         {
259             handle->transfer.subaddressSize--;
260             FLEXIO_I2C_MasterWriteByte(base, ((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize)));
261 
262             if (handle->transfer.subaddressSize == 0U)
263             {
264                 /* Load re-start in advance. */
265                 if (handle->transfer.direction == kFLEXIO_I2C_Read)
266                 {
267 #if I2C_RETRY_TIMES
268                     while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
269                            (0U != --waitTimes))
270                     {
271                     }
272                     if (0U == waitTimes)
273                     {
274                         return false;
275                     }
276 #else
277                     while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
278                     {
279                     }
280 #endif
281                     FLEXIO_I2C_MasterRepeatedStart(base);
282                 }
283             }
284         }
285         else
286         {
287             if (handle->transfer.direction == kFLEXIO_I2C_Write)
288             {
289                 /* Send first byte of data. */
290                 if (handle->transfer.dataSize > 0U)
291                 {
292                     /* Next state, send data. */
293                     handle->state = (uint8_t)kFLEXIO_I2C_SendData;
294 
295                     FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
296                     handle->transfer.data++;
297                     handle->transfer.dataSize--;
298                 }
299                 else
300                 {
301                     FLEXIO_I2C_MasterStop(base);
302 
303 #if I2C_RETRY_TIMES
304                     while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
305                            (0U != --waitTimes))
306                     {
307                     }
308                     if (0U == waitTimes)
309                     {
310                         return false;
311                     }
312 #else
313                     while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
314                     {
315                     }
316 #endif
317                     (void)FLEXIO_I2C_MasterReadByte(base);
318 
319                     handle->state = (uint8_t)kFLEXIO_I2C_Idle;
320                 }
321             }
322             else
323             {
324                 (void)FLEXIO_I2C_MasterSetTransferCount(base, (uint16_t)(handle->transfer.dataSize + 1U));
325                 /* Delay at least one clock cycle so that the restart setup time is up to spec standard. */
326                 SDK_DelayAtLeastUs(1000000UL / base->baudrate, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
327                 FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Read);
328 
329                 /* Next state, receive data begin. */
330                 handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
331             }
332         }
333     }
334     return true;
335 }
336 
FLEXIO_I2C_MasterTransferStateMachineSendData(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,uint32_t statusFlags)337 static bool FLEXIO_I2C_MasterTransferStateMachineSendData(FLEXIO_I2C_Type *base,
338                                                           flexio_i2c_master_handle_t *handle,
339                                                           uint32_t statusFlags)
340 {
341     if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
342     {
343         /* Send one byte of data. */
344         if (handle->transfer.dataSize > 0U)
345         {
346             FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
347 
348             handle->transfer.data++;
349             handle->transfer.dataSize--;
350         }
351         else
352         {
353             FLEXIO_I2C_MasterStop(base);
354 
355 #if I2C_RETRY_TIMES
356             while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
357                    (0U != --waitTimes))
358             {
359             }
360             if (0U == waitTimes)
361             {
362                 return false;
363             }
364 #else
365             while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
366             {
367             }
368 #endif
369             (void)FLEXIO_I2C_MasterReadByte(base);
370 
371             handle->state = (uint8_t)kFLEXIO_I2C_Idle;
372         }
373     }
374     return true;
375 }
376 
FLEXIO_I2C_MasterTransferStateMachineReceiveDataBegin(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,uint32_t statusFlags)377 static bool FLEXIO_I2C_MasterTransferStateMachineReceiveDataBegin(FLEXIO_I2C_Type *base,
378                                                                   flexio_i2c_master_handle_t *handle,
379                                                                   uint32_t statusFlags)
380 {
381     if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
382     {
383         handle->state = (uint8_t)kFLEXIO_I2C_ReceiveData;
384         /* Send nak at the last receive byte. */
385         if (handle->transfer.dataSize == 1U)
386         {
387             FLEXIO_I2C_MasterEnableAck(base, false);
388 #if I2C_RETRY_TIMES
389             while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
390                    (0U != --waitTimes))
391             {
392             }
393             if (0U == waitTimes)
394             {
395                 return false;
396             }
397 #else
398             while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
399             {
400             }
401 #endif
402             FLEXIO_I2C_MasterStop(base);
403         }
404         else
405         {
406             FLEXIO_I2C_MasterEnableAck(base, true);
407         }
408     }
409     else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
410     {
411         /* Read one byte of data. */
412         FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
413     }
414     else
415     {
416         ; /* Avoid MISRA 2012 rule 15.7 */
417     }
418     return true;
419 }
420 
FLEXIO_I2C_MasterTransferStateMachineReceiveData(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,uint32_t statusFlags)421 static status_t FLEXIO_I2C_MasterTransferStateMachineReceiveData(FLEXIO_I2C_Type *base,
422                                                                  flexio_i2c_master_handle_t *handle,
423                                                                  uint32_t statusFlags)
424 {
425     if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
426     {
427         *handle->transfer.data = FLEXIO_I2C_MasterReadByte(base);
428         handle->transfer.data++;
429         if (0U != handle->transfer.dataSize--)
430         {
431             if (handle->transfer.dataSize == 0U)
432             {
433                 FLEXIO_I2C_MasterDisableInterrupts(base, (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
434                 handle->state = (uint8_t)kFLEXIO_I2C_Idle;
435                 /* Return nak if ReceiveNakFlag is not set */
436                 if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) == 0U)
437                 {
438                     return kStatus_FLEXIO_I2C_Nak;
439                 }
440             }
441 
442             /* Send nak at the last receive byte. */
443             if (handle->transfer.dataSize == 1U)
444             {
445                 FLEXIO_I2C_MasterEnableAck(base, false);
446 #if I2C_RETRY_TIMES
447                 while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
448                        (0U != --waitTimes))
449                 {
450                 }
451                 if (0U == waitTimes)
452                 {
453                     return kStatus_FLEXIO_I2C_Timeout;
454                 }
455 #else
456                 while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
457                 {
458                 }
459 #endif
460                 FLEXIO_I2C_MasterStop(base);
461             }
462         }
463     }
464     else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
465     {
466         if (handle->transfer.dataSize > 1U)
467         {
468             FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
469         }
470     }
471     else
472     {
473         ; /* Avoid MISRA 2012 rule 15.7 */
474     }
475     return kStatus_Success;
476 }
477 
FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,uint32_t statusFlags)478 static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
479                                                          flexio_i2c_master_handle_t *handle,
480                                                          uint32_t statusFlags)
481 {
482     status_t status;
483 #if I2C_RETRY_TIMES
484     uint32_t waitTimes = I2C_RETRY_TIMES;
485 #endif
486 
487     if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
488     {
489         /* Clear receive nak flag. */
490         FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
491 
492         if ((!((handle->state == (uint8_t)kFLEXIO_I2C_SendData) && (handle->transfer.dataSize == 0U))) &&
493             (!(((handle->state == (uint8_t)kFLEXIO_I2C_ReceiveData) ||
494                 (handle->state == (uint8_t)kFLEXIO_I2C_ReceiveDataBegin)) &&
495                (handle->transfer.dataSize == 1U))))
496         {
497             (void)FLEXIO_I2C_MasterReadByte(base);
498 
499             FLEXIO_I2C_MasterAbortStop(base);
500 
501             /* Delay one clk cycle to ensure the bus is idle. */
502             SDK_DelayAtLeastUs(1000000UL / base->baudrate, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
503 
504             handle->state = (uint8_t)kFLEXIO_I2C_Idle;
505 
506             return kStatus_FLEXIO_I2C_Nak;
507         }
508     }
509 
510     if (((statusFlags & (uint8_t)kFLEXIO_I2C_RxFullFlag) != 0U) && (handle->state != (uint8_t)kFLEXIO_I2C_ReceiveData))
511     {
512         (void)FLEXIO_I2C_MasterReadByte(base);
513     }
514 
515     switch (handle->state)
516     {
517         /* Initial state, i2c start state. */
518         case (uint8_t)kFLEXIO_I2C_Start:
519             /* Send address byte first. */
520             FLEXIO_I2C_MasterTransferStateMachineStart(base, handle);
521             break;
522 
523         /* Check address only needed for transfer with subaddress */
524         case (uint8_t)kFLEXIO_I2C_SendCommand:
525             if (false == FLEXIO_I2C_MasterTransferStateMachineSendCommand(base, handle, statusFlags))
526             {
527                 return kStatus_FLEXIO_I2C_Timeout;
528             }
529             break;
530 
531         /* Send command byte. */
532         case (uint8_t)kFLEXIO_I2C_SendData:
533             if (false == FLEXIO_I2C_MasterTransferStateMachineSendData(base, handle, statusFlags))
534             {
535                 return kStatus_FLEXIO_I2C_Timeout;
536             }
537             break;
538 
539         case (uint8_t)kFLEXIO_I2C_ReceiveDataBegin:
540             if (false == FLEXIO_I2C_MasterTransferStateMachineReceiveDataBegin(base, handle, statusFlags))
541             {
542                 return kStatus_FLEXIO_I2C_Timeout;
543             }
544             break;
545 
546         case (uint8_t)kFLEXIO_I2C_ReceiveData:
547             status = FLEXIO_I2C_MasterTransferStateMachineReceiveData(base, handle, statusFlags);
548             if (kStatus_Success != status)
549             {
550                 return status;
551             }
552             break;
553 
554         default:
555             /* Add comment to avoid MISRA violation */
556             break;
557     }
558 
559     return kStatus_Success;
560 }
561 
FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,status_t status)562 static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
563                                               flexio_i2c_master_handle_t *handle,
564                                               status_t status)
565 {
566     FLEXIO_I2C_MasterDisableInterrupts(
567         base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
568 
569     if (handle->completionCallback != NULL)
570     {
571         handle->completionCallback(base, handle, status, handle->userData);
572     }
573 }
574 
575 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
576 /*!
577  * brief Make sure the bus isn't already pulled down.
578  *
579  * Check the FLEXIO pin status to see whether either of SDA and SCL pin is pulled down.
580  *
581  * param base Pointer to FLEXIO_I2C_Type structure.
582  * retval kStatus_Success
583  * retval kStatus_FLEXIO_I2C_Busy
584  */
FLEXIO_I2C_CheckForBusyBus(FLEXIO_I2C_Type * base)585 status_t FLEXIO_I2C_CheckForBusyBus(FLEXIO_I2C_Type *base)
586 {
587     uint32_t mask;
588     /* If in certain loops the SDA/SCL is continuously pulled down, then return bus busy status. */
589     /* The loop count is determined by maximum CPU clock frequency */
590     for (uint32_t i = 0U; i < SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 600000U; ++i)
591     {
592         mask = 1UL << base->SDAPinIndex | 1UL << base->SCLPinIndex;
593         if ((FLEXIO_ReadPinInput(base->flexioBase) & mask) == mask)
594         {
595             return kStatus_Success;
596         }
597     }
598     return kStatus_FLEXIO_I2C_Busy;
599 }
600 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
601 
602 /*!
603  * brief Ungates the FlexIO clock, resets the FlexIO module, and configures the FlexIO I2C
604  * hardware configuration.
605  *
606  * Example
607    code
608    FLEXIO_I2C_Type base = {
609    .flexioBase = FLEXIO,
610    .SDAPinIndex = 0,
611    .SCLPinIndex = 1,
612    .shifterIndex = {0,1},
613    .timerIndex = {0,1}
614    };
615    flexio_i2c_master_config_t config = {
616    .enableInDoze = false,
617    .enableInDebug = true,
618    .enableFastAccess = false,
619    .baudRate_Bps = 100000
620    };
621    FLEXIO_I2C_MasterInit(base, &config, srcClock_Hz);
622    endcode
623  *
624  * param base Pointer to FLEXIO_I2C_Type structure.
625  * param masterConfig Pointer to flexio_i2c_master_config_t structure.
626  * param srcClock_Hz FlexIO source clock in Hz.
627  * retval kStatus_Success Initialization successful
628  * retval kStatus_InvalidArgument The source clock exceed upper range limitation
629 */
FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type * base,flexio_i2c_master_config_t * masterConfig,uint32_t srcClock_Hz)630 status_t FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
631 {
632     assert((base != NULL) && (masterConfig != NULL));
633 
634     flexio_shifter_config_t shifterConfig;
635     flexio_timer_config_t timerConfig;
636     uint32_t controlVal = 0;
637     uint16_t timerDiv   = 0;
638     status_t result     = kStatus_Success;
639 
640     (void)memset(&shifterConfig, 0, sizeof(shifterConfig));
641     (void)memset(&timerConfig, 0, sizeof(timerConfig));
642 
643 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
644     /* Ungate flexio clock. */
645     CLOCK_EnableClock(s_flexioClocks[FLEXIO_I2C_GetInstance(base)]);
646 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
647 
648     /* Do hardware configuration. */
649     /* 1. Configure the shifter 0 for tx. */
650     shifterConfig.timerSelect   = base->timerIndex[2];
651     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
652     shifterConfig.pinConfig     = kFLEXIO_PinConfigOpenDrainOrBidirection;
653     shifterConfig.pinSelect     = base->SDAPinIndex;
654     shifterConfig.pinPolarity   = kFLEXIO_PinActiveLow;
655     shifterConfig.shifterMode   = kFLEXIO_ShifterModeTransmit;
656     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
657     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitHigh;
658     shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitLow;
659 
660     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
661 
662     /* 2. Configure the shifter 1 for rx. */
663     shifterConfig.timerSelect   = base->timerIndex[2];
664     shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
665     shifterConfig.pinConfig     = kFLEXIO_PinConfigOutputDisabled;
666     shifterConfig.pinSelect     = base->SDAPinIndex;
667     shifterConfig.pinPolarity   = kFLEXIO_PinActiveHigh;
668     shifterConfig.shifterMode   = kFLEXIO_ShifterModeReceive;
669     shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
670     shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitLow;
671     shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
672 
673     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
674 
675     /*3. Configure the timer 0 and timer 1 for generating bit clock. */
676     /* timer 1 is used to config baudrate */
677     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
678     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
679     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
680     timerConfig.pinConfig       = kFLEXIO_PinConfigOpenDrainOrBidirection;
681     timerConfig.pinSelect       = base->SCLPinIndex;
682     timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
683     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
684     timerConfig.timerOutput     = kFLEXIO_TimerOutputZeroNotAffectedByReset;
685     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
686     timerConfig.timerReset      = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput;
687     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnPreTimerDisable;
688     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerHigh;
689     timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
690     timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
691 
692     /* Set TIMCMP = (baud rate divider / 2) - 1. */
693     timerDiv = (uint16_t)(srcClock_Hz / masterConfig->baudRate_Bps) / 2U - 1U;
694     /* Calculate and assign the actual baudrate. */
695     base->baudrate = srcClock_Hz / (2U * ((uint32_t)timerDiv + 1U));
696 
697     timerConfig.timerCompare = timerDiv;
698 
699     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
700 
701     /* timer 0 is used to config total shift clock edges */
702     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
703     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
704     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
705     timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
706     timerConfig.pinSelect       = base->SCLPinIndex;
707     timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
708     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
709     timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
710     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
711     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
712     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompare;
713     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerHigh;
714     timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
715     timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
716 
717     /* Set TIMCMP when confinguring transfer bytes. */
718     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
719 
720     /* 4. Configure the timer 2 for controlling shifters. */
721     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
722     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
723     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
724     timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
725     timerConfig.pinSelect       = base->SCLPinIndex;
726     timerConfig.pinPolarity     = kFLEXIO_PinActiveLow;
727     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
728     timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
729     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
730     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
731     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnPreTimerDisable;
732     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnPrevTimerEnable;
733     timerConfig.timerStop       = kFLEXIO_TimerStopBitEnableOnTimerCompare;
734     timerConfig.timerStart      = kFLEXIO_TimerStartBitEnabled;
735 
736     /* Set TIMCMP[15:0] = (number of bits x 2) - 1. */
737     timerConfig.timerCompare = 8U * 2U - 1U;
738 
739     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[2], &timerConfig);
740 
741     /* Configure FLEXIO I2C Master. */
742     controlVal = base->flexioBase->CTRL;
743     controlVal &=
744         ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
745     controlVal |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
746                    FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
747     if (!masterConfig->enableInDoze)
748     {
749         controlVal |= FLEXIO_CTRL_DOZEN_MASK;
750     }
751 
752     base->flexioBase->CTRL = controlVal;
753     /* Disable internal IRQs. */
754     FLEXIO_I2C_MasterDisableInterrupts(
755         base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
756     return result;
757 }
758 
759 /*!
760  * brief De-initializes the FlexIO I2C master peripheral. Calling this API Resets the FlexIO I2C master
761  * shifer and timer config, module can't work unless the FLEXIO_I2C_MasterInit is called.
762  *
763  * param base pointer to FLEXIO_I2C_Type structure.
764  */
FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type * base)765 void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base)
766 {
767     base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = 0;
768     base->flexioBase->SHIFTCTL[base->shifterIndex[0]] = 0;
769     base->flexioBase->SHIFTCFG[base->shifterIndex[1]] = 0;
770     base->flexioBase->SHIFTCTL[base->shifterIndex[1]] = 0;
771     base->flexioBase->TIMCFG[base->timerIndex[0]]     = 0;
772     base->flexioBase->TIMCMP[base->timerIndex[0]]     = 0;
773     base->flexioBase->TIMCTL[base->timerIndex[0]]     = 0;
774     base->flexioBase->TIMCFG[base->timerIndex[1]]     = 0;
775     base->flexioBase->TIMCMP[base->timerIndex[1]]     = 0;
776     base->flexioBase->TIMCTL[base->timerIndex[1]]     = 0;
777     base->flexioBase->TIMCFG[base->timerIndex[2]]     = 0;
778     base->flexioBase->TIMCMP[base->timerIndex[2]]     = 0;
779     base->flexioBase->TIMCTL[base->timerIndex[2]]     = 0;
780     /* Clear the shifter flag. */
781     base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[0]);
782     base->flexioBase->SHIFTSTAT = (1UL << base->shifterIndex[1]);
783     /* Clear the timer flag. */
784     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[0]);
785     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[1]);
786     base->flexioBase->TIMSTAT = (1UL << base->timerIndex[2]);
787 }
788 
789 /*!
790  * brief Gets the default configuration to configure the FlexIO module. The configuration
791  * can be used directly for calling the FLEXIO_I2C_MasterInit().
792  *
793  * Example:
794    code
795    flexio_i2c_master_config_t config;
796    FLEXIO_I2C_MasterGetDefaultConfig(&config);
797    endcode
798  * param masterConfig Pointer to flexio_i2c_master_config_t structure.
799 */
FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t * masterConfig)800 void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig)
801 {
802     assert(masterConfig != NULL);
803 
804     /* Initializes the configure structure to zero. */
805     (void)memset(masterConfig, 0, sizeof(*masterConfig));
806 
807     masterConfig->enableMaster     = true;
808     masterConfig->enableInDoze     = false;
809     masterConfig->enableInDebug    = true;
810     masterConfig->enableFastAccess = false;
811 
812     /* Default baud rate at 100kbps. */
813     masterConfig->baudRate_Bps = 100000U;
814 }
815 
816 /*!
817  * brief Gets the FlexIO I2C master status flags.
818  *
819  * param base Pointer to FLEXIO_I2C_Type structure
820  * return Status flag, use status flag to AND #_flexio_i2c_master_status_flags can get the related status.
821  */
822 
FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type * base)823 uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base)
824 {
825     uint32_t status = 0;
826 
827     status =
828         ((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])) >> base->shifterIndex[0]);
829     status |=
830         (((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
831          << 1U);
832     status |=
833         (((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1]))
834          << 2U);
835 
836     return status;
837 }
838 
839 /*!
840  * brief Clears the FlexIO I2C master status flags.
841  *
842  * param base Pointer to FLEXIO_I2C_Type structure.
843  * param mask Status flag.
844  *      The parameter can be any combination of the following values:
845  *          arg kFLEXIO_I2C_RxFullFlag
846  *          arg kFLEXIO_I2C_ReceiveNakFlag
847  */
848 
FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type * base,uint32_t mask)849 void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask)
850 {
851     if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
852     {
853         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[0]);
854     }
855 
856     if ((mask & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
857     {
858         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
859     }
860 
861     if ((mask & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
862     {
863         FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
864     }
865 }
866 
867 /*!
868  * brief Enables the FlexIO i2c master interrupt requests.
869  *
870  * param base Pointer to FLEXIO_I2C_Type structure.
871  * param mask Interrupt source.
872  *     Currently only one interrupt request source:
873  *     arg kFLEXIO_I2C_TransferCompleteInterruptEnable
874  */
FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type * base,uint32_t mask)875 void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
876 {
877     if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable) != 0U)
878     {
879         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
880     }
881     if ((mask & (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable) != 0U)
882     {
883         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
884     }
885 }
886 
887 /*!
888  * brief Disables the FlexIO I2C master interrupt requests.
889  *
890  * param base Pointer to FLEXIO_I2C_Type structure.
891  * param mask Interrupt source.
892  */
FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type * base,uint32_t mask)893 void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
894 {
895     if ((mask & (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable) != 0U)
896     {
897         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
898     }
899     if ((mask & (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable) != 0U)
900     {
901         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
902     }
903 }
904 
905 /*!
906  * brief Sets the FlexIO I2C master transfer baudrate.
907  *
908  * param base Pointer to FLEXIO_I2C_Type structure
909  * param baudRate_Bps the baud rate value in HZ
910  * param srcClock_Hz source clock in HZ
911  */
FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)912 void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
913 {
914     uint16_t timerDiv       = 0;
915     FLEXIO_Type *flexioBase = base->flexioBase;
916 
917     /* Set TIMCMP = (baud rate divider / 2) - 1.*/
918     timerDiv = (uint16_t)((srcClock_Hz / baudRate_Bps) / 2U - 1U);
919 
920     flexioBase->TIMCMP[base->timerIndex[1]] = timerDiv;
921 
922     /* Calculate and assign the actual baudrate. */
923     base->baudrate = srcClock_Hz / (2U * ((uint32_t)timerDiv + 1U));
924 }
925 
926 /*!
927  * brief Sets the number of bytes to be transferred from a start signal to a stop signal.
928  *
929  * note Call this API before a transfer begins because the timer generates a number of clocks according
930  * to the number of bytes that need to be transferred.
931  *
932  * param base Pointer to FLEXIO_I2C_Type structure.
933  * param count Number of bytes need to be transferred from a start signal to a re-start/stop signal
934  * retval kStatus_Success Successfully configured the count.
935  * retval kStatus_InvalidArgument Input argument is invalid.
936  */
FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type * base,uint16_t count)937 status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint16_t count)
938 {
939     /* Calculate whether the transfer count is larger than the max value compare register can achieve */
940     if (count > ((0xFFFFUL - 1UL) / (16UL + 1UL + 1UL)))
941     {
942         return kStatus_InvalidArgument;
943     }
944 
945     uint32_t timerConfig    = 0U;
946     FLEXIO_Type *flexioBase = base->flexioBase;
947 
948     flexioBase->TIMCMP[base->timerIndex[0]] = (uint32_t)count * 18U + 1U;
949     timerConfig                             = flexioBase->TIMCFG[base->timerIndex[0]];
950     timerConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
951     timerConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare);
952     flexioBase->TIMCFG[base->timerIndex[0]] = timerConfig;
953 
954     return kStatus_Success;
955 }
956 
957 /*!
958  * brief Sends START + 7-bit address to the bus.
959  *
960  * note This API should be called when the transfer configuration is ready to send a START signal
961  * and 7-bit address to the bus. This is a non-blocking API, which returns directly after the address
962  * is put into the data register but the address transfer is not finished on the bus. Ensure that
963  * the kFLEXIO_I2C_RxFullFlag status is asserted before calling this API.
964  * param base Pointer to FLEXIO_I2C_Type structure.
965  * param address 7-bit address.
966  * param direction transfer direction.
967  *     This parameter is one of the values in flexio_i2c_direction_t:
968  *        arg kFLEXIO_I2C_Write: Transmit
969  *        arg kFLEXIO_I2C_Read:  Receive
970  */
971 
FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type * base,uint8_t address,flexio_i2c_direction_t direction)972 void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction)
973 {
974     uint32_t data;
975 
976     data = ((uint32_t)address) << 1U | ((direction == kFLEXIO_I2C_Read) ? 1U : 0U);
977 
978     FLEXIO_I2C_MasterWriteByte(base, data);
979 }
980 
981 /*!
982  * brief Sends the repeated start signal on the bus.
983  *
984  * param base Pointer to FLEXIO_I2C_Type structure.
985  */
FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type * base)986 void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base)
987 {
988     /* Prepare for RESTART condition, no stop.*/
989     FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
990 }
991 
992 /*!
993  * brief Sends the stop signal on the bus.
994  *
995  * param base Pointer to FLEXIO_I2C_Type structure.
996  */
FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type * base)997 void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base)
998 {
999     /* Prepare normal stop. */
1000     (void)FLEXIO_I2C_MasterSetTransferCount(base, 0x0U);
1001     FLEXIO_I2C_MasterWriteByte(base, 0x0U);
1002 }
1003 
1004 /*!
1005  * brief Sends the stop signal when transfer is still on-going.
1006  *
1007  * param base Pointer to FLEXIO_I2C_Type structure.
1008  */
FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type * base)1009 void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base)
1010 {
1011     uint32_t tmpConfig;
1012 
1013     /* Prepare abort stop. */
1014     /* Disable timer 0. */
1015     tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[0]];
1016     tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
1017     tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
1018     base->flexioBase->TIMCFG[base->timerIndex[0]] = tmpConfig;
1019 
1020     /* Disable timer 1. */
1021     tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[1]];
1022     tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
1023     tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
1024     base->flexioBase->TIMCFG[base->timerIndex[1]] = tmpConfig;
1025 }
1026 
1027 /*!
1028  * brief Configures the sent ACK/NAK for the following byte.
1029  *
1030  * param base Pointer to FLEXIO_I2C_Type structure.
1031  * param enable True to configure send ACK, false configure to send NAK.
1032  */
FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type * base,bool enable)1033 void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable)
1034 {
1035     uint32_t tmpConfig = 0;
1036 
1037     tmpConfig = base->flexioBase->SHIFTCFG[base->shifterIndex[0]];
1038     tmpConfig &= ~FLEXIO_SHIFTCFG_SSTOP_MASK;
1039     if (enable)
1040     {
1041         tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitLow);
1042     }
1043     else
1044     {
1045         tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitHigh);
1046     }
1047     base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = tmpConfig;
1048 }
1049 
1050 /*!
1051  * brief Sends a buffer of data in bytes.
1052  *
1053  * note This function blocks via polling until all bytes have been sent.
1054  *
1055  * param base Pointer to FLEXIO_I2C_Type structure.
1056  * param txBuff The data bytes to send.
1057  * param txSize The number of data bytes to send.
1058  * retval kStatus_Success Successfully write data.
1059  * retval kStatus_FLEXIO_I2C_Nak Receive NAK during writing data.
1060  * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
1061  */
FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type * base,const uint8_t * txBuff,uint8_t txSize)1062 status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize)
1063 {
1064     assert(txBuff != NULL);
1065     assert(txSize != 0U);
1066 
1067     uint32_t status;
1068 #if I2C_RETRY_TIMES
1069     uint32_t waitTimes = I2C_RETRY_TIMES;
1070 #endif
1071 
1072     while (0U != txSize--)
1073     {
1074         FLEXIO_I2C_MasterWriteByte(base, *txBuff++);
1075 
1076         /* Wait until data transfer complete. */
1077 #if I2C_RETRY_TIMES
1078         waitTimes = I2C_RETRY_TIMES;
1079         while ((0U == ((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
1080                (0U != --waitTimes))
1081         {
1082         }
1083         if (0U == waitTimes)
1084         {
1085             return kStatus_FLEXIO_I2C_Timeout;
1086         }
1087 #else
1088         while (0U == ((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
1089         {
1090         }
1091 #endif
1092 
1093         if ((status & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
1094         {
1095             FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
1096             return kStatus_FLEXIO_I2C_Nak;
1097         }
1098     }
1099     return kStatus_Success;
1100 }
1101 
1102 /*!
1103  * brief Receives a buffer of bytes.
1104  *
1105  * note This function blocks via polling until all bytes have been received.
1106  *
1107  * param base Pointer to FLEXIO_I2C_Type structure.
1108  * param rxBuff The buffer to store the received bytes.
1109  * param rxSize The number of data bytes to be received.
1110  * retval kStatus_Success Successfully read data.
1111  * retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
1112  */
FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type * base,uint8_t * rxBuff,uint8_t rxSize)1113 status_t FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize)
1114 {
1115     assert(rxBuff != NULL);
1116     assert(rxSize != 0U);
1117 
1118 #if I2C_RETRY_TIMES
1119     uint32_t waitTimes = I2C_RETRY_TIMES;
1120 #endif
1121 
1122     while (0U != rxSize--)
1123     {
1124         /* Wait until data transfer complete. */
1125 #if I2C_RETRY_TIMES
1126         waitTimes = I2C_RETRY_TIMES;
1127         while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
1128                (0U != --waitTimes))
1129         {
1130         }
1131         if (0U == waitTimes)
1132         {
1133             return kStatus_FLEXIO_I2C_Timeout;
1134         }
1135 #else
1136         while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
1137         {
1138         }
1139 #endif
1140         *rxBuff++ = FLEXIO_I2C_MasterReadByte(base);
1141     }
1142     return kStatus_Success;
1143 }
1144 
1145 /*!
1146  * brief Performs a master polling transfer on the I2C bus.
1147  *
1148  * note The API does not return until the transfer succeeds or fails due
1149  * to receiving NAK.
1150  *
1151  * param base pointer to FLEXIO_I2C_Type structure.
1152  * param xfer pointer to flexio_i2c_master_transfer_t structure.
1153  * return status of status_t.
1154  */
FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type * base,flexio_i2c_master_transfer_t * xfer)1155 status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_transfer_t *xfer)
1156 {
1157     assert(xfer != NULL);
1158 
1159 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
1160     /* Return an error if the bus is already in use not by us.*/
1161     status_t status = FLEXIO_I2C_CheckForBusyBus(base);
1162     if (status != kStatus_Success)
1163     {
1164         return status;
1165     }
1166 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
1167 
1168     flexio_i2c_master_handle_t tmpHandle;
1169     uint32_t statusFlags;
1170     status_t result = kStatus_Success;
1171 #if I2C_RETRY_TIMES
1172     uint32_t waitTimes = I2C_RETRY_TIMES;
1173 #endif
1174 
1175     /* Zero the handle. */
1176     (void)memset(&tmpHandle, 0, sizeof(tmpHandle));
1177 
1178     /* Set up transfer machine. */
1179     result = FLEXIO_I2C_MasterTransferInitStateMachine(base, &tmpHandle, xfer);
1180     if (result != kStatus_Success)
1181     {
1182         return result;
1183     }
1184 
1185     do
1186     {
1187         /* Wait either tx empty or rx full flag is asserted. */
1188 #if I2C_RETRY_TIMES
1189         waitTimes = I2C_RETRY_TIMES;
1190         while ((0U == ((statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base)) &
1191                        ((uint32_t)kFLEXIO_I2C_TxEmptyFlag | (uint32_t)kFLEXIO_I2C_RxFullFlag))) &&
1192                (0U != --waitTimes))
1193         {
1194         }
1195         if (0U == waitTimes)
1196         {
1197             return kStatus_FLEXIO_I2C_Timeout;
1198         }
1199 #else
1200         while (0U == ((statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base)) &
1201                       ((uint32_t)kFLEXIO_I2C_TxEmptyFlag | (uint32_t)kFLEXIO_I2C_RxFullFlag)))
1202         {
1203         }
1204 #endif
1205         FLEXIO_ClearTimerStatusFlags(base->flexioBase, ((1UL << base->timerIndex[0]) | (1UL << base->timerIndex[1])));
1206         result = FLEXIO_I2C_MasterTransferRunStateMachine(base, &tmpHandle, statusFlags);
1207 
1208     } while ((tmpHandle.state != (uint8_t)kFLEXIO_I2C_Idle) && (result == kStatus_Success));
1209 
1210     /* Timer disable on timer compare, wait until bit clock TSF set, which means timer disable and stop has been sent.
1211      */
1212     while (0U == (FLEXIO_GetTimerStatusFlags(base->flexioBase) & (1UL << base->timerIndex[1])))
1213     {
1214     }
1215 
1216     return result;
1217 }
1218 
1219 /*!
1220  * brief Initializes the I2C handle which is used in transactional functions.
1221  *
1222  * param base Pointer to FLEXIO_I2C_Type structure.
1223  * param handle Pointer to flexio_i2c_master_handle_t structure to store the transfer state.
1224  * param callback Pointer to user callback function.
1225  * param userData User param passed to the callback function.
1226  * retval kStatus_Success Successfully create the handle.
1227  * retval kStatus_OutOfRange The FlexIO type/handle/isr table out of range.
1228  */
FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,flexio_i2c_master_transfer_callback_t callback,void * userData)1229 status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
1230                                                flexio_i2c_master_handle_t *handle,
1231                                                flexio_i2c_master_transfer_callback_t callback,
1232                                                void *userData)
1233 {
1234     assert(handle != NULL);
1235 
1236     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
1237 
1238     /* Zero the handle. */
1239     (void)memset(handle, 0, sizeof(*handle));
1240 
1241     /* Register callback and userData. */
1242     handle->completionCallback = callback;
1243     handle->userData           = userData;
1244 
1245     /* Clear pending NVIC IRQ before enable NVIC IRQ. */
1246     NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_I2C_GetInstance(base)]);
1247     (void)EnableIRQ(flexio_irqs[FLEXIO_I2C_GetInstance(base)]);
1248 
1249     /* Save the context in global variables to support the double weak mechanism. */
1250     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2C_MasterTransferHandleIRQ);
1251 }
1252 
1253 /*!
1254  * brief Performs a master interrupt non-blocking transfer on the I2C bus.
1255  *
1256  * note The API returns immediately after the transfer initiates.
1257  * Call FLEXIO_I2C_MasterTransferGetCount to poll the transfer status to check whether
1258  * the transfer is finished. If the return status is not kStatus_FLEXIO_I2C_Busy, the transfer
1259  * is finished.
1260  *
1261  * param base Pointer to FLEXIO_I2C_Type structure
1262  * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
1263  * param xfer pointer to flexio_i2c_master_transfer_t structure
1264  * retval kStatus_Success Successfully start a transfer.
1265  * retval kStatus_FLEXIO_I2C_Busy FlexIO I2C is not idle, is running another transfer.
1266  */
FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,flexio_i2c_master_transfer_t * xfer)1267 status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
1268                                               flexio_i2c_master_handle_t *handle,
1269                                               flexio_i2c_master_transfer_t *xfer)
1270 {
1271     assert(handle != NULL);
1272     assert(xfer != NULL);
1273 
1274     status_t result = kStatus_Success;
1275 
1276 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
1277     /* Return an error if the bus is already in use not by us.*/
1278     result = FLEXIO_I2C_CheckForBusyBus(base);
1279     if (result != kStatus_Success)
1280     {
1281         return result;
1282     }
1283 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
1284 
1285     if (handle->state != (uint8_t)kFLEXIO_I2C_Idle)
1286     {
1287         return kStatus_FLEXIO_I2C_Busy;
1288     }
1289     else
1290     {
1291         /* Set up transfer machine. */
1292         result = FLEXIO_I2C_MasterTransferInitStateMachine(base, handle, xfer);
1293         if (result != kStatus_Success)
1294         {
1295             return result;
1296         }
1297 
1298         /* Enable both tx empty and rxfull interrupt. */
1299         FLEXIO_I2C_MasterEnableInterrupts(
1300             base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
1301 
1302         return kStatus_Success;
1303     }
1304 }
1305 
1306 /*!
1307  * brief Aborts an interrupt non-blocking transfer early.
1308  *
1309  * note This API can be called at any time when an interrupt non-blocking transfer initiates
1310  * to abort the transfer early.
1311  *
1312  * param base Pointer to FLEXIO_I2C_Type structure
1313  * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
1314  */
FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle)1315 void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle)
1316 {
1317     assert(handle != NULL);
1318 
1319     /* Disable interrupts. */
1320     FLEXIO_I2C_MasterDisableInterrupts(
1321         base, (uint32_t)kFLEXIO_I2C_TxEmptyInterruptEnable | (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
1322 
1323     /* Reset to idle state. */
1324     handle->state = (uint8_t)kFLEXIO_I2C_Idle;
1325 }
1326 
1327 /*!
1328  * brief Gets the master transfer status during a interrupt non-blocking transfer.
1329  *
1330  * param base Pointer to FLEXIO_I2C_Type structure.
1331  * param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
1332  * param count Number of bytes transferred so far by the non-blocking transaction.
1333  * retval kStatus_InvalidArgument count is Invalid.
1334  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1335  * retval kStatus_Success Successfully return the count.
1336  */
FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type * base,flexio_i2c_master_handle_t * handle,size_t * count)1337 status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count)
1338 {
1339     if (NULL == count)
1340     {
1341         return kStatus_InvalidArgument;
1342     }
1343 
1344     /* Catch when there is not an active transfer. */
1345     if (handle->state == (uint8_t)kFLEXIO_I2C_Idle)
1346     {
1347         *count = 0;
1348         return kStatus_NoTransferInProgress;
1349     }
1350 
1351     *count = handle->transferSize - handle->transfer.dataSize;
1352 
1353     return kStatus_Success;
1354 }
1355 
1356 /*!
1357  * brief Master interrupt handler.
1358  *
1359  * param i2cType Pointer to FLEXIO_I2C_Type structure
1360  * param i2cHandle Pointer to flexio_i2c_master_transfer_t structure
1361  */
FLEXIO_I2C_MasterTransferHandleIRQ(void * i2cType,void * i2cHandle)1362 void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle)
1363 {
1364     FLEXIO_I2C_Type *base              = (FLEXIO_I2C_Type *)i2cType;
1365     flexio_i2c_master_handle_t *handle = (flexio_i2c_master_handle_t *)i2cHandle;
1366     uint32_t statusFlags;
1367     status_t result;
1368 
1369     statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base);
1370 
1371     result = FLEXIO_I2C_MasterTransferRunStateMachine(base, handle, statusFlags);
1372 
1373     if (handle->state == (uint8_t)kFLEXIO_I2C_Idle)
1374     {
1375         FLEXIO_I2C_MasterTransferComplete(base, handle, result);
1376     }
1377 }
1378