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_lpi2c.h"
10 #include <stdlib.h>
11 #include <string.h>
12 
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /* Component ID definition, used by tools. */
18 #ifndef FSL_COMPONENT_ID
19 #define FSL_COMPONENT_ID "platform.drivers.lpi2c"
20 #endif
21 
22 /* ! @brief LPI2C master fifo commands. */
23 enum
24 {
25     kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
26     kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
27     kStopCmd   = LPI2C_MTDR_CMD(0x2U), /*!< Generate STOP condition */
28     kStartCmd  = LPI2C_MTDR_CMD(0x4U), /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
29 };
30 
31 /*!
32  * @brief Default watermark values.
33  *
34  * The default watermarks are set to zero.
35  */
36 enum
37 {
38     kDefaultTxWatermark = 0,
39     kDefaultRxWatermark = 0,
40 };
41 
42 /*! @brief States for the state machine used by transactional APIs. */
43 enum
44 {
45     kIdleState = 0,
46     kSendCommandState,
47     kIssueReadCommandState,
48     kTransferDataState,
49     kStopState,
50     kWaitForCompletionState,
51 };
52 
53 /*! @brief Typedef for slave interrupt handler. */
54 typedef void (*lpi2c_slave_isr_t)(LPI2C_Type *base, lpi2c_slave_handle_t *handle);
55 
56 /*******************************************************************************
57  * Prototypes
58  ******************************************************************************/
59 static uint32_t LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,
60                                         uint32_t width_ns,
61                                         uint32_t maxCycles,
62                                         uint32_t prescaler);
63 
64 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base);
65 
66 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone);
67 
68 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle);
69 
70 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags);
71 
72 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance);
73 
74 /*******************************************************************************
75  * Variables
76  ******************************************************************************/
77 
78 /*! @brief Array to map LPI2C instance number to base pointer. */
79 static LPI2C_Type *const kLpi2cBases[] = LPI2C_BASE_PTRS;
80 
81 /*! @brief Array to map LPI2C instance number to IRQ number, used internally for LPI2C master interrupt and EDMA
82 transactional APIs. */
83 IRQn_Type const kLpi2cIrqs[] = LPI2C_IRQS;
84 
85 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
86 /*! @brief Array to map LPI2C instance number to clock gate enum. */
87 static clock_ip_name_t const kLpi2cClocks[] = LPI2C_CLOCKS;
88 
89 #if defined(LPI2C_PERIPH_CLOCKS)
90 /*! @brief Array to map LPI2C instance number to pheripheral clock gate enum. */
91 static const clock_ip_name_t kLpi2cPeriphClocks[] = LPI2C_PERIPH_CLOCKS;
92 #endif
93 
94 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
95 
96 /*! @brief Pointer to master IRQ handler for each instance, used internally for LPI2C master interrupt and EDMA
97 transactional APIs. */
98 lpi2c_master_isr_t s_lpi2cMasterIsr;
99 
100 /*! @brief Pointers to master handles for each instance, used internally for LPI2C master interrupt and EDMA
101 transactional APIs. */
102 void *s_lpi2cMasterHandle[ARRAY_SIZE(kLpi2cBases)];
103 
104 /*! @brief Pointer to slave IRQ handler for each instance. */
105 static lpi2c_slave_isr_t s_lpi2cSlaveIsr;
106 
107 /*! @brief Pointers to slave handles for each instance. */
108 static lpi2c_slave_handle_t *s_lpi2cSlaveHandle[ARRAY_SIZE(kLpi2cBases)];
109 
110 /*******************************************************************************
111  * Code
112  ******************************************************************************/
113 
114 /*!
115  * brief Returns an instance number given a base address.
116  *
117  * If an invalid base address is passed, debug builds will assert. Release builds will just return
118  * instance number 0.
119  *
120  * param base The LPI2C peripheral base address.
121  * return LPI2C instance number starting from 0.
122  */
LPI2C_GetInstance(LPI2C_Type * base)123 uint32_t LPI2C_GetInstance(LPI2C_Type *base)
124 {
125     uint32_t instance;
126     for (instance = 0U; instance < ARRAY_SIZE(kLpi2cBases); ++instance)
127     {
128         if (kLpi2cBases[instance] == base)
129         {
130             break;
131         }
132     }
133 
134     assert(instance < ARRAY_SIZE(kLpi2cBases));
135     return instance;
136 }
137 
138 /*!
139  * @brief Computes a cycle count for a given time in nanoseconds.
140  * @param sourceClock_Hz LPI2C functional clock frequency in Hertz.
141  * @param width_ns Desired with in nanoseconds.
142  * @param maxCycles Maximum cycle count, determined by the number of bits wide the cycle count field is.
143  * @param prescaler LPI2C prescaler setting.
144  */
LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,uint32_t width_ns,uint32_t maxCycles,uint32_t prescaler)145 static uint32_t LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,
146                                         uint32_t width_ns,
147                                         uint32_t maxCycles,
148                                         uint32_t prescaler)
149 {
150     assert(sourceClock_Hz > 0U);
151 
152     uint32_t divider = 1U;
153 
154     while (prescaler != 0U)
155     {
156         divider *= 2U;
157         prescaler--;
158     }
159 
160     uint32_t busCycle_ns = 1000000U / (sourceClock_Hz / divider / 1000U);
161     uint32_t cycles      = 0U;
162 
163     /* Search for the cycle count just below the desired glitch width. */
164     while ((((cycles + 1U) * busCycle_ns) < width_ns) && (cycles + 1U < maxCycles))
165     {
166         ++cycles;
167     }
168 
169     /* If we end up with zero cycles, then set the filter to a single cycle unless the */
170     /* bus clock is greater than 10x the desired glitch width. */
171     if ((cycles == 0U) && (busCycle_ns <= (width_ns * 10U)))
172     {
173         cycles = 1U;
174     }
175 
176     return cycles;
177 }
178 
179 /*!
180  * @brief Convert provided flags to status code, and clear any errors if present.
181  * @param base The LPI2C peripheral base address.
182  * @param status Current status flags value that will be checked.
183  * @retval #kStatus_Success
184  * @retval #kStatus_LPI2C_PinLowTimeout
185  * @retval #kStatus_LPI2C_ArbitrationLost
186  * @retval #kStatus_LPI2C_Nak
187  * @retval #kStatus_LPI2C_FifoError
188  */
189 /* Not static so it can be used from fsl_lpi2c_edma.c. */
LPI2C_MasterCheckAndClearError(LPI2C_Type * base,uint32_t status)190 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status)
191 {
192     status_t result = kStatus_Success;
193 
194     /* Check for error. These errors cause a stop to automatically be sent. We must */
195     /* clear the errors before a new transfer can start. */
196     status &= (uint32_t)kLPI2C_MasterErrorFlags;
197     if (0U != status)
198     {
199         /* Select the correct error code. Ordered by severity, with bus issues first. */
200         if (0U != (status & (uint32_t)kLPI2C_MasterPinLowTimeoutFlag))
201         {
202             result = kStatus_LPI2C_PinLowTimeout;
203         }
204         else if (0U != (status & (uint32_t)kLPI2C_MasterArbitrationLostFlag))
205         {
206             result = kStatus_LPI2C_ArbitrationLost;
207         }
208         else if (0U != (status & (uint32_t)kLPI2C_MasterNackDetectFlag))
209         {
210             result = kStatus_LPI2C_Nak;
211         }
212         else if (0U != (status & (uint32_t)kLPI2C_MasterFifoErrFlag))
213         {
214             result = kStatus_LPI2C_FifoError;
215         }
216         else
217         {
218             ; /* Intentional empty */
219         }
220 
221         /* Clear the flags. */
222         LPI2C_MasterClearStatusFlags(base, status);
223 
224         /* Reset fifos. These flags clear automatically. */
225         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
226     }
227     else
228     {
229         ; /* Intentional empty */
230     }
231 
232     return result;
233 }
234 
235 /*!
236  * @brief Wait until there is room in the tx fifo.
237  * @param base The LPI2C peripheral base address.
238  * @retval #kStatus_Success
239  * @retval #kStatus_LPI2C_PinLowTimeout
240  * @retval #kStatus_LPI2C_ArbitrationLost
241  * @retval #kStatus_LPI2C_Nak
242  * @retval #kStatus_LPI2C_FifoError
243  */
LPI2C_MasterWaitForTxReady(LPI2C_Type * base)244 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base)
245 {
246     status_t result = kStatus_Success;
247     uint32_t status;
248     size_t txCount;
249     size_t txFifoSize = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
250 
251 #if I2C_RETRY_TIMES != 0U
252     uint32_t waitTimes = I2C_RETRY_TIMES;
253 #endif
254     do
255     {
256         /* Get the number of words in the tx fifo and compute empty slots. */
257         LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
258         txCount = txFifoSize - txCount;
259 
260         /* Check for error flags. */
261         status = LPI2C_MasterGetStatusFlags(base);
262         result = LPI2C_MasterCheckAndClearError(base, status);
263         if (kStatus_Success != result)
264         {
265             break;
266         }
267 #if I2C_RETRY_TIMES != 0U
268         waitTimes--;
269     } while ((0U == txCount) && (0U != waitTimes));
270 
271     if (0U == waitTimes)
272     {
273         result = kStatus_LPI2C_Timeout;
274     }
275 #else
276     } while (0U == txCount);
277 #endif
278 
279     return result;
280 }
281 
282 /*!
283  * @brief Make sure the bus isn't already busy.
284  *
285  * A busy bus is allowed if we are the one driving it.
286  *
287  * @param base The LPI2C peripheral base address.
288  * @retval #kStatus_Success
289  * @retval #kStatus_LPI2C_Busy
290  */
291 /* Not static so it can be used from fsl_lpi2c_edma.c. */
LPI2C_CheckForBusyBus(LPI2C_Type * base)292 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base)
293 {
294     status_t ret = kStatus_Success;
295 
296     uint32_t status = LPI2C_MasterGetStatusFlags(base);
297     if ((0U != (status & (uint32_t)kLPI2C_MasterBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_MasterBusyFlag)))
298     {
299         ret = kStatus_LPI2C_Busy;
300     }
301 
302     return ret;
303 }
304 
305 /*!
306  * brief Provides a default configuration for the LPI2C master peripheral.
307  *
308  * This function provides the following default configuration for the LPI2C master peripheral:
309  * code
310  *  masterConfig->enableMaster            = true;
311  *  masterConfig->debugEnable             = false;
312  *  masterConfig->ignoreAck               = false;
313  *  masterConfig->pinConfig               = kLPI2C_2PinOpenDrain;
314  *  masterConfig->baudRate_Hz             = 100000U;
315  *  masterConfig->busIdleTimeout_ns       = 0U;
316  *  masterConfig->pinLowTimeout_ns        = 0U;
317  *  masterConfig->sdaGlitchFilterWidth_ns = 0U;
318  *  masterConfig->sclGlitchFilterWidth_ns = 0U;
319  *  masterConfig->hostRequest.enable      = false;
320  *  masterConfig->hostRequest.source      = kLPI2C_HostRequestExternalPin;
321  *  masterConfig->hostRequest.polarity    = kLPI2C_HostRequestPinActiveHigh;
322  * endcode
323  *
324  * After calling this function, you can override any settings in order to customize the configuration,
325  * prior to initializing the master driver with LPI2C_MasterInit().
326  *
327  * param[out] masterConfig User provided configuration structure for default values. Refer to #lpi2c_master_config_t.
328  */
LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t * masterConfig)329 void LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t *masterConfig)
330 {
331     /* Initializes the configure structure to zero. */
332     (void)memset(masterConfig, 0, sizeof(*masterConfig));
333 
334     masterConfig->enableMaster            = true;
335     masterConfig->debugEnable             = false;
336     masterConfig->enableDoze              = true;
337     masterConfig->ignoreAck               = false;
338     masterConfig->pinConfig               = kLPI2C_2PinOpenDrain;
339     masterConfig->baudRate_Hz             = 100000U;
340     masterConfig->busIdleTimeout_ns       = 0U;
341     masterConfig->pinLowTimeout_ns        = 0U;
342     masterConfig->sdaGlitchFilterWidth_ns = 0U;
343     masterConfig->sclGlitchFilterWidth_ns = 0U;
344     masterConfig->hostRequest.enable      = false;
345     masterConfig->hostRequest.source      = kLPI2C_HostRequestExternalPin;
346     masterConfig->hostRequest.polarity    = kLPI2C_HostRequestPinActiveHigh;
347 }
348 
349 /*!
350  * brief Initializes the LPI2C master peripheral.
351  *
352  * This function enables the peripheral clock and initializes the LPI2C master peripheral as described by the user
353  * provided configuration. A software reset is performed prior to configuration.
354  *
355  * param base The LPI2C peripheral base address.
356  * param masterConfig User provided peripheral configuration. Use LPI2C_MasterGetDefaultConfig() to get a set of
357  * defaults
358  *      that you can override.
359  * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the baud rate divisors,
360  *      filter widths, and timeout periods.
361  */
LPI2C_MasterInit(LPI2C_Type * base,const lpi2c_master_config_t * masterConfig,uint32_t sourceClock_Hz)362 void LPI2C_MasterInit(LPI2C_Type *base, const lpi2c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
363 {
364     uint32_t prescaler;
365     uint32_t cycles;
366     uint32_t cfgr2;
367     uint32_t value;
368 
369 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
370 
371     uint32_t instance = LPI2C_GetInstance(base);
372 
373     /* Ungate the clock. */
374     (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
375 #if defined(LPI2C_PERIPH_CLOCKS)
376     /* Ungate the functional clock in initialize function. */
377     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
378 #endif
379 
380 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
381 
382     /* Reset peripheral before configuring it. */
383     LPI2C_MasterReset(base);
384 
385     /* Doze bit: 0 is enable, 1 is disable */
386     base->MCR = LPI2C_MCR_DBGEN(masterConfig->debugEnable) | LPI2C_MCR_DOZEN(!(masterConfig->enableDoze));
387 
388     /* host request */
389     value = base->MCFGR0;
390     value &= (~(LPI2C_MCFGR0_HREN_MASK | LPI2C_MCFGR0_HRPOL_MASK | LPI2C_MCFGR0_HRSEL_MASK));
391     value |= LPI2C_MCFGR0_HREN(masterConfig->hostRequest.enable) |
392              LPI2C_MCFGR0_HRPOL(masterConfig->hostRequest.polarity) |
393              LPI2C_MCFGR0_HRSEL(masterConfig->hostRequest.source);
394     base->MCFGR0 = value;
395 
396     /* pin config and ignore ack */
397     value = base->MCFGR1;
398     value &= ~(LPI2C_MCFGR1_PINCFG_MASK | LPI2C_MCFGR1_IGNACK_MASK);
399     value |= LPI2C_MCFGR1_PINCFG(masterConfig->pinConfig);
400     value |= LPI2C_MCFGR1_IGNACK(masterConfig->ignoreAck);
401     base->MCFGR1 = value;
402 
403     LPI2C_MasterSetWatermarks(base, (size_t)kDefaultTxWatermark, (size_t)kDefaultRxWatermark);
404 
405     /* Configure glitch filters. */
406     cfgr2 = base->MCFGR2;
407     if (0U != (masterConfig->sdaGlitchFilterWidth_ns))
408     {
409         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sdaGlitchFilterWidth_ns,
410                                          (LPI2C_MCFGR2_FILTSDA_MASK >> LPI2C_MCFGR2_FILTSDA_SHIFT), 1U);
411         cfgr2 &= ~LPI2C_MCFGR2_FILTSDA_MASK;
412         cfgr2 |= LPI2C_MCFGR2_FILTSDA(cycles);
413     }
414     if (0U != masterConfig->sclGlitchFilterWidth_ns)
415     {
416         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sclGlitchFilterWidth_ns,
417                                          (LPI2C_MCFGR2_FILTSCL_MASK >> LPI2C_MCFGR2_FILTSCL_SHIFT), 1U);
418         cfgr2 &= ~LPI2C_MCFGR2_FILTSCL_MASK;
419         cfgr2 |= LPI2C_MCFGR2_FILTSCL(cycles);
420     }
421     base->MCFGR2 = cfgr2;
422 
423     /* Configure baudrate after the SDA/SCL glitch filter setting,
424        since the baudrate calculation needs them as parameter. */
425     LPI2C_MasterSetBaudRate(base, sourceClock_Hz, masterConfig->baudRate_Hz);
426 
427     /* Configure bus idle and pin low timeouts after baudrate setting,
428        since the timeout calculation needs prescaler as parameter. */
429     prescaler = (base->MCFGR1 & LPI2C_MCFGR1_PRESCALE_MASK) >> LPI2C_MCFGR1_PRESCALE_SHIFT;
430 
431     if (0U != (masterConfig->busIdleTimeout_ns))
432     {
433         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->busIdleTimeout_ns,
434                                          (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
435         cfgr2 &= ~LPI2C_MCFGR2_BUSIDLE_MASK;
436         cfgr2 |= LPI2C_MCFGR2_BUSIDLE(cycles);
437     }
438     base->MCFGR2 = cfgr2;
439     if (0U != masterConfig->pinLowTimeout_ns)
440     {
441         cycles       = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->pinLowTimeout_ns / 256U,
442                                          (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
443         base->MCFGR3 = (base->MCFGR3 & ~LPI2C_MCFGR3_PINLOW_MASK) | LPI2C_MCFGR3_PINLOW(cycles);
444     }
445 
446     LPI2C_MasterEnable(base, masterConfig->enableMaster);
447 }
448 
449 /*!
450  * brief Deinitializes the LPI2C master peripheral.
451  *
452  * This function disables the LPI2C master peripheral and gates the clock. It also performs a software
453  * reset to restore the peripheral to reset conditions.
454  *
455  * param base The LPI2C peripheral base address.
456  */
LPI2C_MasterDeinit(LPI2C_Type * base)457 void LPI2C_MasterDeinit(LPI2C_Type *base)
458 {
459     /* Restore to reset state. */
460     LPI2C_MasterReset(base);
461 
462 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
463 
464     uint32_t instance = LPI2C_GetInstance(base);
465 
466     /* Gate clock. */
467     (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
468 #if defined(LPI2C_PERIPH_CLOCKS)
469     /* Gate the functional clock. */
470     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
471 #endif
472 
473 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
474 }
475 
476 /*!
477  * brief Configures LPI2C master data match feature.
478  *
479  * param base The LPI2C peripheral base address.
480  * param matchConfig Settings for the data match feature.
481  */
LPI2C_MasterConfigureDataMatch(LPI2C_Type * base,const lpi2c_data_match_config_t * matchConfig)482 void LPI2C_MasterConfigureDataMatch(LPI2C_Type *base, const lpi2c_data_match_config_t *matchConfig)
483 {
484     /* Disable master mode. */
485     bool wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
486     LPI2C_MasterEnable(base, false);
487 
488     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_MATCFG_MASK) | LPI2C_MCFGR1_MATCFG(matchConfig->matchMode);
489     base->MCFGR0 = (base->MCFGR0 & ~LPI2C_MCFGR0_RDMO_MASK) | LPI2C_MCFGR0_RDMO(matchConfig->rxDataMatchOnly);
490     base->MDMR   = LPI2C_MDMR_MATCH0(matchConfig->match0) | LPI2C_MDMR_MATCH1(matchConfig->match1);
491 
492     /* Restore master mode. */
493     if (wasEnabled)
494     {
495         LPI2C_MasterEnable(base, true);
496     }
497 }
498 
499 /*!
500  * brief Sets the I2C bus frequency for master transactions.
501  *
502  * The LPI2C master is automatically disabled and re-enabled as necessary to configure the baud
503  * rate. Do not call this function during a transfer, or the transfer is aborted.
504  *
505  * note Please note that the second parameter is the clock frequency of LPI2C module, the third
506  * parameter means user configured bus baudrate, this implementation is different from other I2C drivers
507  * which use baudrate configuration as second parameter and source clock frequency as third parameter.
508  *
509  * param base The LPI2C peripheral base address.
510  * param sourceClock_Hz LPI2C functional clock frequency in Hertz.
511  * param baudRate_Hz Requested bus frequency in Hertz.
512  */
LPI2C_MasterSetBaudRate(LPI2C_Type * base,uint32_t sourceClock_Hz,uint32_t baudRate_Hz)513 void LPI2C_MasterSetBaudRate(LPI2C_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Hz)
514 {
515     bool wasEnabled;
516     uint8_t filtScl = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSCL_MASK) >> LPI2C_MCFGR2_FILTSCL_SHIFT);
517 
518     uint8_t divider     = 1U;
519     uint8_t bestDivider = 1U;
520     uint8_t prescale    = 0U;
521     uint8_t bestPre     = 0U;
522 
523     uint8_t clkCycle;
524     uint8_t bestclkCycle = 0U;
525 
526     uint32_t absError  = 0U;
527     uint32_t bestError = 0xffffffffu;
528     uint32_t computedRate;
529 
530     uint32_t tmpReg = 0U;
531 
532     /* Disable master mode. */
533     wasEnabled = (0U != ((base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT));
534     LPI2C_MasterEnable(base, false);
535 
536     /* Baud rate = (sourceClock_Hz / 2 ^ prescale) / (CLKLO + 1 + CLKHI + 1 + SCL_LATENCY)
537      * SCL_LATENCY = ROUNDDOWN((2 + FILTSCL) / (2 ^ prescale))
538      */
539     for (prescale = 0U; prescale <= 7U; prescale++)
540     {
541         /* Calculate the clkCycle, clkCycle = CLKLO + CLKHI, divider = 2 ^ prescale */
542         clkCycle = (uint8_t)((10U * sourceClock_Hz / divider / baudRate_Hz + 5U) / 10U - (2U + filtScl) / divider - 2U);
543         /* According to register description, The max value for CLKLO and CLKHI is 63.
544            however to meet the I2C specification of tBUF, CLKHI should be less than
545            clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U. Refer to the comment of the tmpHigh's
546            calculation for details. So we have:
547            CLKHI < clkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / divider + 1U,
548            clkCycle = CLKHI + CLKLO and
549            sourceClock_Hz / baudRate_Hz / divider = clkCycle + 2 + ROUNDDOWN((2 + FILTSCL) / divider),
550            we can come up with: CLKHI < 0.92 x CLKLO - ROUNDDOWN(2 + FILTSCL) / divider
551            so the max boundary of CLKHI should be 0.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider,
552            and the max boundary of clkCycle is 1.92 x 63 - ROUNDDOWN(2 + FILTSCL) / divider. */
553         if (clkCycle > (120U - (2U + filtScl) / divider))
554         {
555             divider *= 2U;
556             continue;
557         }
558         /* Calculate the computed baudrate and compare it with the desired baudrate */
559         computedRate = (sourceClock_Hz / (uint32_t)divider) /
560                        ((uint32_t)clkCycle + 2U + (2U + (uint32_t)filtScl) / (uint32_t)divider);
561         absError = baudRate_Hz > computedRate ? baudRate_Hz - computedRate : computedRate - baudRate_Hz;
562         if (absError < bestError)
563         {
564             bestPre      = prescale;
565             bestDivider  = divider;
566             bestclkCycle = clkCycle;
567             bestError    = absError;
568 
569             /* If the error is 0, then we can stop searching because we won't find a better match. */
570             if (absError == 0U)
571             {
572                 break;
573             }
574         }
575         divider *= 2U;
576     }
577 
578     /* SCL low time tLO should be larger than or equal to SCL high time tHI:
579        tLO = ((CLKLO + 1) x (2 ^ PRESCALE)) >= tHI = ((CLKHI + 1 + SCL_LATENCY) x (2 ^ PRESCALE)),
580        which is CLKLO >= CLKHI + (2U + filtScl) / bestDivider.
581        Also since bestclkCycle = CLKLO + CLKHI, bestDivider = 2 ^ PRESCALE
582        which makes CLKHI <= (bestclkCycle - (2U + filtScl) / bestDivider) / 2U.
583 
584        The max tBUF should be at least 0.52 times of the SCL clock cycle:
585        tBUF = ((CLKLO + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.52 / baudRate_Hz),
586        plus bestDivider = 2 ^ PRESCALE, bestclkCycle = CLKLO + CLKHI we can come up with
587        CLKHI <= (bestclkCycle - 0.52 x sourceClock_Hz / baudRate_Hz / bestDivider + 1U).
588        In this case to get a safe CLKHI calculation, we can assume:
589     */
590     uint8_t tmpHigh = (bestclkCycle - (2U + filtScl) / bestDivider) / 2U;
591     while (tmpHigh > (bestclkCycle - 52U * sourceClock_Hz / baudRate_Hz / bestDivider / 100U + 1U))
592     {
593         tmpHigh = tmpHigh - 1U;
594     }
595 
596     /* Calculate DATAVD and SETHOLD.
597        To meet the timing requirement of I2C spec for standard mode, fast mode and fast mode plus: */
598     /* The min tHD:STA/tSU:STA/tSU:STO should be at least 0.4 times of the SCL clock cycle, use 0.5 to be safe:
599        tHD:STA = ((SETHOLD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) > (0.5 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
600     uint8_t tmpHold = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 2U) - 1U;
601 
602     /* The max tVD:DAT/tVD:ACK/tHD:DAT should be at most 0.345 times of the SCL clock cycle, use 0.25 to be safe:
603        tVD:DAT = ((DATAVD + 1) x (2 ^ PRESCALE) / sourceClock_Hz) < (0.25 / baudRate_Hz), bestDivider = 2 ^ PRESCALE */
604     uint8_t tmpDataVd = (uint8_t)(sourceClock_Hz / baudRate_Hz / bestDivider / 4U) - 1U;
605 
606     /* The min tSU:DAT should be at least 0.05 times of the SCL clock cycle:
607        tSU:DAT = ((2 + FILTSDA + 2 ^ PRESCALE) / sourceClock_Hz) >= (0.05 / baud),
608        plus bestDivider = 2 ^ PRESCALE, we can come up with:
609        FILTSDA >= (0.05 x sourceClock_Hz / baudRate_Hz - bestDivider - 2) */
610     if ((sourceClock_Hz / baudRate_Hz / 20U) > (bestDivider + 2U))
611     {
612         /* Read out the FILTSDA configuration, if it is smaller than expected, change the setting. */
613         uint8_t filtSda = (uint8_t)((base->MCFGR2 & LPI2C_MCFGR2_FILTSDA_MASK) >> LPI2C_MCFGR2_FILTSDA_SHIFT);
614         if (filtSda < (sourceClock_Hz / baudRate_Hz / 20U - bestDivider - 2U))
615         {
616             filtSda = (uint8_t)(sourceClock_Hz / baudRate_Hz / 20U) - bestDivider - 2U;
617         }
618         base->MCFGR2 = (base->MCFGR2 & ~LPI2C_MCFGR2_FILTSDA_MASK) | LPI2C_MCFGR2_FILTSDA(filtSda);
619     }
620 
621     /* Set CLKHI, CLKLO, SETHOLD, DATAVD value. */
622     tmpReg = LPI2C_MCCR0_CLKHI((uint32_t)tmpHigh) |
623              LPI2C_MCCR0_CLKLO((uint32_t)((uint32_t)bestclkCycle - (uint32_t)tmpHigh)) |
624              LPI2C_MCCR0_SETHOLD((uint32_t)tmpHold) | LPI2C_MCCR0_DATAVD((uint32_t)tmpDataVd);
625     base->MCCR0 = tmpReg;
626 
627     /* Set PRESCALE value. */
628     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_PRESCALE_MASK) | LPI2C_MCFGR1_PRESCALE(bestPre);
629 
630     /* Restore master mode. */
631     if (wasEnabled)
632     {
633         LPI2C_MasterEnable(base, true);
634     }
635 }
636 
637 /*!
638  * brief Sends a START signal and slave address on the I2C bus.
639  *
640  * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
641  * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
642  * 7-bit address specified in the a address parameter. Note that this function does not actually wait
643  * until the START and address are successfully sent on the bus before returning.
644  *
645  * param base The LPI2C peripheral base address.
646  * param address 7-bit slave device address, in bits [6:0].
647  * param dir Master transfer direction, either #kLPI2C_Read or #kLPI2C_Write. This parameter is used to set
648  *      the R/w bit (bit 0) in the transmitted slave address.
649  * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
650  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
651  */
LPI2C_MasterStart(LPI2C_Type * base,uint8_t address,lpi2c_direction_t dir)652 status_t LPI2C_MasterStart(LPI2C_Type *base, uint8_t address, lpi2c_direction_t dir)
653 {
654     /* Return an error if the bus is already in use not by us. */
655     status_t result = LPI2C_CheckForBusyBus(base);
656     if (kStatus_Success == result)
657     {
658         /* Clear all flags. */
659         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
660 
661         /* Turn off auto-stop option. */
662         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
663 
664         /* Wait until there is room in the fifo. */
665         result = LPI2C_MasterWaitForTxReady(base);
666         if (kStatus_Success == result)
667         {
668             /* Issue start command. */
669             base->MTDR = (uint32_t)kStartCmd | (((uint32_t)address << 1U) | (uint32_t)dir);
670         }
671     }
672 
673     return result;
674 }
675 
676 /*!
677  * brief Sends a STOP signal on the I2C bus.
678  *
679  * This function does not return until the STOP signal is seen on the bus, or an error occurs.
680  *
681  * param base The LPI2C peripheral base address.
682  * retval #kStatus_Success The STOP signal was successfully sent on the bus and the transaction terminated.
683  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
684  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
685  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
686  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
687  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
688  */
LPI2C_MasterStop(LPI2C_Type * base)689 status_t LPI2C_MasterStop(LPI2C_Type *base)
690 {
691     /* Wait until there is room in the fifo. */
692     status_t result = LPI2C_MasterWaitForTxReady(base);
693     if (kStatus_Success == result)
694     {
695         /* Send the STOP signal */
696         base->MTDR = (uint32_t)kStopCmd;
697 
698         /* Wait for the stop detected flag to set, indicating the transfer has completed on the bus. */
699         /* Also check for errors while waiting. */
700 #if I2C_RETRY_TIMES != 0U
701         uint32_t waitTimes = I2C_RETRY_TIMES;
702 #endif
703 
704 #if I2C_RETRY_TIMES != 0U
705         while ((result == kStatus_Success) && (0U != waitTimes))
706         {
707             waitTimes--;
708 #else
709         while (result == kStatus_Success)
710         {
711 #endif
712             uint32_t status = LPI2C_MasterGetStatusFlags(base);
713 
714             /* Check for error flags. */
715             result = LPI2C_MasterCheckAndClearError(base, status);
716 
717             /* Check if the stop was sent successfully. */
718             if ((0U != (status & (uint32_t)kLPI2C_MasterStopDetectFlag)) &&
719                 (0U != (status & (uint32_t)kLPI2C_MasterTxReadyFlag)))
720             {
721                 LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterStopDetectFlag);
722                 break;
723             }
724         }
725 
726 #if I2C_RETRY_TIMES != 0U
727         if (0U == waitTimes)
728         {
729             result = kStatus_LPI2C_Timeout;
730         }
731 #endif
732     }
733 
734     return result;
735 }
736 
737 /*!
738  * brief Performs a polling receive transfer on the I2C bus.
739  *
740  * param base  The LPI2C peripheral base address.
741  * param rxBuff The pointer to the data to be transferred.
742  * param rxSize The length in bytes of the data to be transferred.
743  * retval #kStatus_Success Data was received successfully.
744  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
745  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
746  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
747  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
748  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
749  */
750 status_t LPI2C_MasterReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize)
751 {
752     assert(NULL != rxBuff);
753 
754     status_t result = kStatus_Success;
755     uint8_t *buf;
756     size_t tmpRxSize = rxSize;
757 #if I2C_RETRY_TIMES != 0U
758     uint32_t waitTimes;
759 #endif
760 
761     /* Check transfer data size. */
762     if (rxSize > (256U * FSL_FEATURE_LPI2C_FIFO_SIZEn(base)))
763     {
764         return kStatus_InvalidArgument;
765     }
766 
767     /* Handle empty read. */
768     if (rxSize != 0U)
769     {
770         /* Wait until there is room in the command fifo. */
771         result = LPI2C_MasterWaitForTxReady(base);
772         if (kStatus_Success == result)
773         {
774             /* Issue command to receive data. A single write to MTDR can issue read operation of 0xFFU + 1 byte of data
775                at most, so when the rxSize is larger than 0x100U, push multiple read commands to MTDR until rxSize is
776                reached. */
777             while (tmpRxSize != 0U)
778             {
779                 if (tmpRxSize > 256U)
780                 {
781                     base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
782                     tmpRxSize -= 256U;
783                 }
784                 else
785                 {
786                     base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
787                     tmpRxSize  = 0U;
788                 }
789             }
790 
791             /* Receive data */
792             buf = (uint8_t *)rxBuff;
793             while (0U != (rxSize--))
794             {
795 #if I2C_RETRY_TIMES != 0U
796                 waitTimes = I2C_RETRY_TIMES;
797 #endif
798                 /* Read LPI2C receive fifo register. The register includes a flag to indicate whether */
799                 /* the FIFO is empty, so we can both get the data and check if we need to keep reading */
800                 /* using a single register read. */
801                 uint32_t value = 0U;
802                 do
803                 {
804                     /* Check for errors. */
805                     result = LPI2C_MasterCheckAndClearError(base, LPI2C_MasterGetStatusFlags(base));
806                     if (kStatus_Success != result)
807                     {
808                         break;
809                     }
810 
811                     value = base->MRDR;
812 #if I2C_RETRY_TIMES != 0U
813                     waitTimes--;
814                 } while ((0U != (value & LPI2C_MRDR_RXEMPTY_MASK)) && (0U != waitTimes));
815                 if (0U == waitTimes)
816                 {
817                     result = kStatus_LPI2C_Timeout;
818                 }
819 #else
820                 } while (0U != (value & LPI2C_MRDR_RXEMPTY_MASK));
821 #endif
822                 if ((status_t)kStatus_Success != result)
823                 {
824                     break;
825                 }
826 
827                 *buf++ = (uint8_t)(value & LPI2C_MRDR_DATA_MASK);
828             }
829         }
830     }
831 
832     return result;
833 }
834 
835 /*!
836  * brief Performs a polling send transfer on the I2C bus.
837  *
838  * Sends up to a txSize number of bytes to the previously addressed slave device. The slave may
839  * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
840  * function returns #kStatus_LPI2C_Nak.
841  *
842  * param base  The LPI2C peripheral base address.
843  * param txBuff The pointer to the data to be transferred.
844  * param txSize The length in bytes of the data to be transferred.
845  * retval #kStatus_Success Data was sent successfully.
846  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
847  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
848  * retval #kStatus_LPI2C_FifoError FIFO under run or over run.
849  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
850  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
851  */
LPI2C_MasterSend(LPI2C_Type * base,void * txBuff,size_t txSize)852 status_t LPI2C_MasterSend(LPI2C_Type *base, void *txBuff, size_t txSize)
853 {
854     status_t result = kStatus_Success;
855     uint8_t *buf    = (uint8_t *)txBuff;
856 
857     assert(NULL != txBuff);
858 
859     /* Send data buffer */
860     while (0U != (txSize--))
861     {
862         /* Wait until there is room in the fifo. This also checks for errors. */
863         result = LPI2C_MasterWaitForTxReady(base);
864         if (kStatus_Success != result)
865         {
866             break;
867         }
868 
869         /* Write byte into LPI2C master data register. */
870         base->MTDR = *buf++;
871     }
872 
873     return result;
874 }
875 
876 /*!
877  * brief Performs a master polling transfer on the I2C bus.
878  *
879  * note The API does not return until the transfer succeeds or fails due
880  * to error happens during transfer.
881  *
882  * param base The LPI2C peripheral base address.
883  * param transfer Pointer to the transfer structure.
884  * retval #kStatus_Success Data was received successfully.
885  * retval #kStatus_LPI2C_Busy Another master is currently utilizing the bus.
886  * retval #kStatus_LPI2C_Nak The slave device sent a NAK in response to a byte.
887  * retval #kStatus_LPI2C_FifoError FIFO under run or overrun.
888  * retval #kStatus_LPI2C_ArbitrationLost Arbitration lost error.
889  * retval #kStatus_LPI2C_PinLowTimeout SCL or SDA were held low longer than the timeout.
890  */
LPI2C_MasterTransferBlocking(LPI2C_Type * base,lpi2c_master_transfer_t * transfer)891 status_t LPI2C_MasterTransferBlocking(LPI2C_Type *base, lpi2c_master_transfer_t *transfer)
892 {
893     assert(NULL != transfer);
894     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
895 
896     status_t result = kStatus_Success;
897     uint16_t commandBuffer[7];
898     uint32_t cmdCount = 0U;
899 
900     /* Check transfer data size in read operation. */
901     if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > (256U * FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
902     {
903         return kStatus_InvalidArgument;
904     }
905 
906     /* Return an error if the bus is already in use not by us. */
907     result = LPI2C_CheckForBusyBus(base);
908     if (kStatus_Success == result)
909     {
910         /* Clear all flags. */
911         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
912 
913         /* Turn off auto-stop option. */
914         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
915 
916         lpi2c_direction_t direction = (0U != transfer->subaddressSize) ? kLPI2C_Write : transfer->direction;
917         if (0U == (transfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
918         {
919             commandBuffer[cmdCount++] =
920                 (uint16_t)kStartCmd |
921                 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)direction);
922         }
923 
924         /* Subaddress, MSB first. */
925         if (0U != transfer->subaddressSize)
926         {
927             uint32_t subaddressRemaining = transfer->subaddressSize;
928             while (0U != subaddressRemaining--)
929             {
930                 uint8_t subaddressByte    = (uint8_t)((transfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
931                 commandBuffer[cmdCount++] = subaddressByte;
932             }
933         }
934 
935         /* Reads need special handling. */
936         if ((0U != transfer->dataSize) && (transfer->direction == kLPI2C_Read))
937         {
938             /* Need to send repeated start if switching directions to read. */
939             if (direction == kLPI2C_Write)
940             {
941                 commandBuffer[cmdCount++] =
942                     (uint16_t)kStartCmd |
943                     (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
944             }
945         }
946 
947         /* Send command buffer */
948         uint32_t index = 0U;
949         while (0U != cmdCount--)
950         {
951             /* Wait until there is room in the fifo. This also checks for errors. */
952             result = LPI2C_MasterWaitForTxReady(base);
953             if (kStatus_Success != result)
954             {
955                 break;
956             }
957 
958             /* Write byte into LPI2C master data register. */
959             base->MTDR = commandBuffer[index];
960             index++;
961         }
962 
963         if (kStatus_Success == result)
964         {
965             /* Transmit data. */
966             if ((transfer->direction == kLPI2C_Write) && (transfer->dataSize > 0U))
967             {
968                 /* Send Data. */
969                 result = LPI2C_MasterSend(base, transfer->data, transfer->dataSize);
970             }
971 
972             /* Receive Data. */
973             if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > 0U))
974             {
975                 result = LPI2C_MasterReceive(base, transfer->data, transfer->dataSize);
976             }
977 
978             if (kStatus_Success == result)
979             {
980                 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
981                 {
982                     result = LPI2C_MasterStop(base);
983                 }
984             }
985         }
986     }
987 
988     return result;
989 }
990 
991 /*!
992  * brief Creates a new handle for the LPI2C master non-blocking APIs.
993  *
994  * The creation of a handle is for use with the non-blocking APIs. Once a handle
995  * is created, there is not a corresponding destroy handle. If the user wants to
996  * terminate a transfer, the LPI2C_MasterTransferAbort() API shall be called.
997  *
998  *
999  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
1000  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
1001  * enable the associated INTMUX IRQ in application.
1002  *
1003  * param base The LPI2C peripheral base address.
1004  * param[out] handle Pointer to the LPI2C master driver handle.
1005  * param callback User provided pointer to the asynchronous callback function.
1006  * param userData User provided pointer to the application callback data.
1007  */
LPI2C_MasterTransferCreateHandle(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_callback_t callback,void * userData)1008 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
1009                                       lpi2c_master_handle_t *handle,
1010                                       lpi2c_master_transfer_callback_t callback,
1011                                       void *userData)
1012 {
1013     uint32_t instance;
1014 
1015     assert(NULL != handle);
1016 
1017     /* Clear out the handle. */
1018     (void)memset(handle, 0, sizeof(*handle));
1019 
1020     /* Look up instance number */
1021     instance = LPI2C_GetInstance(base);
1022 
1023     /* Save base and instance. */
1024     handle->completionCallback = callback;
1025     handle->userData           = userData;
1026 
1027     /* Save this handle for IRQ use. */
1028     s_lpi2cMasterHandle[instance] = handle;
1029 
1030     /* Set irq handler. */
1031     s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
1032 
1033     /* Clear internal IRQ enables and enable NVIC IRQ. */
1034     LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1035 
1036     /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1037      In some cases the LPI2C IRQ is configured through INTMUX, user needs to enable
1038      INTMUX IRQ in application code. */
1039     (void)EnableIRQ(kLpi2cIrqs[instance]);
1040 }
1041 
1042 /*!
1043  * @brief Execute states until FIFOs are exhausted.
1044  * @param handle Master nonblocking driver handle.
1045  * @param[out] isDone Set to true if the transfer has completed.
1046  * @retval #kStatus_Success
1047  * @retval #kStatus_LPI2C_PinLowTimeout
1048  * @retval #kStatus_LPI2C_ArbitrationLost
1049  * @retval #kStatus_LPI2C_Nak
1050  * @retval #kStatus_LPI2C_FifoError
1051  */
LPI2C_RunTransferStateMachine(LPI2C_Type * base,lpi2c_master_handle_t * handle,bool * isDone)1052 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
1053 {
1054     uint32_t status;
1055     status_t result = kStatus_Success;
1056     lpi2c_master_transfer_t *xfer;
1057     size_t txCount;
1058     size_t rxCount;
1059     size_t txFifoSize   = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
1060     bool state_complete = false;
1061     uint16_t sendval;
1062 
1063     /* Set default isDone return value. */
1064     *isDone = false;
1065 
1066     /* Check for errors. */
1067     status = LPI2C_MasterGetStatusFlags(base);
1068     /* For the last byte, nack flag is expected.
1069        Do not check and clear kLPI2C_MasterNackDetectFlag for the last byte,
1070        in case FIFO is emptied when stop command has not been sent. */
1071     if (handle->remainingBytes == 0U)
1072     {
1073         status &= ~(uint32_t)kLPI2C_MasterNackDetectFlag;
1074     }
1075     result = LPI2C_MasterCheckAndClearError(base, status);
1076     if (kStatus_Success == result)
1077     {
1078         /* Get pointer to private data. */
1079         xfer = &handle->transfer;
1080 
1081         /* Get fifo counts and compute room in tx fifo. */
1082         LPI2C_MasterGetFifoCounts(base, &rxCount, &txCount);
1083         txCount = txFifoSize - txCount;
1084 
1085         while (!state_complete)
1086         {
1087             /* Execute the state. */
1088             switch (handle->state)
1089             {
1090                 case (uint8_t)kSendCommandState:
1091                     /* Make sure there is room in the tx fifo for the next command. */
1092                     if (0U == txCount--)
1093                     {
1094                         state_complete = true;
1095                         break;
1096                     }
1097 
1098                     /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
1099                     sendval    = ((uint16_t)handle->buf[0]) | (((uint16_t)handle->buf[1]) << 8U);
1100                     base->MTDR = sendval;
1101                     handle->buf++;
1102                     handle->buf++;
1103 
1104                     /* Count down until all commands are sent. */
1105                     if (--handle->remainingBytes == 0U)
1106                     {
1107                         /* Choose next state and set up buffer pointer and count. */
1108                         if (0U != xfer->dataSize)
1109                         {
1110                             /* Either a send or receive transfer is next. */
1111                             handle->state          = (uint8_t)kTransferDataState;
1112                             handle->buf            = (uint8_t *)xfer->data;
1113                             handle->remainingBytes = (uint16_t)xfer->dataSize;
1114                             if (xfer->direction == kLPI2C_Read)
1115                             {
1116                                 /* Disable TX interrupt */
1117                                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1118                                 /* Issue command to receive data. A single write to MTDR can issue read operation of
1119                                    0xFFU + 1 byte of data at most, so when the dataSize is larger than 0x100U, push
1120                                    multiple read commands to MTDR until dataSize is reached. */
1121                                 size_t tmpRxSize = xfer->dataSize;
1122                                 while (tmpRxSize != 0U)
1123                                 {
1124                                     if (tmpRxSize > 256U)
1125                                     {
1126                                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
1127                                         tmpRxSize -= 256U;
1128                                     }
1129                                     else
1130                                     {
1131                                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
1132                                         tmpRxSize  = 0U;
1133                                     }
1134                                 }
1135                             }
1136                         }
1137                         else
1138                         {
1139                             /* No transfer, so move to stop state. */
1140                             handle->state = (uint8_t)kStopState;
1141                         }
1142                     }
1143                     break;
1144 
1145                 case (uint8_t)kIssueReadCommandState:
1146                     /* Make sure there is room in the tx fifo for the read command. */
1147                     if (0U == txCount--)
1148                     {
1149                         state_complete = true;
1150                         break;
1151                     }
1152 
1153                     base->MTDR = (uint32_t)kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1U);
1154 
1155                     /* Move to transfer state. */
1156                     handle->state = (uint8_t)kTransferDataState;
1157                     if (xfer->direction == kLPI2C_Read)
1158                     {
1159                         /* Disable TX interrupt */
1160                         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1161                     }
1162                     break;
1163 
1164                 case (uint8_t)kTransferDataState:
1165                     if (xfer->direction == kLPI2C_Write)
1166                     {
1167                         /* Make sure there is room in the tx fifo. */
1168                         if (0U == txCount--)
1169                         {
1170                             state_complete = true;
1171                             break;
1172                         }
1173 
1174                         /* Put byte to send in fifo. */
1175                         base->MTDR = *(handle->buf)++;
1176                     }
1177                     else
1178                     {
1179                         /* XXX handle receive sizes > 256, use kIssueReadCommandState */
1180                         /* Make sure there is data in the rx fifo. */
1181                         if (0U == rxCount--)
1182                         {
1183                             state_complete = true;
1184                             break;
1185                         }
1186 
1187                         /* Read byte from fifo. */
1188                         *(handle->buf)++ = (uint8_t)(base->MRDR & LPI2C_MRDR_DATA_MASK);
1189                     }
1190 
1191                     /* Move to stop when the transfer is done. */
1192                     if (--handle->remainingBytes == 0U)
1193                     {
1194                         if (xfer->direction == kLPI2C_Write)
1195                         {
1196                             state_complete = true;
1197                         }
1198                         handle->state = (uint8_t)kStopState;
1199                     }
1200                     break;
1201 
1202                 case (uint8_t)kStopState:
1203                     /* Only issue a stop transition if the caller requested it. */
1204                     if ((xfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1205                     {
1206                         /* Make sure there is room in the tx fifo for the stop command. */
1207                         if (0U == txCount--)
1208                         {
1209                             state_complete = true;
1210                             break;
1211                         }
1212 
1213                         base->MTDR = (uint32_t)kStopCmd;
1214                     }
1215                     else
1216                     {
1217                         /* If all data is read and no stop flag is required to send, we are done. */
1218                         if (xfer->direction == kLPI2C_Read)
1219                         {
1220                             *isDone = true;
1221                         }
1222                         state_complete = true;
1223                     }
1224                     handle->state = (uint8_t)kWaitForCompletionState;
1225                     break;
1226 
1227                 case (uint8_t)kWaitForCompletionState:
1228                     if ((xfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1229                     {
1230                         /* We stay in this state until the stop state is detected. */
1231                         if (0U != (status & (uint32_t)kLPI2C_MasterStopDetectFlag))
1232                         {
1233                             *isDone = true;
1234                         }
1235                     }
1236                     else
1237                     {
1238                         /* If all data is pushed to FIFO and no stop flag is required to send, we need to make sure they
1239                            are all send out to bus. */
1240                         if ((xfer->direction == kLPI2C_Write) && ((base->MFSR & LPI2C_MFSR_TXCOUNT_MASK) == 0U))
1241                         {
1242                             /* We stay in this state until the data is sent out to bus. */
1243                             *isDone = true;
1244                         }
1245                     }
1246                     state_complete = true;
1247                     break;
1248                 default:
1249                     assert(false);
1250                     break;
1251             }
1252         }
1253     }
1254     return result;
1255 }
1256 
1257 /*!
1258  * @brief Prepares the transfer state machine and fills in the command buffer.
1259  * @param handle Master nonblocking driver handle.
1260  */
LPI2C_InitTransferStateMachine(lpi2c_master_handle_t * handle)1261 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
1262 {
1263     lpi2c_master_transfer_t *xfer = &handle->transfer;
1264 
1265     /* Handle no start option. */
1266     if (0U != (xfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1267     {
1268         if (xfer->direction == kLPI2C_Read)
1269         {
1270             /* Need to issue read command first. */
1271             handle->state = (uint8_t)kIssueReadCommandState;
1272         }
1273         else
1274         {
1275             /* Start immediately in the data transfer state. */
1276             handle->state = (uint8_t)kTransferDataState;
1277         }
1278 
1279         handle->buf            = (uint8_t *)xfer->data;
1280         handle->remainingBytes = (uint16_t)xfer->dataSize;
1281     }
1282     else
1283     {
1284         uint16_t *cmd     = (uint16_t *)&handle->commandBuffer;
1285         uint32_t cmdCount = 0U;
1286 
1287         /* Initial direction depends on whether a subaddress was provided, and of course the actual */
1288         /* data transfer direction. */
1289         lpi2c_direction_t direction = (0U != xfer->subaddressSize) ? kLPI2C_Write : xfer->direction;
1290 
1291         /* Start command. */
1292         cmd[cmdCount++] =
1293             (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
1294 
1295         /* Subaddress, MSB first. */
1296         if (0U != xfer->subaddressSize)
1297         {
1298             uint32_t subaddressRemaining = xfer->subaddressSize;
1299             while (0U != (subaddressRemaining--))
1300             {
1301                 uint8_t subaddressByte = (uint8_t)((xfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1302                 cmd[cmdCount++]        = subaddressByte;
1303             }
1304         }
1305 
1306         /* Reads need special handling. */
1307         if ((0U != xfer->dataSize) && (xfer->direction == kLPI2C_Read))
1308         {
1309             /* Need to send repeated start if switching directions to read. */
1310             if (direction == kLPI2C_Write)
1311             {
1312                 cmd[cmdCount++] = (uint16_t)kStartCmd |
1313                                   (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1314             }
1315         }
1316 
1317         /* Set up state machine for transferring the commands. */
1318         handle->state          = (uint8_t)kSendCommandState;
1319         handle->remainingBytes = (uint16_t)cmdCount;
1320         handle->buf            = (uint8_t *)&handle->commandBuffer;
1321     }
1322 }
1323 
1324 /*!
1325  * brief Performs a non-blocking transaction on the I2C bus.
1326  *
1327  * param base The LPI2C peripheral base address.
1328  * param handle Pointer to the LPI2C master driver handle.
1329  * param transfer The pointer to the transfer descriptor.
1330  * retval #kStatus_Success The transaction was started successfully.
1331  * retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or a non-blocking
1332  *      transaction is already in progress.
1333  */
LPI2C_MasterTransferNonBlocking(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_t * transfer)1334 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
1335                                          lpi2c_master_handle_t *handle,
1336                                          lpi2c_master_transfer_t *transfer)
1337 {
1338     assert(NULL != handle);
1339     assert(NULL != transfer);
1340     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1341 
1342     status_t result;
1343 
1344     /* Check transfer data size in read operation. */
1345     if ((transfer->direction == kLPI2C_Read) &&
1346         (transfer->dataSize > (256U * (uint32_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1347     {
1348         return kStatus_InvalidArgument;
1349     }
1350 
1351     /* Return busy if another transaction is in progress. */
1352     if (handle->state != (uint8_t)kIdleState)
1353     {
1354         result = kStatus_LPI2C_Busy;
1355     }
1356     else
1357     {
1358         result = LPI2C_CheckForBusyBus(base);
1359     }
1360 
1361     if ((status_t)kStatus_Success == result)
1362     {
1363         /* Disable LPI2C IRQ sources while we configure stuff. */
1364         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1365 
1366         /* Reset FIFO in case there are data. */
1367         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1368 
1369         /* Save transfer into handle. */
1370         handle->transfer = *transfer;
1371 
1372         /* Generate commands to send. */
1373         LPI2C_InitTransferStateMachine(handle);
1374 
1375         /* Clear all flags. */
1376         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1377 
1378         /* Turn off auto-stop option. */
1379         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1380 
1381         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1382         LPI2C_MasterEnableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1383     }
1384 
1385     return result;
1386 }
1387 
1388 /*!
1389  * brief Returns number of bytes transferred so far.
1390  * param base The LPI2C peripheral base address.
1391  * param handle Pointer to the LPI2C master driver handle.
1392  * param[out] count Number of bytes transferred so far by the non-blocking transaction.
1393  * retval #kStatus_Success
1394  * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1395  */
LPI2C_MasterTransferGetCount(LPI2C_Type * base,lpi2c_master_handle_t * handle,size_t * count)1396 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
1397 {
1398     status_t result = kStatus_Success;
1399 
1400     assert(NULL != handle);
1401 
1402     if (NULL == count)
1403     {
1404         result = kStatus_InvalidArgument;
1405     }
1406 
1407     /* Catch when there is not an active transfer. */
1408     else if (handle->state == (uint8_t)kIdleState)
1409     {
1410         *count = 0;
1411         result = kStatus_NoTransferInProgress;
1412     }
1413     else
1414     {
1415         uint8_t state;
1416         uint16_t remainingBytes;
1417         uint32_t dataSize;
1418 
1419         /* Cache some fields with IRQs disabled. This ensures all field values */
1420         /* are synchronized with each other during an ongoing transfer. */
1421         uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
1422         LPI2C_MasterDisableInterrupts(base, irqs);
1423         state          = handle->state;
1424         remainingBytes = handle->remainingBytes;
1425         dataSize       = handle->transfer.dataSize;
1426         LPI2C_MasterEnableInterrupts(base, irqs);
1427 
1428         /* Get transfer count based on current transfer state. */
1429         switch (state)
1430         {
1431             case (uint8_t)kIdleState:
1432             case (uint8_t)kSendCommandState:
1433             case (uint8_t)
1434                 kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1435                 *count = 0;
1436                 break;
1437 
1438             case (uint8_t)kTransferDataState:
1439                 *count = dataSize - remainingBytes;
1440                 break;
1441 
1442             case (uint8_t)kStopState:
1443             case (uint8_t)kWaitForCompletionState:
1444             default:
1445                 *count = dataSize;
1446                 break;
1447         }
1448     }
1449 
1450     return result;
1451 }
1452 
1453 /*!
1454  * brief Terminates a non-blocking LPI2C master transmission early.
1455  *
1456  * note It is not safe to call this function from an IRQ handler that has a higher priority than the
1457  *      LPI2C peripheral's IRQ priority.
1458  *
1459  * param base The LPI2C peripheral base address.
1460  * param handle Pointer to the LPI2C master driver handle.
1461  * retval #kStatus_Success A transaction was successfully aborted.
1462  * retval #kStatus_LPI2C_Idle There is not a non-blocking transaction currently in progress.
1463  */
LPI2C_MasterTransferAbort(LPI2C_Type * base,lpi2c_master_handle_t * handle)1464 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1465 {
1466     if (handle->state != (uint8_t)kIdleState)
1467     {
1468         /* Disable internal IRQ enables. */
1469         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1470 
1471         /* Reset fifos. */
1472         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1473 
1474         /* If master is still busy and has not send out stop signal yet. */
1475         if ((LPI2C_MasterGetStatusFlags(base) & ((uint32_t)kLPI2C_MasterStopDetectFlag |
1476                                                  (uint32_t)kLPI2C_MasterBusyFlag)) == (uint32_t)kLPI2C_MasterBusyFlag)
1477         {
1478             /* Send a stop command to finalize the transfer. */
1479             base->MTDR = (uint32_t)kStopCmd;
1480         }
1481 
1482         /* Reset handle. */
1483         handle->state = (uint8_t)kIdleState;
1484     }
1485 }
1486 
1487 /*!
1488  * brief Reusable routine to handle master interrupts.
1489  * note This function does not need to be called unless you are reimplementing the
1490  *  nonblocking API's interrupt handler routines to add special functionality.
1491  * param base The LPI2C peripheral base address.
1492  * param lpi2cMasterHandle Pointer to the LPI2C master driver handle.
1493  */
LPI2C_MasterTransferHandleIRQ(LPI2C_Type * base,void * lpi2cMasterHandle)1494 void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, void *lpi2cMasterHandle)
1495 {
1496     assert(lpi2cMasterHandle != NULL);
1497 
1498     lpi2c_master_handle_t *handle = (lpi2c_master_handle_t *)lpi2cMasterHandle;
1499     bool isDone                   = false;
1500     status_t result;
1501 
1502     /* Don't do anything if we don't have a valid handle. */
1503     if (NULL != handle)
1504     {
1505         if (handle->state != (uint8_t)kIdleState)
1506         {
1507             result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1508 
1509             if ((result != kStatus_Success) || isDone)
1510             {
1511                 /* Handle error, terminate xfer */
1512                 if (result != kStatus_Success)
1513                 {
1514                     LPI2C_MasterTransferAbort(base, handle);
1515                 }
1516 
1517                 /* Disable internal IRQ enables. */
1518                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1519 
1520                 /* Set handle to idle state. */
1521                 handle->state = (uint8_t)kIdleState;
1522 
1523                 /* Invoke callback. */
1524                 if (NULL != handle->completionCallback)
1525                 {
1526                     handle->completionCallback(base, handle, result, handle->userData);
1527                 }
1528             }
1529         }
1530     }
1531 }
1532 
1533 /*!
1534  * brief Provides a default configuration for the LPI2C slave peripheral.
1535  *
1536  * This function provides the following default configuration for the LPI2C slave peripheral:
1537  * code
1538  *  slaveConfig->enableSlave               = true;
1539  *  slaveConfig->address0                  = 0U;
1540  *  slaveConfig->address1                  = 0U;
1541  *  slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1542  *  slaveConfig->filterDozeEnable          = true;
1543  *  slaveConfig->filterEnable              = true;
1544  *  slaveConfig->enableGeneralCall         = false;
1545  *  slaveConfig->sclStall.enableAck        = false;
1546  *  slaveConfig->sclStall.enableTx         = true;
1547  *  slaveConfig->sclStall.enableRx         = true;
1548  *  slaveConfig->sclStall.enableAddress    = true;
1549  *  slaveConfig->ignoreAck                 = false;
1550  *  slaveConfig->enableReceivedAddressRead = false;
1551  *  slaveConfig->sdaGlitchFilterWidth_ns   = 0;
1552  *  slaveConfig->sclGlitchFilterWidth_ns   = 0;
1553  *  slaveConfig->dataValidDelay_ns         = 0;
1554  *  slaveConfig->clockHoldTime_ns          = 0;
1555  * endcode
1556  *
1557  * After calling this function, override any settings  to customize the configuration,
1558  * prior to initializing the master driver with LPI2C_SlaveInit(). Be sure to override at least the a
1559  * address0 member of the configuration structure with the desired slave address.
1560  *
1561  * param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
1562  *      #lpi2c_slave_config_t.
1563  */
LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t * slaveConfig)1564 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1565 {
1566     /* Initializes the configure structure to zero. */
1567     (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
1568 
1569     slaveConfig->enableSlave               = true;
1570     slaveConfig->address0                  = 0U;
1571     slaveConfig->address1                  = 0U;
1572     slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1573     slaveConfig->filterDozeEnable          = true;
1574     slaveConfig->filterEnable              = true;
1575     slaveConfig->enableGeneralCall         = false;
1576     slaveConfig->sclStall.enableAck        = false;
1577     slaveConfig->sclStall.enableTx         = true;
1578     slaveConfig->sclStall.enableRx         = true;
1579     slaveConfig->sclStall.enableAddress    = false;
1580     slaveConfig->ignoreAck                 = false;
1581     slaveConfig->enableReceivedAddressRead = false;
1582     slaveConfig->sdaGlitchFilterWidth_ns   = 0U; /* TODO determine default width values */
1583     slaveConfig->sclGlitchFilterWidth_ns   = 0U;
1584     slaveConfig->dataValidDelay_ns         = 0U;
1585     slaveConfig->clockHoldTime_ns          = 0U;
1586 }
1587 
1588 /*!
1589  * brief Initializes the LPI2C slave peripheral.
1590  *
1591  * This function enables the peripheral clock and initializes the LPI2C slave peripheral as described by the user
1592  * provided configuration.
1593  *
1594  * param base The LPI2C peripheral base address.
1595  * param slaveConfig User provided peripheral configuration. Use LPI2C_SlaveGetDefaultConfig() to get a set of defaults
1596  *      that you can override.
1597  * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the filter widths,
1598  *      data valid delay, and clock hold time.
1599  */
LPI2C_SlaveInit(LPI2C_Type * base,const lpi2c_slave_config_t * slaveConfig,uint32_t sourceClock_Hz)1600 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1601 {
1602     uint32_t tmpCycle;
1603 
1604 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1605 
1606     uint32_t instance = LPI2C_GetInstance(base);
1607 
1608     /* Ungate the clock. */
1609     (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
1610 #if defined(LPI2C_PERIPH_CLOCKS)
1611     /* Ungate the functional clock in initialize function. */
1612     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1613 #endif
1614 
1615 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1616 
1617     /* Restore to reset conditions. */
1618     LPI2C_SlaveReset(base);
1619 
1620     /* Configure peripheral. */
1621     base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1622 
1623     base->SCFGR1 =
1624         LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1625         LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1626         LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1627         LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1628         LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1629 
1630     tmpCycle =
1631         LPI2C_SCFGR2_FILTSDA(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns,
1632                                                      (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT), 1U));
1633     tmpCycle |=
1634         LPI2C_SCFGR2_FILTSCL(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns,
1635                                                      (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT), 1U));
1636     tmpCycle |= LPI2C_SCFGR2_DATAVD(LPI2C_GetCyclesForWidth(
1637         sourceClock_Hz, slaveConfig->dataValidDelay_ns, (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 1U));
1638 
1639     base->SCFGR2 = tmpCycle | LPI2C_SCFGR2_CLKHOLD(LPI2C_GetCyclesForWidth(
1640                                   sourceClock_Hz, slaveConfig->clockHoldTime_ns,
1641                                   (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT), 1U));
1642 
1643     /* Save SCR to last so we don't enable slave until it is configured */
1644     base->SCR = LPI2C_SCR_FILTDZ(slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1645                 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1646 }
1647 
1648 /*!
1649  * brief Deinitializes the LPI2C slave peripheral.
1650  *
1651  * This function disables the LPI2C slave peripheral and gates the clock. It also performs a software
1652  * reset to restore the peripheral to reset conditions.
1653  *
1654  * param base The LPI2C peripheral base address.
1655  */
LPI2C_SlaveDeinit(LPI2C_Type * base)1656 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1657 {
1658     LPI2C_SlaveReset(base);
1659 
1660 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1661 
1662     uint32_t instance = LPI2C_GetInstance(base);
1663 
1664     /* Gate the clock. */
1665     (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
1666 
1667 #if defined(LPI2C_PERIPH_CLOCKS)
1668     /* Gate the functional clock. */
1669     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1670 #endif
1671 
1672 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1673 }
1674 
1675 /*!
1676  * @brief Convert provided flags to status code, and clear any errors if present.
1677  * @param base The LPI2C peripheral base address.
1678  * @param status Current status flags value that will be checked.
1679  * @retval #kStatus_Success
1680  * @retval #kStatus_LPI2C_BitError
1681  * @retval #kStatus_LPI2C_FifoError
1682  */
LPI2C_SlaveCheckAndClearError(LPI2C_Type * base,uint32_t flags)1683 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1684 {
1685     status_t result = kStatus_Success;
1686 
1687     flags &= (uint32_t)kLPI2C_SlaveErrorFlags;
1688     if (0U != flags)
1689     {
1690         if (0U != (flags & (uint32_t)kLPI2C_SlaveBitErrFlag))
1691         {
1692             result = kStatus_LPI2C_BitError;
1693         }
1694         else if (0U != (flags & (uint32_t)kLPI2C_SlaveFifoErrFlag))
1695         {
1696             result = kStatus_LPI2C_FifoError;
1697         }
1698         else
1699         {
1700             ; /* Intentional empty */
1701         }
1702 
1703         /* Clear the errors. */
1704         LPI2C_SlaveClearStatusFlags(base, flags);
1705     }
1706     else
1707     {
1708         ; /* Intentional empty */
1709     }
1710 
1711     return result;
1712 }
1713 
1714 /*!
1715  * brief Performs a polling send transfer on the I2C bus.
1716  *
1717  * param base  The LPI2C peripheral base address.
1718  * param txBuff The pointer to the data to be transferred.
1719  * param txSize The length in bytes of the data to be transferred.
1720  * param[out] actualTxSize
1721  * return Error or success status returned by API.
1722  */
LPI2C_SlaveSend(LPI2C_Type * base,void * txBuff,size_t txSize,size_t * actualTxSize)1723 status_t LPI2C_SlaveSend(LPI2C_Type *base, void *txBuff, size_t txSize, size_t *actualTxSize)
1724 {
1725     status_t result  = kStatus_Success;
1726     uint8_t *buf     = (uint8_t *)txBuff;
1727     size_t remaining = txSize;
1728 
1729     assert(NULL != txBuff);
1730 
1731 #if I2C_RETRY_TIMES != 0U
1732     uint32_t waitTimes = I2C_RETRY_TIMES;
1733 #endif
1734 
1735     /* Clear stop flag. */
1736     LPI2C_SlaveClearStatusFlags(base,
1737                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1738 
1739     while (0U != remaining)
1740     {
1741         uint32_t flags;
1742 
1743         /* Wait until we can transmit. */
1744         do
1745         {
1746             /* Check for errors */
1747             flags  = LPI2C_SlaveGetStatusFlags(base);
1748             result = LPI2C_SlaveCheckAndClearError(base, flags);
1749             if (kStatus_Success != result)
1750             {
1751                 if (NULL != actualTxSize)
1752                 {
1753                     *actualTxSize = txSize - remaining;
1754                 }
1755                 break;
1756             }
1757 #if I2C_RETRY_TIMES != 0U
1758             waitTimes--;
1759         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1760                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1761                  (0U != waitTimes));
1762         if (0U == waitTimes)
1763         {
1764             result = kStatus_LPI2C_Timeout;
1765         }
1766 #else
1767         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1768                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
1769 #endif
1770 
1771         if (kStatus_Success != result)
1772         {
1773             break;
1774         }
1775 
1776         /* Send a byte. */
1777         if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
1778         {
1779             base->STDR = *buf++;
1780             --remaining;
1781         }
1782 
1783         /* Exit loop if we see a stop or restart in transfer*/
1784         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1785             (remaining != 0U))
1786         {
1787             LPI2C_SlaveClearStatusFlags(
1788                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1789             break;
1790         }
1791     }
1792 
1793     if (NULL != actualTxSize)
1794     {
1795         *actualTxSize = txSize - remaining;
1796     }
1797 
1798     return result;
1799 }
1800 
1801 /*!
1802  * brief Performs a polling receive transfer on the I2C bus.
1803  *
1804  * param base  The LPI2C peripheral base address.
1805  * param rxBuff The pointer to the data to be transferred.
1806  * param rxSize The length in bytes of the data to be transferred.
1807  * param[out] actualRxSize
1808  * return Error or success status returned by API.
1809  */
LPI2C_SlaveReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize,size_t * actualRxSize)1810 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
1811 {
1812     status_t result  = kStatus_Success;
1813     uint8_t *buf     = (uint8_t *)rxBuff;
1814     size_t remaining = rxSize;
1815 
1816     assert(NULL != rxBuff);
1817 
1818 #if I2C_RETRY_TIMES != 0U
1819     uint32_t waitTimes = I2C_RETRY_TIMES;
1820 #endif
1821 
1822     /* Clear stop flag. */
1823     LPI2C_SlaveClearStatusFlags(base,
1824                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1825 
1826     while (0U != remaining)
1827     {
1828         uint32_t flags;
1829 
1830         /* Wait until we can receive. */
1831         do
1832         {
1833             /* Check for errors */
1834             flags  = LPI2C_SlaveGetStatusFlags(base);
1835             result = LPI2C_SlaveCheckAndClearError(base, flags);
1836             if (kStatus_Success != result)
1837             {
1838                 if (NULL != actualRxSize)
1839                 {
1840                     *actualRxSize = rxSize - remaining;
1841                 }
1842                 break;
1843             }
1844 #if I2C_RETRY_TIMES != 0U
1845             waitTimes--;
1846         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1847                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1848                  (0U != waitTimes));
1849         if (0U == waitTimes)
1850         {
1851             result = kStatus_LPI2C_Timeout;
1852         }
1853 #else
1854         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1855                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
1856 #endif
1857 
1858         if ((status_t)kStatus_Success != result)
1859         {
1860             break;
1861         }
1862 
1863         /* Receive a byte. */
1864         if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
1865         {
1866             *buf++ = (uint8_t)(base->SRDR & LPI2C_SRDR_DATA_MASK);
1867             --remaining;
1868         }
1869 
1870         /* Exit loop if we see a stop or restart */
1871         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1872             (remaining != 0U))
1873         {
1874             LPI2C_SlaveClearStatusFlags(
1875                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1876             break;
1877         }
1878     }
1879 
1880     if (NULL != actualRxSize)
1881     {
1882         *actualRxSize = rxSize - remaining;
1883     }
1884 
1885     return result;
1886 }
1887 
1888 /*!
1889  * brief Creates a new handle for the LPI2C slave non-blocking APIs.
1890  *
1891  * The creation of a handle is for use with the non-blocking APIs. Once a handle
1892  * is created, there is not a corresponding destroy handle. If the user wants to
1893  * terminate a transfer, the LPI2C_SlaveTransferAbort() API shall be called.
1894  *
1895  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
1896  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
1897  * enable the associated INTMUX IRQ in application.
1898 
1899  * param base The LPI2C peripheral base address.
1900  * param[out] handle Pointer to the LPI2C slave driver handle.
1901  * param callback User provided pointer to the asynchronous callback function.
1902  * param userData User provided pointer to the application callback data.
1903  */
LPI2C_SlaveTransferCreateHandle(LPI2C_Type * base,lpi2c_slave_handle_t * handle,lpi2c_slave_transfer_callback_t callback,void * userData)1904 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
1905                                      lpi2c_slave_handle_t *handle,
1906                                      lpi2c_slave_transfer_callback_t callback,
1907                                      void *userData)
1908 {
1909     uint32_t instance;
1910 
1911     assert(NULL != handle);
1912 
1913     /* Clear out the handle. */
1914     (void)memset(handle, 0, sizeof(*handle));
1915 
1916     /* Look up instance number */
1917     instance = LPI2C_GetInstance(base);
1918 
1919     /* Save base and instance. */
1920     handle->callback = callback;
1921     handle->userData = userData;
1922 
1923     /* Save this handle for IRQ use. */
1924     s_lpi2cSlaveHandle[instance] = handle;
1925 
1926     /* Set irq handler. */
1927     s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
1928 
1929     /* Clear internal IRQ enables and enable NVIC IRQ. */
1930     LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
1931     (void)EnableIRQ(kLpi2cIrqs[instance]);
1932 
1933     /* Nack by default. */
1934     base->STAR = LPI2C_STAR_TXNACK_MASK;
1935 }
1936 
1937 /*!
1938  * brief Starts accepting slave transfers.
1939  *
1940  * Call this API after calling I2C_SlaveInit() and LPI2C_SlaveTransferCreateHandle() to start processing
1941  * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
1942  * callback that was passed into the call to LPI2C_SlaveTransferCreateHandle(). The callback is always invoked
1943  * from the interrupt context.
1944  *
1945  * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
1946  * the OR'd combination of #lpi2c_slave_transfer_event_t enumerators for the events you wish to receive.
1947  * The #kLPI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need
1948  * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
1949  * receive events that are always enabled. In addition, the #kLPI2C_SlaveAllEvents constant is provided as
1950  * a convenient way to enable all events.
1951  *
1952  * param base The LPI2C peripheral base address.
1953  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
1954  * param eventMask Bit mask formed by OR'ing together #lpi2c_slave_transfer_event_t enumerators to specify
1955  *      which events to send to the callback. Other accepted values are 0 to get a default set of
1956  *      only the transmit and receive events, and #kLPI2C_SlaveAllEvents to enable all events.
1957  *
1958  * retval #kStatus_Success Slave transfers were successfully started.
1959  * retval #kStatus_LPI2C_Busy Slave transfers have already been started on this handle.
1960  */
LPI2C_SlaveTransferNonBlocking(LPI2C_Type * base,lpi2c_slave_handle_t * handle,uint32_t eventMask)1961 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
1962 {
1963     status_t result = kStatus_Success;
1964 
1965     assert(NULL != handle);
1966 
1967     /* Return busy if another transaction is in progress. */
1968     if (handle->isBusy)
1969     {
1970         result = kStatus_LPI2C_Busy;
1971     }
1972     else
1973     {
1974         /* Return an error if the bus is already in use not by us. */
1975         uint32_t status = LPI2C_SlaveGetStatusFlags(base);
1976         if ((0U != (status & (uint32_t)kLPI2C_SlaveBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_SlaveBusyFlag)))
1977         {
1978             result = kStatus_LPI2C_Busy;
1979         }
1980     }
1981 
1982     if ((status_t)kStatus_Success == result)
1983     {
1984         /* Disable LPI2C IRQ sources while we configure stuff. */
1985         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
1986 
1987         /* Clear transfer in handle. */
1988         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
1989 
1990         /* Record that we're busy. */
1991         handle->isBusy = true;
1992 
1993         /* Set up event mask. tx and rx are always enabled. */
1994         handle->eventMask = eventMask | (uint32_t)kLPI2C_SlaveTransmitEvent | (uint32_t)kLPI2C_SlaveReceiveEvent;
1995 
1996         /* Ack by default. */
1997         base->STAR = 0U;
1998 
1999         /* Clear all flags. */
2000         LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags);
2001 
2002         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2003         LPI2C_SlaveEnableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2004     }
2005 
2006     return result;
2007 }
2008 
2009 /*!
2010  * brief Gets the slave transfer status during a non-blocking transfer.
2011  * param base The LPI2C peripheral base address.
2012  * param handle Pointer to i2c_slave_handle_t structure.
2013  * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
2014  *      required.
2015  * retval #kStatus_Success
2016  * retval #kStatus_NoTransferInProgress
2017  */
LPI2C_SlaveTransferGetCount(LPI2C_Type * base,lpi2c_slave_handle_t * handle,size_t * count)2018 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
2019 {
2020     status_t status = kStatus_Success;
2021 
2022     assert(NULL != handle);
2023 
2024     if (count == NULL)
2025     {
2026         status = kStatus_InvalidArgument;
2027     }
2028 
2029     /* Catch when there is not an active transfer. */
2030     else if (!handle->isBusy)
2031     {
2032         *count = 0;
2033         status = kStatus_NoTransferInProgress;
2034     }
2035 
2036     /* For an active transfer, just return the count from the handle. */
2037     else
2038     {
2039         *count = handle->transferredCount;
2040     }
2041 
2042     return status;
2043 }
2044 
2045 /*!
2046  * brief Aborts the slave non-blocking transfers.
2047  * note This API could be called at any time to stop slave for handling the bus events.
2048  * param base The LPI2C peripheral base address.
2049  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2050  * retval #kStatus_Success
2051  * retval #kStatus_LPI2C_Idle
2052  */
LPI2C_SlaveTransferAbort(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2053 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2054 {
2055     assert(NULL != handle);
2056 
2057     /* Return idle if no transaction is in progress. */
2058     if (handle->isBusy)
2059     {
2060         /* Disable LPI2C IRQ sources. */
2061         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2062 
2063         /* Nack by default. */
2064         base->STAR = LPI2C_STAR_TXNACK_MASK;
2065 
2066         /* Reset transfer info. */
2067         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2068 
2069         /* We're no longer busy. */
2070         handle->isBusy = false;
2071     }
2072 }
2073 
2074 /*!
2075  * brief Reusable routine to handle slave interrupts.
2076  * note This function does not need to be called unless you are reimplementing the
2077  *  non blocking API's interrupt handler routines to add special functionality.
2078  * param base The LPI2C peripheral base address.
2079  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2080  */
LPI2C_SlaveTransferHandleIRQ(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2081 void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2082 {
2083     uint32_t flags;
2084     lpi2c_slave_transfer_t *xfer;
2085 
2086     /* Check for a valid handle in case of a spurious interrupt. */
2087     if (NULL != handle)
2088     {
2089         xfer = &handle->transfer;
2090 
2091         /* Get status flags. */
2092         flags = LPI2C_SlaveGetStatusFlags(base);
2093 
2094         if (0U != (flags & ((uint32_t)kLPI2C_SlaveBitErrFlag | (uint32_t)kLPI2C_SlaveFifoErrFlag)))
2095         {
2096             xfer->event            = kLPI2C_SlaveCompletionEvent;
2097             xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
2098 
2099             if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveCompletionEvent)) && (NULL != handle->callback))
2100             {
2101                 handle->callback(base, xfer, handle->userData);
2102             }
2103         }
2104         else
2105         {
2106             if (0U !=
2107                 (flags & (((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag) | ((uint32_t)kLPI2C_SlaveStopDetectFlag))))
2108             {
2109                 xfer->event = (0U != (flags & (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)) ?
2110                                   kLPI2C_SlaveRepeatedStartEvent :
2111                                   kLPI2C_SlaveCompletionEvent;
2112                 xfer->receivedAddress  = 0U;
2113                 xfer->completionStatus = kStatus_Success;
2114                 xfer->transferredCount = handle->transferredCount;
2115 
2116                 if (xfer->event == kLPI2C_SlaveCompletionEvent)
2117                 {
2118                     handle->isBusy = false;
2119                 }
2120 
2121                 if (handle->wasTransmit)
2122                 {
2123                     /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
2124                     /* tx flag before it sees the nack from the master-receiver, thus causing one more */
2125                     /* count that the master actually receives. */
2126                     --xfer->transferredCount;
2127                     handle->wasTransmit = false;
2128                 }
2129 
2130                 /* Clear the flag. */
2131                 LPI2C_SlaveClearStatusFlags(base, flags & ((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag |
2132                                                            (uint32_t)kLPI2C_SlaveStopDetectFlag));
2133 
2134                 /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
2135                 base->STAR = 0U;
2136 
2137                 if ((0U != (handle->eventMask & (uint32_t)xfer->event)) && (NULL != handle->callback))
2138                 {
2139                     handle->callback(base, xfer, handle->userData);
2140                 }
2141 
2142                 /* Clean up transfer info on completion, after the callback has been invoked. */
2143                 (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2144             }
2145             if (0U != (flags & (uint32_t)kLPI2C_SlaveAddressValidFlag))
2146             {
2147                 xfer->event           = kLPI2C_SlaveAddressMatchEvent;
2148                 xfer->receivedAddress = (uint8_t)(base->SASR & LPI2C_SASR_RADDR_MASK);
2149 
2150                 /* Update handle status to busy because slave is addressed. */
2151                 handle->isBusy = true;
2152                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
2153                 {
2154                     handle->callback(base, xfer, handle->userData);
2155                 }
2156             }
2157             if (0U != (flags & (uint32_t)kLPI2C_SlaveTransmitAckFlag))
2158             {
2159                 xfer->event = kLPI2C_SlaveTransmitAckEvent;
2160 
2161                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) && (NULL != handle->callback))
2162                 {
2163                     handle->callback(base, xfer, handle->userData);
2164                 }
2165             }
2166 
2167             /* Handle transmit and receive. */
2168             if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2169             {
2170                 handle->wasTransmit = true;
2171 
2172                 /* If we're out of data, invoke callback to get more. */
2173                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2174                 {
2175                     xfer->event = kLPI2C_SlaveTransmitEvent;
2176                     if (NULL != handle->callback)
2177                     {
2178                         handle->callback(base, xfer, handle->userData);
2179                     }
2180 
2181                     /* Clear the transferred count now that we have a new buffer. */
2182                     handle->transferredCount = 0U;
2183                 }
2184 
2185                 /* Transmit a byte. */
2186                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2187                 {
2188                     base->STDR = *xfer->data++;
2189                     --xfer->dataSize;
2190                     ++handle->transferredCount;
2191                 }
2192             }
2193             if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2194             {
2195                 /* If we're out of room in the buffer, invoke callback to get another. */
2196                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2197                 {
2198                     xfer->event = kLPI2C_SlaveReceiveEvent;
2199                     if (NULL != handle->callback)
2200                     {
2201                         handle->callback(base, xfer, handle->userData);
2202                     }
2203 
2204                     /* Clear the transferred count now that we have a new buffer. */
2205                     handle->transferredCount = 0U;
2206                 }
2207 
2208                 /* Receive a byte. */
2209                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2210                 {
2211                     *xfer->data++ = (uint8_t)base->SRDR;
2212                     --xfer->dataSize;
2213                     ++handle->transferredCount;
2214                 }
2215                 else
2216                 {
2217                     /* We don't have any room to receive more data, so send a nack. */
2218                     base->STAR = LPI2C_STAR_TXNACK_MASK;
2219                 }
2220             }
2221         }
2222     }
2223 }
2224 
2225 #if !(defined(FSL_FEATURE_I2C_HAS_NO_IRQ) && FSL_FEATURE_I2C_HAS_NO_IRQ)
2226 /*!
2227  * @brief Shared IRQ handler that can call both master and slave ISRs.
2228  *
2229  * The master and slave ISRs are called through function pointers in order to decouple
2230  * this code from the ISR functions. Without this, the linker would always pull in both
2231  * ISRs and every function they call, even if only the functional API was used.
2232  *
2233  * @param base The LPI2C peripheral base address.
2234  * @param instance The LPI2C peripheral instance number.
2235  */
LPI2C_CommonIRQHandler(LPI2C_Type * base,uint32_t instance)2236 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
2237 {
2238     /* Check for master IRQ. */
2239     if ((0U != (base->MCR & LPI2C_MCR_MEN_MASK)) && (NULL != s_lpi2cMasterIsr))
2240     {
2241         /* Master mode. */
2242         s_lpi2cMasterIsr(base, s_lpi2cMasterHandle[instance]);
2243     }
2244 
2245     /* Check for slave IRQ. */
2246     if ((0U != (base->SCR & LPI2C_SCR_SEN_MASK)) && (NULL != s_lpi2cSlaveIsr))
2247     {
2248         /* Slave mode. */
2249         s_lpi2cSlaveIsr(base, s_lpi2cSlaveHandle[instance]);
2250     }
2251     SDK_ISR_EXIT_BARRIER;
2252 }
2253 #endif
2254 
2255 #if defined(LPI2C0)
2256 /* Implementation of LPI2C0 handler named in startup code. */
2257 void LPI2C0_DriverIRQHandler(void);
LPI2C0_DriverIRQHandler(void)2258 void LPI2C0_DriverIRQHandler(void)
2259 {
2260     LPI2C_CommonIRQHandler(LPI2C0, 0U);
2261 }
2262 #endif
2263 
2264 #if defined(LPI2C1)
2265 /* Implementation of LPI2C1 handler named in startup code. */
2266 void LPI2C1_DriverIRQHandler(void);
LPI2C1_DriverIRQHandler(void)2267 void LPI2C1_DriverIRQHandler(void)
2268 {
2269     LPI2C_CommonIRQHandler(LPI2C1, 1U);
2270 }
2271 #endif
2272 
2273 #if defined(LPI2C2)
2274 /* Implementation of LPI2C2 handler named in startup code. */
2275 void LPI2C2_DriverIRQHandler(void);
LPI2C2_DriverIRQHandler(void)2276 void LPI2C2_DriverIRQHandler(void)
2277 {
2278     LPI2C_CommonIRQHandler(LPI2C2, 2U);
2279 }
2280 #endif
2281 
2282 #if defined(LPI2C3)
2283 /* Implementation of LPI2C3 handler named in startup code. */
2284 void LPI2C3_DriverIRQHandler(void);
LPI2C3_DriverIRQHandler(void)2285 void LPI2C3_DriverIRQHandler(void)
2286 {
2287     LPI2C_CommonIRQHandler(LPI2C3, 3U);
2288 }
2289 #endif
2290 
2291 #if defined(LPI2C4)
2292 /* Implementation of LPI2C4 handler named in startup code. */
2293 void LPI2C4_DriverIRQHandler(void);
LPI2C4_DriverIRQHandler(void)2294 void LPI2C4_DriverIRQHandler(void)
2295 {
2296     LPI2C_CommonIRQHandler(LPI2C4, 4U);
2297 }
2298 #endif
2299 
2300 #if defined(LPI2C5)
2301 /* Implementation of LPI2C5 handler named in startup code. */
2302 void LPI2C5_DriverIRQHandler(void);
LPI2C5_DriverIRQHandler(void)2303 void LPI2C5_DriverIRQHandler(void)
2304 {
2305     LPI2C_CommonIRQHandler(LPI2C5, 5U);
2306 }
2307 #endif
2308 
2309 #if defined(LPI2C6)
2310 /* Implementation of LPI2C6 handler named in startup code. */
2311 void LPI2C6_DriverIRQHandler(void);
LPI2C6_DriverIRQHandler(void)2312 void LPI2C6_DriverIRQHandler(void)
2313 {
2314     LPI2C_CommonIRQHandler(LPI2C6, 6U);
2315 }
2316 #endif
2317 
2318 #if defined(CM4_0__LPI2C)
2319 /* Implementation of CM4_0__LPI2C handler named in startup code. */
2320 void M4_0_LPI2C_DriverIRQHandler(void);
M4_0_LPI2C_DriverIRQHandler(void)2321 void M4_0_LPI2C_DriverIRQHandler(void)
2322 {
2323     LPI2C_CommonIRQHandler(CM4_0__LPI2C, LPI2C_GetInstance(CM4_0__LPI2C));
2324 }
2325 #endif
2326 
2327 #if defined(CM4__LPI2C)
2328 /* Implementation of CM4__LPI2C handler named in startup code. */
2329 void M4_LPI2C_DriverIRQHandler(void);
M4_LPI2C_DriverIRQHandler(void)2330 void M4_LPI2C_DriverIRQHandler(void)
2331 {
2332     LPI2C_CommonIRQHandler(CM4__LPI2C, LPI2C_GetInstance(CM4__LPI2C));
2333 }
2334 #endif
2335 
2336 #if defined(CM4_1__LPI2C)
2337 /* Implementation of CM4_1__LPI2C handler named in startup code. */
2338 void M4_1_LPI2C_DriverIRQHandler(void);
M4_1_LPI2C_DriverIRQHandler(void)2339 void M4_1_LPI2C_DriverIRQHandler(void)
2340 {
2341     LPI2C_CommonIRQHandler(CM4_1__LPI2C, LPI2C_GetInstance(CM4_1__LPI2C));
2342 }
2343 #endif
2344 
2345 #if defined(DMA__LPI2C0)
2346 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2347 void DMA_I2C0_INT_DriverIRQHandler(void);
DMA_I2C0_INT_DriverIRQHandler(void)2348 void DMA_I2C0_INT_DriverIRQHandler(void)
2349 {
2350     LPI2C_CommonIRQHandler(DMA__LPI2C0, LPI2C_GetInstance(DMA__LPI2C0));
2351 }
2352 #endif
2353 
2354 #if defined(DMA__LPI2C1)
2355 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2356 void DMA_I2C1_INT_DriverIRQHandler(void);
DMA_I2C1_INT_DriverIRQHandler(void)2357 void DMA_I2C1_INT_DriverIRQHandler(void)
2358 {
2359     LPI2C_CommonIRQHandler(DMA__LPI2C1, LPI2C_GetInstance(DMA__LPI2C1));
2360 }
2361 #endif
2362 
2363 #if defined(DMA__LPI2C2)
2364 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2365 void DMA_I2C2_INT_DriverIRQHandler(void);
DMA_I2C2_INT_DriverIRQHandler(void)2366 void DMA_I2C2_INT_DriverIRQHandler(void)
2367 {
2368     LPI2C_CommonIRQHandler(DMA__LPI2C2, LPI2C_GetInstance(DMA__LPI2C2));
2369 }
2370 #endif
2371 
2372 #if defined(DMA__LPI2C3)
2373 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2374 void DMA_I2C3_INT_DriverIRQHandler(void);
DMA_I2C3_INT_DriverIRQHandler(void)2375 void DMA_I2C3_INT_DriverIRQHandler(void)
2376 {
2377     LPI2C_CommonIRQHandler(DMA__LPI2C3, LPI2C_GetInstance(DMA__LPI2C3));
2378 }
2379 #endif
2380 
2381 #if defined(DMA__LPI2C4)
2382 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2383 void DMA_I2C4_INT_DriverIRQHandler(void);
DMA_I2C4_INT_DriverIRQHandler(void)2384 void DMA_I2C4_INT_DriverIRQHandler(void)
2385 {
2386     LPI2C_CommonIRQHandler(DMA__LPI2C4, LPI2C_GetInstance(DMA__LPI2C4));
2387 }
2388 #endif
2389 
2390 #if defined(ADMA__LPI2C0)
2391 /* Implementation of DMA__LPI2C0 handler named in startup code. */
2392 void ADMA_I2C0_INT_DriverIRQHandler(void);
ADMA_I2C0_INT_DriverIRQHandler(void)2393 void ADMA_I2C0_INT_DriverIRQHandler(void)
2394 {
2395     LPI2C_CommonIRQHandler(ADMA__LPI2C0, LPI2C_GetInstance(ADMA__LPI2C0));
2396 }
2397 #endif
2398 
2399 #if defined(ADMA__LPI2C1)
2400 /* Implementation of DMA__LPI2C1 handler named in startup code. */
2401 void ADMA_I2C1_INT_DriverIRQHandler(void);
ADMA_I2C1_INT_DriverIRQHandler(void)2402 void ADMA_I2C1_INT_DriverIRQHandler(void)
2403 {
2404     LPI2C_CommonIRQHandler(ADMA__LPI2C1, LPI2C_GetInstance(ADMA__LPI2C1));
2405 }
2406 #endif
2407 
2408 #if defined(ADMA__LPI2C2)
2409 /* Implementation of DMA__LPI2C2 handler named in startup code. */
2410 void ADMA_I2C2_INT_DriverIRQHandler(void);
ADMA_I2C2_INT_DriverIRQHandler(void)2411 void ADMA_I2C2_INT_DriverIRQHandler(void)
2412 {
2413     LPI2C_CommonIRQHandler(ADMA__LPI2C2, LPI2C_GetInstance(ADMA__LPI2C2));
2414 }
2415 #endif
2416 
2417 #if defined(ADMA__LPI2C3)
2418 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2419 void ADMA_I2C3_INT_DriverIRQHandler(void);
ADMA_I2C3_INT_DriverIRQHandler(void)2420 void ADMA_I2C3_INT_DriverIRQHandler(void)
2421 {
2422     LPI2C_CommonIRQHandler(ADMA__LPI2C3, LPI2C_GetInstance(ADMA__LPI2C3));
2423 }
2424 #endif
2425 
2426 #if defined(ADMA__LPI2C4)
2427 /* Implementation of DMA__LPI2C3 handler named in startup code. */
2428 void ADMA_I2C4_INT_DriverIRQHandler(void);
ADMA_I2C4_INT_DriverIRQHandler(void)2429 void ADMA_I2C4_INT_DriverIRQHandler(void)
2430 {
2431     LPI2C_CommonIRQHandler(ADMA__LPI2C4, LPI2C_GetInstance(ADMA__LPI2C4));
2432 }
2433 #endif
2434