• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef HPM_I2C_DRV_H
9 #define HPM_I2C_DRV_H
10 #include "hpm_common.h"
11 #include "hpm_i2c_regs.h"
12 #include "hpm_soc_feature.h"
13 
14 /**
15  * @brief I2C driver APIs
16  * @defgroup i2c_interface I2C driver APIs
17  * @ingroup io_interfaces
18  * @{
19  */
20 
21 /**
22  * @brief I2C status
23  */
24 enum {
25     status_i2c_no_ack = MAKE_STATUS(status_group_i2c, 1),
26     status_i2c_invalid_data = MAKE_STATUS(status_group_i2c, 2),
27     status_i2c_no_addr_hit = MAKE_STATUS(status_group_i2c, 3),
28     status_i2c_transmit_not_completed = MAKE_STATUS(status_group_i2c, 4),
29     status_i2c_not_supported = MAKE_STATUS(status_group_i2c, 9),
30 };
31 
32 /**
33  * @brief I2C CMD
34  */
35 #define I2C_CMD_NO_ACTION (I2C_CMD_CMD_SET(0))
36 #define I2C_CMD_ISSUE_DATA_TRANSMISSION (I2C_CMD_CMD_SET(1))
37 #define I2C_CMD_ACK (I2C_CMD_CMD_SET(2))
38 #define I2C_CMD_NACK (I2C_CMD_CMD_SET(3))
39 #define I2C_CMD_CLEAR_FIFO (I2C_CMD_CMD_SET(4))
40 #define I2C_CMD_RESET (I2C_CMD_CMD_SET(5))
41 
42 /**
43  * @brief I2C data direction
44  */
45 #define I2C_DIR_MASTER_WRITE (0U)
46 #define I2C_DIR_MASTER_READ (1U)
47 #define I2C_DIR_SLAVE_READ (0U)
48 #define I2C_DIR_SLAVE_WRITE (1U)
49 
50 /**
51  * @brief I2C events for interrupt enable and status check
52  */
53 #define I2C_EVENT_TRANSACTION_COMPLETE  I2C_INTEN_CMPL_MASK
54 #define I2C_EVENT_BYTE_RECEIVED         I2C_INTEN_BYTERECV_MASK
55 #define I2C_EVENT_BYTE_TRANSMIT         I2C_INTEN_BYTETRANS_MASK
56 #define I2C_EVENT_START_CONDITION       I2C_INTEN_START_MASK
57 #define I2C_EVENT_STOP_CONDITION        I2C_INTEN_STOP_MASK
58 #define I2C_EVENT_LOSS_ARBITRATION      I2C_INTEN_ARBLOSE_MASK
59 #define I2C_EVENT_ADDRESS_HIT           I2C_INTEN_ADDRHIT_MASK
60 #define I2C_EVENT_FIFO_HALF             I2C_INTEN_FIFOHALF_MASK
61 #define I2C_EVENT_FIFO_FULL             I2C_INTEN_FIFOFULL_MASK
62 #define I2C_EVENT_FIFO_EMPTY            I2C_INTEN_FIFOEMPTY_MASK
63 
64 #define I2C_EVENT_ALL_MASK          (I2C_INTEN_CMPL_MASK \
65                                         | I2C_INTEN_BYTERECV_MASK \
66                                         | I2C_INTEN_BYTETRANS_MASK \
67                                         | I2C_INTEN_START_MASK \
68                                         | I2C_INTEN_STOP_MASK \
69                                         | I2C_INTEN_ARBLOSE_MASK \
70                                         | I2C_INTEN_ADDRHIT_MASK \
71                                         | I2C_INTEN_FIFOHALF_MASK \
72                                         | I2C_INTEN_FIFOFULL_MASK \
73                                         | I2C_INTEN_FIFOEMPTY_MASK)
74 /**
75  * @brief I2C status for status check only
76  */
77 #define I2C_STATUS_LINE_SDA             I2C_STATUS_LINESDA_MASK
78 #define I2C_STATUS_LINE_SCL             I2C_STATUS_LINESCL_MASK
79 #define I2C_STATUS_GENERAL_CALL         I2C_STATUS_GENCALL_MASK
80 #define I2C_STATUS_BUS_BUSY             I2C_STATUS_BUSBUSY_MASK
81 #define I2C_STATUS_ACK                  I2C_STATUS_ACK_MASK
82 
83 /**
84  * @brief I2C config
85  */
86 typedef struct {
87     bool is_10bit_addressing;
88     uint8_t i2c_mode;
89 } i2c_config_t;
90 
91 /**
92  * @brief I2C mode
93  */
94 typedef enum i2c_mode {
95     i2c_mode_normal,
96     i2c_mode_fast,
97     i2c_mode_fast_plus,
98 } i2c_mode_t;
99 
100 #ifdef __cplusplus
101 extern "C" {
102 #endif
103 
104 /**
105  * @brief respond NACK
106  *
107  * @param [in] ptr I2C base address
108  */
i2c_respond_Nack(I2C_Type * ptr)109 static inline void i2c_respond_Nack(I2C_Type *ptr)
110 {
111     ptr->CMD = I2C_CMD_NACK;
112 }
113 
114 /**
115  * @brief respond ACK
116  *
117  * @param [in] ptr I2C base address
118  */
i2c_respond_ack(I2C_Type * ptr)119 static inline void i2c_respond_ack(I2C_Type *ptr)
120 {
121     ptr->CMD = I2C_CMD_ACK;
122 }
123 
124 /**
125  * @brief clear I2C fifo
126  *
127  * @param [in] ptr I2C base address
128  */
i2c_clear_fifo(I2C_Type * ptr)129 static inline void i2c_clear_fifo(I2C_Type *ptr)
130 {
131     ptr->CMD = I2C_CMD_CLEAR_FIFO;
132 }
133 
134 /**
135  * @brief check data count
136  *
137  * @details It indicates number of bytes to transfer
138  *
139  * @param [in] ptr I2C base address
140  * @retval data count value in byte
141  */
i2c_get_data_count(I2C_Type * ptr)142 static inline uint8_t i2c_get_data_count(I2C_Type *ptr)
143 {
144     return I2C_CTRL_DATACNT_GET(ptr->CTRL);
145 }
146 
147 /**
148  * @brief check if I2C FIFO is full
149  *
150  * @param [in] ptr I2C base address
151  * @retval true if FIFO is full
152  */
i2c_fifo_is_full(I2C_Type * ptr)153 static inline bool i2c_fifo_is_full(I2C_Type *ptr)
154 {
155     return ptr->STATUS & I2C_STATUS_FIFOFULL_MASK;
156 }
157 
158 /**
159  * @brief check if I2C FIFO is half
160  *
161  * @note When I2C is transmitting data, it indicates if fifo is half-empty;
162  * @note When I2C is receiving data, it indicates if fifo is half full.
163  *
164  * @param [in] ptr I2C base address
165  * @retval true if FIFO is half empty or full
166  */
i2c_fifo_is_half(I2C_Type * ptr)167 static inline bool i2c_fifo_is_half(I2C_Type *ptr)
168 {
169     return ptr->STATUS & I2C_STATUS_FIFOHALF_MASK;
170 }
171 
172 /**
173  * @brief check if I2C FIFO is empty
174  *
175  * @param [in] ptr I2C base address
176  * @retval true if FIFO is empty
177  */
i2c_fifo_is_empty(I2C_Type * ptr)178 static inline bool i2c_fifo_is_empty(I2C_Type *ptr)
179 {
180     return ptr->STATUS & I2C_STATUS_FIFOEMPTY_MASK;
181 }
182 
183 /**
184  * @brief check if I2C is writing
185  *
186  * @param [in] ptr I2C base address
187  * @retval bool value
188  *  @arg true: receive data if master mode, send data in slave mode
189  *  @arg false: send data if master mode, reveive data in slave mode
190  *
191  */
i2c_is_writing(I2C_Type * ptr)192 static inline bool i2c_is_writing(I2C_Type *ptr)
193 {
194     return (ptr->CTRL & I2C_CTRL_DIR_MASK);
195 }
196 
197 /**
198  * @brief check if I2C is reading
199  *
200  * @param [in] ptr I2C base address
201  * @retval bool value
202  *  @arg true: send data if master mode, receive data in slave mode
203  *  @arg false: receive data if master mode, send data in slave mode
204  *
205  */
i2c_is_reading(I2C_Type * ptr)206 static inline bool i2c_is_reading(I2C_Type *ptr)
207 {
208     return !i2c_is_writing(ptr);
209 }
210 
211 /**
212  * @brief clear status
213  *
214  * @details Clear status based on mask
215  *
216  * @param [in] ptr I2C base address
217  * @param [in] mask mask to clear status
218  */
i2c_clear_status(I2C_Type * ptr,uint32_t mask)219 static inline void i2c_clear_status(I2C_Type *ptr, uint32_t mask)
220 {
221     ptr->STATUS |= (mask & I2C_EVENT_ALL_MASK);
222 }
223 
224 /**
225  * @brief get status
226  *
227  * @details Get current I2C status bits
228  *
229  * @param [in] ptr I2C base address
230  * @retval current I2C status
231  */
i2c_get_status(I2C_Type * ptr)232 static inline uint32_t i2c_get_status(I2C_Type *ptr)
233 {
234     return ptr->STATUS;
235 }
236 
237 /**
238  * @brief disable interrupts
239  *
240  * @details Disable interrupts based on given mask
241  *
242  * @param [in] ptr I2C base address
243  * @param [in] mask interrupt mask to be disabled
244  */
i2c_disable_irq(I2C_Type * ptr,uint32_t mask)245 static inline void i2c_disable_irq(I2C_Type *ptr, uint32_t mask)
246 {
247     ptr->INTEN &= ~mask;
248 }
249 
250 /**
251  * @brief enable interrupts
252  *
253  * @details Enable interrupts based on given mask
254  *
255  * @param [in] ptr I2C base address
256  * @param [in] mask interrupt mask to be enabled
257  */
i2c_enable_irq(I2C_Type * ptr,uint32_t mask)258 static inline void i2c_enable_irq(I2C_Type *ptr, uint32_t mask)
259 {
260     ptr->INTEN |= mask;
261 }
262 
263 /**
264  * @brief enable 10 bit address mode
265  *
266  * @details enable 10 bit address mode, if not, address is 7 bit mode
267  *
268  * @param [in] ptr I2C base address
269  * @param [in] enable
270  *  @arg true: enable 10 bit address mode
271  *  @arg false: enable 7 bit address mode
272  */
i2c_enable_10bit_address_mode(I2C_Type * ptr,bool enable)273 static inline void i2c_enable_10bit_address_mode(I2C_Type *ptr, bool enable)
274 {
275     ptr->SETUP |= I2C_SETUP_ADDRESSING_SET(enable);
276 }
277 
278 /**
279  * @brief I2C master initialization
280  *
281  * @details Initialized I2C controller working at master mode
282  *
283  * @param [in] ptr I2C base address
284  * @param [in] src_clk_in_hz I2C controller source clock source frequency in Hz
285  * @param [in] config i2c_config_t
286  * @retval hpm_stat_t: status_success if initialization is completed without any error
287  */
288 hpm_stat_t i2c_init_master(I2C_Type *ptr,
289                            uint32_t src_clk_in_hz,
290                            i2c_config_t *config);
291 
292 /**
293  * @brief I2C master write data to specific address of certain slave device
294  *
295  * @details Write to certain I2C device at specific address within that device
296  *
297  * @param [in] ptr I2C base address
298  * @param [in] device_address I2C slave address
299  * @param [in] addr address in that I2C device
300  * @param [in] addr_size_in_byte I2C address in byte
301  * @param [in] buf pointer of the data to be sent
302  * @param [in] size_in_byte size of data to be sent in bytes
303  * @retval hpm_stat_t: status_success if writing is completed without any error
304  */
305 hpm_stat_t i2c_master_address_write(I2C_Type *ptr,
306                             const uint16_t device_address,
307                             uint8_t *addr,
308                             uint8_t addr_size_in_byte,
309                             uint8_t *buf,
310                             const uint32_t size_in_byte);
311 
312 /**
313  * @brief I2C master read data from specific address of certain slave device
314  *
315  * @details Read fram certain I2C device at specific address within that device
316  *
317  * @param [in] ptr I2C base address
318  * @param [in] device_address I2C slave address
319  * @param [in] addr address in that I2C device
320  * @param [in] addr_size_in_byte I2C address in byte
321  * @param [out] buf pointer of the buffer to receive data read from the device
322  * @param [in] size size of data to be read in bytes
323  * @retval hpm_stat_t: status_success if reading is completed without any error
324  */
325 hpm_stat_t i2c_master_address_read(I2C_Type *ptr,
326                            const uint16_t device_address,
327                            uint8_t *addr,
328                            uint8_t addr_size_in_byte,
329                            uint8_t *buf,
330                            const uint32_t size);
331 
332 /**
333  * @brief I2C master write data to certain slave device
334  *
335  * @details Write data to I2C device
336  *
337  * @param [in] ptr I2C base address
338  * @param [in] device_address I2C slave address
339  * @param [in] buf pointer of the data to be sent
340  * @param [in] size size of data to be sent in bytes
341  * @retval hpm_stat_t: status_success if writing is completed without any error
342  */
343 hpm_stat_t i2c_master_write(I2C_Type *ptr,
344                             const uint16_t device_address,
345                             uint8_t *buf,
346                             const uint32_t size);
347 
348 /**
349  * @brief I2C master start write data by DMA
350  *
351  * @details Write data to I2C device by DMA
352  *
353  * @param [in] i2c_ptr I2C base address
354  * @param [in] device_address I2C slave address
355  * @param [in] size size of data to be sent in bytes
356  */
357 void i2c_master_start_dma_write(I2C_Type *i2c_ptr, const uint16_t device_address, uint32_t size);
358 
359 /**
360  * @brief I2C master start read data by DMA
361  *
362  * @details Read data to I2C device by DMA
363  *
364  * @param [in] i2c_ptr I2C base address
365  * @param [in] device_address I2C slave address
366  * @param [in] size size of data to be read in bytes
367  */
368 void i2c_master_start_dma_read(I2C_Type *i2c_ptr, const uint16_t device_address, uint32_t size);
369 
370 /**
371  * @brief I2C master read data from certain slave device
372  *
373  * @details Read data from I2C device
374  *
375  * @param [in] ptr I2C base address
376  * @param [in] device_address I2C slave address
377  * @param [out] buf pointer of the buffer to store data read from device
378  * @param [in] size size of data to be read in bytes
379  * @retval hpm_stat_t: status_success if reading is completed without any error
380  */
381 hpm_stat_t i2c_master_read(I2C_Type *ptr,
382                            const uint16_t device_address,
383                            uint8_t *buf,
384                            const uint32_t size);
385 /**
386  * @brief I2C slave initialization
387  *
388  * @details Initialize I2C controller working at slave mode
389  *
390  * @param [in] ptr I2C base address
391  * @param [in] src_clk_in_hz I2C controller source clock source frequency in Hz
392  * @param [in] config I2C configuration structure
393  * @param [in] slave_address I2C address to be used at slave mode
394  * @retval hpm_stat_t: status_success if initialization is completed without any error
395  */
396 hpm_stat_t i2c_init_slave(I2C_Type *ptr, uint32_t src_clk_in_hz,
397                           i2c_config_t *config, const uint16_t slave_address);
398 
399 /**
400  * @brief I2C slave read data
401  *
402  * @details Read data at slave mode
403  *
404  * @param [in] ptr I2C base address
405  * @param [in] buf pointer of the buffer to store data read from device
406  * @param [in] size size of data to be read in bytes
407  * @retval hpm_stat_t: status_success if reading is completed without any error
408  */
409 hpm_stat_t i2c_slave_read(I2C_Type *ptr, uint8_t *buf, const uint32_t size);
410 
411 /**
412  * @brief I2C slave write data
413  *
414  * @details Write data at slave mode.
415  *
416  * @param [in] ptr I2C base address
417  * @param [in] buf pointer of the buffer to store data sent from device
418  * @param [in] size size of data to be sent in bytes
419  * @retval hpm_stat_t status_success if writing is completed without any error
420  */
421 hpm_stat_t i2c_slave_write(I2C_Type *ptr, uint8_t *buf, const uint32_t size);
422 
423 /**
424  * @brief reset I2C
425  *
426  * @param [in] ptr I2C base address
427  */
428 void i2c_reset(I2C_Type *ptr);
429 
430 /**
431  * @brief Enable i2c DMA
432  *
433  * @param [in] ptr I2C base address
434  */
i2c_dma_enable(I2C_Type * ptr)435 static inline void i2c_dma_enable(I2C_Type *ptr)
436 {
437     ptr->SETUP |= I2C_SETUP_DMAEN_MASK;
438 }
439 
440 /**
441  * @brief Disable i2c DMA
442  *
443  * @param [in] ptr I2C base address
444  */
i2c_dma_disable(I2C_Type * ptr)445 static inline void i2c_dma_disable(I2C_Type *ptr)
446 {
447     ptr->SETUP &= ~I2C_SETUP_DMAEN_MASK;
448 }
449 
450 /**
451  * @brief I2C slave dma transfer data
452  *
453  * @note The direction of data transmission depends on Master setting
454  *
455  * @param [in] ptr I2C base address
456  * @param [in] size size of data in bytes
457  */
458 void i2c_slave_dma_transfer(I2C_Type *ptr,  const uint32_t size);
459 
460 /**
461  * @}
462  */
463 
464 #ifdef __cplusplus
465 }
466 #endif
467 
468 #endif /* HPM_I2C_DRV_H */
469 
470