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