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 (kLpi2cBases[instance] == 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     uint16_t commandBuffer[7];
932     uint32_t cmdCount = 0U;
933 
934     /* Check transfer data size in read operation. */
935     if ((transfer->direction == kLPI2C_Read) &&
936         (transfer->dataSize > (256UL * (uint32_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
937     {
938         return kStatus_InvalidArgument;
939     }
940 
941     /* Return an error if the bus is already in use not by us. */
942     result = LPI2C_CheckForBusyBus(base);
943     if (kStatus_Success == result)
944     {
945         /* Clear all flags. */
946         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
947 
948         /* Turn off auto-stop option. */
949         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
950 
951         lpi2c_direction_t direction = (0U != transfer->subaddressSize) ? kLPI2C_Write : transfer->direction;
952         if (0U == (transfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
953         {
954             commandBuffer[cmdCount++] =
955                 (uint16_t)kStartCmd |
956                 (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)direction);
957         }
958 
959         /* Subaddress, MSB first. */
960         if (0U != transfer->subaddressSize)
961         {
962             uint32_t subaddressRemaining = transfer->subaddressSize;
963             while (0U != subaddressRemaining--)
964             {
965                 uint8_t subaddressByte    = (uint8_t)((transfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
966                 commandBuffer[cmdCount++] = subaddressByte;
967             }
968         }
969 
970         /* Reads need special handling. */
971         if ((0U != transfer->dataSize) && (transfer->direction == kLPI2C_Read))
972         {
973             /* Need to send repeated start if switching directions to read. */
974             if (direction == kLPI2C_Write)
975             {
976                 commandBuffer[cmdCount++] =
977                     (uint16_t)kStartCmd |
978                     (uint16_t)((uint16_t)((uint16_t)transfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
979             }
980         }
981 
982         /* Send command buffer */
983         uint32_t index = 0U;
984         while (0U != cmdCount--)
985         {
986             /* Wait until there is room in the fifo. This also checks for errors. */
987             result = LPI2C_MasterWaitForTxReady(base);
988             if (kStatus_Success != result)
989             {
990                 break;
991             }
992 
993             /* Write byte into LPI2C master data register. */
994             base->MTDR = commandBuffer[index];
995             index++;
996         }
997 
998         if (kStatus_Success == result)
999         {
1000             /* Transmit data. */
1001             if ((transfer->direction == kLPI2C_Write) && (transfer->dataSize > 0U))
1002             {
1003                 /* Send Data. */
1004                 result = LPI2C_MasterSend(base, transfer->data, transfer->dataSize);
1005             }
1006 
1007             /* Receive Data. */
1008             if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > 0U))
1009             {
1010                 result = LPI2C_MasterReceive(base, transfer->data, transfer->dataSize);
1011             }
1012 
1013             if (kStatus_Success == result)
1014             {
1015                 if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1016                 {
1017                     result = LPI2C_MasterStop(base);
1018                 }
1019             }
1020         }
1021 
1022         /* Transmit fail */
1023         if (kStatus_Success != result)
1024         {
1025             if ((transfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1026             {
1027                 (void)LPI2C_MasterStop(base);
1028             }
1029         }
1030     }
1031 
1032     return result;
1033 }
1034 
1035 /*!
1036  * brief Creates a new handle for the LPI2C master non-blocking APIs.
1037  *
1038  * The creation of a handle is for use with the non-blocking APIs. Once a handle
1039  * is created, there is not a corresponding destroy handle. If the user wants to
1040  * terminate a transfer, the LPI2C_MasterTransferAbort() API shall be called.
1041  *
1042  *
1043  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
1044  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
1045  * enable the associated INTMUX IRQ in application.
1046  *
1047  * param base The LPI2C peripheral base address.
1048  * param[out] handle Pointer to the LPI2C master driver handle.
1049  * param callback User provided pointer to the asynchronous callback function.
1050  * param userData User provided pointer to the application callback data.
1051  */
LPI2C_MasterTransferCreateHandle(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_callback_t callback,void * userData)1052 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
1053                                       lpi2c_master_handle_t *handle,
1054                                       lpi2c_master_transfer_callback_t callback,
1055                                       void *userData)
1056 {
1057     uint32_t instance;
1058 
1059     assert(NULL != handle);
1060 
1061     /* Clear out the handle. */
1062     (void)memset(handle, 0, sizeof(*handle));
1063 
1064     /* Look up instance number */
1065     instance = LPI2C_GetInstance(base);
1066 
1067     /* Save base and instance. */
1068     handle->completionCallback = callback;
1069     handle->userData           = userData;
1070 
1071     if(LP_FLEXCOMM_GetBaseAddress(instance) != 0U)
1072     {
1073         lpi2c_to_lpflexcomm_t handler;
1074         (void)memset(&handler, 0, sizeof(handler));
1075 
1076         /* Save the handle in global variables to support the double weak mechanism. */
1077         handler.lpi2c_master_handler = LPI2C_MasterTransferHandleIRQ;
1078         LP_FLEXCOMM_SetIRQHandler(LPI2C_GetInstance(base), handler.lpflexcomm_handler, handle, LP_FLEXCOMM_PERIPH_LPI2C);
1079     }
1080     else
1081     {
1082          /* Save this handle for IRQ use. */
1083         s_lpi2cMasterHandle[instance] = handle;
1084 
1085         /* Set irq handler. */
1086         s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
1087     }
1088 
1089     /* Clear internal IRQ enables and enable NVIC IRQ. */
1090     LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1091 
1092     /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1093      In some cases the LPI2C IRQ is configured through INTMUX, user needs to enable
1094      INTMUX IRQ in application code. */
1095     (void)EnableIRQ(kLpi2cIrqs[instance]);
1096 }
1097 
1098 /*!
1099  * @brief Execute states until FIFOs are exhausted.
1100  * @param handle Master nonblocking driver handle.
1101  * @param[out] isDone Set to true if the transfer has completed.
1102  * @retval #kStatus_Success
1103  * @retval #kStatus_LPI2C_PinLowTimeout
1104  * @retval #kStatus_LPI2C_ArbitrationLost
1105  * @retval #kStatus_LPI2C_Nak
1106  * @retval #kStatus_LPI2C_FifoError
1107  */
LPI2C_RunTransferStateMachine(LPI2C_Type * base,lpi2c_master_handle_t * handle,bool * isDone)1108 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
1109 {
1110     uint32_t status;
1111     status_t result = kStatus_Success;
1112     lpi2c_master_transfer_t *xfer;
1113     size_t txCount;
1114     size_t rxCount;
1115     size_t txFifoSize   = (size_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
1116     bool state_complete = false;
1117     uint16_t sendval;
1118 
1119     /* Set default isDone return value. */
1120     *isDone = false;
1121 
1122     /* Check for errors. */
1123     status = LPI2C_MasterGetStatusFlags(base);
1124 
1125     /* Get fifo counts. */
1126     LPI2C_MasterGetFifoCounts(base, &rxCount, &txCount);
1127 
1128     /* Get pointer to private data. */
1129     xfer = &handle->transfer;
1130 
1131     /* For the last byte, nack flag is expected.
1132        Do not check and clear kLPI2C_MasterNackDetectFlag for the last byte,
1133        in case FIFO is emptied when stop command has not been sent. */
1134     if (handle->remainingBytes == 0U)
1135     {
1136         /* When data size is not zero which means it is not only one byte of address is sent, and */
1137         /* when the txfifo is empty, or have one byte which is the stop command, then the nack status can be ignored. */
1138         if ((xfer->dataSize != 0U) &&
1139             ((txCount == 0U) || ((txCount == 1U) && (handle->state == (uint8_t)kWaitForCompletionState) &&
1140                                  ((xfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U))))
1141         {
1142             status &= ~(uint32_t)kLPI2C_MasterNackDetectFlag;
1143         }
1144     }
1145 
1146     result = LPI2C_MasterCheckAndClearError(base, status);
1147 
1148     if (kStatus_Success == result)
1149     {
1150         /* Compute room in tx fifo */
1151         txCount = txFifoSize - txCount;
1152 
1153         while (!state_complete)
1154         {
1155             /* Execute the state. */
1156             switch (handle->state)
1157             {
1158                 case (uint8_t)kSendCommandState:
1159                     /* Make sure there is room in the tx fifo for the next command. */
1160                     if (0U == txCount--)
1161                     {
1162                         state_complete = true;
1163                         break;
1164                     }
1165 
1166                     /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
1167                     sendval    = ((uint16_t)handle->buf[0]) | (((uint16_t)handle->buf[1]) << 8U);
1168                     base->MTDR = sendval;
1169                     handle->buf++;
1170                     handle->buf++;
1171 
1172                     /* Count down until all commands are sent. */
1173                     if (--handle->remainingBytes == 0U)
1174                     {
1175                         /* Choose next state and set up buffer pointer and count. */
1176                         if (0U != xfer->dataSize)
1177                         {
1178                             /* Either a send or receive transfer is next. */
1179                             handle->state          = (uint8_t)kTransferDataState;
1180                             handle->buf            = (uint8_t *)xfer->data;
1181                             handle->remainingBytes = (uint16_t)xfer->dataSize;
1182                             if (xfer->direction == kLPI2C_Read)
1183                             {
1184                                 /* Disable TX interrupt */
1185                                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1186                                 /* Issue command to receive data. A single write to MTDR can issue read operation of
1187                                    0xFFU + 1 byte of data at most, so when the dataSize is larger than 0x100U, push
1188                                    multiple read commands to MTDR until dataSize is reached. */
1189                                 size_t tmpRxSize = xfer->dataSize;
1190                                 while (tmpRxSize != 0U)
1191                                 {
1192                                     LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
1193                                     while (txFifoSize == txCount)
1194                                     {
1195                                         LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
1196                                     }
1197 
1198                                     if (tmpRxSize > 256U)
1199                                     {
1200                                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(0xFFU);
1201                                         tmpRxSize -= 256U;
1202                                     }
1203                                     else
1204                                     {
1205                                         base->MTDR = (uint32_t)(kRxDataCmd) | (uint32_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
1206                                         tmpRxSize  = 0U;
1207                                     }
1208                                 }
1209                             }
1210                         }
1211                         else
1212                         {
1213                             /* No transfer, so move to stop state. */
1214                             handle->state = (uint8_t)kStopState;
1215                         }
1216                     }
1217                     break;
1218 
1219                 case (uint8_t)kIssueReadCommandState:
1220                     /* Make sure there is room in the tx fifo for the read command. */
1221                     if (0U == txCount--)
1222                     {
1223                         state_complete = true;
1224                         break;
1225                     }
1226 
1227                     base->MTDR = (uint32_t)kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1U);
1228 
1229                     /* Move to transfer state. */
1230                     handle->state = (uint8_t)kTransferDataState;
1231                     if (xfer->direction == kLPI2C_Read)
1232                     {
1233                         /* Disable TX interrupt */
1234                         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterTxReadyFlag);
1235                     }
1236                     break;
1237 
1238                 case (uint8_t)kTransferDataState:
1239                     if (xfer->direction == kLPI2C_Write)
1240                     {
1241                         /* Make sure there is room in the tx fifo. */
1242                         if (0U == txCount--)
1243                         {
1244                             state_complete = true;
1245                             break;
1246                         }
1247 
1248                         /* Put byte to send in fifo. */
1249                         base->MTDR = *(handle->buf)++;
1250                     }
1251                     else
1252                     {
1253                         /* XXX handle receive sizes > 256, use kIssueReadCommandState */
1254                         /* Make sure there is data in the rx fifo. */
1255                         if (0U == rxCount--)
1256                         {
1257                             state_complete = true;
1258                             break;
1259                         }
1260 
1261                         /* Read byte from fifo. */
1262                         *(handle->buf)++ = (uint8_t)(base->MRDR & LPI2C_MRDR_DATA_MASK);
1263                     }
1264 
1265                     /* Move to stop when the transfer is done. */
1266                     if (--handle->remainingBytes == 0U)
1267                     {
1268                         if (xfer->direction == kLPI2C_Write)
1269                         {
1270                             state_complete = true;
1271                         }
1272                         handle->state = (uint8_t)kStopState;
1273                     }
1274                     break;
1275 
1276                 case (uint8_t)kStopState:
1277                     /* Only issue a stop transition if the caller requested it. */
1278                     if ((xfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1279                     {
1280                         /* Make sure there is room in the tx fifo for the stop command. */
1281                         if (0U == txCount--)
1282                         {
1283                             state_complete = true;
1284                             break;
1285                         }
1286 
1287                         base->MTDR = (uint32_t)kStopCmd;
1288                     }
1289                     else
1290                     {
1291                         /* If all data is read and no stop flag is required to send, we are done. */
1292                         if (xfer->direction == kLPI2C_Read)
1293                         {
1294                             *isDone = true;
1295                         }
1296                         state_complete = true;
1297                     }
1298                     handle->state = (uint8_t)kWaitForCompletionState;
1299                     break;
1300 
1301                 case (uint8_t)kWaitForCompletionState:
1302                     if ((xfer->flags & (uint32_t)kLPI2C_TransferNoStopFlag) == 0U)
1303                     {
1304                         /* We stay in this state until the stop state is detected. */
1305                         if (0U != (status & (uint32_t)kLPI2C_MasterStopDetectFlag))
1306                         {
1307                             *isDone = true;
1308                         }
1309                     }
1310                     else
1311                     {
1312                         /* If all data is pushed to FIFO and no stop flag is required to send, we need to make sure they
1313                            are all send out to bus. */
1314                         if ((xfer->direction == kLPI2C_Write) && ((base->MFSR & LPI2C_MFSR_TXCOUNT_MASK) == 0U))
1315                         {
1316                             /* We stay in this state until the data is sent out to bus. */
1317                             *isDone = true;
1318                         }
1319                     }
1320                     state_complete = true;
1321                     break;
1322                 default:
1323                     assert(false);
1324                     break;
1325             }
1326         }
1327     }
1328     return result;
1329 }
1330 
1331 /*!
1332  * @brief Prepares the transfer state machine and fills in the command buffer.
1333  * @param handle Master nonblocking driver handle.
1334  */
LPI2C_InitTransferStateMachine(lpi2c_master_handle_t * handle)1335 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
1336 {
1337     lpi2c_master_transfer_t *xfer = &handle->transfer;
1338 
1339     /* Handle no start option. */
1340     if (0U != (xfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag))
1341     {
1342         if (xfer->direction == kLPI2C_Read)
1343         {
1344             /* Need to issue read command first. */
1345             handle->state = (uint8_t)kIssueReadCommandState;
1346         }
1347         else
1348         {
1349             /* Start immediately in the data transfer state. */
1350             handle->state = (uint8_t)kTransferDataState;
1351         }
1352 
1353         handle->buf            = (uint8_t *)xfer->data;
1354         handle->remainingBytes = (uint16_t)xfer->dataSize;
1355     }
1356     else
1357     {
1358         uint16_t *cmd     = (uint16_t *)&handle->commandBuffer;
1359         uint32_t cmdCount = 0U;
1360 
1361         /* Initial direction depends on whether a subaddress was provided, and of course the actual */
1362         /* data transfer direction. */
1363         lpi2c_direction_t direction = (0U != xfer->subaddressSize) ? kLPI2C_Write : xfer->direction;
1364 
1365         /* Start command. */
1366         cmd[cmdCount++] =
1367             (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
1368 
1369         /* Subaddress, MSB first. */
1370         if (0U != xfer->subaddressSize)
1371         {
1372             uint32_t subaddressRemaining = xfer->subaddressSize;
1373             while (0U != (subaddressRemaining--))
1374             {
1375                 uint8_t subaddressByte = (uint8_t)((xfer->subaddress >> (8U * subaddressRemaining)) & 0xffU);
1376                 cmd[cmdCount++]        = subaddressByte;
1377             }
1378         }
1379 
1380         /* Reads need special handling. */
1381         if ((0U != xfer->dataSize) && (xfer->direction == kLPI2C_Read))
1382         {
1383             /* Need to send repeated start if switching directions to read. */
1384             if (direction == kLPI2C_Write)
1385             {
1386                 cmd[cmdCount++] = (uint16_t)kStartCmd |
1387                                   (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
1388             }
1389         }
1390 
1391         /* Set up state machine for transferring the commands. */
1392         handle->state          = (uint8_t)kSendCommandState;
1393         handle->remainingBytes = (uint16_t)cmdCount;
1394         handle->buf            = (uint8_t *)&handle->commandBuffer;
1395     }
1396 }
1397 
1398 /*!
1399  * brief Performs a non-blocking transaction on the I2C bus.
1400  *
1401  * param base The LPI2C peripheral base address.
1402  * param handle Pointer to the LPI2C master driver handle.
1403  * param transfer The pointer to the transfer descriptor.
1404  * retval #kStatus_Success The transaction was started successfully.
1405  * retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or a non-blocking
1406  *      transaction is already in progress.
1407  */
LPI2C_MasterTransferNonBlocking(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_t * transfer)1408 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
1409                                          lpi2c_master_handle_t *handle,
1410                                          lpi2c_master_transfer_t *transfer)
1411 {
1412     assert(NULL != handle);
1413     assert(NULL != transfer);
1414     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1415 
1416     status_t result;
1417 
1418     /* Check transfer data size in read operation. */
1419     if ((transfer->direction == kLPI2C_Read) &&
1420         (transfer->dataSize > (256U * (uint32_t)FSL_FEATURE_LPI2C_FIFO_SIZEn(base))))
1421     {
1422         return kStatus_InvalidArgument;
1423     }
1424 
1425     /* Return busy if another transaction is in progress. */
1426     if (handle->state != (uint8_t)kIdleState)
1427     {
1428         result = kStatus_LPI2C_Busy;
1429     }
1430     else
1431     {
1432         result = LPI2C_CheckForBusyBus(base);
1433     }
1434 
1435     if ((status_t)kStatus_Success == result)
1436     {
1437         /* Disable LPI2C IRQ sources while we configure stuff. */
1438         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1439 
1440         /* Reset FIFO in case there are data. */
1441         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1442 
1443         /* Save transfer into handle. */
1444         handle->transfer = *transfer;
1445 
1446         /* Generate commands to send. */
1447         LPI2C_InitTransferStateMachine(handle);
1448 
1449         /* Clear all flags. */
1450         LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
1451 
1452         /* Turn off auto-stop option. */
1453         base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
1454 
1455         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1456         LPI2C_MasterEnableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1457     }
1458 
1459     return result;
1460 }
1461 
1462 /*!
1463  * brief Returns number of bytes transferred so far.
1464  * param base The LPI2C peripheral base address.
1465  * param handle Pointer to the LPI2C master driver handle.
1466  * param[out] count Number of bytes transferred so far by the non-blocking transaction.
1467  * retval #kStatus_Success
1468  * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1469  */
LPI2C_MasterTransferGetCount(LPI2C_Type * base,lpi2c_master_handle_t * handle,size_t * count)1470 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
1471 {
1472     status_t result = kStatus_Success;
1473 
1474     assert(NULL != handle);
1475 
1476     if (NULL == count)
1477     {
1478         result = kStatus_InvalidArgument;
1479     }
1480 
1481     /* Catch when there is not an active transfer. */
1482     else if (handle->state == (uint8_t)kIdleState)
1483     {
1484         *count = 0;
1485         result = kStatus_NoTransferInProgress;
1486     }
1487     else
1488     {
1489         uint8_t state;
1490         uint16_t remainingBytes;
1491         uint32_t dataSize;
1492 
1493         /* Cache some fields with IRQs disabled. This ensures all field values */
1494         /* are synchronized with each other during an ongoing transfer. */
1495         uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
1496         LPI2C_MasterDisableInterrupts(base, irqs);
1497         state          = handle->state;
1498         remainingBytes = handle->remainingBytes;
1499         dataSize       = handle->transfer.dataSize;
1500         LPI2C_MasterEnableInterrupts(base, irqs);
1501 
1502         /* Get transfer count based on current transfer state. */
1503         switch (state)
1504         {
1505             case (uint8_t)kIdleState:
1506             case (uint8_t)kSendCommandState:
1507             case (uint8_t)
1508                 kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1509                 *count = 0;
1510                 break;
1511 
1512             case (uint8_t)kTransferDataState:
1513                 *count = dataSize - remainingBytes;
1514                 break;
1515 
1516             case (uint8_t)kStopState:
1517             case (uint8_t)kWaitForCompletionState:
1518             default:
1519                 *count = dataSize;
1520                 break;
1521         }
1522     }
1523 
1524     return result;
1525 }
1526 
1527 /*!
1528  * brief Terminates a non-blocking LPI2C master transmission early.
1529  *
1530  * note It is not safe to call this function from an IRQ handler that has a higher priority than the
1531  *      LPI2C peripheral's IRQ priority.
1532  *
1533  * param base The LPI2C peripheral base address.
1534  * param handle Pointer to the LPI2C master driver handle.
1535  * retval #kStatus_Success A transaction was successfully aborted.
1536  * retval #kStatus_LPI2C_Idle There is not a non-blocking transaction currently in progress.
1537  */
LPI2C_MasterTransferAbort(LPI2C_Type * base,lpi2c_master_handle_t * handle)1538 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1539 {
1540     if (handle->state != (uint8_t)kIdleState)
1541     {
1542         /* Disable internal IRQ enables. */
1543         LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1544 
1545         /* Reset fifos. */
1546         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1547 
1548         /* If master is still busy and has not send out stop signal yet. */
1549         if ((LPI2C_MasterGetStatusFlags(base) & ((uint32_t)kLPI2C_MasterStopDetectFlag |
1550                                                  (uint32_t)kLPI2C_MasterBusyFlag)) == (uint32_t)kLPI2C_MasterBusyFlag)
1551         {
1552             /* Send a stop command to finalize the transfer. */
1553             base->MTDR = (uint32_t)kStopCmd;
1554         }
1555 
1556         /* Reset handle. */
1557         handle->state = (uint8_t)kIdleState;
1558     }
1559 }
1560 
1561 /*!
1562  * brief Reusable routine to handle master interrupts.
1563  * note This function does not need to be called unless you are reimplementing the
1564  *  nonblocking API's interrupt handler routines to add special functionality.
1565  * param instance The LPI2C instance.
1566  * param lpi2cMasterHandle Pointer to the LPI2C master driver handle.
1567  */
LPI2C_MasterTransferHandleIRQ(uint32_t instance,void * lpi2cMasterHandle)1568 void LPI2C_MasterTransferHandleIRQ(uint32_t instance, void *lpi2cMasterHandle)
1569 {
1570     assert(lpi2cMasterHandle != NULL);
1571     assert(instance < ARRAY_SIZE(kLpi2cBases));
1572     LPI2C_Type *base              = kLpi2cBases[instance];
1573     lpi2c_master_handle_t *handle = (lpi2c_master_handle_t *)lpi2cMasterHandle;
1574     bool isDone                   = false;
1575     status_t result;
1576 
1577     /* Don't do anything if we don't have a valid handle. */
1578     if (NULL != handle)
1579     {
1580         if (handle->state != (uint8_t)kIdleState)
1581         {
1582             result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1583 
1584             if ((result != kStatus_Success) || isDone)
1585             {
1586                 /* Handle error, terminate xfer */
1587                 if (result != kStatus_Success)
1588                 {
1589                     LPI2C_MasterTransferAbort(base, handle);
1590                 }
1591 
1592                 /* Disable internal IRQ enables. */
1593                 LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
1594 
1595                 /* Set handle to idle state. */
1596                 handle->state = (uint8_t)kIdleState;
1597 
1598                 /* Invoke callback. */
1599                 if (NULL != handle->completionCallback)
1600                 {
1601                     handle->completionCallback(base, handle, result, handle->userData);
1602                 }
1603             }
1604         }
1605     }
1606 }
1607 
1608 /*!
1609  * brief Provides a default configuration for the LPI2C slave peripheral.
1610  *
1611  * This function provides the following default configuration for the LPI2C slave peripheral:
1612  * code
1613  *  slaveConfig->enableSlave               = true;
1614  *  slaveConfig->address0                  = 0U;
1615  *  slaveConfig->address1                  = 0U;
1616  *  slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1617  *  slaveConfig->filterDozeEnable          = true;
1618  *  slaveConfig->filterEnable              = true;
1619  *  slaveConfig->enableGeneralCall         = false;
1620  *  slaveConfig->sclStall.enableAck        = false;
1621  *  slaveConfig->sclStall.enableTx         = true;
1622  *  slaveConfig->sclStall.enableRx         = true;
1623  *  slaveConfig->sclStall.enableAddress    = true;
1624  *  slaveConfig->ignoreAck                 = false;
1625  *  slaveConfig->enableReceivedAddressRead = false;
1626  *  slaveConfig->sdaGlitchFilterWidth_ns   = 0;
1627  *  slaveConfig->sclGlitchFilterWidth_ns   = 0;
1628  *  slaveConfig->dataValidDelay_ns         = 0;
1629  *  slaveConfig->clockHoldTime_ns          = 0;
1630  * endcode
1631  *
1632  * After calling this function, override any settings  to customize the configuration,
1633  * prior to initializing the master driver with LPI2C_SlaveInit(). Be sure to override at least the a
1634  * address0 member of the configuration structure with the desired slave address.
1635  *
1636  * param[out] slaveConfig User provided configuration structure that is set to default values. Refer to
1637  *      #lpi2c_slave_config_t.
1638  */
LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t * slaveConfig)1639 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1640 {
1641     /* Initializes the configure structure to zero. */
1642     (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
1643 
1644     slaveConfig->enableSlave               = true;
1645     slaveConfig->address0                  = 0U;
1646     slaveConfig->address1                  = 0U;
1647     slaveConfig->addressMatchMode          = kLPI2C_MatchAddress0;
1648     slaveConfig->filterDozeEnable          = true;
1649     slaveConfig->filterEnable              = true;
1650     slaveConfig->enableGeneralCall         = false;
1651     slaveConfig->sclStall.enableAck        = false;
1652     slaveConfig->sclStall.enableTx         = true;
1653     slaveConfig->sclStall.enableRx         = true;
1654     slaveConfig->sclStall.enableAddress    = false;
1655     slaveConfig->ignoreAck                 = false;
1656     slaveConfig->enableReceivedAddressRead = false;
1657     slaveConfig->sdaGlitchFilterWidth_ns   = 0U; /* Set to 0 to disable the function */
1658     slaveConfig->sclGlitchFilterWidth_ns   = 0U; /* Set to 0 to disable the function */
1659     slaveConfig->dataValidDelay_ns         = 0U;
1660     /* When enabling the slave tx SCL stall, set the default clock hold time to 250ns according
1661        to I2C spec for standard mode baudrate(100k). User can manually change it to 100ns or 50ns
1662        for fast-mode(400k) or fast-mode+(1m). */
1663     slaveConfig->clockHoldTime_ns = 250U;
1664 }
1665 
1666 /*!
1667  * brief Initializes the LPI2C slave peripheral.
1668  *
1669  * This function enables the peripheral clock and initializes the LPI2C slave peripheral as described by the user
1670  * provided configuration.
1671  *
1672  * param base The LPI2C peripheral base address.
1673  * param slaveConfig User provided peripheral configuration. Use LPI2C_SlaveGetDefaultConfig() to get a set of defaults
1674  *      that you can override.
1675  * param sourceClock_Hz Frequency in Hertz of the LPI2C functional clock. Used to calculate the filter widths,
1676  *      data valid delay, and clock hold time.
1677  */
LPI2C_SlaveInit(LPI2C_Type * base,const lpi2c_slave_config_t * slaveConfig,uint32_t sourceClock_Hz)1678 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1679 {
1680     uint32_t tmpReg;
1681     uint32_t tmpCycle;
1682     uint32_t instance = LPI2C_GetInstance(base);
1683 
1684     if(LP_FLEXCOMM_GetBaseAddress(instance) != 0U)
1685     {
1686 
1687 #if !(defined(LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER) && LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER)
1688         /* initialize flexcomm to LPI2C mode */
1689         status_t status = LP_FLEXCOMM_Init(instance, LP_FLEXCOMM_PERIPH_LPI2C);
1690         if (kStatus_Success != status)
1691         {
1692             assert(false);
1693         }
1694 #endif /* LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER */
1695 
1696     }
1697     else
1698     {
1699 
1700 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1701         /* Ungate the clock. */
1702         (void)CLOCK_EnableClock(kLpi2cClocks[instance]);
1703 #if defined(LPI2C_PERIPH_CLOCKS)
1704         /* Ungate the functional clock in initialize function. */
1705         CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1706 #endif
1707 
1708 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1709 
1710     }
1711 
1712     /* Restore to reset conditions. */
1713     LPI2C_SlaveReset(base);
1714 
1715     /* Configure peripheral. */
1716     base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1717 
1718     base->SCFGR1 =
1719         LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1720         LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1721         LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1722         LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1723         LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1724 
1725     /* Calculate SDA filter width. The width is equal to FILTSDA+3 cycles of functional clock.
1726        And set FILTSDA to 0 disables the fileter, so the min value is 4. */
1727     tmpReg = LPI2C_SCFGR2_FILTSDA(
1728         LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns, 4U,
1729                                 (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT) + 3U, 0U) -
1730         3U);
1731 
1732     /* Calculate SDL filter width. The width is equal to FILTSCL+3 cycles of functional clock.
1733        And set FILTSCL to 0 disables the fileter, so the min value is 4. */
1734     tmpCycle = LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns, 4U,
1735                                        (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT) + 3U, 0U);
1736     tmpReg |= LPI2C_SCFGR2_FILTSCL(tmpCycle - 3U);
1737 
1738     /* Calculate data valid time. The time is equal to FILTSCL+DATAVD+3 cycles of functional clock.
1739        So the min value is FILTSCL+3. */
1740     tmpReg |= LPI2C_SCFGR2_DATAVD(
1741         LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->dataValidDelay_ns, tmpCycle,
1742                                 tmpCycle + (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 0U) -
1743         tmpCycle);
1744 
1745     /* Calculate clock hold time. The time is equal to CLKHOLD+3 cycles of functional clock.
1746        So the min value is 3. */
1747     base->SCFGR2 =
1748         tmpReg | LPI2C_SCFGR2_CLKHOLD(
1749                      LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->clockHoldTime_ns, 3U,
1750                                              (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT) + 3U, 0U) -
1751                      3U);
1752 
1753     /* Save SCR to last so we don't enable slave until it is configured */
1754     base->SCR = LPI2C_SCR_FILTDZ(!slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1755                 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1756 }
1757 
1758 /*!
1759  * brief Deinitializes the LPI2C slave peripheral.
1760  *
1761  * This function disables the LPI2C slave peripheral and gates the clock. It also performs a software
1762  * reset to restore the peripheral to reset conditions.
1763  *
1764  * param base The LPI2C peripheral base address.
1765  */
LPI2C_SlaveDeinit(LPI2C_Type * base)1766 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1767 {
1768     uint32_t instance = LPI2C_GetInstance(base);
1769 
1770     /* Restore to reset state. */
1771     LPI2C_SlaveReset(base);
1772     if(LP_FLEXCOMM_GetBaseAddress(instance) != 0U)
1773     {
1774 #if !(defined(LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER) && LPFLEXCOMM_INIT_NOT_USED_IN_DRIVER)
1775         LP_FLEXCOMM_Deinit(instance);
1776 #endif
1777     }
1778     else
1779     {
1780 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1781         /* Gate clock. */
1782         (void)CLOCK_DisableClock(kLpi2cClocks[instance]);
1783 #if defined(LPI2C_PERIPH_CLOCKS)
1784         /* Gate the functional clock. */
1785         CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1786 #endif
1787 
1788 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1789     }
1790 }
1791 
1792 /*!
1793  * @brief Convert provided flags to status code, and clear any errors if present.
1794  * @param base The LPI2C peripheral base address.
1795  * @param status Current status flags value that will be checked.
1796  * @retval #kStatus_Success
1797  * @retval #kStatus_LPI2C_BitError
1798  * @retval #kStatus_LPI2C_FifoError
1799  */
LPI2C_SlaveCheckAndClearError(LPI2C_Type * base,uint32_t flags)1800 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1801 {
1802     status_t result = kStatus_Success;
1803 
1804     flags &= (uint32_t)kLPI2C_SlaveErrorFlags;
1805     if (0U != flags)
1806     {
1807         if (0U != (flags & (uint32_t)kLPI2C_SlaveBitErrFlag))
1808         {
1809             result = kStatus_LPI2C_BitError;
1810         }
1811         else if (0U != (flags & (uint32_t)kLPI2C_SlaveFifoErrFlag))
1812         {
1813             result = kStatus_LPI2C_FifoError;
1814         }
1815         else
1816         {
1817             ; /* Intentional empty */
1818         }
1819 
1820         /* Clear the errors. */
1821         LPI2C_SlaveClearStatusFlags(base, flags);
1822     }
1823     else
1824     {
1825         ; /* Intentional empty */
1826     }
1827 
1828     return result;
1829 }
1830 
1831 /*!
1832  * brief Performs a polling send transfer on the I2C bus.
1833  *
1834  * param base  The LPI2C peripheral base address.
1835  * param txBuff The pointer to the data to be transferred.
1836  * param txSize The length in bytes of the data to be transferred.
1837  * param[out] actualTxSize
1838  * return Error or success status returned by API.
1839  */
LPI2C_SlaveSend(LPI2C_Type * base,void * txBuff,size_t txSize,size_t * actualTxSize)1840 status_t LPI2C_SlaveSend(LPI2C_Type *base, void *txBuff, size_t txSize, size_t *actualTxSize)
1841 {
1842     status_t result  = kStatus_Success;
1843     uint8_t *buf     = (uint8_t *)txBuff;
1844     size_t remaining = txSize;
1845 
1846     assert(NULL != txBuff);
1847 
1848 #if I2C_RETRY_TIMES != 0U
1849     uint32_t waitTimes = I2C_RETRY_TIMES;
1850 #endif
1851 
1852     /* Clear stop flag. */
1853     LPI2C_SlaveClearStatusFlags(base,
1854                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1855 
1856     while (0U != remaining)
1857     {
1858         uint32_t flags;
1859 
1860         /* Wait until we can transmit. */
1861         do
1862         {
1863             /* Check for errors */
1864             flags  = LPI2C_SlaveGetStatusFlags(base);
1865             result = LPI2C_SlaveCheckAndClearError(base, flags);
1866             if (kStatus_Success != result)
1867             {
1868                 if (NULL != actualTxSize)
1869                 {
1870                     *actualTxSize = txSize - remaining;
1871                 }
1872                 break;
1873             }
1874 #if I2C_RETRY_TIMES != 0U
1875             waitTimes--;
1876         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1877                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1878                  (0U != waitTimes));
1879         if (0U == waitTimes)
1880         {
1881             result = kStatus_LPI2C_Timeout;
1882         }
1883 #else
1884         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveTxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1885                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
1886 #endif
1887 
1888         if (kStatus_Success != result)
1889         {
1890             break;
1891         }
1892 
1893         /* Send a byte. */
1894         if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
1895         {
1896             base->STDR = *buf++;
1897             --remaining;
1898         }
1899 
1900         /* Exit loop if we see a stop or restart in transfer*/
1901         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1902             (remaining != 0U))
1903         {
1904             LPI2C_SlaveClearStatusFlags(
1905                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1906             break;
1907         }
1908     }
1909 
1910     if (NULL != actualTxSize)
1911     {
1912         *actualTxSize = txSize - remaining;
1913     }
1914 
1915     return result;
1916 }
1917 
1918 /*!
1919  * brief Performs a polling receive transfer on the I2C bus.
1920  *
1921  * param base  The LPI2C peripheral base address.
1922  * param rxBuff The pointer to the data to be transferred.
1923  * param rxSize The length in bytes of the data to be transferred.
1924  * param[out] actualRxSize
1925  * return Error or success status returned by API.
1926  */
LPI2C_SlaveReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize,size_t * actualRxSize)1927 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
1928 {
1929     status_t result  = kStatus_Success;
1930     uint8_t *buf     = (uint8_t *)rxBuff;
1931     size_t remaining = rxSize;
1932 
1933     assert(NULL != rxBuff);
1934 
1935 #if I2C_RETRY_TIMES != 0U
1936     uint32_t waitTimes = I2C_RETRY_TIMES;
1937 #endif
1938 
1939     /* Clear stop flag. */
1940     LPI2C_SlaveClearStatusFlags(base,
1941                                 (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1942 
1943     while (0U != remaining)
1944     {
1945         uint32_t flags;
1946 
1947         /* Wait until we can receive. */
1948         do
1949         {
1950             /* Check for errors */
1951             flags  = LPI2C_SlaveGetStatusFlags(base);
1952             result = LPI2C_SlaveCheckAndClearError(base, flags);
1953             if (kStatus_Success != result)
1954             {
1955                 if (NULL != actualRxSize)
1956                 {
1957                     *actualRxSize = rxSize - remaining;
1958                 }
1959                 break;
1960             }
1961 #if I2C_RETRY_TIMES != 0U
1962             waitTimes--;
1963         } while ((0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1964                                   (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1965                  (0U != waitTimes));
1966         if (0U == waitTimes)
1967         {
1968             result = kStatus_LPI2C_Timeout;
1969         }
1970 #else
1971         } while (0U == (flags & ((uint32_t)kLPI2C_SlaveRxReadyFlag | (uint32_t)kLPI2C_SlaveStopDetectFlag |
1972                                  (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)));
1973 #endif
1974 
1975         if ((status_t)kStatus_Success != result)
1976         {
1977             break;
1978         }
1979 
1980         /* Receive a byte. */
1981         if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
1982         {
1983             *buf++ = (uint8_t)(base->SRDR & LPI2C_SRDR_DATA_MASK);
1984             --remaining;
1985         }
1986 
1987         /* Exit loop if we see a stop or restart */
1988         if ((0U != (flags & ((uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag))) &&
1989             (remaining != 0U))
1990         {
1991             LPI2C_SlaveClearStatusFlags(
1992                 base, (uint32_t)kLPI2C_SlaveStopDetectFlag | (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag);
1993             break;
1994         }
1995     }
1996 
1997     if (NULL != actualRxSize)
1998     {
1999         *actualRxSize = rxSize - remaining;
2000     }
2001 
2002     return result;
2003 }
2004 
2005 /*!
2006  * brief Creates a new handle for the LPI2C slave non-blocking APIs.
2007  *
2008  * The creation of a handle is for use with the non-blocking APIs. Once a handle
2009  * is created, there is not a corresponding destroy handle. If the user wants to
2010  * terminate a transfer, the LPI2C_SlaveTransferAbort() API shall be called.
2011  *
2012  * note The function also enables the NVIC IRQ for the input LPI2C. Need to notice
2013  * that on some SoCs the LPI2C IRQ is connected to INTMUX, in this case user needs to
2014  * enable the associated INTMUX IRQ in application.
2015 
2016  * param base The LPI2C peripheral base address.
2017  * param[out] handle Pointer to the LPI2C slave driver handle.
2018  * param callback User provided pointer to the asynchronous callback function.
2019  * param userData User provided pointer to the application callback data.
2020  */
LPI2C_SlaveTransferCreateHandle(LPI2C_Type * base,lpi2c_slave_handle_t * handle,lpi2c_slave_transfer_callback_t callback,void * userData)2021 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
2022                                      lpi2c_slave_handle_t *handle,
2023                                      lpi2c_slave_transfer_callback_t callback,
2024                                      void *userData)
2025 {
2026     uint32_t instance;
2027 
2028     assert(NULL != handle);
2029 
2030     /* Clear out the handle. */
2031     (void)memset(handle, 0, sizeof(*handle));
2032 
2033     /* Look up instance number */
2034     instance = LPI2C_GetInstance(base);
2035 
2036     /* Save base and instance. */
2037     handle->callback = callback;
2038     handle->userData = userData;
2039 
2040     if(LP_FLEXCOMM_GetBaseAddress(instance) != 0U)
2041     {
2042         lpi2c_to_lpflexcomm_t handler;
2043         (void)memset(&handler, 0, sizeof(handler));
2044 
2045         /* Save the handle in global variables to support the double weak mechanism. */
2046         handler.lpi2c_slave_handler = LPI2C_SlaveTransferHandleIRQ;
2047         LP_FLEXCOMM_SetIRQHandler(LPI2C_GetInstance(base), handler.lpflexcomm_handler, handle, LP_FLEXCOMM_PERIPH_LPI2C);
2048     }
2049     else
2050     {
2051         /* Save this handle for IRQ use. */
2052         s_lpi2cSlaveHandle[instance] = handle;
2053 
2054         /* Set irq handler. */
2055         s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
2056     }
2057 
2058     /* Clear internal IRQ enables and enable NVIC IRQ. */
2059     LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2060     (void)EnableIRQ(kLpi2cIrqs[instance]);
2061 
2062     /* Nack by default. */
2063     base->STAR = LPI2C_STAR_TXNACK_MASK;
2064 }
2065 
2066 /*!
2067  * brief Starts accepting slave transfers.
2068  *
2069  * Call this API after calling I2C_SlaveInit() and LPI2C_SlaveTransferCreateHandle() to start processing
2070  * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
2071  * callback that was passed into the call to LPI2C_SlaveTransferCreateHandle(). The callback is always invoked
2072  * from the interrupt context.
2073  *
2074  * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
2075  * the OR'd combination of #lpi2c_slave_transfer_event_t enumerators for the events you wish to receive.
2076  * The #kLPI2C_SlaveTransmitEvent and #kLPI2C_SlaveReceiveEvent events are always enabled and do not need
2077  * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
2078  * receive events that are always enabled. In addition, the #kLPI2C_SlaveAllEvents constant is provided as
2079  * a convenient way to enable all events.
2080  *
2081  * param base The LPI2C peripheral base address.
2082  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2083  * param eventMask Bit mask formed by OR'ing together #lpi2c_slave_transfer_event_t enumerators to specify
2084  *      which events to send to the callback. Other accepted values are 0 to get a default set of
2085  *      only the transmit and receive events, and #kLPI2C_SlaveAllEvents to enable all events.
2086  *
2087  * retval #kStatus_Success Slave transfers were successfully started.
2088  * retval #kStatus_LPI2C_Busy Slave transfers have already been started on this handle.
2089  */
LPI2C_SlaveTransferNonBlocking(LPI2C_Type * base,lpi2c_slave_handle_t * handle,uint32_t eventMask)2090 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
2091 {
2092     status_t result = kStatus_Success;
2093 
2094     assert(NULL != handle);
2095 
2096     /* Return busy if another transaction is in progress. */
2097     if (handle->isBusy)
2098     {
2099         result = kStatus_LPI2C_Busy;
2100     }
2101     else
2102     {
2103         /* Return an error if the bus is already in use not by us. */
2104         uint32_t status = LPI2C_SlaveGetStatusFlags(base);
2105         if ((0U != (status & (uint32_t)kLPI2C_SlaveBusBusyFlag)) && (0U == (status & (uint32_t)kLPI2C_SlaveBusyFlag)))
2106         {
2107             result = kStatus_LPI2C_Busy;
2108         }
2109     }
2110 
2111     if ((status_t)kStatus_Success == result)
2112     {
2113         /* Disable LPI2C IRQ sources while we configure stuff. */
2114         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2115 
2116         /* Clear transfer in handle. */
2117         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2118 
2119         /* Record that we're busy. */
2120         handle->isBusy = true;
2121 
2122         /* Set up event mask. tx and rx are always enabled. */
2123         handle->eventMask = eventMask | (uint32_t)kLPI2C_SlaveTransmitEvent | (uint32_t)kLPI2C_SlaveReceiveEvent;
2124 
2125         /* Ack by default. */
2126         base->STAR = 0U;
2127 
2128         /* Clear all flags. */
2129         LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags);
2130 
2131         /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2132         LPI2C_SlaveEnableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2133     }
2134 
2135     return result;
2136 }
2137 
2138 /*!
2139  * brief Gets the slave transfer status during a non-blocking transfer.
2140  * param base The LPI2C peripheral base address.
2141  * param handle Pointer to i2c_slave_handle_t structure.
2142  * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
2143  *      required.
2144  * retval #kStatus_Success
2145  * retval #kStatus_NoTransferInProgress
2146  */
LPI2C_SlaveTransferGetCount(LPI2C_Type * base,lpi2c_slave_handle_t * handle,size_t * count)2147 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
2148 {
2149     status_t status = kStatus_Success;
2150 
2151     assert(NULL != handle);
2152 
2153     if (count == NULL)
2154     {
2155         status = kStatus_InvalidArgument;
2156     }
2157 
2158     /* Catch when there is not an active transfer. */
2159     else if (!handle->isBusy)
2160     {
2161         *count = 0;
2162         status = kStatus_NoTransferInProgress;
2163     }
2164 
2165     /* For an active transfer, just return the count from the handle. */
2166     else
2167     {
2168         *count = handle->transferredCount;
2169     }
2170 
2171     return status;
2172 }
2173 
2174 /*!
2175  * brief Aborts the slave non-blocking transfers.
2176  * note This API could be called at any time to stop slave for handling the bus events.
2177  * param base The LPI2C peripheral base address.
2178  * param handle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2179  * retval #kStatus_Success
2180  * retval #kStatus_LPI2C_Idle
2181  */
LPI2C_SlaveTransferAbort(LPI2C_Type * base,lpi2c_slave_handle_t * handle)2182 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
2183 {
2184     assert(NULL != handle);
2185 
2186     /* Return idle if no transaction is in progress. */
2187     if (handle->isBusy)
2188     {
2189         /* Disable LPI2C IRQ sources. */
2190         LPI2C_SlaveDisableInterrupts(base, (uint32_t)kLPI2C_SlaveIrqFlags);
2191 
2192         /* Nack by default. */
2193         base->STAR = LPI2C_STAR_TXNACK_MASK;
2194 
2195         /* Reset transfer info. */
2196         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2197 
2198         /* We're no longer busy. */
2199         handle->isBusy = false;
2200     }
2201 }
2202 
2203 /*!
2204  * brief Reusable routine to handle slave interrupts.
2205  * note This function does not need to be called unless you are reimplementing the
2206  *  non blocking API's interrupt handler routines to add special functionality.
2207  * param instance The LPI2C instance.
2208  * param lpi2cSlaveHandle Pointer to #lpi2c_slave_handle_t structure which stores the transfer state.
2209  */
LPI2C_SlaveTransferHandleIRQ(uint32_t instance,void * lpi2cSlaveHandle)2210 void LPI2C_SlaveTransferHandleIRQ(uint32_t instance, void *lpi2cSlaveHandle)
2211 {
2212     assert(instance < ARRAY_SIZE(kLpi2cBases));
2213     uint32_t flags;
2214     lpi2c_slave_transfer_t *xfer;
2215     LPI2C_Type *base             = kLpi2cBases[instance];
2216     lpi2c_slave_handle_t *handle = (lpi2c_slave_handle_t *)lpi2cSlaveHandle;
2217 
2218     /* Check for a valid handle in case of a spurious interrupt. */
2219     if (NULL != handle)
2220     {
2221         xfer = &handle->transfer;
2222 
2223         /* Get status flags. */
2224         flags = LPI2C_SlaveGetStatusFlags(base);
2225 
2226         if (0U != (flags & ((uint32_t)kLPI2C_SlaveBitErrFlag | (uint32_t)kLPI2C_SlaveFifoErrFlag)))
2227         {
2228             xfer->event            = kLPI2C_SlaveCompletionEvent;
2229             xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
2230 
2231             if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveCompletionEvent)) && (NULL != handle->callback))
2232             {
2233                 handle->callback(base, xfer, handle->userData);
2234             }
2235         }
2236         else
2237         {
2238             if (0U !=
2239                 (flags & (((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag) | ((uint32_t)kLPI2C_SlaveStopDetectFlag))))
2240             {
2241                 xfer->event = (0U != (flags & (uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag)) ?
2242                                   kLPI2C_SlaveRepeatedStartEvent :
2243                                   kLPI2C_SlaveCompletionEvent;
2244                 xfer->receivedAddress  = 0U;
2245                 xfer->completionStatus = kStatus_Success;
2246                 xfer->transferredCount = handle->transferredCount;
2247 
2248                 if (xfer->event == kLPI2C_SlaveCompletionEvent)
2249                 {
2250                     handle->isBusy = false;
2251                 }
2252 
2253                 if (handle->wasTransmit)
2254                 {
2255                     /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
2256                     /* tx flag before it sees the nack from the master-receiver, thus causing one more */
2257                     /* count that the master actually receives. */
2258                     --xfer->transferredCount;
2259                     handle->wasTransmit = false;
2260                 }
2261 
2262                 /* Clear the flag. */
2263                 LPI2C_SlaveClearStatusFlags(base, flags & ((uint32_t)kLPI2C_SlaveRepeatedStartDetectFlag |
2264                                                            (uint32_t)kLPI2C_SlaveStopDetectFlag));
2265 
2266                 /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
2267                 base->STAR = 0U;
2268 
2269                 if ((0U != (handle->eventMask & (uint32_t)xfer->event)) && (NULL != handle->callback))
2270                 {
2271                     handle->callback(base, xfer, handle->userData);
2272                 }
2273 
2274                 if (0U != (flags & (uint32_t)kLPI2C_SlaveStopDetectFlag))
2275                 {
2276                     /* Clean up transfer info on completion, after the callback has been invoked. */
2277                     (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
2278                 }
2279             }
2280             if (0U != (flags & (uint32_t)kLPI2C_SlaveAddressValidFlag))
2281             {
2282                 xfer->event           = kLPI2C_SlaveAddressMatchEvent;
2283                 xfer->receivedAddress = (uint8_t)(base->SASR & LPI2C_SASR_RADDR_MASK);
2284 
2285                 /* Update handle status to busy because slave is addressed. */
2286                 handle->isBusy = true;
2287                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
2288                 {
2289                     handle->callback(base, xfer, handle->userData);
2290                 }
2291             }
2292             if (0U != (flags & (uint32_t)kLPI2C_SlaveTransmitAckFlag))
2293             {
2294                 xfer->event = kLPI2C_SlaveTransmitAckEvent;
2295 
2296                 if ((0U != (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) && (NULL != handle->callback))
2297                 {
2298                     handle->callback(base, xfer, handle->userData);
2299                 }
2300                 else
2301                 {
2302                     LPI2C_SlaveTransmitAck(base, true);
2303                 }
2304             }
2305 
2306             /* Handle transmit and receive. */
2307             if (0U != (flags & (uint32_t)kLPI2C_SlaveTxReadyFlag))
2308             {
2309                 handle->wasTransmit = true;
2310 
2311                 /* If we're out of data, invoke callback to get more. */
2312                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2313                 {
2314                     xfer->event = kLPI2C_SlaveTransmitEvent;
2315                     if (NULL != handle->callback)
2316                     {
2317                         handle->callback(base, xfer, handle->userData);
2318                     }
2319 
2320                     /* Clear the transferred count now that we have a new buffer. */
2321                     handle->transferredCount = 0U;
2322                 }
2323 
2324                 /* Transmit a byte. */
2325                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2326                 {
2327                     base->STDR = *xfer->data++;
2328                     --xfer->dataSize;
2329                     ++handle->transferredCount;
2330                 }
2331             }
2332             if (0U != (flags & (uint32_t)kLPI2C_SlaveRxReadyFlag))
2333             {
2334                 /* If we're out of room in the buffer, invoke callback to get another. */
2335                 if ((NULL == xfer->data) || (0U == xfer->dataSize))
2336                 {
2337                     xfer->event = kLPI2C_SlaveReceiveEvent;
2338                     if (NULL != handle->callback)
2339                     {
2340                         handle->callback(base, xfer, handle->userData);
2341                     }
2342 
2343                     /* Clear the transferred count now that we have a new buffer. */
2344                     handle->transferredCount = 0U;
2345                 }
2346 
2347                 /* Receive a byte. */
2348                 if ((NULL != xfer->data) && (0U != xfer->dataSize))
2349                 {
2350                     *xfer->data++ = (uint8_t)base->SRDR;
2351                     --xfer->dataSize;
2352                     ++handle->transferredCount;
2353 					if (0U != (base->SCFGR1 & LPI2C_SCFGR1_ACKSTALL_MASK))
2354                     {
2355                         if (((0U == (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) ||
2356                              (NULL == handle->callback)))
2357                         {
2358                             LPI2C_SlaveTransmitAck(base, true);
2359                         }
2360                     }
2361                 }
2362                 else
2363                 {
2364                     /* We don't have any room to receive more data, so send a nack. */
2365                     if (0U != (base->SCFGR1 & LPI2C_SCFGR1_ACKSTALL_MASK))
2366                     {
2367                         if (((0U == (handle->eventMask & (uint32_t)kLPI2C_SlaveTransmitAckEvent)) ||
2368                              (NULL == handle->callback)))
2369                         {
2370                             LPI2C_SlaveTransmitAck(base, false);
2371                         }
2372                     }
2373                 }
2374             }
2375         }
2376     }
2377 }
2378 
2379 #if !(defined(FSL_FEATURE_I2C_HAS_NO_IRQ) && FSL_FEATURE_I2C_HAS_NO_IRQ)
2380 /*!
2381  * @brief Shared IRQ handler that can call both master and slave ISRs.
2382  *
2383  * The master and slave ISRs are called through function pointers in order to decouple
2384  * this code from the ISR functions. Without this, the linker would always pull in both
2385  * ISRs and every function they call, even if only the functional API was used.
2386  *
2387  * @param base The LPI2C peripheral base address.
2388  * @param instance The LPI2C peripheral instance number.
2389  */
2390 void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance);
LPI2C_CommonIRQHandler(LPI2C_Type * base,uint32_t instance)2391 void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
2392 {
2393     /* Check for master IRQ. */
2394     if ((0U != (base->MCR & LPI2C_MCR_MEN_MASK)) && (NULL != s_lpi2cMasterIsr))
2395     {
2396         /* Master mode. */
2397         s_lpi2cMasterIsr(instance, s_lpi2cMasterHandle[instance]);
2398     }
2399 
2400     /* Check for slave IRQ. */
2401     if ((0U != (base->SCR & LPI2C_SCR_SEN_MASK)) && (NULL != s_lpi2cSlaveIsr))
2402     {
2403         /* Slave mode. */
2404         s_lpi2cSlaveIsr(instance, s_lpi2cSlaveHandle[instance]);
2405     }
2406     SDK_ISR_EXIT_BARRIER;
2407 }
2408 #endif
2409 
2410 #if defined(LPI2C15)
2411 /* Implementation of LPI2C15 handler named in startup code. */
2412 void LPI2C15_DriverIRQHandler(void);
LPI2C15_DriverIRQHandler(void)2413 void LPI2C15_DriverIRQHandler(void)
2414 {
2415     LPI2C_CommonIRQHandler(LPI2C15, 15U);
2416 }
2417 #endif
2418