1 #include "bflb_i2c.h"
2 #include "bflb_clock.h"
3 #include "hardware/i2c_reg.h"
4 
5 #define PUT_UINT32_LE(field, value)            \
6     do {                                       \
7         (field)[0] = (uint8_t)((value) >> 0);  \
8         (field)[1] = (uint8_t)((value) >> 8);  \
9         (field)[2] = (uint8_t)((value) >> 16); \
10         (field)[3] = (uint8_t)((value) >> 24); \
11     } while (0)
12 
bflb_i2c_addr_config(struct bflb_device_s * dev,uint16_t slaveaddr,uint16_t subaddr,uint8_t subaddr_size,bool is_addr_10bit)13 static void bflb_i2c_addr_config(struct bflb_device_s *dev, uint16_t slaveaddr, uint16_t subaddr, uint8_t subaddr_size, bool is_addr_10bit)
14 {
15     uint32_t regval;
16     uint32_t reg_base;
17 
18     reg_base = dev->reg_base;
19 
20     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
21 
22     if (subaddr_size > 0) {
23         regval |= I2C_CR_I2C_SUB_ADDR_EN;
24         regval &= ~I2C_CR_I2C_SUB_ADDR_BC_MASK;
25         regval |= ((subaddr_size - 1) << I2C_CR_I2C_SUB_ADDR_BC_SHIFT);
26     } else {
27         regval &= ~I2C_CR_I2C_SUB_ADDR_EN;
28     }
29 
30     regval &= ~I2C_CR_I2C_SLV_ADDR_MASK;
31     regval |= (slaveaddr << I2C_CR_I2C_SLV_ADDR_SHIFT);
32 #if !defined(BL602) && !defined(BL702)
33     if (is_addr_10bit) {
34         regval |= I2C_CR_I2C_10B_ADDR_EN;
35     } else {
36         regval &= ~I2C_CR_I2C_10B_ADDR_EN;
37     }
38 #endif
39     regval &= ~I2C_CR_I2C_SCL_SYNC_EN;
40     putreg32(subaddr, reg_base + I2C_SUB_ADDR_OFFSET);
41     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
42 }
43 
bflb_i2c_set_dir(struct bflb_device_s * dev,bool is_in)44 static inline void bflb_i2c_set_dir(struct bflb_device_s *dev, bool is_in)
45 {
46     uint32_t regval;
47     uint32_t reg_base;
48 
49     reg_base = dev->reg_base;
50 
51     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
52 
53     if (is_in) {
54         regval |= I2C_CR_I2C_PKT_DIR;
55     } else {
56         regval &= ~I2C_CR_I2C_PKT_DIR;
57     }
58     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
59 }
60 
bflb_i2c_set_datalen(struct bflb_device_s * dev,uint16_t data_len)61 static inline void bflb_i2c_set_datalen(struct bflb_device_s *dev, uint16_t data_len)
62 {
63     uint32_t regval;
64     uint32_t reg_base;
65 
66     reg_base = dev->reg_base;
67 
68     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
69     regval &= ~I2C_CR_I2C_PKT_LEN_MASK;
70     regval |= ((data_len - 1) << I2C_CR_I2C_PKT_LEN_SHIFT) & I2C_CR_I2C_PKT_LEN_MASK;
71     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
72 }
73 
bflb_i2c_set_frequence(struct bflb_device_s * dev,uint32_t freq)74 static void bflb_i2c_set_frequence(struct bflb_device_s *dev, uint32_t freq)
75 {
76     uint32_t regval;
77     uint32_t reg_base;
78     uint32_t phase;
79     uint32_t tmp;
80 
81     reg_base = dev->reg_base;
82 
83     phase = bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_I2C, dev->idx) / (freq * 4) - 1;
84 
85     if (freq > 100000) {
86         tmp = ((phase / 4) / 0.5);
87     } else {
88         tmp = (phase / 4);
89     }
90 
91     regval = (phase - tmp) << I2C_CR_I2C_PRD_S_PH_0_SHIFT;
92     regval |= (phase + tmp) << I2C_CR_I2C_PRD_S_PH_1_SHIFT;
93     regval |= (phase) << I2C_CR_I2C_PRD_S_PH_2_SHIFT;
94     regval |= (phase) << I2C_CR_I2C_PRD_S_PH_3_SHIFT;
95 
96     putreg32(regval, reg_base + I2C_PRD_START_OFFSET);
97     putreg32(regval, reg_base + I2C_PRD_STOP_OFFSET);
98 
99     regval = (phase - tmp) << I2C_CR_I2C_PRD_D_PH_0_SHIFT;
100     regval |= (phase + tmp) << I2C_CR_I2C_PRD_D_PH_1_SHIFT;
101     regval |= (phase + tmp) << I2C_CR_I2C_PRD_D_PH_2_SHIFT;
102     regval |= (phase - tmp) << I2C_CR_I2C_PRD_D_PH_3_SHIFT;
103     putreg32(regval, reg_base + I2C_PRD_DATA_OFFSET);
104 }
105 
bflb_i2c_isbusy(struct bflb_device_s * dev)106 static inline bool bflb_i2c_isbusy(struct bflb_device_s *dev)
107 {
108     uint32_t regval;
109     uint32_t reg_base;
110 
111     reg_base = dev->reg_base;
112 
113     regval = getreg32(reg_base + I2C_BUS_BUSY_OFFSET);
114 
115     if (regval & I2C_STS_I2C_BUS_BUSY) {
116         return true;
117     }
118 
119     return false;
120 }
121 
bflb_i2c_isend(struct bflb_device_s * dev)122 static inline bool bflb_i2c_isend(struct bflb_device_s *dev)
123 {
124     uint32_t regval;
125     uint32_t reg_base;
126 
127     reg_base = dev->reg_base;
128 
129     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
130 
131     if (regval & I2C_END_INT) {
132         return true;
133     }
134 
135     return false;
136 }
137 
bflb_i2c_isnak(struct bflb_device_s * dev)138 static inline bool bflb_i2c_isnak(struct bflb_device_s *dev)
139 {
140     uint32_t regval;
141     uint32_t reg_base;
142 
143     reg_base = dev->reg_base;
144 
145     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
146 
147     if (regval & I2C_NAK_INT) {
148         return true;
149     }
150 
151     return false;
152 }
153 
bflb_i2c_enable(struct bflb_device_s * dev)154 static inline void bflb_i2c_enable(struct bflb_device_s *dev)
155 {
156     uint32_t regval;
157     uint32_t reg_base;
158 
159     reg_base = dev->reg_base;
160 
161     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
162     regval |= I2C_CR_I2C_M_EN;
163     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
164 }
165 
bflb_i2c_disable(struct bflb_device_s * dev)166 static inline void bflb_i2c_disable(struct bflb_device_s *dev)
167 {
168     uint32_t regval;
169     uint32_t reg_base;
170 
171     reg_base = dev->reg_base;
172 
173     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
174     regval &= ~I2C_CR_I2C_M_EN;
175     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
176     /* Clear I2C fifo */
177     regval = getreg32(reg_base + I2C_FIFO_CONFIG_0_OFFSET);
178     regval |= I2C_TX_FIFO_CLR;
179     regval |= I2C_RX_FIFO_CLR;
180     putreg32(regval, reg_base + I2C_FIFO_CONFIG_0_OFFSET);
181     /* Clear I2C interrupt status */
182     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
183     regval |= I2C_CR_I2C_END_CLR;
184     regval |= I2C_CR_I2C_NAK_CLR;
185     regval |= I2C_CR_I2C_ARB_CLR;
186     putreg32(regval, reg_base + I2C_INT_STS_OFFSET);
187 }
188 
bflb_i2c_isenable(struct bflb_device_s * dev)189 static inline bool bflb_i2c_isenable(struct bflb_device_s *dev)
190 {
191     uint32_t regval;
192     uint32_t reg_base;
193 
194     reg_base = dev->reg_base;
195 
196     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
197     if (regval & I2C_CR_I2C_M_EN) {
198         return true;
199     }
200 
201     return false;
202 }
203 
bflb_i2c_write_bytes(struct bflb_device_s * dev,uint8_t * data,uint32_t len)204 static int bflb_i2c_write_bytes(struct bflb_device_s *dev, uint8_t *data, uint32_t len)
205 {
206     uint32_t reg_base;
207     uint32_t temp = 0;
208     uint8_t *tmp_buf;
209     // uint64_t start_time;
210 
211     reg_base = dev->reg_base;
212     tmp_buf = data;
213     while (len >= 4) {
214         for (uint8_t i = 0; i < 4; i++) {
215             temp += (tmp_buf[i] << ((i % 4) * 8));
216         }
217         tmp_buf += 4;
218         len -= 4;
219         // start_time = bflb_mtimer_get_time_ms();
220         // while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_TX_FIFO_CNT_MASK) == 0) {
221         //     if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
222         //         return -ETIMEDOUT;
223         //     }
224         // }
225         putreg32(temp, reg_base + I2C_FIFO_WDATA_OFFSET);
226         if (!bflb_i2c_isenable(dev)) {
227             bflb_i2c_enable(dev);
228         }
229         temp = 0;
230     }
231 
232     if (len > 0) {
233         for (uint8_t i = 0; i < len; i++) {
234             temp += (tmp_buf[i] << ((i % 4) * 8));
235         }
236         // start_time = bflb_mtimer_get_time_ms();
237         // while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_TX_FIFO_CNT_MASK) == 0) {
238         //     if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
239         //         return -ETIMEDOUT;
240         //     }
241         // }
242         putreg32(temp, reg_base + I2C_FIFO_WDATA_OFFSET);
243         if (!bflb_i2c_isenable(dev)) {
244             bflb_i2c_enable(dev);
245         }
246     }
247 
248     // start_time = bflb_mtimer_get_time_ms();
249     // while (bflb_i2c_isbusy(dev) || !bflb_i2c_isend(dev) || bflb_i2c_isnak(dev)) {
250     //     if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
251     //         return -ETIMEDOUT;
252     //     }
253     // }
254     bflb_i2c_disable(dev);
255 
256     return 0;
257 }
258 
bflb_i2c_read_bytes(struct bflb_device_s * dev,uint8_t * data,uint32_t len)259 static int bflb_i2c_read_bytes(struct bflb_device_s *dev, uint8_t *data, uint32_t len)
260 {
261     uint32_t reg_base;
262     uint32_t temp = 0;
263     uint8_t *tmp_buf;
264     // uint64_t start_time;
265 
266     reg_base = dev->reg_base;
267     tmp_buf = data;
268 
269     bflb_i2c_enable(dev);
270 
271     while (len >= 4) {
272         // start_time = bflb_mtimer_get_time_ms();
273         // while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_RX_FIFO_CNT_MASK) == 0) {
274         //     if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
275         //         return -ETIMEDOUT;
276         //     }
277         // }
278         temp = getreg32(reg_base + I2C_FIFO_RDATA_OFFSET);
279         PUT_UINT32_LE(tmp_buf, temp);
280         tmp_buf += 4;
281         len -= 4;
282     }
283 
284     if (len > 0) {
285         // start_time = bflb_mtimer_get_time_ms();
286         // while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_RX_FIFO_CNT_MASK) == 0) {
287         //     if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
288         //         return -ETIMEDOUT;
289         //     }
290         // }
291         temp = getreg32(reg_base + I2C_FIFO_RDATA_OFFSET);
292 
293         for (uint8_t i = 0; i < len; i++) {
294             tmp_buf[i] = (temp >> (i * 8)) & 0xff;
295         }
296     }
297 
298     // start_time = bflb_mtimer_get_time_ms();
299     // while (bflb_i2c_isbusy(dev) || !bflb_i2c_isend(dev)) {
300     //     if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
301     //         return -ETIMEDOUT;
302     //     }
303     // }
304     bflb_i2c_disable(dev);
305 
306     return 0;
307 }
308 
bflb_i2c_init(struct bflb_device_s * dev,uint32_t frequency)309 void bflb_i2c_init(struct bflb_device_s *dev, uint32_t frequency)
310 {
311     uint32_t regval;
312     uint32_t reg_base;
313 
314     reg_base = dev->reg_base;
315 
316     bflb_i2c_disable(dev);
317 
318     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
319 
320     regval |= (I2C_CR_I2C_END_MASK |
321                I2C_CR_I2C_TXF_MASK |
322                I2C_CR_I2C_RXF_MASK |
323                I2C_CR_I2C_NAK_MASK |
324                I2C_CR_I2C_ARB_MASK |
325                I2C_CR_I2C_FER_MASK);
326 
327     putreg32(regval, reg_base + I2C_INT_STS_OFFSET);
328 
329     bflb_i2c_set_frequence(dev, frequency);
330 }
331 
bflb_i2c_deinit(struct bflb_device_s * dev)332 void bflb_i2c_deinit(struct bflb_device_s *dev)
333 {
334     uint32_t regval;
335     uint32_t reg_base;
336 
337     reg_base = dev->reg_base;
338 
339     bflb_i2c_disable(dev);
340 
341     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
342 
343     regval |= (I2C_CR_I2C_END_MASK |
344                I2C_CR_I2C_TXF_MASK |
345                I2C_CR_I2C_RXF_MASK |
346                I2C_CR_I2C_NAK_MASK |
347                I2C_CR_I2C_ARB_MASK |
348                I2C_CR_I2C_FER_MASK);
349 
350     putreg32(regval, reg_base + I2C_INT_STS_OFFSET);
351 }
352 
bflb_i2c_link_txdma(struct bflb_device_s * dev,bool enable)353 void bflb_i2c_link_txdma(struct bflb_device_s *dev, bool enable)
354 {
355     uint32_t reg_base;
356     uint32_t regval;
357 
358     reg_base = dev->reg_base;
359     regval = getreg32(reg_base + I2C_FIFO_CONFIG_0_OFFSET);
360     if (enable) {
361         regval |= I2C_DMA_TX_EN;
362     } else {
363         regval &= ~I2C_DMA_TX_EN;
364     }
365     putreg32(regval, reg_base + I2C_FIFO_CONFIG_0_OFFSET);
366 }
367 
bflb_i2c_link_rxdma(struct bflb_device_s * dev,bool enable)368 void bflb_i2c_link_rxdma(struct bflb_device_s *dev, bool enable)
369 {
370     uint32_t reg_base;
371     uint32_t regval;
372 
373     reg_base = dev->reg_base;
374     regval = getreg32(reg_base + I2C_FIFO_CONFIG_0_OFFSET);
375     if (enable) {
376         regval |= I2C_DMA_RX_EN;
377     } else {
378         regval &= ~I2C_DMA_RX_EN;
379     }
380     putreg32(regval, reg_base + I2C_FIFO_CONFIG_0_OFFSET);
381 }
382 
bflb_i2c_transfer(struct bflb_device_s * dev,struct bflb_i2c_msg_s * msgs,int count)383 int bflb_i2c_transfer(struct bflb_device_s *dev, struct bflb_i2c_msg_s *msgs, int count)
384 {
385     uint16_t subaddr = 0;
386     uint16_t subaddr_size = 0;
387     bool is_addr_10bit = false;
388     int ret = 0;
389 
390     bflb_i2c_disable(dev);
391 
392     for (uint16_t i = 0; i < count; i++) {
393         if (msgs[i].flags & I2C_M_TEN) {
394             is_addr_10bit = true;
395         } else {
396             is_addr_10bit = false;
397         }
398         if (msgs[i].flags & I2C_M_NOSTOP) {
399             subaddr = 0;
400             for (uint8_t j = 0; j < msgs[i].length; j++) {
401                 subaddr += msgs[i].buffer[j] << (j * 8);
402             }
403             subaddr_size = msgs[i].length;
404             bflb_i2c_addr_config(dev, msgs[i].addr, subaddr, subaddr_size, is_addr_10bit);
405             i++;
406         } else {
407             subaddr = 0;
408             subaddr_size = 0;
409             bflb_i2c_addr_config(dev, msgs[i].addr, subaddr, subaddr_size, is_addr_10bit);
410         }
411 
412         if (msgs[i].length > 256) {
413             return -EINVAL;
414         }
415         bflb_i2c_set_datalen(dev, msgs[i].length);
416         if (msgs[i].flags & I2C_M_READ) {
417             bflb_i2c_set_dir(dev, 1);
418             if ((msgs[i].flags & I2C_M_DMA) == 0) {
419                 ret = bflb_i2c_read_bytes(dev, msgs[i].buffer, msgs[i].length);
420                 if (ret < 0) {
421                     return ret;
422                 }
423             } else {
424                 bflb_i2c_enable(dev);
425             }
426         } else {
427             bflb_i2c_set_dir(dev, 0);
428             if ((msgs[i].flags & I2C_M_DMA) == 0) {
429                 ret = bflb_i2c_write_bytes(dev, msgs[i].buffer, msgs[i].length);
430                 if (ret < 0) {
431                     return ret;
432                 }
433             } else {
434                 bflb_i2c_enable(dev);
435             }
436         }
437     }
438 
439     return 0;
440 }
441 
bflb_i2c_int_mask(struct bflb_device_s * dev,uint32_t int_type,bool mask)442 void bflb_i2c_int_mask(struct bflb_device_s *dev, uint32_t int_type, bool mask)
443 {
444     uint32_t reg_base;
445     uint32_t regval;
446 
447     reg_base = dev->reg_base;
448     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
449     regval &= ~((int_type & 0xff) << 8);
450     if (mask) {
451         regval |= (int_type & 0xff) << 8;
452     }
453     putreg32(regval, reg_base + I2C_INT_STS_OFFSET);
454 }
455 
bflb_i2c_int_clear(struct bflb_device_s * dev,uint32_t int_clear)456 void bflb_i2c_int_clear(struct bflb_device_s *dev, uint32_t int_clear)
457 {
458     uint32_t reg_base;
459     uint32_t regval;
460 
461     reg_base = dev->reg_base;
462     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
463     regval |= (int_clear & 0xff) << 16;
464     putreg32(regval, reg_base + I2C_INT_STS_OFFSET);
465 }
466 
bflb_i2c_get_intstatus(struct bflb_device_s * dev)467 uint32_t bflb_i2c_get_intstatus(struct bflb_device_s *dev)
468 {
469     uint32_t reg_base;
470 
471     reg_base = dev->reg_base;
472     return (getreg32(reg_base + I2C_INT_STS_OFFSET) & 0xff);
473 }
474 
bflb_i2c_feature_control(struct bflb_device_s * dev,int cmd,size_t arg)475 int bflb_i2c_feature_control(struct bflb_device_s *dev, int cmd, size_t arg)
476 {
477     int ret = 0;
478     switch (cmd) {
479         default:
480             ret = -EPERM;
481             break;
482     }
483     return ret;
484 }
485