1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_lpi2c.h"
10 #include <stdlib.h>
11 #include <string.h>
12 
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /*! @brief Common sets of flags used by the driver. */
18 enum _lpi2c_flag_constants
19 {
20     /*! All flags which are cleared by the driver upon starting a transfer. */
21     kMasterClearFlags = kLPI2C_MasterEndOfPacketFlag | kLPI2C_MasterStopDetectFlag | kLPI2C_MasterNackDetectFlag |
22                         kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterFifoErrFlag | kLPI2C_MasterPinLowTimeoutFlag |
23                         kLPI2C_MasterDataMatchFlag,
24 
25     /*! IRQ sources enabled by the non-blocking transactional API. */
26     kMasterIrqFlags = kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterTxReadyFlag | kLPI2C_MasterRxReadyFlag |
27                       kLPI2C_MasterStopDetectFlag | kLPI2C_MasterNackDetectFlag | kLPI2C_MasterPinLowTimeoutFlag |
28                       kLPI2C_MasterFifoErrFlag,
29 
30     /*! Errors to check for. */
31     kMasterErrorFlags = kLPI2C_MasterNackDetectFlag | kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterFifoErrFlag |
32                         kLPI2C_MasterPinLowTimeoutFlag,
33 
34     /*! All flags which are cleared by the driver upon starting a transfer. */
35     kSlaveClearFlags = kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveBitErrFlag |
36                        kLPI2C_SlaveFifoErrFlag,
37 
38     /*! IRQ sources enabled by the non-blocking transactional API. */
39     kSlaveIrqFlags = kLPI2C_SlaveTxReadyFlag | kLPI2C_SlaveRxReadyFlag | kLPI2C_SlaveStopDetectFlag |
40                      kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveFifoErrFlag | kLPI2C_SlaveBitErrFlag |
41                      kLPI2C_SlaveTransmitAckFlag | kLPI2C_SlaveAddressValidFlag,
42 
43     /*! Errors to check for. */
44     kSlaveErrorFlags = kLPI2C_SlaveFifoErrFlag | kLPI2C_SlaveBitErrFlag,
45 };
46 
47 /* ! @brief LPI2C master fifo commands. */
48 enum _lpi2c_master_fifo_cmd
49 {
50     kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
51     kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
52     kStopCmd = LPI2C_MTDR_CMD(0x2U),   /*!< Generate STOP condition */
53     kStartCmd = LPI2C_MTDR_CMD(0x4U),  /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
54 };
55 
56 /*!
57  * @brief Default watermark values.
58  *
59  * The default watermarks are set to zero.
60  */
61 enum _lpi2c_default_watermarks
62 {
63     kDefaultTxWatermark = 0,
64     kDefaultRxWatermark = 0,
65 };
66 
67 /*! @brief States for the state machine used by transactional APIs. */
68 enum _lpi2c_transfer_states
69 {
70     kIdleState = 0,
71     kSendCommandState,
72     kIssueReadCommandState,
73     kTransferDataState,
74     kStopState,
75     kWaitForCompletionState,
76 };
77 
78 /*! @brief Typedef for master interrupt handler. */
79 typedef void (*lpi2c_master_isr_t)(LPI2C_Type *base, lpi2c_master_handle_t *handle);
80 
81 /*! @brief Typedef for slave interrupt handler. */
82 typedef void (*lpi2c_slave_isr_t)(LPI2C_Type *base, lpi2c_slave_handle_t *handle);
83 
84 /*******************************************************************************
85  * Prototypes
86  ******************************************************************************/
87 
88 /* Not static so it can be used from fsl_lpi2c_edma.c. */
89 uint32_t LPI2C_GetInstance(LPI2C_Type *base);
90 
91 static uint32_t LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,
92                                         uint32_t width_ns,
93                                         uint32_t maxCycles,
94                                         uint32_t prescaler);
95 
96 /* Not static so it can be used from fsl_lpi2c_edma.c. */
97 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status);
98 
99 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base);
100 
101 /* Not static so it can be used from fsl_lpi2c_edma.c. */
102 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base);
103 
104 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone);
105 
106 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle);
107 
108 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags);
109 
110 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance);
111 
112 /*******************************************************************************
113  * Variables
114  ******************************************************************************/
115 
116 /*! @brief Array to map LPI2C instance number to base pointer. */
117 static LPI2C_Type *const kLpi2cBases[] = LPI2C_BASE_PTRS;
118 
119 /*! @brief Array to map LPI2C instance number to IRQ number. */
120 static IRQn_Type const kLpi2cIrqs[] = LPI2C_IRQS;
121 
122 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
123 /*! @brief Array to map LPI2C instance number to clock gate enum. */
124 static clock_ip_name_t const kLpi2cClocks[] = LPI2C_CLOCKS;
125 
126 #if defined(LPI2C_PERIPH_CLOCKS)
127 /*! @brief Array to map LPI2C instance number to pheripheral clock gate enum. */
128 static const clock_ip_name_t kLpi2cPeriphClocks[] = LPI2C_PERIPH_CLOCKS;
129 #endif
130 
131 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
132 
133 /*! @brief Pointer to master IRQ handler for each instance. */
134 static lpi2c_master_isr_t s_lpi2cMasterIsr;
135 
136 /*! @brief Pointers to master handles for each instance. */
137 static lpi2c_master_handle_t *s_lpi2cMasterHandle[FSL_FEATURE_SOC_LPI2C_COUNT];
138 
139 /*! @brief Pointer to slave IRQ handler for each instance. */
140 static lpi2c_slave_isr_t s_lpi2cSlaveIsr;
141 
142 /*! @brief Pointers to slave handles for each instance. */
143 static lpi2c_slave_handle_t *s_lpi2cSlaveHandle[FSL_FEATURE_SOC_LPI2C_COUNT];
144 
145 /*******************************************************************************
146  * Code
147  ******************************************************************************/
148 
149 /*!
150  * @brief Returns an instance number given a base address.
151  *
152  * If an invalid base address is passed, debug builds will assert. Release builds will just return
153  * instance number 0.
154  *
155  * @param base The LPI2C peripheral base address.
156  * @return LPI2C instance number starting from 0.
157  */
LPI2C_GetInstance(LPI2C_Type * base)158 uint32_t LPI2C_GetInstance(LPI2C_Type *base)
159 {
160     uint32_t instance;
161     for (instance = 0; instance < ARRAY_SIZE(kLpi2cBases); ++instance)
162     {
163         if (kLpi2cBases[instance] == base)
164         {
165             return instance;
166         }
167     }
168 
169     assert(false);
170     return 0;
171 }
172 
173 /*!
174  * @brief Computes a cycle count for a given time in nanoseconds.
175  * @param sourceClock_Hz LPI2C functional clock frequency in Hertz.
176  * @param width_ns Desired with in nanoseconds.
177  * @param maxCycles Maximum cycle count, determined by the number of bits wide the cycle count field is.
178  * @param prescaler LPI2C prescaler setting. Pass 1 if the prescaler should not be used, as for slave glitch widths.
179  */
LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,uint32_t width_ns,uint32_t maxCycles,uint32_t prescaler)180 static uint32_t LPI2C_GetCyclesForWidth(uint32_t sourceClock_Hz,
181                                         uint32_t width_ns,
182                                         uint32_t maxCycles,
183                                         uint32_t prescaler)
184 {
185     uint32_t busCycle_ns = 1000000 / (sourceClock_Hz / prescaler / 1000);
186     uint32_t cycles = 0;
187 
188     /* Search for the cycle count just below the desired glitch width. */
189     while ((((cycles + 1) * busCycle_ns) < width_ns) && (cycles + 1 < maxCycles))
190     {
191         ++cycles;
192     }
193 
194     /* If we end up with zero cycles, then set the filter to a single cycle unless the */
195     /* bus clock is greater than 10x the desired glitch width. */
196     if ((cycles == 0) && (busCycle_ns <= (width_ns * 10)))
197     {
198         cycles = 1;
199     }
200 
201     return cycles;
202 }
203 
204 /*!
205  * @brief Convert provided flags to status code, and clear any errors if present.
206  * @param base The LPI2C peripheral base address.
207  * @param status Current status flags value that will be checked.
208  * @retval #kStatus_Success
209  * @retval #kStatus_LPI2C_PinLowTimeout
210  * @retval #kStatus_LPI2C_ArbitrationLost
211  * @retval #kStatus_LPI2C_Nak
212  * @retval #kStatus_LPI2C_FifoError
213  */
LPI2C_MasterCheckAndClearError(LPI2C_Type * base,uint32_t status)214 status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status)
215 {
216     status_t result = kStatus_Success;
217 
218     /* Check for error. These errors cause a stop to automatically be sent. We must */
219     /* clear the errors before a new transfer can start. */
220     status &= kMasterErrorFlags;
221     if (status)
222     {
223         /* Select the correct error code. Ordered by severity, with bus issues first. */
224         if (status & kLPI2C_MasterPinLowTimeoutFlag)
225         {
226             result = kStatus_LPI2C_PinLowTimeout;
227         }
228         else if (status & kLPI2C_MasterArbitrationLostFlag)
229         {
230             result = kStatus_LPI2C_ArbitrationLost;
231         }
232         else if (status & kLPI2C_MasterNackDetectFlag)
233         {
234             result = kStatus_LPI2C_Nak;
235         }
236         else if (status & kLPI2C_MasterFifoErrFlag)
237         {
238             result = kStatus_LPI2C_FifoError;
239         }
240         else
241         {
242             assert(false);
243         }
244 
245         /* Clear the flags. */
246         LPI2C_MasterClearStatusFlags(base, status);
247 
248         /* Reset fifos. These flags clear automatically. */
249         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
250     }
251 
252     return result;
253 }
254 
255 /*!
256  * @brief Wait until there is room in the tx fifo.
257  * @param base The LPI2C peripheral base address.
258  * @retval #kStatus_Success
259  * @retval #kStatus_LPI2C_PinLowTimeout
260  * @retval #kStatus_LPI2C_ArbitrationLost
261  * @retval #kStatus_LPI2C_Nak
262  * @retval #kStatus_LPI2C_FifoError
263  */
LPI2C_MasterWaitForTxReady(LPI2C_Type * base)264 static status_t LPI2C_MasterWaitForTxReady(LPI2C_Type *base)
265 {
266     uint32_t status;
267     size_t txCount;
268     size_t txFifoSize = FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
269     do
270     {
271         status_t result;
272 
273         /* Get the number of words in the tx fifo and compute empty slots. */
274         LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
275         txCount = txFifoSize - txCount;
276 
277         /* Check for error flags. */
278         status = LPI2C_MasterGetStatusFlags(base);
279         result = LPI2C_MasterCheckAndClearError(base, status);
280         if (result)
281         {
282             return result;
283         }
284     } while (!txCount);
285 
286     return kStatus_Success;
287 }
288 
289 /*!
290  * @brief Make sure the bus isn't already busy.
291  *
292  * A busy bus is allowed if we are the one driving it.
293  *
294  * @param base The LPI2C peripheral base address.
295  * @retval #kStatus_Success
296  * @retval #kStatus_LPI2C_Busy
297  */
LPI2C_CheckForBusyBus(LPI2C_Type * base)298 status_t LPI2C_CheckForBusyBus(LPI2C_Type *base)
299 {
300     uint32_t status = LPI2C_MasterGetStatusFlags(base);
301     if ((status & kLPI2C_MasterBusBusyFlag) && (!(status & kLPI2C_MasterBusyFlag)))
302     {
303         return kStatus_LPI2C_Busy;
304     }
305 
306     return kStatus_Success;
307 }
308 
LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t * masterConfig)309 void LPI2C_MasterGetDefaultConfig(lpi2c_master_config_t *masterConfig)
310 {
311     masterConfig->enableMaster = true;
312     masterConfig->debugEnable = false;
313     masterConfig->enableDoze = true;
314     masterConfig->ignoreAck = false;
315     masterConfig->pinConfig = kLPI2C_2PinOpenDrain;
316     masterConfig->baudRate_Hz = 100000U;
317     masterConfig->busIdleTimeout_ns = 0;
318     masterConfig->pinLowTimeout_ns = 0;
319     masterConfig->sdaGlitchFilterWidth_ns = 0;
320     masterConfig->sclGlitchFilterWidth_ns = 0;
321     masterConfig->hostRequest.enable = false;
322     masterConfig->hostRequest.source = kLPI2C_HostRequestExternalPin;
323     masterConfig->hostRequest.polarity = kLPI2C_HostRequestPinActiveHigh;
324 }
325 
LPI2C_MasterInit(LPI2C_Type * base,const lpi2c_master_config_t * masterConfig,uint32_t sourceClock_Hz)326 void LPI2C_MasterInit(LPI2C_Type *base, const lpi2c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
327 {
328     uint32_t prescaler;
329     uint32_t cycles;
330     uint32_t cfgr2;
331     uint32_t value;
332 
333 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
334 
335     uint32_t instance = LPI2C_GetInstance(base);
336 
337     /* Ungate the clock. */
338     CLOCK_EnableClock(kLpi2cClocks[instance]);
339 #if defined(LPI2C_PERIPH_CLOCKS)
340     /* Ungate the functional clock in initialize function. */
341     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
342 #endif
343 
344 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
345 
346     /* Reset peripheral before configuring it. */
347     LPI2C_MasterReset(base);
348 
349     /* Doze bit: 0 is enable, 1 is disable */
350     base->MCR = LPI2C_MCR_DBGEN(masterConfig->debugEnable) | LPI2C_MCR_DOZEN(!(masterConfig->enableDoze));
351 
352     /* host request */
353     value = base->MCFGR0;
354     value &= (~(LPI2C_MCFGR0_HREN_MASK | LPI2C_MCFGR0_HRPOL_MASK | LPI2C_MCFGR0_HRSEL_MASK));
355     value |= LPI2C_MCFGR0_HREN(masterConfig->hostRequest.enable) |
356              LPI2C_MCFGR0_HRPOL(masterConfig->hostRequest.polarity) |
357              LPI2C_MCFGR0_HRSEL(masterConfig->hostRequest.source);
358     base->MCFGR0 = value;
359 
360     /* pin config and ignore ack */
361     value = base->MCFGR1;
362     value &= ~(LPI2C_MCFGR1_PINCFG_MASK | LPI2C_MCFGR1_IGNACK_MASK);
363     value |= LPI2C_MCFGR1_PINCFG(masterConfig->pinConfig);
364     value |= LPI2C_MCFGR1_IGNACK(masterConfig->ignoreAck);
365     base->MCFGR1 = value;
366 
367     LPI2C_MasterSetWatermarks(base, kDefaultTxWatermark, kDefaultRxWatermark);
368 
369     LPI2C_MasterSetBaudRate(base, sourceClock_Hz, masterConfig->baudRate_Hz);
370 
371     /* Configure glitch filters and bus idle and pin low timeouts. */
372     prescaler = (base->MCFGR1 & LPI2C_MCFGR1_PRESCALE_MASK) >> LPI2C_MCFGR1_PRESCALE_SHIFT;
373     cfgr2 = base->MCFGR2;
374     if (masterConfig->busIdleTimeout_ns)
375     {
376         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->busIdleTimeout_ns,
377                                          (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
378         cfgr2 &= ~LPI2C_MCFGR2_BUSIDLE_MASK;
379         cfgr2 |= LPI2C_MCFGR2_BUSIDLE(cycles);
380     }
381     if (masterConfig->sdaGlitchFilterWidth_ns)
382     {
383         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sdaGlitchFilterWidth_ns,
384                                          (LPI2C_MCFGR2_FILTSDA_MASK >> LPI2C_MCFGR2_FILTSDA_SHIFT), 1);
385         cfgr2 &= ~LPI2C_MCFGR2_FILTSDA_MASK;
386         cfgr2 |= LPI2C_MCFGR2_FILTSDA(cycles);
387     }
388     if (masterConfig->sclGlitchFilterWidth_ns)
389     {
390         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->sclGlitchFilterWidth_ns,
391                                          (LPI2C_MCFGR2_FILTSCL_MASK >> LPI2C_MCFGR2_FILTSCL_SHIFT), 1);
392         cfgr2 &= ~LPI2C_MCFGR2_FILTSCL_MASK;
393         cfgr2 |= LPI2C_MCFGR2_FILTSCL(cycles);
394     }
395     base->MCFGR2 = cfgr2;
396     if (masterConfig->pinLowTimeout_ns)
397     {
398         cycles = LPI2C_GetCyclesForWidth(sourceClock_Hz, masterConfig->pinLowTimeout_ns / 256,
399                                          (LPI2C_MCFGR2_BUSIDLE_MASK >> LPI2C_MCFGR2_BUSIDLE_SHIFT), prescaler);
400         base->MCFGR3 = (base->MCFGR3 & ~LPI2C_MCFGR3_PINLOW_MASK) | LPI2C_MCFGR3_PINLOW(cycles);
401     }
402 
403     LPI2C_MasterEnable(base, masterConfig->enableMaster);
404 }
405 
LPI2C_MasterDeinit(LPI2C_Type * base)406 void LPI2C_MasterDeinit(LPI2C_Type *base)
407 {
408     /* Restore to reset state. */
409     LPI2C_MasterReset(base);
410 
411 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
412 
413     uint32_t instance = LPI2C_GetInstance(base);
414 
415     /* Gate clock. */
416     CLOCK_DisableClock(kLpi2cClocks[instance]);
417 #if defined(LPI2C_PERIPH_CLOCKS)
418     /* Gate the functional clock. */
419     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
420 #endif
421 
422 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
423 }
424 
LPI2C_MasterConfigureDataMatch(LPI2C_Type * base,const lpi2c_data_match_config_t * config)425 void LPI2C_MasterConfigureDataMatch(LPI2C_Type *base, const lpi2c_data_match_config_t *config)
426 {
427     /* Disable master mode. */
428     bool wasEnabled = (base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT;
429     LPI2C_MasterEnable(base, false);
430 
431     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_MATCFG_MASK) | LPI2C_MCFGR1_MATCFG(config->matchMode);
432     base->MCFGR0 = (base->MCFGR0 & ~LPI2C_MCFGR0_RDMO_MASK) | LPI2C_MCFGR0_RDMO(config->rxDataMatchOnly);
433     base->MDMR = LPI2C_MDMR_MATCH0(config->match0) | LPI2C_MDMR_MATCH1(config->match1);
434 
435     /* Restore master mode. */
436     if (wasEnabled)
437     {
438         LPI2C_MasterEnable(base, true);
439     }
440 }
441 
LPI2C_MasterSetBaudRate(LPI2C_Type * base,uint32_t sourceClock_Hz,uint32_t baudRate_Hz)442 void LPI2C_MasterSetBaudRate(LPI2C_Type *base, uint32_t sourceClock_Hz, uint32_t baudRate_Hz)
443 {
444     uint32_t prescale = 0;
445     uint32_t bestPre = 0;
446     uint32_t bestClkHi = 0;
447     uint32_t absError = 0;
448     uint32_t bestError = 0xffffffffu;
449     uint32_t value;
450     uint32_t clkHiCycle;
451     uint32_t computedRate;
452     int i;
453     bool wasEnabled;
454 
455     /* Disable master mode. */
456     wasEnabled = (base->MCR & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT;
457     LPI2C_MasterEnable(base, false);
458 
459     /* Baud rate = (sourceClock_Hz/2^prescale)/(CLKLO+1+CLKHI+1 + ROUNDDOWN((2+FILTSCL)/2^prescale) */
460     /* Assume CLKLO = 2*CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2. */
461     for (prescale = 1; (prescale <= 128) && (bestError != 0); prescale = 2 * prescale)
462     {
463         for (clkHiCycle = 1; clkHiCycle < 32; clkHiCycle++)
464         {
465             if (clkHiCycle == 1)
466             {
467                 computedRate = (sourceClock_Hz / prescale) / (1 + 3 + 2 + 2 / prescale);
468             }
469             else
470             {
471                 computedRate = (sourceClock_Hz / prescale) / (3 * clkHiCycle + 2 + 2 / prescale);
472             }
473 
474             absError = baudRate_Hz > computedRate ? baudRate_Hz - computedRate : computedRate - baudRate_Hz;
475 
476             if (absError < bestError)
477             {
478                 bestPre = prescale;
479                 bestClkHi = clkHiCycle;
480                 bestError = absError;
481 
482                 /* If the error is 0, then we can stop searching because we won't find a better match. */
483                 if (absError == 0)
484                 {
485                     break;
486                 }
487             }
488         }
489     }
490 
491     /* Standard, fast, fast mode plus and ultra-fast transfers. */
492     value = LPI2C_MCCR0_CLKHI(bestClkHi);
493 
494     if (bestClkHi < 2)
495     {
496         value |= LPI2C_MCCR0_CLKLO(3) | LPI2C_MCCR0_SETHOLD(2) | LPI2C_MCCR0_DATAVD(1);
497     }
498     else
499     {
500         value |= LPI2C_MCCR0_CLKLO(2 * bestClkHi) | LPI2C_MCCR0_SETHOLD(bestClkHi) | LPI2C_MCCR0_DATAVD(bestClkHi / 2);
501     }
502 
503     base->MCCR0 = value;
504 
505     for (i = 0; i < 8; i++)
506     {
507         if (bestPre == (1U << i))
508         {
509             bestPre = i;
510             break;
511         }
512     }
513     base->MCFGR1 = (base->MCFGR1 & ~LPI2C_MCFGR1_PRESCALE_MASK) | LPI2C_MCFGR1_PRESCALE(bestPre);
514 
515     /* Restore master mode. */
516     if (wasEnabled)
517     {
518         LPI2C_MasterEnable(base, true);
519     }
520 }
521 
LPI2C_MasterStart(LPI2C_Type * base,uint8_t address,lpi2c_direction_t dir)522 status_t LPI2C_MasterStart(LPI2C_Type *base, uint8_t address, lpi2c_direction_t dir)
523 {
524     /* Return an error if the bus is already in use not by us. */
525     status_t result = LPI2C_CheckForBusyBus(base);
526     if (result)
527     {
528         return result;
529     }
530 
531     /* Clear all flags. */
532     LPI2C_MasterClearStatusFlags(base, kMasterClearFlags);
533 
534     /* Turn off auto-stop option. */
535     base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
536 
537     /* Wait until there is room in the fifo. */
538     result = LPI2C_MasterWaitForTxReady(base);
539     if (result)
540     {
541         return result;
542     }
543 
544     /* Issue start command. */
545     base->MTDR = kStartCmd | (((uint32_t)address << 1U) | (uint32_t)dir);
546 
547     return kStatus_Success;
548 }
549 
LPI2C_MasterStop(LPI2C_Type * base)550 status_t LPI2C_MasterStop(LPI2C_Type *base)
551 {
552     /* Wait until there is room in the fifo. */
553     status_t result = LPI2C_MasterWaitForTxReady(base);
554     if (result)
555     {
556         return result;
557     }
558 
559     /* Send the STOP signal */
560     base->MTDR = kStopCmd;
561 
562     /* Wait for the stop detected flag to set, indicating the transfer has completed on the bus. */
563     /* Also check for errors while waiting. */
564     while (result == kStatus_Success)
565     {
566         uint32_t status = LPI2C_MasterGetStatusFlags(base);
567 
568         /* Check for error flags. */
569         result = LPI2C_MasterCheckAndClearError(base, status);
570 
571         /* Check if the stop was sent successfully. */
572         if (status & kLPI2C_MasterStopDetectFlag)
573         {
574             LPI2C_MasterClearStatusFlags(base, kLPI2C_MasterStopDetectFlag);
575             break;
576         }
577     }
578 
579     return result;
580 }
581 
LPI2C_MasterReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize)582 status_t LPI2C_MasterReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize)
583 {
584     status_t result;
585     uint8_t *buf;
586 
587     assert(rxBuff);
588 
589     /* Handle empty read. */
590     if (!rxSize)
591     {
592         return kStatus_Success;
593     }
594 
595     /* Wait until there is room in the command fifo. */
596     result = LPI2C_MasterWaitForTxReady(base);
597     if (result)
598     {
599         return result;
600     }
601 
602     /* Issue command to receive data. */
603     base->MTDR = kRxDataCmd | LPI2C_MTDR_DATA(rxSize - 1);
604 
605     /* Receive data */
606     buf = (uint8_t *)rxBuff;
607     while (rxSize--)
608     {
609         /* Read LPI2C receive fifo register. The register includes a flag to indicate whether */
610         /* the FIFO is empty, so we can both get the data and check if we need to keep reading */
611         /* using a single register read. */
612         uint32_t value;
613         do
614         {
615             /* Check for errors. */
616             result = LPI2C_MasterCheckAndClearError(base, LPI2C_MasterGetStatusFlags(base));
617             if (result)
618             {
619                 return result;
620             }
621 
622             value = base->MRDR;
623         } while (value & LPI2C_MRDR_RXEMPTY_MASK);
624 
625         *buf++ = value & LPI2C_MRDR_DATA_MASK;
626     }
627 
628     return kStatus_Success;
629 }
630 
LPI2C_MasterSend(LPI2C_Type * base,const void * txBuff,size_t txSize)631 status_t LPI2C_MasterSend(LPI2C_Type *base, const void *txBuff, size_t txSize)
632 {
633     uint8_t *buf = (uint8_t *)((void *)txBuff);
634 
635     assert(txBuff);
636 
637     /* Send data buffer */
638     while (txSize--)
639     {
640         /* Wait until there is room in the fifo. This also checks for errors. */
641         status_t result = LPI2C_MasterWaitForTxReady(base);
642         if (result)
643         {
644             return result;
645         }
646 
647         /* Write byte into LPI2C master data register. */
648         base->MTDR = *buf++;
649     }
650 
651     return kStatus_Success;
652 }
653 
LPI2C_MasterTransferCreateHandle(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_callback_t callback,void * userData)654 void LPI2C_MasterTransferCreateHandle(LPI2C_Type *base,
655                                       lpi2c_master_handle_t *handle,
656                                       lpi2c_master_transfer_callback_t callback,
657                                       void *userData)
658 {
659     uint32_t instance;
660 
661     assert(handle);
662 
663     /* Clear out the handle. */
664     memset(handle, 0, sizeof(*handle));
665 
666     /* Look up instance number */
667     instance = LPI2C_GetInstance(base);
668 
669     /* Save base and instance. */
670     handle->completionCallback = callback;
671     handle->userData = userData;
672 
673     /* Save this handle for IRQ use. */
674     s_lpi2cMasterHandle[instance] = handle;
675 
676     /* Set irq handler. */
677     s_lpi2cMasterIsr = LPI2C_MasterTransferHandleIRQ;
678 
679     /* Clear internal IRQ enables and enable NVIC IRQ. */
680     LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
681     EnableIRQ(kLpi2cIrqs[instance]);
682 }
683 
684 /*!
685  * @brief Execute states until FIFOs are exhausted.
686  * @param handle Master nonblocking driver handle.
687  * @param[out] isDone Set to true if the transfer has completed.
688  * @retval #kStatus_Success
689  * @retval #kStatus_LPI2C_PinLowTimeout
690  * @retval #kStatus_LPI2C_ArbitrationLost
691  * @retval #kStatus_LPI2C_Nak
692  * @retval #kStatus_LPI2C_FifoError
693  */
LPI2C_RunTransferStateMachine(LPI2C_Type * base,lpi2c_master_handle_t * handle,bool * isDone)694 static status_t LPI2C_RunTransferStateMachine(LPI2C_Type *base, lpi2c_master_handle_t *handle, bool *isDone)
695 {
696     uint32_t status;
697     status_t result = kStatus_Success;
698     lpi2c_master_transfer_t *xfer;
699     size_t txCount;
700     size_t rxCount;
701     size_t txFifoSize = FSL_FEATURE_LPI2C_FIFO_SIZEn(base);
702     bool state_complete = false;
703 
704     /* Set default isDone return value. */
705     *isDone = false;
706 
707     /* Check for errors. */
708     status = LPI2C_MasterGetStatusFlags(base);
709     result = LPI2C_MasterCheckAndClearError(base, status);
710     if (result)
711     {
712         return result;
713     }
714 
715     /* Get pointer to private data. */
716     xfer = &handle->transfer;
717 
718     /* Get fifo counts and compute room in tx fifo. */
719     LPI2C_MasterGetFifoCounts(base, &rxCount, &txCount);
720     txCount = txFifoSize - txCount;
721 
722     while (!state_complete)
723     {
724         /* Execute the state. */
725         switch (handle->state)
726         {
727             case kSendCommandState:
728             {
729                 /* Make sure there is room in the tx fifo for the next command. */
730                 if (!txCount--)
731                 {
732                     state_complete = true;
733                     break;
734                 }
735 
736                 /* Issue command. buf is a uint8_t* pointing at the uint16 command array. */
737                 base->MTDR = *(uint16_t *)handle->buf;
738                 handle->buf += sizeof(uint16_t);
739 
740                 /* Count down until all commands are sent. */
741                 if (--handle->remainingBytes == 0)
742                 {
743                     /* Choose next state and set up buffer pointer and count. */
744                     if (xfer->dataSize)
745                     {
746                         /* Either a send or receive transfer is next. */
747                         handle->state = kTransferDataState;
748                         handle->buf = (uint8_t *)xfer->data;
749                         handle->remainingBytes = xfer->dataSize;
750                         if (xfer->direction == kLPI2C_Read)
751                         {
752                             /* Disable TX interrupt */
753                             LPI2C_MasterDisableInterrupts(base, kLPI2C_MasterTxReadyFlag);
754                         }
755                     }
756                     else
757                     {
758                         /* No transfer, so move to stop state. */
759                         handle->state = kStopState;
760                     }
761                 }
762                 break;
763             }
764 
765             case kIssueReadCommandState:
766                 /* Make sure there is room in the tx fifo for the read command. */
767                 if (!txCount--)
768                 {
769                     state_complete = true;
770                     break;
771                 }
772 
773                 base->MTDR = kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1);
774 
775                 /* Move to transfer state. */
776                 handle->state = kTransferDataState;
777                 if (xfer->direction == kLPI2C_Read)
778                 {
779                     /* Disable TX interrupt */
780                     LPI2C_MasterDisableInterrupts(base, kLPI2C_MasterTxReadyFlag);
781                 }
782                 break;
783 
784             case kTransferDataState:
785                 if (xfer->direction == kLPI2C_Write)
786                 {
787                     /* Make sure there is room in the tx fifo. */
788                     if (!txCount--)
789                     {
790                         state_complete = true;
791                         break;
792                     }
793 
794                     /* Put byte to send in fifo. */
795                     base->MTDR = *(handle->buf)++;
796                 }
797                 else
798                 {
799                     /* XXX handle receive sizes > 256, use kIssueReadCommandState */
800                     /* Make sure there is data in the rx fifo. */
801                     if (!rxCount--)
802                     {
803                         state_complete = true;
804                         break;
805                     }
806 
807                     /* Read byte from fifo. */
808                     *(handle->buf)++ = base->MRDR & LPI2C_MRDR_DATA_MASK;
809                 }
810 
811                 /* Move to stop when the transfer is done. */
812                 if (--handle->remainingBytes == 0)
813                 {
814                     handle->state = kStopState;
815                 }
816                 break;
817 
818             case kStopState:
819                 /* Only issue a stop transition if the caller requested it. */
820                 if ((xfer->flags & kLPI2C_TransferNoStopFlag) == 0)
821                 {
822                     /* Make sure there is room in the tx fifo for the stop command. */
823                     if (!txCount--)
824                     {
825                         state_complete = true;
826                         break;
827                     }
828 
829                     base->MTDR = kStopCmd;
830                 }
831                 else
832                 {
833                     /* Caller doesn't want to send a stop, so we're done now. */
834                     *isDone = true;
835                     state_complete = true;
836                     break;
837                 }
838                 handle->state = kWaitForCompletionState;
839                 break;
840 
841             case kWaitForCompletionState:
842                 /* We stay in this state until the stop state is detected. */
843                 if (status & kLPI2C_MasterStopDetectFlag)
844                 {
845                     *isDone = true;
846                 }
847                 state_complete = true;
848                 break;
849             default:
850                 assert(false);
851                 break;
852         }
853     }
854     return result;
855 }
856 
857 /*!
858  * @brief Prepares the transfer state machine and fills in the command buffer.
859  * @param handle Master nonblocking driver handle.
860  */
LPI2C_InitTransferStateMachine(lpi2c_master_handle_t * handle)861 static void LPI2C_InitTransferStateMachine(lpi2c_master_handle_t *handle)
862 {
863     lpi2c_master_transfer_t *xfer = &handle->transfer;
864 
865     /* Handle no start option. */
866     if (xfer->flags & kLPI2C_TransferNoStartFlag)
867     {
868         if (xfer->direction == kLPI2C_Read)
869         {
870             /* Need to issue read command first. */
871             handle->state = kIssueReadCommandState;
872         }
873         else
874         {
875             /* Start immediately in the data transfer state. */
876             handle->state = kTransferDataState;
877         }
878 
879         handle->buf = (uint8_t *)xfer->data;
880         handle->remainingBytes = xfer->dataSize;
881     }
882     else
883     {
884         uint16_t *cmd = (uint16_t *)&handle->commandBuffer;
885         uint32_t cmdCount = 0;
886 
887         /* Initial direction depends on whether a subaddress was provided, and of course the actual */
888         /* data transfer direction. */
889         lpi2c_direction_t direction = xfer->subaddressSize ? kLPI2C_Write : xfer->direction;
890 
891         /* Start command. */
892         cmd[cmdCount++] =
893             (uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
894 
895         /* Subaddress, MSB first. */
896         if (xfer->subaddressSize)
897         {
898             uint32_t subaddressRemaining = xfer->subaddressSize;
899             while (subaddressRemaining--)
900             {
901                 uint8_t subaddressByte = (xfer->subaddress >> (8 * subaddressRemaining)) & 0xff;
902                 cmd[cmdCount++] = subaddressByte;
903             }
904         }
905 
906         /* Reads need special handling. */
907         if ((xfer->dataSize) && (xfer->direction == kLPI2C_Read))
908         {
909             /* Need to send repeated start if switching directions to read. */
910             if (direction == kLPI2C_Write)
911             {
912                 cmd[cmdCount++] = (uint16_t)kStartCmd |
913                                   (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
914             }
915 
916             /* Read command. */
917             cmd[cmdCount++] = kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1);
918         }
919 
920         /* Set up state machine for transferring the commands. */
921         handle->state = kSendCommandState;
922         handle->remainingBytes = cmdCount;
923         handle->buf = (uint8_t *)&handle->commandBuffer;
924     }
925 }
926 
LPI2C_MasterTransferNonBlocking(LPI2C_Type * base,lpi2c_master_handle_t * handle,lpi2c_master_transfer_t * transfer)927 status_t LPI2C_MasterTransferNonBlocking(LPI2C_Type *base,
928                                          lpi2c_master_handle_t *handle,
929                                          lpi2c_master_transfer_t *transfer)
930 {
931     status_t result;
932 
933     assert(handle);
934     assert(transfer);
935     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
936 
937     /* Return busy if another transaction is in progress. */
938     if (handle->state != kIdleState)
939     {
940         return kStatus_LPI2C_Busy;
941     }
942 
943     /* Return an error if the bus is already in use not by us. */
944     result = LPI2C_CheckForBusyBus(base);
945     if (result)
946     {
947         return result;
948     }
949 
950     /* Disable LPI2C IRQ sources while we configure stuff. */
951     LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
952 
953     /* Save transfer into handle. */
954     handle->transfer = *transfer;
955 
956     /* Generate commands to send. */
957     LPI2C_InitTransferStateMachine(handle);
958 
959     /* Clear all flags. */
960     LPI2C_MasterClearStatusFlags(base, kMasterClearFlags);
961 
962     /* Turn off auto-stop option. */
963     base->MCFGR1 &= ~LPI2C_MCFGR1_AUTOSTOP_MASK;
964 
965     /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
966     LPI2C_MasterEnableInterrupts(base, kMasterIrqFlags);
967 
968     return result;
969 }
970 
LPI2C_MasterTransferGetCount(LPI2C_Type * base,lpi2c_master_handle_t * handle,size_t * count)971 status_t LPI2C_MasterTransferGetCount(LPI2C_Type *base, lpi2c_master_handle_t *handle, size_t *count)
972 {
973     assert(handle);
974 
975     if (!count)
976     {
977         return kStatus_InvalidArgument;
978     }
979 
980     /* Catch when there is not an active transfer. */
981     if (handle->state == kIdleState)
982     {
983         *count = 0;
984         return kStatus_NoTransferInProgress;
985     }
986 
987     uint8_t state;
988     uint16_t remainingBytes;
989     uint32_t dataSize;
990 
991     /* Cache some fields with IRQs disabled. This ensures all field values */
992     /* are synchronized with each other during an ongoing transfer. */
993     uint32_t irqs = LPI2C_MasterGetEnabledInterrupts(base);
994     LPI2C_MasterDisableInterrupts(base, irqs);
995     state = handle->state;
996     remainingBytes = handle->remainingBytes;
997     dataSize = handle->transfer.dataSize;
998     LPI2C_MasterEnableInterrupts(base, irqs);
999 
1000     /* Get transfer count based on current transfer state. */
1001     switch (state)
1002     {
1003         case kIdleState:
1004         case kSendCommandState:
1005         case kIssueReadCommandState: /* XXX return correct value for this state when >256 reads are supported */
1006             *count = 0;
1007             break;
1008 
1009         case kTransferDataState:
1010             *count = dataSize - remainingBytes;
1011             break;
1012 
1013         case kStopState:
1014         case kWaitForCompletionState:
1015         default:
1016             *count = dataSize;
1017             break;
1018     }
1019 
1020     return kStatus_Success;
1021 }
1022 
LPI2C_MasterTransferAbort(LPI2C_Type * base,lpi2c_master_handle_t * handle)1023 void LPI2C_MasterTransferAbort(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1024 {
1025     if (handle->state != kIdleState)
1026     {
1027         /* Disable internal IRQ enables. */
1028         LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
1029 
1030         /* Reset fifos. */
1031         base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
1032 
1033         /* Send a stop command to finalize the transfer. */
1034         base->MTDR = kStopCmd;
1035 
1036         /* Reset handle. */
1037         handle->state = kIdleState;
1038     }
1039 }
1040 
LPI2C_MasterTransferHandleIRQ(LPI2C_Type * base,lpi2c_master_handle_t * handle)1041 void LPI2C_MasterTransferHandleIRQ(LPI2C_Type *base, lpi2c_master_handle_t *handle)
1042 {
1043     bool isDone;
1044     status_t result;
1045 
1046     /* Don't do anything if we don't have a valid handle. */
1047     if (!handle)
1048     {
1049         return;
1050     }
1051 
1052     if (handle->state == kIdleState)
1053     {
1054         return;
1055     }
1056 
1057     result = LPI2C_RunTransferStateMachine(base, handle, &isDone);
1058 
1059     if (isDone || (result != kStatus_Success))
1060     {
1061         /* XXX need to handle data that may be in rx fifo below watermark level? */
1062 
1063         /* XXX handle error, terminate xfer */
1064 
1065         /* Disable internal IRQ enables. */
1066         LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
1067 
1068         /* Set handle to idle state. */
1069         handle->state = kIdleState;
1070 
1071         /* Invoke callback. */
1072         if (handle->completionCallback)
1073         {
1074             handle->completionCallback(base, handle, result, handle->userData);
1075         }
1076     }
1077 }
1078 
LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t * slaveConfig)1079 void LPI2C_SlaveGetDefaultConfig(lpi2c_slave_config_t *slaveConfig)
1080 {
1081     slaveConfig->enableSlave = true;
1082     slaveConfig->address0 = 0U;
1083     slaveConfig->address1 = 0U;
1084     slaveConfig->addressMatchMode = kLPI2C_MatchAddress0;
1085     slaveConfig->filterDozeEnable = true;
1086     slaveConfig->filterEnable = true;
1087     slaveConfig->enableGeneralCall = false;
1088     slaveConfig->sclStall.enableAck = false;
1089     slaveConfig->sclStall.enableTx = true;
1090     slaveConfig->sclStall.enableRx = true;
1091     slaveConfig->sclStall.enableAddress = false;
1092     slaveConfig->ignoreAck = false;
1093     slaveConfig->enableReceivedAddressRead = false;
1094     slaveConfig->sdaGlitchFilterWidth_ns = 0; /* TODO determine default width values */
1095     slaveConfig->sclGlitchFilterWidth_ns = 0;
1096     slaveConfig->dataValidDelay_ns = 0;
1097     slaveConfig->clockHoldTime_ns = 0;
1098 }
1099 
LPI2C_SlaveInit(LPI2C_Type * base,const lpi2c_slave_config_t * slaveConfig,uint32_t sourceClock_Hz)1100 void LPI2C_SlaveInit(LPI2C_Type *base, const lpi2c_slave_config_t *slaveConfig, uint32_t sourceClock_Hz)
1101 {
1102 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1103 
1104     uint32_t instance = LPI2C_GetInstance(base);
1105 
1106     /* Ungate the clock. */
1107     CLOCK_EnableClock(kLpi2cClocks[instance]);
1108 #if defined(LPI2C_PERIPH_CLOCKS)
1109     /* Ungate the functional clock in initialize function. */
1110     CLOCK_EnableClock(kLpi2cPeriphClocks[instance]);
1111 #endif
1112 
1113 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1114 
1115     /* Restore to reset conditions. */
1116     LPI2C_SlaveReset(base);
1117 
1118     /* Configure peripheral. */
1119     base->SAMR = LPI2C_SAMR_ADDR0(slaveConfig->address0) | LPI2C_SAMR_ADDR1(slaveConfig->address1);
1120 
1121     base->SCFGR1 =
1122         LPI2C_SCFGR1_ADDRCFG(slaveConfig->addressMatchMode) | LPI2C_SCFGR1_IGNACK(slaveConfig->ignoreAck) |
1123         LPI2C_SCFGR1_RXCFG(slaveConfig->enableReceivedAddressRead) | LPI2C_SCFGR1_GCEN(slaveConfig->enableGeneralCall) |
1124         LPI2C_SCFGR1_ACKSTALL(slaveConfig->sclStall.enableAck) | LPI2C_SCFGR1_TXDSTALL(slaveConfig->sclStall.enableTx) |
1125         LPI2C_SCFGR1_RXSTALL(slaveConfig->sclStall.enableRx) |
1126         LPI2C_SCFGR1_ADRSTALL(slaveConfig->sclStall.enableAddress);
1127 
1128     base->SCFGR2 =
1129         LPI2C_SCFGR2_FILTSDA(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sdaGlitchFilterWidth_ns,
1130                                                      (LPI2C_SCFGR2_FILTSDA_MASK >> LPI2C_SCFGR2_FILTSDA_SHIFT), 1)) |
1131         LPI2C_SCFGR2_FILTSCL(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->sclGlitchFilterWidth_ns,
1132                                                      (LPI2C_SCFGR2_FILTSCL_MASK >> LPI2C_SCFGR2_FILTSCL_SHIFT), 1)) |
1133         LPI2C_SCFGR2_DATAVD(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->dataValidDelay_ns,
1134                                                     (LPI2C_SCFGR2_DATAVD_MASK >> LPI2C_SCFGR2_DATAVD_SHIFT), 1)) |
1135         LPI2C_SCFGR2_CLKHOLD(LPI2C_GetCyclesForWidth(sourceClock_Hz, slaveConfig->clockHoldTime_ns,
1136                                                      (LPI2C_SCFGR2_CLKHOLD_MASK >> LPI2C_SCFGR2_CLKHOLD_SHIFT), 1));
1137 
1138     /* Save SCR to last so we don't enable slave until it is configured */
1139     base->SCR = LPI2C_SCR_FILTDZ(slaveConfig->filterDozeEnable) | LPI2C_SCR_FILTEN(slaveConfig->filterEnable) |
1140                 LPI2C_SCR_SEN(slaveConfig->enableSlave);
1141 }
1142 
LPI2C_SlaveDeinit(LPI2C_Type * base)1143 void LPI2C_SlaveDeinit(LPI2C_Type *base)
1144 {
1145     LPI2C_SlaveReset(base);
1146 
1147 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1148 
1149     uint32_t instance = LPI2C_GetInstance(base);
1150 
1151     /* Gate the clock. */
1152     CLOCK_DisableClock(kLpi2cClocks[instance]);
1153 
1154 #if defined(LPI2C_PERIPH_CLOCKS)
1155     /* Gate the functional clock. */
1156     CLOCK_DisableClock(kLpi2cPeriphClocks[instance]);
1157 #endif
1158 
1159 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1160 }
1161 
1162 /*!
1163  * @brief Convert provided flags to status code, and clear any errors if present.
1164  * @param base The LPI2C peripheral base address.
1165  * @param status Current status flags value that will be checked.
1166  * @retval #kStatus_Success
1167  * @retval #kStatus_LPI2C_BitError
1168  * @retval #kStatus_LPI2C_FifoError
1169  */
LPI2C_SlaveCheckAndClearError(LPI2C_Type * base,uint32_t flags)1170 static status_t LPI2C_SlaveCheckAndClearError(LPI2C_Type *base, uint32_t flags)
1171 {
1172     status_t result = kStatus_Success;
1173 
1174     flags &= kSlaveErrorFlags;
1175     if (flags)
1176     {
1177         if (flags & kLPI2C_SlaveBitErrFlag)
1178         {
1179             result = kStatus_LPI2C_BitError;
1180         }
1181         else if (flags & kLPI2C_SlaveFifoErrFlag)
1182         {
1183             result = kStatus_LPI2C_FifoError;
1184         }
1185         else
1186         {
1187             assert(false);
1188         }
1189 
1190         /* Clear the errors. */
1191         LPI2C_SlaveClearStatusFlags(base, flags);
1192     }
1193 
1194     return result;
1195 }
1196 
LPI2C_SlaveSend(LPI2C_Type * base,const void * txBuff,size_t txSize,size_t * actualTxSize)1197 status_t LPI2C_SlaveSend(LPI2C_Type *base, const void *txBuff, size_t txSize, size_t *actualTxSize)
1198 {
1199     uint8_t *buf = (uint8_t *)((void *)txBuff);
1200     size_t remaining = txSize;
1201 
1202     assert(txBuff);
1203 
1204     while (remaining)
1205     {
1206         uint32_t flags;
1207         status_t result;
1208 
1209         /* Wait until we can transmit. */
1210         do
1211         {
1212             /* Check for errors */
1213             flags = LPI2C_SlaveGetStatusFlags(base);
1214             result = LPI2C_SlaveCheckAndClearError(base, flags);
1215             if (result)
1216             {
1217                 if (actualTxSize)
1218                 {
1219                     *actualTxSize = txSize - remaining;
1220                 }
1221                 return result;
1222             }
1223         } while (
1224             !(flags & (kLPI2C_SlaveTxReadyFlag | kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag)));
1225 
1226         /* Send a byte. */
1227         if (flags & kLPI2C_SlaveTxReadyFlag)
1228         {
1229             base->STDR = *buf++;
1230             --remaining;
1231         }
1232 
1233         /* Exit loop if we see a stop or restart */
1234         if (flags & (kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag))
1235         {
1236             LPI2C_SlaveClearStatusFlags(base, kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag);
1237             break;
1238         }
1239     }
1240 
1241     if (actualTxSize)
1242     {
1243         *actualTxSize = txSize - remaining;
1244     }
1245 
1246     return kStatus_Success;
1247 }
1248 
LPI2C_SlaveReceive(LPI2C_Type * base,void * rxBuff,size_t rxSize,size_t * actualRxSize)1249 status_t LPI2C_SlaveReceive(LPI2C_Type *base, void *rxBuff, size_t rxSize, size_t *actualRxSize)
1250 {
1251     uint8_t *buf = (uint8_t *)rxBuff;
1252     size_t remaining = rxSize;
1253 
1254     assert(rxBuff);
1255 
1256     while (remaining)
1257     {
1258         uint32_t flags;
1259         status_t result;
1260 
1261         /* Wait until we can receive. */
1262         do
1263         {
1264             /* Check for errors */
1265             flags = LPI2C_SlaveGetStatusFlags(base);
1266             result = LPI2C_SlaveCheckAndClearError(base, flags);
1267             if (result)
1268             {
1269                 if (actualRxSize)
1270                 {
1271                     *actualRxSize = rxSize - remaining;
1272                 }
1273                 return result;
1274             }
1275         } while (
1276             !(flags & (kLPI2C_SlaveRxReadyFlag | kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag)));
1277 
1278         /* Receive a byte. */
1279         if (flags & kLPI2C_SlaveRxReadyFlag)
1280         {
1281             *buf++ = base->SRDR & LPI2C_SRDR_DATA_MASK;
1282             --remaining;
1283         }
1284 
1285         /* Exit loop if we see a stop or restart */
1286         if (flags & (kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag))
1287         {
1288             LPI2C_SlaveClearStatusFlags(base, kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveRepeatedStartDetectFlag);
1289             break;
1290         }
1291     }
1292 
1293     if (actualRxSize)
1294     {
1295         *actualRxSize = rxSize - remaining;
1296     }
1297 
1298     return kStatus_Success;
1299 }
1300 
LPI2C_SlaveTransferCreateHandle(LPI2C_Type * base,lpi2c_slave_handle_t * handle,lpi2c_slave_transfer_callback_t callback,void * userData)1301 void LPI2C_SlaveTransferCreateHandle(LPI2C_Type *base,
1302                                      lpi2c_slave_handle_t *handle,
1303                                      lpi2c_slave_transfer_callback_t callback,
1304                                      void *userData)
1305 {
1306     uint32_t instance;
1307 
1308     assert(handle);
1309 
1310     /* Clear out the handle. */
1311     memset(handle, 0, sizeof(*handle));
1312 
1313     /* Look up instance number */
1314     instance = LPI2C_GetInstance(base);
1315 
1316     /* Save base and instance. */
1317     handle->callback = callback;
1318     handle->userData = userData;
1319 
1320     /* Save this handle for IRQ use. */
1321     s_lpi2cSlaveHandle[instance] = handle;
1322 
1323     /* Set irq handler. */
1324     s_lpi2cSlaveIsr = LPI2C_SlaveTransferHandleIRQ;
1325 
1326     /* Clear internal IRQ enables and enable NVIC IRQ. */
1327     LPI2C_SlaveDisableInterrupts(base, kSlaveIrqFlags);
1328     EnableIRQ(kLpi2cIrqs[instance]);
1329 
1330     /* Nack by default. */
1331     base->STAR = LPI2C_STAR_TXNACK_MASK;
1332 }
1333 
LPI2C_SlaveTransferNonBlocking(LPI2C_Type * base,lpi2c_slave_handle_t * handle,uint32_t eventMask)1334 status_t LPI2C_SlaveTransferNonBlocking(LPI2C_Type *base, lpi2c_slave_handle_t *handle, uint32_t eventMask)
1335 {
1336     uint32_t status;
1337 
1338     assert(handle);
1339 
1340     /* Return busy if another transaction is in progress. */
1341     if (handle->isBusy)
1342     {
1343         return kStatus_LPI2C_Busy;
1344     }
1345 
1346     /* Return an error if the bus is already in use not by us. */
1347     status = LPI2C_SlaveGetStatusFlags(base);
1348     if ((status & kLPI2C_SlaveBusBusyFlag) && (!(status & kLPI2C_SlaveBusyFlag)))
1349     {
1350         return kStatus_LPI2C_Busy;
1351     }
1352 
1353     /* Disable LPI2C IRQ sources while we configure stuff. */
1354     LPI2C_SlaveDisableInterrupts(base, kSlaveIrqFlags);
1355 
1356     /* Clear transfer in handle. */
1357     memset(&handle->transfer, 0, sizeof(handle->transfer));
1358 
1359     /* Record that we're busy. */
1360     handle->isBusy = true;
1361 
1362     /* Set up event mask. tx and rx are always enabled. */
1363     handle->eventMask = eventMask | kLPI2C_SlaveTransmitEvent | kLPI2C_SlaveReceiveEvent;
1364 
1365     /* Ack by default. */
1366     base->STAR = 0;
1367 
1368     /* Clear all flags. */
1369     LPI2C_SlaveClearStatusFlags(base, kSlaveClearFlags);
1370 
1371     /* Enable LPI2C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
1372     LPI2C_SlaveEnableInterrupts(base, kSlaveIrqFlags);
1373 
1374     return kStatus_Success;
1375 }
1376 
LPI2C_SlaveTransferGetCount(LPI2C_Type * base,lpi2c_slave_handle_t * handle,size_t * count)1377 status_t LPI2C_SlaveTransferGetCount(LPI2C_Type *base, lpi2c_slave_handle_t *handle, size_t *count)
1378 {
1379     assert(handle);
1380 
1381     if (!count)
1382     {
1383         return kStatus_InvalidArgument;
1384     }
1385 
1386     /* Catch when there is not an active transfer. */
1387     if (!handle->isBusy)
1388     {
1389         *count = 0;
1390         return kStatus_NoTransferInProgress;
1391     }
1392 
1393     /* For an active transfer, just return the count from the handle. */
1394     *count = handle->transferredCount;
1395 
1396     return kStatus_Success;
1397 }
1398 
LPI2C_SlaveTransferAbort(LPI2C_Type * base,lpi2c_slave_handle_t * handle)1399 void LPI2C_SlaveTransferAbort(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
1400 {
1401     assert(handle);
1402 
1403     /* Return idle if no transaction is in progress. */
1404     if (handle->isBusy)
1405     {
1406         /* Disable LPI2C IRQ sources. */
1407         LPI2C_SlaveDisableInterrupts(base, kSlaveIrqFlags);
1408 
1409         /* Nack by default. */
1410         base->STAR = LPI2C_STAR_TXNACK_MASK;
1411 
1412         /* Reset transfer info. */
1413         memset(&handle->transfer, 0, sizeof(handle->transfer));
1414 
1415         /* We're no longer busy. */
1416         handle->isBusy = false;
1417     }
1418 }
1419 
LPI2C_SlaveTransferHandleIRQ(LPI2C_Type * base,lpi2c_slave_handle_t * handle)1420 void LPI2C_SlaveTransferHandleIRQ(LPI2C_Type *base, lpi2c_slave_handle_t *handle)
1421 {
1422     uint32_t flags;
1423     lpi2c_slave_transfer_t *xfer;
1424 
1425     /* Check for a valid handle in case of a spurious interrupt. */
1426     if (!handle)
1427     {
1428         return;
1429     }
1430 
1431     xfer = &handle->transfer;
1432 
1433     /* Get status flags. */
1434     flags = LPI2C_SlaveGetStatusFlags(base);
1435 
1436     if (flags & (kLPI2C_SlaveBitErrFlag | kLPI2C_SlaveFifoErrFlag))
1437     {
1438         xfer->event = kLPI2C_SlaveCompletionEvent;
1439         xfer->completionStatus = LPI2C_SlaveCheckAndClearError(base, flags);
1440 
1441         if ((handle->eventMask & kLPI2C_SlaveCompletionEvent) && (handle->callback))
1442         {
1443             handle->callback(base, xfer, handle->userData);
1444         }
1445         return;
1446     }
1447     if (flags & (kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveStopDetectFlag))
1448     {
1449         xfer->event = (flags & kLPI2C_SlaveRepeatedStartDetectFlag) ? kLPI2C_SlaveRepeatedStartEvent :
1450                                                                       kLPI2C_SlaveCompletionEvent;
1451         xfer->receivedAddress = 0;
1452         xfer->completionStatus = kStatus_Success;
1453         xfer->transferredCount = handle->transferredCount;
1454 
1455         if (xfer->event == kLPI2C_SlaveCompletionEvent)
1456         {
1457             handle->isBusy = false;
1458         }
1459 
1460         if (handle->wasTransmit)
1461         {
1462             /* Subtract one from the transmit count to offset the fact that LPI2C asserts the */
1463             /* tx flag before it sees the nack from the master-receiver, thus causing one more */
1464             /* count that the master actually receives. */
1465             --xfer->transferredCount;
1466             handle->wasTransmit = false;
1467         }
1468 
1469         /* Clear the flag. */
1470         LPI2C_SlaveClearStatusFlags(base, flags & (kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveStopDetectFlag));
1471 
1472         /* Revert to sending an Ack by default, in case we sent a Nack for receive. */
1473         base->STAR = 0;
1474 
1475         if ((handle->eventMask & xfer->event) && (handle->callback))
1476         {
1477             handle->callback(base, xfer, handle->userData);
1478         }
1479 
1480         /* Clean up transfer info on completion, after the callback has been invoked. */
1481         memset(&handle->transfer, 0, sizeof(handle->transfer));
1482     }
1483     if (flags & kLPI2C_SlaveAddressValidFlag)
1484     {
1485         xfer->event = kLPI2C_SlaveAddressMatchEvent;
1486         xfer->receivedAddress = base->SASR & LPI2C_SASR_RADDR_MASK;
1487 
1488         if ((handle->eventMask & kLPI2C_SlaveAddressMatchEvent) && (handle->callback))
1489         {
1490             handle->callback(base, xfer, handle->userData);
1491         }
1492     }
1493     if (flags & kLPI2C_SlaveTransmitAckFlag)
1494     {
1495         xfer->event = kLPI2C_SlaveTransmitAckEvent;
1496 
1497         if ((handle->eventMask & kLPI2C_SlaveTransmitAckEvent) && (handle->callback))
1498         {
1499             handle->callback(base, xfer, handle->userData);
1500         }
1501     }
1502 
1503     /* Handle transmit and receive. */
1504     if (flags & kLPI2C_SlaveTxReadyFlag)
1505     {
1506         handle->wasTransmit = true;
1507 
1508         /* If we're out of data, invoke callback to get more. */
1509         if ((!xfer->data) || (!xfer->dataSize))
1510         {
1511             xfer->event = kLPI2C_SlaveTransmitEvent;
1512             if (handle->callback)
1513             {
1514                 handle->callback(base, xfer, handle->userData);
1515             }
1516 
1517             /* Clear the transferred count now that we have a new buffer. */
1518             handle->transferredCount = 0;
1519         }
1520 
1521         /* Transmit a byte. */
1522         if ((xfer->data) && (xfer->dataSize))
1523         {
1524             base->STDR = *xfer->data++;
1525             --xfer->dataSize;
1526             ++handle->transferredCount;
1527         }
1528     }
1529     if (flags & kLPI2C_SlaveRxReadyFlag)
1530     {
1531         /* If we're out of room in the buffer, invoke callback to get another. */
1532         if ((!xfer->data) || (!xfer->dataSize))
1533         {
1534             xfer->event = kLPI2C_SlaveReceiveEvent;
1535             if (handle->callback)
1536             {
1537                 handle->callback(base, xfer, handle->userData);
1538             }
1539 
1540             /* Clear the transferred count now that we have a new buffer. */
1541             handle->transferredCount = 0;
1542         }
1543 
1544         /* Receive a byte. */
1545         if ((xfer->data) && (xfer->dataSize))
1546         {
1547             *xfer->data++ = base->SRDR;
1548             --xfer->dataSize;
1549             ++handle->transferredCount;
1550         }
1551         else
1552         {
1553             /* We don't have any room to receive more data, so send a nack. */
1554             base->STAR = LPI2C_STAR_TXNACK_MASK;
1555         }
1556     }
1557 }
1558 
1559 /*!
1560  * @brief Shared IRQ handler that can call both master and slave ISRs.
1561  *
1562  * The master and slave ISRs are called through function pointers in order to decouple
1563  * this code from the ISR functions. Without this, the linker would always pull in both
1564  * ISRs and every function they call, even if only the functional API was used.
1565  *
1566  * @param base The LPI2C peripheral base address.
1567  * @param instance The LPI2C peripheral instance number.
1568  */
LPI2C_CommonIRQHandler(LPI2C_Type * base,uint32_t instance)1569 static void LPI2C_CommonIRQHandler(LPI2C_Type *base, uint32_t instance)
1570 {
1571     /* Check for master IRQ. */
1572     if ((base->MCR & LPI2C_MCR_MEN_MASK) && s_lpi2cMasterIsr)
1573     {
1574         /* Master mode. */
1575         s_lpi2cMasterIsr(base, s_lpi2cMasterHandle[instance]);
1576     }
1577 
1578     /* Check for slave IRQ. */
1579     if ((base->SCR & LPI2C_SCR_SEN_MASK) && s_lpi2cSlaveIsr)
1580     {
1581         /* Slave mode. */
1582         s_lpi2cSlaveIsr(base, s_lpi2cSlaveHandle[instance]);
1583     }
1584 }
1585 
1586 #if defined(LPI2C0)
1587 /* Implementation of LPI2C0 handler named in startup code. */
LPI2C0_DriverIRQHandler(void)1588 void LPI2C0_DriverIRQHandler(void)
1589 {
1590     LPI2C_CommonIRQHandler(LPI2C0, 0);
1591 }
1592 #endif
1593 
1594 #if defined(LPI2C1)
1595 /* Implementation of LPI2C1 handler named in startup code. */
LPI2C1_DriverIRQHandler(void)1596 void LPI2C1_DriverIRQHandler(void)
1597 {
1598     LPI2C_CommonIRQHandler(LPI2C1, 1);
1599 }
1600 #endif
1601 
1602 #if defined(LPI2C2)
1603 /* Implementation of LPI2C2 handler named in startup code. */
LPI2C2_DriverIRQHandler(void)1604 void LPI2C2_DriverIRQHandler(void)
1605 {
1606     LPI2C_CommonIRQHandler(LPI2C2, 2);
1607 }
1608 #endif
1609 
1610 #if defined(LPI2C3)
1611 /* Implementation of LPI2C3 handler named in startup code. */
LPI2C3_DriverIRQHandler(void)1612 void LPI2C3_DriverIRQHandler(void)
1613 {
1614     LPI2C_CommonIRQHandler(LPI2C3, 3);
1615 }
1616 #endif
1617 
1618 #if defined(CM4_0_LPI2C)
1619 /* Implementation of CM4_0_LPI2C handler named in startup code. */
M4_0_LPI2C_IRQHandler(void)1620 void M4_0_LPI2C_IRQHandler(void)
1621 {
1622     LPI2C_CommonIRQHandler(CM4_0_LPI2C, LPI2C_GetInstance(CM4_0_LPI2C));
1623 }
1624 #endif
1625 
1626 #if defined(CM4_1_LPI2C)
1627 /* Implementation of CM4_1_LPI2C handler named in startup code. */
M4_1_LPI2C_IRQHandler(void)1628 void M4_1_LPI2C_IRQHandler(void)
1629 {
1630     LPI2C_CommonIRQHandler(CM4_1_LPI2C, LPI2C_GetInstance(CM4_1_LPI2C));
1631 }
1632 #endif
1633 
1634 #if defined(DMA_LPI2C0)
1635 /* Implementation of DMA_LPI2C0 handler named in startup code. */
DMA_I2C0_INT_IRQHandler(void)1636 void DMA_I2C0_INT_IRQHandler(void)
1637 {
1638     LPI2C_CommonIRQHandler(DMA_LPI2C0, LPI2C_GetInstance(DMA_LPI2C0));
1639 }
1640 #endif
1641 
1642 #if defined(DMA_LPI2C1)
1643 /* Implementation of DMA_LPI2C1 handler named in startup code. */
DMA_I2C1_INT_IRQHandler(void)1644 void DMA_I2C1_INT_IRQHandler(void)
1645 {
1646     LPI2C_CommonIRQHandler(DMA_LPI2C1, LPI2C_GetInstance(DMA_LPI2C1));
1647 }
1648 #endif
1649 
1650 #if defined(DMA_LPI2C2)
1651 /* Implementation of DMA_LPI2C2 handler named in startup code. */
DMA_I2C2_INT_IRQHandler(void)1652 void DMA_I2C2_INT_IRQHandler(void)
1653 {
1654     LPI2C_CommonIRQHandler(DMA_LPI2C2, LPI2C_GetInstance(DMA_LPI2C2));
1655 }
1656 #endif
1657 
1658 #if defined(DMA_LPI2C3)
1659 /* Implementation of DMA_LPI2C3 handler named in startup code. */
DMA_I2C3_INT_IRQHandler(void)1660 void DMA_I2C3_INT_IRQHandler(void)
1661 {
1662     LPI2C_CommonIRQHandler(DMA_LPI2C3, LPI2C_GetInstance(DMA_LPI2C3));
1663 }
1664 #endif
1665 
1666 #if defined(DMA_LPI2C4)
1667 /* Implementation of DMA_LPI2C3 handler named in startup code. */
DMA_I2C4_INT_IRQHandler(void)1668 void DMA_I2C4_INT_IRQHandler(void)
1669 {
1670     LPI2C_CommonIRQHandler(DMA_LPI2C4, LPI2C_GetInstance(DMA_LPI2C4));
1671 }
1672 #endif
1673