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