• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_RETRY_COUNT
15 #define HPM_I2C_DRV_DEFAULT_RETRY_COUNT (5000U)
16 #endif
17 
18 #define period_in_100ps(freq) (10000000000UL / (freq))
19 
20 typedef struct {
21     uint32_t t_high;
22     uint32_t t_low;
23     uint16_t t_sp;
24     uint16_t t_sudat;
25     uint16_t t_hddat;
26     uint16_t t_sclhi;
27     uint16_t t_sclratio;
28 } i2c_timing_t;
29 
i2c_configure_timing(uint32_t src_clk_in_hz,i2c_mode_t i2c_mode,i2c_timing_t * timing)30 static hpm_stat_t i2c_configure_timing(uint32_t src_clk_in_hz,
31                                        i2c_mode_t i2c_mode,
32                                        i2c_timing_t *timing)
33 {
34     int32_t setup_time, hold_time, period;
35     int32_t temp1, temp2, temp3;
36     int32_t tpclk = period_in_100ps(src_clk_in_hz);
37 
38     switch (i2c_mode) {
39     /*
40      *          |Standard mode | Fast mode | Fast mode plus | Uint
41      * ---------+--------------+-----------+----------------+-------
42      *  t_high  |     4.0      |    0.6    |     0.26       |   us
43      *  t_low   |     4.7      |    1.3    |     0.5        |   us
44      *
45      */
46     /* time uint: 100ps */
47     case i2c_mode_fast:
48         timing->t_high = 6000;
49         timing->t_low = 13000;
50         timing->t_sclratio = 2;
51         setup_time = 1000;
52         hold_time = 3000;
53         period = period_in_100ps(400000); /**< baudrate 400KHz */
54         break;
55     case i2c_mode_fast_plus:
56         timing->t_high = 2600;
57         timing->t_low = 5000;
58         timing->t_sclratio = 2;
59         setup_time = 500;
60         hold_time = 0;
61         period = period_in_100ps(1000000); /**< baudrate 1MHz */
62         break;
63     case i2c_mode_normal:
64         timing->t_high = 40000;
65         timing->t_low = 47000;
66         timing->t_sclratio = 1;
67         setup_time = 2500;
68         hold_time = 3000;
69         period = period_in_100ps(100000); /**< baudrate 100KHz */
70         break;
71     default:
72         return status_i2c_not_supported;
73     }
74 
75     /*
76      * Spike Suppression | Standard | Fast mode | Fast mode plus | Uint
77      *                   | mode     |           |                |
78      * ------------------+----------+-----------+----------------+-------
79      *    t_sp (min)     |    -     |  0 - 50   |    0 - 50      |   ns
80      *
81      * T_SP = 50ns / (tpclk * (TPM + 1))
82      */
83     timing->t_sp = 500 / period_in_100ps(src_clk_in_hz) / (HPM_I2C_DRV_DEFAULT_TPM + 1);
84 
85     /*
86      * Setup time       |Standard mode | Fast mode | Fast mode plus | Uint
87      * -----------------+--------------+-----------+----------------+-------
88      *  t_sudat (min)   |     250      |    100    |     50         |   ns
89      *
90      * Setup time = (2 * tpclk) + (2 + T_SP + T_SUDAT) * tpclk * (TPM + 1)
91      */
92     temp1 = (setup_time - 2 * tpclk) / tpclk / (HPM_I2C_DRV_DEFAULT_TPM + 1) - 2 - timing->t_sp;
93     timing->t_sudat = MAX(temp1, 0);
94     /*
95      * Hold time       |Standard mode | Fast mode | Fast mode plus | Uint
96      * ----------------+--------------+-----------+----------------+-------
97      *  t_hddata (min) |     300      |    300    |     0          |   ns
98      *
99      * Hold time = (2 * tpclk) + (2 + T_SP + T_HDDAT) * tpclk * (TPM + 1)
100      */
101     temp1 = (hold_time - 2 * tpclk) / tpclk / (HPM_I2C_DRV_DEFAULT_TPM + 1) - 2 - timing->t_sp;
102     timing->t_hddat = MAX(temp1, 0);
103 
104     /*
105      * SCLK High period = (2 * tpclk) + (2 + T_SP + T_SCLHi) * tpclk * (TPM + 1) > t_high;
106      */
107     temp1 = (timing->t_high - 2 * tpclk) / tpclk / (HPM_I2C_DRV_DEFAULT_TPM + 1) - 2 - timing->t_sp;
108 
109     /*
110      * SCLK High period = (2 * tpclk) + (2 + T_SP + T_SCLHi) * tpclk * (TPM + 1) > period / (1 + ratio);
111      */
112     temp2 = (period / (1 + timing->t_sclratio) - 2 * tpclk) / tpclk / (HPM_I2C_DRV_DEFAULT_TPM + 1) - 2 - timing->t_sp;
113 
114     /*
115      * SCLK Low period = (2 * tpclk) + (2 + T_SP + T_SCLHi * ratio) * tpclk * (TPM + 1) > t_low;
116      */
117     temp3 = ((timing->t_low - 2 * tpclk) / tpclk / (HPM_I2C_DRV_DEFAULT_TPM + 1) - 2 - timing->t_sp) / (timing->t_sclratio);
118 
119     timing->t_sclhi = MAX(MAX(temp1, temp2), temp3);
120 
121     /* update high_period and low_period to calculated value */
122     timing->t_high = 2 * tpclk + (2 + timing->t_sp + timing->t_sclhi) * tpclk;
123     timing->t_low = timing->t_high * timing->t_sclratio;
124 
125     return status_success;
126 }
127 
i2c_reset(I2C_Type * ptr)128 void i2c_reset(I2C_Type *ptr)
129 {
130     ptr->CTRL = 0;
131     ptr->CMD = I2C_CMD_RESET;
132     ptr->SETUP &= ~I2C_SETUP_IICEN_MASK;
133 }
134 
i2c_init_master(I2C_Type * ptr,uint32_t src_clk_in_hz,i2c_config_t * config)135 hpm_stat_t i2c_init_master(I2C_Type *ptr, uint32_t src_clk_in_hz, i2c_config_t *config)
136 {
137     hpm_stat_t stat = status_success;
138     i2c_timing_t timing = {0};
139 
140     i2c_reset(ptr);
141 
142     stat = i2c_configure_timing(src_clk_in_hz, config->i2c_mode, &timing);
143     if (status_success != stat) {
144         return stat;
145     }
146 
147     ptr->TPM = I2C_TPM_TPM_SET(HPM_I2C_DRV_DEFAULT_TPM);
148 
149     ptr->SETUP = I2C_SETUP_T_SP_SET(timing.t_sp)
150         | I2C_SETUP_T_SUDAT_SET(timing.t_sudat)
151         | I2C_SETUP_T_HDDAT_SET(timing.t_hddat)
152         | I2C_SETUP_T_SCLRADIO_SET(timing.t_sclratio - 1)
153         | I2C_SETUP_T_SCLHI_SET(timing.t_sclhi)
154         | I2C_SETUP_ADDRESSING_SET(config->is_10bit_addressing)
155         | I2C_SETUP_IICEN_MASK
156         | I2C_SETUP_MASTER_MASK;
157 
158     return status_success;
159 }
160 
i2c_master_address_read(I2C_Type * ptr,const uint16_t device_address,uint8_t * addr,uint32_t addr_size_in_byte,uint8_t * buf,const uint32_t size_in_byte)161 hpm_stat_t i2c_master_address_read(I2C_Type *ptr, const uint16_t device_address,
162                                    uint8_t *addr, uint32_t addr_size_in_byte,
163                                    uint8_t *buf, const uint32_t size_in_byte)
164 {
165     hpm_stat_t stat = status_success;
166     uint32_t left;
167     uint32_t retry;
168     if (((addr_size_in_byte == 0) || (addr_size_in_byte > I2C_SOC_TRANSFER_COUNT_MAX)) ||
169         ((size_in_byte == 0) || (size_in_byte > I2C_SOC_TRANSFER_COUNT_MAX))) {
170         return status_invalid_argument;
171     }
172 
173     retry = 0;
174     while (ptr->STATUS & I2C_STATUS_BUSBUSY_MASK) {
175         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
176             break;
177         }
178         retry++;
179     }
180     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
181         return status_timeout;
182     }
183 
184     /* W1C, clear CMPL bit to avoid blocking the transmission */
185     ptr->STATUS = I2C_STATUS_CMPL_MASK;
186 
187     ptr->CMD = I2C_CMD_CLEAR_FIFO;
188     ptr->CTRL = I2C_CTRL_PHASE_START_MASK
189         | I2C_CTRL_PHASE_ADDR_MASK
190         | I2C_CTRL_PHASE_DATA_MASK
191         | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE)
192         | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(addr_size_in_byte) >> 8U)
193         | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(addr_size_in_byte));
194 
195     ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
196 
197     left = addr_size_in_byte;
198     while (left) {
199         ptr->DATA = *(addr++);
200         left--;
201     }
202     ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
203 
204     /* Before starting to transmit data, judge addrhit to ensure that the slave address exists on the bus. */
205     retry = 0;
206     while (!(ptr->STATUS & I2C_STATUS_ADDRHIT_MASK)) {
207         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
208             break;
209         }
210         retry++;
211     }
212     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
213         /* the address misses, a stop needs to be added to prevent the bus from being busy. */
214         ptr->STATUS = I2C_STATUS_CMPL_MASK;
215         ptr->CTRL = I2C_CTRL_PHASE_STOP_MASK;
216         ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
217         return status_i2c_no_addr_hit;
218     }
219     ptr->STATUS = I2C_STATUS_ADDRHIT_MASK;
220 
221     retry = 0;
222     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
223         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
224             break;
225         }
226         retry++;
227     }
228     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
229         return status_timeout;
230     }
231     /* W1C, clear CMPL bit to avoid blocking the transmission */
232     ptr->STATUS = I2C_STATUS_CMPL_MASK;
233 
234     ptr->CMD = I2C_CMD_CLEAR_FIFO;
235     ptr->CTRL = I2C_CTRL_PHASE_START_MASK
236         | I2C_CTRL_PHASE_STOP_MASK
237         | I2C_CTRL_PHASE_ADDR_MASK
238         | I2C_CTRL_PHASE_DATA_MASK
239         | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ)
240         | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(addr_size_in_byte) >> 8U)
241         | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size_in_byte));
242     ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
243 
244     retry = 0;
245     left = size_in_byte;
246     while (left) {
247         if (!(ptr->STATUS & I2C_STATUS_FIFOEMPTY_MASK)) {
248             *(buf++) = ptr->DATA;
249             left--;
250             retry = 0;
251         } else {
252             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
253                 break;
254             }
255             retry++;
256         }
257     }
258 
259     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
260         return status_timeout;
261     }
262 
263     retry = 0;
264     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
265         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
266             break;
267         }
268         retry++;
269     }
270     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
271         return status_timeout;
272     }
273     return stat;
274 }
275 
i2c_master_address_write(I2C_Type * ptr,const uint16_t device_address,uint8_t * addr,uint32_t addr_size_in_byte,uint8_t * buf,const uint32_t size_in_byte)276 hpm_stat_t i2c_master_address_write(I2C_Type *ptr, const uint16_t device_address,
277                                     uint8_t *addr, uint32_t addr_size_in_byte,
278                                     uint8_t *buf, const uint32_t size_in_byte)
279 {
280     hpm_stat_t stat = status_success;
281     uint32_t left;
282     uint32_t retry;
283 
284     if (((addr_size_in_byte == 0) || (addr_size_in_byte > I2C_SOC_TRANSFER_COUNT_MAX)) ||
285         ((size_in_byte == 0) || (size_in_byte > I2C_SOC_TRANSFER_COUNT_MAX)) ||
286         ((addr_size_in_byte + size_in_byte) > I2C_SOC_TRANSFER_COUNT_MAX)) {
287         return status_invalid_argument;
288     }
289 
290     retry = 0;
291     while (ptr->STATUS & I2C_STATUS_BUSBUSY_MASK) {
292         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
293             break;
294         }
295         retry++;
296     }
297     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
298         return status_timeout;
299     }
300 
301     /* W1C, clear CMPL bit to avoid blocking the transmission */
302     ptr->STATUS = I2C_STATUS_CMPL_MASK;
303 
304     ptr->CMD = I2C_CMD_CLEAR_FIFO;
305     ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
306     ptr->CTRL = I2C_CTRL_PHASE_START_MASK
307         | I2C_CTRL_PHASE_STOP_MASK
308         | I2C_CTRL_PHASE_ADDR_MASK
309         | I2C_CTRL_PHASE_DATA_MASK
310         | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE)
311         | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size_in_byte + addr_size_in_byte) >> 8U)
312         | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size_in_byte + addr_size_in_byte));
313 
314     left = addr_size_in_byte;
315     while (left) {
316         ptr->DATA = *(addr++);
317         left--;
318     }
319     ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
320 
321     /* Before starting to transmit data, judge addrhit to ensure that the slave address exists on the bus. */
322     retry = 0;
323     while (!(ptr->STATUS & I2C_STATUS_ADDRHIT_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_i2c_no_addr_hit;
331     }
332     ptr->STATUS = I2C_STATUS_ADDRHIT_MASK;
333 
334     retry = 0;
335     left = size_in_byte;
336     while (left) {
337         if (!(ptr->STATUS & I2C_STATUS_FIFOFULL_MASK)) {
338             ptr->DATA = *(buf++);
339             left--;
340             retry = 0;
341         } else {
342             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
343                 break;
344             }
345             retry++;
346         }
347     }
348     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
349         return status_timeout;
350     }
351 
352     retry = 0;
353     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
354         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
355             break;
356         } else {
357             retry++;
358         }
359     }
360 
361     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
362         return status_timeout;
363     }
364 
365     return stat;
366 }
367 
i2c_master_read(I2C_Type * ptr,const uint16_t device_address,uint8_t * buf,const uint32_t size)368 hpm_stat_t i2c_master_read(I2C_Type *ptr, const uint16_t device_address,
369                            uint8_t *buf, const uint32_t size)
370 {
371     hpm_stat_t stat = status_success;
372     uint32_t left;
373     uint32_t retry;
374     if (size > I2C_SOC_TRANSFER_COUNT_MAX) {
375         return status_invalid_argument;
376     }
377 
378     retry = 0;
379     while (ptr->STATUS & I2C_STATUS_BUSBUSY_MASK) {
380         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
381             break;
382         }
383         retry++;
384     }
385     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
386         return status_timeout;
387     }
388 
389     /* W1C, clear CMPL bit to avoid blocking the transmission */
390     ptr->STATUS = I2C_STATUS_CMPL_MASK;
391 
392     ptr->CMD = I2C_CMD_CLEAR_FIFO;
393     ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
394     ptr->CTRL = I2C_CTRL_PHASE_START_MASK
395         | I2C_CTRL_PHASE_STOP_MASK
396         | I2C_CTRL_PHASE_ADDR_MASK
397         | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ);
398     if (size > 0) {
399         ptr->CTRL |= I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U)
400                     | I2C_CTRL_PHASE_DATA_MASK
401                     | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
402     }
403     ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
404 
405     /* Before starting to transmit data, judge addrhit to ensure that the slave address exists on the bus. */
406     retry = 0;
407     while (!(ptr->STATUS & I2C_STATUS_ADDRHIT_MASK)) {
408         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
409             break;
410         }
411         retry++;
412     }
413     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
414         return status_i2c_no_addr_hit;
415     }
416     ptr->STATUS = I2C_STATUS_ADDRHIT_MASK;
417     /* when size is zero, it's probe slave device, so directly return success */
418     if (size == 0) {
419         return status_success;
420     }
421 
422     retry = 0;
423     left = size;
424     while (left) {
425         if (!(ptr->STATUS & I2C_STATUS_FIFOEMPTY_MASK)) {
426             *(buf++) = ptr->DATA;
427             left--;
428             retry = 0;
429         } else {
430             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
431                 break;
432             }
433             retry++;
434         }
435     }
436     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
437         return status_timeout;
438     }
439 
440     retry = 0;
441     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
442         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
443             break;
444         }
445         retry++;
446     };
447     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
448         return status_timeout;
449     }
450 
451     if (i2c_get_data_count(ptr) && (size)) {
452         return status_i2c_transmit_not_completed;
453     }
454 
455     return stat;
456 }
457 
i2c_master_write(I2C_Type * ptr,const uint16_t device_address,uint8_t * buf,const uint32_t size)458 hpm_stat_t i2c_master_write(I2C_Type *ptr, const uint16_t device_address,
459                             uint8_t *buf, const uint32_t size)
460 {
461     hpm_stat_t stat = status_success;
462     uint32_t retry;
463     uint32_t left;
464 
465     if (size > I2C_SOC_TRANSFER_COUNT_MAX) {
466         return status_invalid_argument;
467     }
468 
469     retry = 0;
470     while (ptr->STATUS & I2C_STATUS_BUSBUSY_MASK) {
471         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
472             break;
473         }
474         retry++;
475     }
476     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
477         return status_timeout;
478     }
479 
480     /* W1C, clear CMPL bit to avoid blocking the transmission */
481     ptr->STATUS = I2C_STATUS_CMPL_MASK;
482 
483     ptr->CMD = I2C_CMD_CLEAR_FIFO;
484     ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
485     ptr->CTRL = I2C_CTRL_PHASE_START_MASK
486         | I2C_CTRL_PHASE_STOP_MASK
487         | I2C_CTRL_PHASE_ADDR_MASK
488         | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE);
489     if (size > 0) {
490         ptr->CTRL |= I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U)
491                     | I2C_CTRL_PHASE_DATA_MASK
492                     | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
493     }
494     ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
495 
496     /* Before starting to transmit data, judge addrhit to ensure that the slave address exists on the bus. */
497     retry = 0;
498     while (!(ptr->STATUS & I2C_STATUS_ADDRHIT_MASK)) {
499         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
500             break;
501         }
502         retry++;
503     }
504     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
505         return status_i2c_no_addr_hit;
506     }
507     ptr->STATUS = I2C_STATUS_ADDRHIT_MASK;
508     /* when size is zero, it's probe slave device, so directly return success */
509     if (size == 0) {
510         return status_success;
511     }
512 
513     retry = 0;
514     left = size;
515     while (left) {
516         if (!(ptr->STATUS & I2C_STATUS_FIFOFULL_MASK)) {
517             ptr->DATA = *(buf++);
518             left--;
519             retry = 0;
520         } else {
521             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
522                 break;
523             }
524             retry++;
525         }
526     }
527     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
528         return status_timeout;
529     }
530 
531     retry = 0;
532     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
533         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
534             break;
535         }
536         retry++;
537     }
538     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
539         return status_timeout;
540     }
541 
542     if (i2c_get_data_count(ptr) && (size)) {
543         return status_i2c_transmit_not_completed;
544     }
545 
546     return stat;
547 }
548 
i2c_init_slave(I2C_Type * ptr,uint32_t src_clk_in_hz,i2c_config_t * config,const uint16_t slave_address)549 hpm_stat_t i2c_init_slave(I2C_Type *ptr, uint32_t src_clk_in_hz,
550                           i2c_config_t *config, const uint16_t slave_address)
551 {
552     hpm_stat_t stat = status_success;
553     i2c_timing_t timing = {0};
554 
555     i2c_reset(ptr);
556 
557     ptr->ADDR = I2C_ADDR_ADDR_SET(slave_address);
558 
559     stat = i2c_configure_timing(src_clk_in_hz, config->i2c_mode, &timing);
560     if (status_success != stat) {
561         return stat;
562     }
563 
564     ptr->TPM = I2C_TPM_TPM_SET(HPM_I2C_DRV_DEFAULT_TPM);
565 
566     ptr->SETUP = I2C_SETUP_T_SP_SET(timing.t_sp)
567         | I2C_SETUP_T_SUDAT_SET(timing.t_sudat)
568         | I2C_SETUP_T_HDDAT_SET(timing.t_hddat)
569         | I2C_SETUP_T_SCLRADIO_SET(timing.t_sclratio - 1)
570         | I2C_SETUP_T_SCLHI_SET(timing.t_sclhi)
571         | I2C_SETUP_ADDRESSING_SET(config->is_10bit_addressing)
572         | I2C_SETUP_IICEN_MASK;
573 
574     return stat;
575 }
576 
i2c_slave_write(I2C_Type * ptr,uint8_t * buf,const uint32_t size)577 hpm_stat_t i2c_slave_write(I2C_Type *ptr, uint8_t *buf, const uint32_t size)
578 {
579     volatile uint32_t status;
580     uint32_t retry;
581     uint32_t left;
582 
583     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
584         return status_invalid_argument;
585     }
586 
587     /* wait for address hit */
588     retry = 0;
589     while (!(ptr->STATUS & I2C_STATUS_ADDRHIT_MASK)) {
590         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
591             break;
592         }
593         retry++;
594     }
595     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
596         return status_fail;
597     }
598 
599     /* W1C, clear CMPL bit and clear ADDRHIT bit to avoid blocking the transmission */
600     ptr->STATUS = I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK;
601     ptr->CMD = I2C_CMD_CLEAR_FIFO;
602 
603     retry = 0;
604     left = size;
605     while (left) {
606         status = ptr->STATUS;
607         if (!(status & I2C_STATUS_FIFOFULL_MASK)) {
608             ptr->DATA = *(buf++);
609             left--;
610             retry = 0;
611         } else {
612             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
613                 break;
614             }
615             retry++;
616         }
617     }
618     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
619         return status_timeout;
620     }
621 
622     retry = 0;
623     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
624         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
625             break;
626         }
627         retry++;
628     }
629     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
630         return status_timeout;
631     }
632     /* clear status, CMPL must to be cleared at slave mode before next transaction */
633     ptr->STATUS = I2C_STATUS_CMPL_MASK;
634 
635     if (i2c_get_data_count(ptr) != size) {
636         return status_i2c_transmit_not_completed;
637     }
638 
639     return status_success;
640 }
641 
i2c_slave_read(I2C_Type * ptr,uint8_t * buf,const uint32_t size)642 hpm_stat_t i2c_slave_read(I2C_Type *ptr,
643                           uint8_t *buf,
644                           const uint32_t size)
645 {
646     volatile uint32_t status;
647     uint32_t retry;
648     uint32_t left;
649 
650     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
651         return status_invalid_argument;
652     }
653 
654     /* wait for address hit */
655     retry = 0;
656     while (!(ptr->STATUS & I2C_STATUS_ADDRHIT_MASK)) {
657         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
658             break;
659         }
660         retry++;
661     }
662     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
663         return status_fail;
664     }
665 
666     /* W1C, clear CMPL bit and clear ADDRHIT bit to avoid blocking the transmission */
667     ptr->STATUS = I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK;
668     ptr->CMD = I2C_CMD_CLEAR_FIFO;
669 
670     retry = 0;
671     left = size;
672     while (left) {
673         status = ptr->STATUS;
674         if (!(status & I2C_STATUS_FIFOEMPTY_MASK)) {
675             *(buf++) = ptr->DATA;
676             left--;
677             retry = 0;
678         } else {
679             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
680                 break;
681             }
682             retry++;
683         }
684     }
685     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
686         return status_timeout;
687     }
688 
689     retry = 0;
690     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
691         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
692             break;
693         }
694         retry++;
695     }
696     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
697         return status_timeout;
698     }
699     /* clear status, CMPL must to be cleared at slave mode before next transaction */
700     ptr->STATUS = I2C_STATUS_CMPL_MASK;
701 
702     if (i2c_get_data_count(ptr) != size) {
703         return status_i2c_transmit_not_completed;
704     }
705 
706     return status_success;
707 }
708 
i2c_master_start_dma_write(I2C_Type * i2c_ptr,const uint16_t device_address,uint32_t size)709 hpm_stat_t i2c_master_start_dma_write(I2C_Type *i2c_ptr, const uint16_t device_address, uint32_t size)
710 {
711     uint32_t retry = 0;
712     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
713         return status_invalid_argument;
714     }
715 
716     while (i2c_ptr->STATUS & I2C_STATUS_BUSBUSY_MASK) {
717         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
718             break;
719         }
720         retry++;
721     }
722     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
723         return status_timeout;
724     }
725 
726     /* W1C, clear CMPL bit to avoid blocking the transmission */
727     i2c_ptr->STATUS = I2C_STATUS_CMPL_MASK;
728 
729     i2c_ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
730     i2c_ptr->CTRL = I2C_CTRL_PHASE_START_MASK
731         | I2C_CTRL_PHASE_STOP_MASK
732         | I2C_CTRL_PHASE_ADDR_MASK
733         | I2C_CTRL_PHASE_DATA_MASK
734         | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE)
735         | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U)
736         | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
737 
738     i2c_ptr->SETUP |= I2C_SETUP_DMAEN_MASK;
739 
740     i2c_ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
741 
742     return status_success;
743 }
744 
i2c_master_start_dma_read(I2C_Type * i2c_ptr,const uint16_t device_address,uint32_t size)745 hpm_stat_t i2c_master_start_dma_read(I2C_Type *i2c_ptr, const uint16_t device_address, uint32_t size)
746 {
747     uint32_t retry = 0;
748     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
749         return status_invalid_argument;
750     }
751 
752     while (i2c_ptr->STATUS & I2C_STATUS_BUSBUSY_MASK) {
753         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
754             break;
755         }
756         retry++;
757     }
758     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
759         return status_timeout;
760     }
761     /* W1C, clear CMPL bit to avoid blocking the transmission */
762     i2c_ptr->STATUS = I2C_STATUS_CMPL_MASK;
763 
764     i2c_ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
765     i2c_ptr->CTRL = I2C_CTRL_PHASE_START_MASK
766         | I2C_CTRL_PHASE_STOP_MASK
767         | I2C_CTRL_PHASE_ADDR_MASK
768         | I2C_CTRL_PHASE_DATA_MASK
769         | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ)
770         | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U)
771         | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
772 
773     i2c_ptr->SETUP |= I2C_SETUP_DMAEN_MASK;
774 
775     i2c_ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
776 
777     return status_success;
778 }
779 
i2c_slave_dma_transfer(I2C_Type * i2c_ptr,uint32_t size)780 hpm_stat_t i2c_slave_dma_transfer(I2C_Type *i2c_ptr, uint32_t size)
781 {
782     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
783         return status_invalid_argument;
784     }
785 
786     /* W1C, clear CMPL bit to avoid blocking the transmission */
787     i2c_ptr->STATUS = I2C_STATUS_CMPL_MASK;
788 
789     i2c_ptr->CTRL &= ~(I2C_CTRL_DATACNT_HIGH_MASK | I2C_CTRL_DATACNT_MASK);
790     i2c_ptr->CTRL |= I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U) | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
791 
792     i2c_ptr->SETUP |= I2C_SETUP_DMAEN_MASK;
793 
794     return status_success;
795 }
796 
i2c_master_configure_transfer(I2C_Type * i2c_ptr,const uint16_t device_address,uint32_t size,bool read)797 hpm_stat_t i2c_master_configure_transfer(I2C_Type *i2c_ptr, const uint16_t device_address, uint32_t size, bool read)
798 {
799     uint32_t retry = 0;
800     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
801         return status_invalid_argument;
802     }
803 
804     while (i2c_ptr->STATUS & I2C_STATUS_BUSBUSY_MASK) {
805         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
806             break;
807         }
808         retry++;
809     }
810     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
811         return status_timeout;
812     }
813     /* W1C, clear CMPL bit to avoid blocking the transmission */
814     i2c_ptr->STATUS = I2C_STATUS_CMPL_MASK;
815     i2c_ptr->CMD = I2C_CMD_CLEAR_FIFO;
816     i2c_ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
817     i2c_ptr->CTRL = I2C_CTRL_PHASE_START_MASK
818                 | I2C_CTRL_PHASE_STOP_MASK
819                 | I2C_CTRL_PHASE_ADDR_MASK
820                 | I2C_CTRL_PHASE_DATA_MASK
821                 | I2C_CTRL_DIR_SET(read)
822                 | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U)
823                 | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
824 
825     i2c_ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
826 
827     return status_success;
828 }
829 
i2c_master_seq_transmit(I2C_Type * ptr,const uint16_t device_address,uint8_t * buf,const uint32_t size,i2c_seq_transfer_opt_t opt)830 hpm_stat_t i2c_master_seq_transmit(I2C_Type *ptr, const uint16_t device_address,
831                                     uint8_t *buf, const uint32_t size, i2c_seq_transfer_opt_t opt)
832 {
833     uint32_t ctrl;
834     uint32_t retry = 0;
835     uint32_t left = 0;
836 
837     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
838         return status_invalid_argument;
839     }
840 
841     /* W1C, clear CMPL bit to avoid blocking the transmission */
842     ptr->STATUS = I2C_STATUS_CMPL_MASK;
843     ptr->CMD = I2C_CMD_CLEAR_FIFO;
844     ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
845 
846     switch (opt) {
847     case i2c_frist_frame:
848         ctrl = I2C_CTRL_PHASE_START_SET(true) | I2C_CTRL_PHASE_STOP_SET(false) \
849                | I2C_CTRL_PHASE_ADDR_SET(true);
850         break;
851     case i2c_next_frame:
852         ctrl = I2C_CTRL_PHASE_START_SET(false) | I2C_CTRL_PHASE_STOP_SET(false) \
853                | I2C_CTRL_PHASE_ADDR_SET(false);
854         break;
855     case i2c_last_frame:
856         ctrl = I2C_CTRL_PHASE_START_SET(false) | I2C_CTRL_PHASE_STOP_SET(true) \
857                | I2C_CTRL_PHASE_ADDR_SET(false);
858         break;
859     default:
860         return status_invalid_argument;
861     }
862 
863     ptr->CTRL = ctrl | I2C_CTRL_PHASE_DATA_SET(true) \
864                 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE) \
865                 | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U) \
866                 | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
867     /* enable auto ack */
868     ptr->INTEN &= ~I2C_EVENT_BYTE_RECEIVED;
869     ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
870 
871     retry = 0;
872     left = size;
873     while (left) {
874         if (!(ptr->STATUS & I2C_STATUS_FIFOFULL_MASK)) {
875             ptr->DATA = *(buf++);
876             left--;
877             retry = 0;
878         } else {
879             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
880                 break;
881             }
882             retry++;
883         }
884     }
885     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
886         return status_timeout;
887     }
888 
889     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
890         return status_timeout;
891     }
892     retry = 0;
893     while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
894         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
895             break;
896         }
897         retry++;
898     }
899     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
900         return status_timeout;
901     }
902     /* clear status, CMPL must to be cleared at slave mode before next transaction */
903     ptr->STATUS = I2C_STATUS_CMPL_MASK;
904     return status_success;
905 }
906 
i2c_master_seq_receive(I2C_Type * ptr,const uint16_t device_address,uint8_t * buf,const uint32_t size,i2c_seq_transfer_opt_t opt)907 hpm_stat_t i2c_master_seq_receive(I2C_Type *ptr, const uint16_t device_address,
908                                     uint8_t *buf, const uint32_t size, i2c_seq_transfer_opt_t opt)
909 {
910    uint32_t ctrl;
911     uint32_t retry = 0;
912     uint32_t left = 0;
913 
914     if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) {
915         return status_invalid_argument;
916     }
917 
918     /* W1C, clear CMPL bit to avoid blocking the transmission */
919     ptr->STATUS = I2C_STATUS_CMPL_MASK;
920     ptr->CMD = I2C_CMD_CLEAR_FIFO;
921     ptr->ADDR = I2C_ADDR_ADDR_SET(device_address);
922 
923     switch (opt) {
924     case i2c_frist_frame:
925         ctrl = I2C_CTRL_PHASE_START_SET(true) | I2C_CTRL_PHASE_STOP_SET(false) \
926                | I2C_CTRL_PHASE_ADDR_SET(true);
927         break;
928     case i2c_next_frame:
929         ctrl = I2C_CTRL_PHASE_START_SET(false) | I2C_CTRL_PHASE_STOP_SET(false) \
930                | I2C_CTRL_PHASE_ADDR_SET(false);
931         break;
932     case i2c_last_frame:
933         ctrl = I2C_CTRL_PHASE_START_SET(false) | I2C_CTRL_PHASE_STOP_SET(true) \
934                | I2C_CTRL_PHASE_ADDR_SET(false);
935         break;
936     default:
937         return status_invalid_argument;
938     }
939 
940     ptr->CTRL = ctrl | I2C_CTRL_PHASE_DATA_SET(true) \
941                 | I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ) \
942                 | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U) \
943                 | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size));
944 
945     /* disable auto ack */
946     ptr->INTEN |= I2C_EVENT_BYTE_RECEIVED;
947     ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION;
948 
949     retry = 0;
950     left = size;
951     while (left) {
952         if (!(ptr->STATUS & I2C_STATUS_FIFOEMPTY_MASK)) {
953             *(buf++) = ptr->DATA;
954             left--;
955             if ((left == 0) && (opt == i2c_last_frame)) {
956                 ptr->CMD = I2C_CMD_NACK;
957             } else {
958                 ptr->CMD = I2C_CMD_ACK;
959             }
960             retry = 0;
961         } else {
962             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
963                 break;
964             }
965             retry++;
966         }
967     }
968     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
969         return status_timeout;
970     }
971 
972     if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
973         return status_timeout;
974     }
975     if (opt  == i2c_last_frame) {
976         retry = 0;
977         while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) {
978             if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
979                 break;
980             }
981             retry++;
982         }
983         if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) {
984             return status_timeout;
985         }
986     }
987     /* clear status, CMPL must to be cleared at slave mode before next transaction */
988     ptr->STATUS = I2C_STATUS_CMPL_MASK;
989     /* default auto ack */
990     ptr->INTEN &= ~I2C_EVENT_BYTE_RECEIVED;
991 
992     return status_success;
993 }
994 
995