1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #ifndef _FSL_FLEXIO_I2C_MASTER_H_
9 #define _FSL_FLEXIO_I2C_MASTER_H_
10 
11 #include "fsl_common.h"
12 #include "fsl_flexio.h"
13 
14 /*!
15  * @addtogroup flexio_i2c_master
16  * @{
17  */
18 
19 /*******************************************************************************
20  * Definitions
21  ******************************************************************************/
22 
23 /*! @name Driver version */
24 /*@{*/
25 /*! @brief FlexIO I2C master driver version 2.4.0. */
26 #define FSL_FLEXIO_I2C_MASTER_DRIVER_VERSION (MAKE_VERSION(2, 4, 0))
27 /*@}*/
28 
29 /*! @brief Retry times for waiting flag. */
30 #ifndef I2C_RETRY_TIMES
31 #define I2C_RETRY_TIMES 0U /* Define to zero means keep waiting until the flag is assert/deassert. */
32 #endif
33 
34 /*! @brief FlexIO I2C transfer status*/
35 enum
36 {
37     kStatus_FLEXIO_I2C_Busy    = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 0), /*!< I2C is busy doing transfer. */
38     kStatus_FLEXIO_I2C_Idle    = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 1), /*!< I2C is busy doing transfer. */
39     kStatus_FLEXIO_I2C_Nak     = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 2), /*!< NAK received during transfer. */
40     kStatus_FLEXIO_I2C_Timeout = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 3), /*!< Timeout polling status flags. */
41 };
42 
43 /*! @brief Define FlexIO I2C master interrupt mask. */
44 enum _flexio_i2c_master_interrupt
45 {
46     kFLEXIO_I2C_TxEmptyInterruptEnable = 0x1U, /*!< Tx buffer empty interrupt enable. */
47     kFLEXIO_I2C_RxFullInterruptEnable  = 0x2U, /*!< Rx buffer full interrupt enable. */
48 };
49 
50 /*! @brief Define FlexIO I2C master status mask. */
51 enum _flexio_i2c_master_status_flags
52 {
53     kFLEXIO_I2C_TxEmptyFlag    = 0x1U, /*!< Tx shifter empty flag. */
54     kFLEXIO_I2C_RxFullFlag     = 0x2U, /*!< Rx shifter full/Transfer complete flag. */
55     kFLEXIO_I2C_ReceiveNakFlag = 0x4U, /*!< Receive NAK flag. */
56 };
57 
58 /*! @brief Direction of master transfer.*/
59 typedef enum _flexio_i2c_direction
60 {
61     kFLEXIO_I2C_Write = 0x0U, /*!< Master send to slave. */
62     kFLEXIO_I2C_Read  = 0x1U, /*!< Master receive from slave. */
63 } flexio_i2c_direction_t;
64 
65 /*! @brief Define FlexIO I2C master access structure typedef. */
66 typedef struct _flexio_i2c_type
67 {
68     FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
69     uint8_t SDAPinIndex;     /*!< Pin select for I2C SDA. */
70     uint8_t SCLPinIndex;     /*!< Pin select for I2C SCL. */
71     uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO I2C. */
72     uint8_t timerIndex[3];   /*!< Timer index used in FlexIO I2C. */
73     uint32_t baudrate;       /*!< Master transfer baudrate, used to calculate delay time. */
74 } FLEXIO_I2C_Type;
75 
76 /*! @brief Define FlexIO I2C master user configuration structure. */
77 typedef struct _flexio_i2c_master_config
78 {
79     bool enableMaster;     /*!< Enables the FlexIO I2C peripheral at initialization time. */
80     bool enableInDoze;     /*!< Enable/disable FlexIO operation in doze mode. */
81     bool enableInDebug;    /*!< Enable/disable FlexIO operation in debug mode. */
82     bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers, fast access requires
83                            the FlexIO clock to be at least twice the frequency of the bus clock. */
84     uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
85 } flexio_i2c_master_config_t;
86 
87 /*! @brief Define FlexIO I2C master transfer structure. */
88 typedef struct _flexio_i2c_master_transfer
89 {
90     uint32_t flags;                   /*!< Transfer flag which controls the transfer, reserved for FlexIO I2C. */
91     uint8_t slaveAddress;             /*!< 7-bit slave address. */
92     flexio_i2c_direction_t direction; /*!< Transfer direction, read or write. */
93     uint32_t subaddress;              /*!< Sub address. Transferred MSB first. */
94     uint8_t subaddressSize;           /*!< Size of command buffer. */
95     uint8_t volatile *data;           /*!< Transfer buffer. */
96     volatile size_t dataSize;         /*!< Transfer size. */
97 } flexio_i2c_master_transfer_t;
98 
99 /*! @brief FlexIO I2C master handle typedef. */
100 typedef struct _flexio_i2c_master_handle flexio_i2c_master_handle_t;
101 
102 /*! @brief FlexIO I2C master transfer callback typedef. */
103 typedef void (*flexio_i2c_master_transfer_callback_t)(FLEXIO_I2C_Type *base,
104                                                       flexio_i2c_master_handle_t *handle,
105                                                       status_t status,
106                                                       void *userData);
107 
108 /*! @brief Define FlexIO I2C master handle structure. */
109 struct _flexio_i2c_master_handle
110 {
111     flexio_i2c_master_transfer_t transfer;                    /*!< FlexIO I2C master transfer copy. */
112     size_t transferSize;                                      /*!< Total bytes to be transferred. */
113     uint8_t state;                                            /*!< Transfer state maintained during transfer. */
114     flexio_i2c_master_transfer_callback_t completionCallback; /*!< Callback function called at transfer event. */
115                                                               /*!< Callback function called at transfer event. */
116     void *userData;                                           /*!< Callback parameter passed to callback function. */
117     bool needRestart;                                         /*!< Whether master needs to send re-start signal. */
118 };
119 
120 /*******************************************************************************
121  * API
122  ******************************************************************************/
123 
124 #if defined(__cplusplus)
125 extern "C" {
126 #endif /*_cplusplus*/
127 
128 /*!
129  * @name Initialization and deinitialization
130  * @{
131  */
132 
133 #if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
134 /*!
135  * @brief Make sure the bus isn't already pulled down.
136  *
137  * Check the FLEXIO pin status to see whether either of SDA and SCL pin is pulled down.
138  *
139  * @param base Pointer to FLEXIO_I2C_Type structure..
140  * @retval kStatus_Success
141  * @retval kStatus_FLEXIO_I2C_Busy
142  */
143 status_t FLEXIO_I2C_CheckForBusyBus(FLEXIO_I2C_Type *base);
144 #endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
145 
146 /*!
147  * @brief Ungates the FlexIO clock, resets the FlexIO module, and configures the FlexIO I2C
148  * hardware configuration.
149  *
150  * Example
151    @code
152    FLEXIO_I2C_Type base = {
153    .flexioBase = FLEXIO,
154    .SDAPinIndex = 0,
155    .SCLPinIndex = 1,
156    .shifterIndex = {0,1},
157    .timerIndex = {0,1}
158    };
159    flexio_i2c_master_config_t config = {
160    .enableInDoze = false,
161    .enableInDebug = true,
162    .enableFastAccess = false,
163    .baudRate_Bps = 100000
164    };
165    FLEXIO_I2C_MasterInit(base, &config, srcClock_Hz);
166    @endcode
167  *
168  * @param base Pointer to FLEXIO_I2C_Type structure.
169  * @param masterConfig Pointer to flexio_i2c_master_config_t structure.
170  * @param srcClock_Hz FlexIO source clock in Hz.
171  * @retval kStatus_Success Initialization successful
172  * @retval kStatus_InvalidArgument The source clock exceed upper range limitation
173 */
174 status_t FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
175 
176 /*!
177  * @brief De-initializes the FlexIO I2C master peripheral. Calling this API Resets the FlexIO I2C master
178  * shifer and timer config, module can't work unless the FLEXIO_I2C_MasterInit is called.
179  *
180  * @param base pointer to FLEXIO_I2C_Type structure.
181  */
182 void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base);
183 
184 /*!
185  * @brief Gets the default configuration to configure the FlexIO module. The configuration
186  * can be used directly for calling the FLEXIO_I2C_MasterInit().
187  *
188  * Example:
189    @code
190    flexio_i2c_master_config_t config;
191    FLEXIO_I2C_MasterGetDefaultConfig(&config);
192    @endcode
193  * @param masterConfig Pointer to flexio_i2c_master_config_t structure.
194 */
195 void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig);
196 
197 /*!
198  * @brief Enables/disables the FlexIO module operation.
199  *
200  * @param base Pointer to FLEXIO_I2C_Type structure.
201  * @param enable Pass true to enable module, false does not have any effect.
202  */
FLEXIO_I2C_MasterEnable(FLEXIO_I2C_Type * base,bool enable)203 static inline void FLEXIO_I2C_MasterEnable(FLEXIO_I2C_Type *base, bool enable)
204 {
205     if (enable)
206     {
207         base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
208     }
209 }
210 
211 /* @} */
212 
213 /*!
214  * @name Status
215  * @{
216  */
217 
218 /*!
219  * @brief Gets the FlexIO I2C master status flags.
220  *
221  * @param base Pointer to FLEXIO_I2C_Type structure
222  * @return Status flag, use status flag to AND #_flexio_i2c_master_status_flags can get the related status.
223  */
224 
225 uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base);
226 
227 /*!
228  * @brief Clears the FlexIO I2C master status flags.
229  *
230  * @param base Pointer to FLEXIO_I2C_Type structure.
231  * @param mask Status flag.
232  *      The parameter can be any combination of the following values:
233  *          @arg kFLEXIO_I2C_RxFullFlag
234  *          @arg kFLEXIO_I2C_ReceiveNakFlag
235  */
236 
237 void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask);
238 
239 /*@}*/
240 
241 /*!
242  * @name Interrupts
243  * @{
244  */
245 
246 /*!
247  * @brief Enables the FlexIO i2c master interrupt requests.
248  *
249  * @param base Pointer to FLEXIO_I2C_Type structure.
250  * @param mask Interrupt source.
251  *     Currently only one interrupt request source:
252  *     @arg kFLEXIO_I2C_TransferCompleteInterruptEnable
253  */
254 void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
255 
256 /*!
257  * @brief Disables the FlexIO I2C master interrupt requests.
258  *
259  * @param base Pointer to FLEXIO_I2C_Type structure.
260  * @param mask Interrupt source.
261  */
262 void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
263 
264 /*@}*/
265 
266 /*!
267  * @name Bus Operations
268  * @{
269  */
270 
271 /*!
272  * @brief Sets the FlexIO I2C master transfer baudrate.
273  *
274  * @param base Pointer to FLEXIO_I2C_Type structure
275  * @param baudRate_Bps the baud rate value in HZ
276  * @param srcClock_Hz source clock in HZ
277  */
278 void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
279 
280 /*!
281  * @brief Sends START + 7-bit address to the bus.
282  *
283  * @note This API should be called when the transfer configuration is ready to send a START signal
284  * and 7-bit address to the bus. This is a non-blocking API, which returns directly after the address
285  * is put into the data register but the address transfer is not finished on the bus. Ensure that
286  * the kFLEXIO_I2C_RxFullFlag status is asserted before calling this API.
287  * @param base Pointer to FLEXIO_I2C_Type structure.
288  * @param address 7-bit address.
289  * @param direction transfer direction.
290  *     This parameter is one of the values in flexio_i2c_direction_t:
291  *        @arg kFLEXIO_I2C_Write: Transmit
292  *        @arg kFLEXIO_I2C_Read:  Receive
293  */
294 
295 void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction);
296 
297 /*!
298  * @brief Sends the stop signal on the bus.
299  *
300  * @param base Pointer to FLEXIO_I2C_Type structure.
301  */
302 void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base);
303 
304 /*!
305  * @brief Sends the repeated start signal on the bus.
306  *
307  * @param base Pointer to FLEXIO_I2C_Type structure.
308  */
309 void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base);
310 
311 /*!
312  * @brief Sends the stop signal when transfer is still on-going.
313  *
314  * @param base Pointer to FLEXIO_I2C_Type structure.
315  */
316 void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base);
317 
318 /*!
319  * @brief Configures the sent ACK/NAK for the following byte.
320  *
321  * @param base Pointer to FLEXIO_I2C_Type structure.
322  * @param enable True to configure send ACK, false configure to send NAK.
323  */
324 void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable);
325 
326 /*!
327  * @brief Sets the number of bytes to be transferred from a start signal to a stop signal.
328  *
329  * @note Call this API before a transfer begins because the timer generates a number of clocks according
330  * to the number of bytes that need to be transferred.
331  *
332  * @param base Pointer to FLEXIO_I2C_Type structure.
333  * @param count Number of bytes need to be transferred from a start signal to a re-start/stop signal
334  * @retval kStatus_Success Successfully configured the count.
335  * @retval kStatus_InvalidArgument Input argument is invalid.
336  */
337 status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint16_t count);
338 
339 /*!
340  * @brief Writes one byte of data to the I2C bus.
341  *
342  * @note This is a non-blocking API, which returns directly after the data is put into the
343  * data register but the data transfer is not finished on the bus. Ensure that
344  * the TxEmptyFlag is asserted before calling this API.
345  *
346  * @param base Pointer to FLEXIO_I2C_Type structure.
347  * @param data a byte of data.
348  */
FLEXIO_I2C_MasterWriteByte(FLEXIO_I2C_Type * base,uint32_t data)349 static inline void FLEXIO_I2C_MasterWriteByte(FLEXIO_I2C_Type *base, uint32_t data)
350 {
351     base->flexioBase->SHIFTBUFBBS[base->shifterIndex[0]] = data;
352 }
353 
354 /*!
355  * @brief Reads one byte of data from the I2C bus.
356  *
357  * @note This is a non-blocking API, which returns directly after the data is read from the
358  * data register. Ensure that the data is ready in the register.
359  *
360  * @param base Pointer to FLEXIO_I2C_Type structure.
361  * @return data byte read.
362  */
FLEXIO_I2C_MasterReadByte(FLEXIO_I2C_Type * base)363 static inline uint8_t FLEXIO_I2C_MasterReadByte(FLEXIO_I2C_Type *base)
364 {
365     return (uint8_t)(base->flexioBase->SHIFTBUFBIS[base->shifterIndex[1]]);
366 }
367 
368 /*!
369  * @brief Sends a buffer of data in bytes.
370  *
371  * @note This function blocks via polling until all bytes have been sent.
372  *
373  * @param base Pointer to FLEXIO_I2C_Type structure.
374  * @param txBuff The data bytes to send.
375  * @param txSize The number of data bytes to send.
376  * @retval kStatus_Success Successfully write data.
377  * @retval kStatus_FLEXIO_I2C_Nak Receive NAK during writing data.
378  * @retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
379  */
380 status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize);
381 
382 /*!
383  * @brief Receives a buffer of bytes.
384  *
385  * @note This function blocks via polling until all bytes have been received.
386  *
387  * @param base Pointer to FLEXIO_I2C_Type structure.
388  * @param rxBuff The buffer to store the received bytes.
389  * @param rxSize The number of data bytes to be received.
390  * @retval kStatus_Success Successfully read data.
391  * @retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
392  */
393 status_t FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize);
394 
395 /*!
396  * @brief Performs a master polling transfer on the I2C bus.
397  *
398  * @note The API does not return until the transfer succeeds or fails due
399  * to receiving NAK.
400  *
401  * @param base pointer to FLEXIO_I2C_Type structure.
402  * @param xfer pointer to flexio_i2c_master_transfer_t structure.
403  * @return status of status_t.
404  */
405 status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_transfer_t *xfer);
406 /*@}*/
407 
408 /*Transactional APIs*/
409 
410 /*!
411  * @name Transactional
412  * @{
413  */
414 
415 /*!
416  * @brief Initializes the I2C handle which is used in transactional functions.
417  *
418  * @param base Pointer to FLEXIO_I2C_Type structure.
419  * @param handle Pointer to flexio_i2c_master_handle_t structure to store the transfer state.
420  * @param callback Pointer to user callback function.
421  * @param userData User param passed to the callback function.
422  * @retval kStatus_Success Successfully create the handle.
423  * @retval kStatus_OutOfRange The FlexIO type/handle/isr table out of range.
424  */
425 status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
426                                                flexio_i2c_master_handle_t *handle,
427                                                flexio_i2c_master_transfer_callback_t callback,
428                                                void *userData);
429 
430 /*!
431  * @brief Performs a master interrupt non-blocking transfer on the I2C bus.
432  *
433  * @note The API returns immediately after the transfer initiates.
434  * Call FLEXIO_I2C_MasterTransferGetCount to poll the transfer status to check whether
435  * the transfer is finished. If the return status is not kStatus_FLEXIO_I2C_Busy, the transfer
436  * is finished.
437  *
438  * @param base Pointer to FLEXIO_I2C_Type structure
439  * @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
440  * @param xfer pointer to flexio_i2c_master_transfer_t structure
441  * @retval kStatus_Success Successfully start a transfer.
442  * @retval kStatus_FLEXIO_I2C_Busy FlexIO I2C is not idle, is running another transfer.
443  */
444 status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
445                                               flexio_i2c_master_handle_t *handle,
446                                               flexio_i2c_master_transfer_t *xfer);
447 
448 /*!
449  * @brief Gets the master transfer status during a interrupt non-blocking transfer.
450  *
451  * @param base Pointer to FLEXIO_I2C_Type structure.
452  * @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
453  * @param count Number of bytes transferred so far by the non-blocking transaction.
454  * @retval kStatus_InvalidArgument count is Invalid.
455  * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
456  * @retval kStatus_Success Successfully return the count.
457  */
458 status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count);
459 
460 /*!
461  * @brief Aborts an interrupt non-blocking transfer early.
462  *
463  * @note This API can be called at any time when an interrupt non-blocking transfer initiates
464  * to abort the transfer early.
465  *
466  * @param base Pointer to FLEXIO_I2C_Type structure
467  * @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
468  */
469 void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle);
470 
471 /*!
472  * @brief Master interrupt handler.
473  *
474  * @param i2cType Pointer to FLEXIO_I2C_Type structure
475  * @param i2cHandle Pointer to flexio_i2c_master_transfer_t structure
476  */
477 void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle);
478 
479 /*@}*/
480 
481 #if defined(__cplusplus)
482 }
483 #endif /*_cplusplus*/
484 /*@}*/
485 
486 #endif /*_FSL_FLEXIO_I2C_MASTER_H_*/
487