1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_i2c_drv.h"
9
10 #ifndef HPM_I2C_DRV_DEFAULT_TPM
11 #define HPM_I2C_DRV_DEFAULT_TPM (0U)
12 #endif
13
14 #ifndef HPM_I2C_DRV_DEFAULT_SCL_RATIO
15 #define HPM_I2C_DRV_DEFAULT_SCL_RATIO (1U)
16 #endif
17
18 #ifndef HPM_I2C_DRV_DEFAULT_RETRY_COUNT
19 #define HPM_I2C_DRV_DEFAULT_RETRY_COUNT (5000U)
20 #endif
21
22 #define period_in_ns(freq) (1000000000UL / (freq))
23
24 typedef struct {
25 uint32_t t_high;
26 uint32_t t_low;
27 uint16_t t_sp;
28 uint16_t t_sudat;
29 uint16_t t_hddat;
30 uint16_t t_sclhi_min1;
31 uint16_t t_sclhi_min2;
32 uint16_t t_sclratio;
33 } i2c_timing_t;
34
i2c_configure_timing(uint32_t src_clk_in_hz,i2c_mode_t i2c_mode,i2c_timing_t * timing)35 static hpm_stat_t i2c_configure_timing(uint32_t src_clk_in_hz,
36 i2c_mode_t i2c_mode,
37 i2c_timing_t *timing)
38 {
39 switch (i2c_mode) {
40 /*
41 * |Standard mode | Fast mode | Fast mode plus | Uint
42 * ---------+--------------+-----------+----------------+-------
43 * t_high | 4.0 | 0.6 | 0.26 | us
44 * t_low | 4.7 | 1.3 | 0.5 | us
45 *
46 */
47 case i2c_mode_fast:
48 timing->t_high = 600;
49 timing->t_low = 1300;
50 break;
51 case i2c_mode_fast_plus:
52 timing->t_high = 260;
53 timing->t_low = 500;
54 break;
55 case i2c_mode_normal:
56 timing->t_high = 4000;
57 timing->t_low = 4700;
58 break;
59 default:
60 return status_i2c_not_supported;
61 }
62
63 /*
64 * Spike Suppression | Standard | Fast mode | Fast mode plus | Uint
65 * | mode | | |
66 * ------------------+----------+-----------+----------------+-------
67 * t_sp (min) | - | 0 - 50 | 0 - 50 | ns
68 *
69 * T_SP = 50ns / (25ns * (TPM + 1))
70 */
71 timing->t_sp = 50 / period_in_ns(src_clk_in_hz) / (HPM_I2C_DRV_DEFAULT_TPM + 1);
72
73 /*
74 * Setup time |Standard mode | Fast mode | Fast mode plus | Uint
75 * -----------------+--------------+-----------+----------------+-------
76 * t_sudat (min) | 250 | 100 | 50 | ns
77 *
78 * Setup time = (2 * tpclk) + (2 + T_SP + T_SUDAT) * tpclk * (TPM + 1)
79 */
80 timing->t_sudat = (250 - 2 * period_in_ns(src_clk_in_hz)) / period_in_ns(src_clk_in_hz) - 2 - timing->t_sp;
81
82 /*
83 * Hold time |Standard mode | Fast mode | Fast mode plus | Uint
84 * ----------------+--------------+-----------+----------------+-------
85 * t_hddata (min) | 300 | 300 | 0 | ns
86 *
87 * Hold time = (2 * tpclk) + (2 + T_SP + T_HDDAT) * tpclk * (TPM + 1)
88 */
89 timing->t_hddat = (300 - 2 * period_in_ns(src_clk_in_hz)) / period_in_ns(src_clk_in_hz) - 2 - timing->t_sp;
90
91 /*
92 * SCLK High period = (2 * tpclk) + (2 + T_SP + T_SCLHi) * tpclk * (TPM + 1) > t_high;
93 */
94 timing->t_sclhi_min1 = (timing->t_high - 2 * period_in_ns(src_clk_in_hz))
95 / (HPM_I2C_DRV_DEFAULT_TPM + 1) / period_in_ns(src_clk_in_hz) - 2 - timing->t_sp;
96
97 /*
98 * SCLK Low period = (2 * tpclk) + (2 + T_SP + T_SCLHi * ratio) * tpclk * (TPM + 1) > t_low;
99 */
100 timing->t_sclhi_min2 = ((timing->t_low - 2 * period_in_ns(src_clk_in_hz))
101 / (HPM_I2C_DRV_DEFAULT_TPM + 1) / period_in_ns(src_clk_in_hz) - 2 - timing->t_sp)
102 / (timing->t_sclratio);
103
104 return status_success;
105 }
106
i2c_reset(I2C_Type * ptr)107 void i2c_reset(I2C_Type *ptr)
108 {
109 ptr->CTRL = 0;
110 ptr->CMD = I2C_CMD_RESET;
111 ptr->SETUP &= ~I2C_SETUP_IICEN_MASK;
112 }
113
i2c_init_master(I2C_Type * ptr,uint32_t src_clk_in_hz,i2c_config_t * config)114 hpm_stat_t i2c_init_master(I2C_Type *ptr, uint32_t src_clk_in_hz, i2c_config_t *config)
115 {
116 hpm_stat_t stat = status_success;
117 i2c_timing_t timing = {0};
118
119 i2c_reset(ptr);
120
121 timing.t_sclratio = HPM_I2C_DRV_DEFAULT_SCL_RATIO;
122 stat = i2c_configure_timing(src_clk_in_hz, config->i2c_mode, &timing);
123 if (status_success != stat) {
124 return stat;
125 }
126
127 ptr->TPM = I2C_TPM_TPM_SET(HPM_I2C_DRV_DEFAULT_TPM);
128
129 ptr->SETUP = I2C_SETUP_T_SP_SET(timing.t_sp)
130 | I2C_SETUP_T_SUDAT_SET(timing.t_sudat)
131 | I2C_SETUP_T_HDDAT_SET(timing.t_hddat)
132 | I2C_SETUP_T_SCLRADIO_SET(timing.t_sclratio - 1)
133 | I2C_SETUP_T_SCLHI_SET(MAX(timing.t_sclhi_min1, timing.t_sclhi_min2))
134 | I2C_SETUP_ADDRESSING_SET(config->is_10bit_addressing)
135 | I2C_SETUP_IICEN_MASK
136 | I2C_SETUP_MASTER_MASK;
137
138 return status_success;
139 }
140
i2c_master_address_read(I2C_Type * ptr,const uint16_t device_address,uint8_t * addr,uint8_t addr_size_in_byte,uint8_t * buf,const uint32_t size_in_byte)141 hpm_stat_t i2c_master_address_read(I2C_Type *ptr, const uint16_t device_address,
142 uint8_t *addr, uint8_t addr_size_in_byte,
143 uint8_t *buf, const uint32_t size_in_byte)
144 {
145 hpm_stat_t stat = status_success;
146 uint32_t left;
147 uint32_t retry;
148
149 ptr->CMD = I2C_CMD_RESET;
150
151 ptr->CMD = I2C_CMD_CLEAR_FIFO;
152 ptr->CTRL = I2C_CTRL_PHASE_START_MASK
153 | I2C_CTRL_PHASE_STOP_MASK
154 | I2C_CTRL_PHASE_ADDR_MASK
155 | I2C_CTRL_PHASE_DATA_MASK
156 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE)
157 | I2C_CTRL_DATACNT_SET(addr_size_in_byte);
158
159 ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
160
161 left = addr_size_in_byte;
162 while (left) {
163 ptr->DATA = *(addr++);
164 left--;
165 }
166 ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
167
168 retry = 0;
169 while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
170 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
171 break;
172 }
173 retry++;
174 }
175 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
176 return status_timeout;
177 }
178
179 ptr->CMD = I2C_CMD_CLEAR_FIFO;
180 ptr->CTRL = I2C_CTRL_PHASE_START_MASK
181 | I2C_CTRL_PHASE_STOP_MASK
182 | I2C_CTRL_PHASE_ADDR_MASK
183 | I2C_CTRL_PHASE_DATA_MASK
184 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ)
185 | I2C_CTRL_DATACNT_SET(size_in_byte);
186 ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
187
188 retry = 0;
189 left = size_in_byte;
190 while (left) {
191 if (!(ptr->STATUS & I2C_STATUS_FIFOEMPTY_MASK)) {
192 *(buf++) = ptr->DATA;
193 left--;
194 retry = 0;
195 } else {
196 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
197 break;
198 }
199 retry++;
200 }
201 }
202
203 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
204 return status_timeout;
205 }
206
207 retry = 0;
208 while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
209 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
210 break;
211 }
212 retry++;
213 }
214 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
215 return status_timeout;
216 }
217 ptr->STATUS |= I2C_STATUS_CMPL_MASK;
218 return stat;
219 }
220
i2c_master_address_write(I2C_Type * ptr,const uint16_t device_address,uint8_t * addr,uint8_t addr_size_in_byte,uint8_t * buf,const uint32_t size_in_byte)221 hpm_stat_t i2c_master_address_write(I2C_Type *ptr, const uint16_t device_address,
222 uint8_t *addr, uint8_t addr_size_in_byte,
223 uint8_t *buf, const uint32_t size_in_byte)
224 {
225 hpm_stat_t stat = status_success;
226 uint32_t left;
227 uint32_t retry;
228
229 ptr->CMD = I2C_CMD_RESET;
230
231 ptr->CMD = I2C_CMD_CLEAR_FIFO;
232 ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
233 ptr->CTRL = I2C_CTRL_PHASE_START_MASK
234 | I2C_CTRL_PHASE_STOP_MASK
235 | I2C_CTRL_PHASE_ADDR_MASK
236 | I2C_CTRL_PHASE_DATA_MASK
237 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE)
238 | I2C_CTRL_DATACNT_SET(size_in_byte + addr_size_in_byte);
239
240 left = addr_size_in_byte;
241 while (left) {
242 ptr->DATA = *(addr++);
243 left--;
244 }
245 ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
246
247 retry = 0;
248 left = size_in_byte;
249 while (left) {
250 if (!(ptr->STATUS & I2C_STATUS_FIFOFULL_MASK)) {
251 ptr->DATA = *(buf++);
252 left--;
253 retry = 0;
254 } else {
255 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
256 break;
257 }
258 retry++;
259 }
260 }
261 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
262 return status_timeout;
263 }
264
265 retry = 0;
266 while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
267 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
268 break;
269 } else {
270 retry++;
271 }
272 }
273
274 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
275 return status_timeout;
276 }
277
278 ptr->STATUS |= I2C_STATUS_CMPL_MASK;
279
280 ptr->CMD = I2C_CMD_RESET;
281 return stat;
282 }
283
i2c_master_read(I2C_Type * ptr,const uint16_t device_address,uint8_t * buf,const uint32_t size)284 hpm_stat_t i2c_master_read(I2C_Type *ptr, const uint16_t device_address,
285 uint8_t *buf, const uint32_t size)
286 {
287 hpm_stat_t stat = status_success;
288 uint32_t left;
289 uint32_t retry;
290
291 ptr->CMD = I2C_CMD_CLEAR_FIFO;
292 ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
293 ptr->CTRL = I2C_CTRL_PHASE_START_MASK
294 | I2C_CTRL_PHASE_STOP_MASK
295 | I2C_CTRL_PHASE_ADDR_MASK
296 | I2C_CTRL_PHASE_DATA_MASK
297 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ)
298 | I2C_CTRL_DATACNT_SET(size);
299 ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
300
301 retry = 0;
302 left = size;
303 while (left) {
304 if (!(ptr->STATUS & I2C_STATUS_FIFOEMPTY_MASK)) {
305 *(buf++) = ptr->DATA;
306 left--;
307 if (left) {
308 ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
309 }
310 retry = 0;
311 } else {
312 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
313 break;
314 }
315 retry++;
316 }
317 }
318 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
319 return status_timeout;
320 }
321
322 retry = 0;
323 while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
324 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
325 break;
326 }
327 retry++;
328 };
329 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
330 return status_timeout;
331 }
332
333 if (!(ptr->STATUS & I2C_STATUS_ADDRHIT_MASK)) {
334 /* I2C slave did not receive this transaction correctly. */
335 return status_fail;
336 }
337
338 ptr->STATUS |= I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK;
339
340 ptr->INTEN = 0;
341 if (i2c_get_data_count(ptr)) {
342 return status_i2c_transmit_not_completed;
343 }
344
345 return stat;
346 }
347
i2c_master_write(I2C_Type * ptr,const uint16_t device_address,uint8_t * buf,const uint32_t size)348 hpm_stat_t i2c_master_write(I2C_Type *ptr, const uint16_t device_address,
349 uint8_t *buf, const uint32_t size)
350 {
351 hpm_stat_t stat = status_success;
352 uint32_t retry;
353 uint32_t left;
354
355 ptr->CMD = I2C_CMD_CLEAR_FIFO;
356 ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
357 ptr->CTRL = I2C_CTRL_PHASE_START_MASK
358 | I2C_CTRL_PHASE_STOP_MASK
359 | I2C_CTRL_PHASE_ADDR_MASK
360 | I2C_CTRL_PHASE_DATA_MASK
361 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE)
362 | I2C_CTRL_DATACNT_SET(size);
363
364 retry = 0;
365 left = size;
366 while (left) {
367 if (!(ptr->STATUS & I2C_STATUS_FIFOFULL_MASK)) {
368 ptr->DATA = *(buf++);
369 left--;
370 ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
371 retry = 0;
372 } else {
373 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
374 break;
375 }
376 retry++;
377 }
378 }
379 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
380 return status_timeout;
381 }
382
383 retry = 0;
384 while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
385 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
386 break;
387 }
388 retry++;
389 }
390 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
391 return status_timeout;
392 }
393 ptr->STATUS |= I2C_STATUS_CMPL_MASK;
394
395 ptr->INTEN = 0;
396 if (i2c_get_data_count(ptr)) {
397 return status_i2c_transmit_not_completed;
398 }
399
400 ptr->CMD = I2C_CMD_RESET;
401 return stat;
402 }
403
i2c_init_slave(I2C_Type * ptr,uint32_t src_clk_in_hz,i2c_config_t * config,const uint16_t slave_address)404 hpm_stat_t i2c_init_slave(I2C_Type *ptr, uint32_t src_clk_in_hz,
405 i2c_config_t *config, const uint16_t slave_address)
406 {
407 hpm_stat_t stat = status_success;
408 i2c_timing_t timing = {0};
409
410 i2c_reset(ptr);
411
412 ptr->ADDR = I2C_ADDR_ADDR_SET(slave_address);
413
414 timing.t_sclratio = HPM_I2C_DRV_DEFAULT_SCL_RATIO;
415 stat = i2c_configure_timing(src_clk_in_hz, config->i2c_mode, &timing);
416 if (status_success != stat) {
417 return stat;
418 }
419
420 ptr->TPM = I2C_TPM_TPM_SET(HPM_I2C_DRV_DEFAULT_TPM);
421
422 ptr->SETUP = I2C_SETUP_T_SP_SET(timing.t_sp)
423 | I2C_SETUP_T_SUDAT_SET(timing.t_sudat)
424 | I2C_SETUP_T_HDDAT_SET(timing.t_hddat)
425 | I2C_SETUP_T_SCLRADIO_SET(timing.t_sclratio - 1)
426 | I2C_SETUP_T_SCLHI_SET(MAX(timing.t_sclhi_min1, timing.t_sclhi_min2))
427 | I2C_SETUP_ADDRESSING_SET(config->is_10bit_addressing)
428 | I2C_SETUP_IICEN_MASK;
429
430 return stat;
431 }
432
i2c_slave_write(I2C_Type * ptr,uint8_t * buf,const uint32_t size)433 hpm_stat_t i2c_slave_write(I2C_Type *ptr, uint8_t *buf, const uint32_t size)
434 {
435 volatile uint32_t status;
436 uint32_t retry;
437 uint32_t left;
438
439 retry = 0;
440 left = size;
441 while (left) {
442 status = ptr->STATUS;
443 if (!(status & I2C_STATUS_FIFOFULL_MASK)) {
444 ptr->DATA = *(buf++);
445 left--;
446 retry = 0;
447 } else {
448 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
449 break;
450 }
451 retry++;
452 }
453 }
454 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
455 return status_timeout;
456 }
457
458 retry = 0;
459 while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
460 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
461 break;
462 }
463 retry++;
464 }
465 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
466 return status_timeout;
467 }
468 /* clear status, CMPL must to be cleared at slave mode before next transaction */
469 i2c_clear_status(ptr, ptr->STATUS);
470
471 if (i2c_get_data_count(ptr) != size) {
472 return status_i2c_transmit_not_completed;
473 }
474
475 return status_success;
476 }
477
i2c_slave_read(I2C_Type * ptr,uint8_t * buf,const uint32_t size)478 hpm_stat_t i2c_slave_read(I2C_Type *ptr,
479 uint8_t *buf,
480 const uint32_t size)
481 {
482 volatile uint32_t status;
483 uint32_t retry;
484 uint32_t left;
485
486 retry = 0;
487 left = size;
488 while (left) {
489 status = ptr->STATUS;
490 if (!(status & I2C_STATUS_FIFOEMPTY_MASK)) {
491 *(buf++) = ptr->DATA;
492 left--;
493 retry = 0;
494 } else {
495 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
496 break;
497 }
498 retry++;
499 }
500 }
501 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
502 return status_timeout;
503 }
504
505 retry = 0;
506 while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
507 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
508 break;
509 }
510 retry++;
511 }
512 if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
513 return status_timeout;
514 }
515 /* clear status, CMPL must to be cleared at slave mode before next transaction */
516 i2c_clear_status(ptr, ptr->STATUS);
517
518 if (i2c_get_data_count(ptr) != size) {
519 return status_i2c_transmit_not_completed;
520 }
521
522 return status_success;
523 }
524
i2c_master_start_dma_write(I2C_Type * i2c_ptr,const uint16_t device_address,uint32_t size)525 void i2c_master_start_dma_write(I2C_Type *i2c_ptr, const uint16_t device_address, uint32_t size)
526 {
527 i2c_ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
528 i2c_ptr->CTRL = I2C_CTRL_PHASE_START_MASK
529 | I2C_CTRL_PHASE_STOP_MASK
530 | I2C_CTRL_PHASE_ADDR_MASK
531 | I2C_CTRL_PHASE_DATA_MASK
532 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE)
533 | I2C_CTRL_DATACNT_SET(size);
534
535 i2c_ptr->SETUP |= I2C_SETUP_DMAEN_MASK;
536
537 i2c_ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
538 }
539
i2c_master_start_dma_read(I2C_Type * i2c_ptr,const uint16_t device_address,uint32_t size)540 void i2c_master_start_dma_read(I2C_Type *i2c_ptr, const uint16_t device_address, uint32_t size)
541 {
542 i2c_ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
543 i2c_ptr->CTRL = I2C_CTRL_PHASE_START_MASK
544 | I2C_CTRL_PHASE_STOP_MASK
545 | I2C_CTRL_PHASE_ADDR_MASK
546 | I2C_CTRL_PHASE_DATA_MASK
547 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ)
548 | I2C_CTRL_DATACNT_SET(size);
549
550 i2c_ptr->SETUP |= I2C_SETUP_DMAEN_MASK;
551
552 i2c_ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
553 }
554
i2c_slave_dma_transfer(I2C_Type * i2c_ptr,uint32_t size)555 void i2c_slave_dma_transfer(I2C_Type *i2c_ptr, uint32_t size)
556 {
557 i2c_ptr->CTRL |= I2C_CTRL_DATACNT_SET(size);
558
559 i2c_ptr->SETUP |= I2C_SETUP_DMAEN_MASK;
560 }
561