1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023/04/15     chushicheng  first version
9  */
10 
11 #include "drv_soft_i2c.h"
12 #include "bflb_gpio.h"
13 #include "bflb_common.h"
14 
15 #ifdef BSP_USING_SOFT_I2C1
16 
17 #define DBG_LEVEL   DBG_LOG
18 #include <rtdbg.h>
19 #define LOG_TAG "DRV.I2C"
20 
21 // i2c1
22 #ifdef SOFT_I2C1_SCL_USING_GPIO0
23 #define BSP_I2C1_SCL_PIN           GPIO_PIN_0
24 #elif defined(SOFT_I2C1_SCL_USING_GPIO2)
25 #define BSP_I2C1_SCL_PIN           GPIO_PIN_2
26 #elif defined(SOFT_I2C1_SCL_USING_GPIO4)
27 #define BSP_I2C1_SCL_PIN           GPIO_PIN_4
28 #elif defined(SOFT_I2C1_SCL_USING_GPIO6)
29 #define BSP_I2C1_SCL_PIN           GPIO_PIN_6
30 #elif defined(SOFT_I2C1_SCL_USING_GPIO8)
31 #define BSP_I2C1_SCL_PIN           GPIO_PIN_8
32 #elif defined(SOFT_I2C1_SCL_USING_GPIO10)
33 #define BSP_I2C1_SCL_PIN           GPIO_PIN_10
34 #elif defined(SOFT_I2C1_SCL_USING_GPIO12)
35 #define BSP_I2C1_SCL_PIN           GPIO_PIN_12
36 #elif defined(SOFT_I2C1_SCL_USING_GPIO14)
37 #define BSP_I2C1_SCL_PIN           GPIO_PIN_14
38 #elif defined(SOFT_I2C1_SCL_USING_GPIO16)
39 #define BSP_I2C1_SCL_PIN           GPIO_PIN_16
40 #elif defined(SOFT_I2C1_SCL_USING_GPIO18)
41 #define BSP_I2C1_SCL_PIN           GPIO_PIN_18
42 #elif defined(SOFT_I2C1_SCL_USING_GPIO20)
43 #define BSP_I2C1_SCL_PIN           GPIO_PIN_20
44 #elif defined(SOFT_I2C1_SCL_USING_GPIO22)
45 #define BSP_I2C1_SCL_PIN           GPIO_PIN_22
46 #elif defined(SOFT_I2C1_SCL_USING_GPIO24)
47 #define BSP_I2C1_SCL_PIN           GPIO_PIN_24
48 #elif defined(SOFT_I2C1_SCL_USING_GPIO26)
49 #define BSP_I2C1_SCL_PIN           GPIO_PIN_26
50 #elif defined(SOFT_I2C1_SCL_USING_GPIO28)
51 #define BSP_I2C1_SCL_PIN           GPIO_PIN_28
52 #elif defined(SOFT_I2C1_SCL_USING_GPIO30)
53 #define BSP_I2C1_SCL_PIN           GPIO_PIN_30
54 #elif defined(SOFT_I2C1_SCL_USING_GPIO32)
55 #define BSP_I2C1_SCL_PIN           GPIO_PIN_32
56 #elif defined(SOFT_I2C1_SCL_USING_GPIO34)
57 #define BSP_I2C1_SCL_PIN           GPIO_PIN_34
58 #elif defined(SOFT_I2C1_SCL_USING_GPIO36)
59 #define BSP_I2C1_SCL_PIN           GPIO_PIN_36
60 #elif defined(SOFT_I2C1_SCL_USING_GPIO38)
61 #define BSP_I2C1_SCL_PIN           GPIO_PIN_38
62 #elif defined(SOFT_I2C1_SCL_USING_GPIO40)
63 #define BSP_I2C1_SCL_PIN           GPIO_PIN_40
64 #elif defined(SOFT_I2C1_SCL_USING_GPIO42)
65 #define BSP_I2C1_SCL_PIN           GPIO_PIN_42
66 #elif defined(SOFT_I2C1_SCL_USING_GPIO44)
67 #define BSP_I2C1_SCL_PIN           GPIO_PIN_44
68 #endif
69 
70 #ifdef SOFT_I2C1_SDA_USING_GPIO1
71 #define BSP_I2C1_SDA_PIN           GPIO_PIN_1
72 #elif defined(SOFT_I2C1_SDA_USING_GPIO3)
73 #define BSP_I2C1_SDA_PIN           GPIO_PIN_3
74 #elif defined(SOFT_I2C1_SDA_USING_GPIO5)
75 #define BSP_I2C1_SDA_PIN           GPIO_PIN_5
76 #elif defined(SOFT_I2C1_SDA_USING_GPIO7)
77 #define BSP_I2C1_SDA_PIN           GPIO_PIN_7
78 #elif defined(SOFT_I2C1_SDA_USING_GPIO9)
79 #define BSP_I2C1_SDA_PIN           GPIO_PIN_9
80 #elif defined(SOFT_I2C1_SDA_USING_GPIO11)
81 #define BSP_I2C1_SDA_PIN           GPIO_PIN_11
82 #elif defined(SOFT_I2C1_SDA_USING_GPIO13)
83 #define BSP_I2C1_SDA_PIN           GPIO_PIN_13
84 #elif defined(SOFT_I2C1_SDA_USING_GPIO15)
85 #define BSP_I2C1_SDA_PIN           GPIO_PIN_15
86 #elif defined(SOFT_I2C1_SDA_USING_GPIO17)
87 #define BSP_I2C1_SDA_PIN           GPIO_PIN_17
88 #elif defined(SOFT_I2C1_SDA_USING_GPIO19)
89 #define BSP_I2C1_SDA_PIN           GPIO_PIN_19
90 #elif defined(SOFT_I2C1_SDA_USING_GPIO21)
91 #define BSP_I2C1_SDA_PIN           GPIO_PIN_21
92 #elif defined(SOFT_I2C1_SDA_USING_GPIO23)
93 #define BSP_I2C1_SDA_PIN           GPIO_PIN_23
94 #elif defined(SOFT_I2C1_SDA_USING_GPIO25)
95 #define BSP_I2C1_SDA_PIN           GPIO_PIN_25
96 #elif defined(SOFT_I2C1_SDA_USING_GPIO27)
97 #define BSP_I2C1_SDA_PIN           GPIO_PIN_27
98 #elif defined(SOFT_I2C1_SDA_USING_GPIO29)
99 #define BSP_I2C1_SDA_PIN           GPIO_PIN_29
100 #elif defined(SOFT_I2C1_SDA_USING_GPIO31)
101 #define BSP_I2C1_SDA_PIN           GPIO_PIN_31
102 #elif defined(SOFT_I2C1_SDA_USING_GPIO33)
103 #define BSP_I2C1_SDA_PIN           GPIO_PIN_33
104 #elif defined(SOFT_I2C1_SDA_USING_GPIO35)
105 #define BSP_I2C1_SDA_PIN           GPIO_PIN_35
106 #elif defined(SOFT_I2C1_SDA_USING_GPIO37)
107 #define BSP_I2C1_SDA_PIN           GPIO_PIN_37
108 #elif defined(SOFT_I2C1_SDA_USING_GPIO39)
109 #define BSP_I2C1_SDA_PIN           GPIO_PIN_39
110 #elif defined(SOFT_I2C1_SDA_USING_GPIO41)
111 #define BSP_I2C1_SDA_PIN           GPIO_PIN_41
112 #elif defined(SOFT_I2C1_SDA_USING_GPIO43)
113 #define BSP_I2C1_SDA_PIN           GPIO_PIN_43
114 #elif defined(SOFT_I2C1_SDA_USING_GPIO45)
115 #define BSP_I2C1_SDA_PIN           GPIO_PIN_45
116 #endif
117 
118 static const struct bl_soft_i2c_config soft_i2c_config[] =
119 {
120 #ifdef BSP_USING_SOFT_I2C1
121     I2C1_BUS_CONFIG,
122 #endif
123 };
124 
125 static struct bl_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
126 
127 /**
128  * This function initializes the i2c pin.
129  *
130  * @param bl i2c dirver class.
131  */
bl_i2c_gpio_init(struct bl_i2c * i2c)132 static void bl_i2c_gpio_init(struct bl_i2c *i2c)
133 {
134     struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)i2c->ops.data;
135 
136     rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
137     rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
138 
139     rt_pin_write(cfg->scl, PIN_HIGH);
140     rt_pin_write(cfg->sda, PIN_HIGH);
141 }
142 
bl_i2c_pin_init(void)143 static void bl_i2c_pin_init(void)
144 {
145     rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct bl_i2c);
146 
147     for(rt_size_t i = 0; i < obj_num; i++)
148     {
149         bl_i2c_gpio_init(&i2c_obj[i]);
150     }
151 }
152 
153 /**
154  * This function sets the sda pin.
155  *
156  * @param bl config class.
157  * @param The sda pin state.
158  */
bl_set_sda(void * data,rt_int32_t state)159 static void bl_set_sda(void *data, rt_int32_t state)
160 {
161     struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
162     if (state)
163     {
164         rt_pin_write(cfg->sda, PIN_HIGH);
165     }
166     else
167     {
168         rt_pin_write(cfg->sda, PIN_LOW);
169     }
170 }
171 
172 /**
173  * This function sets the scl pin.
174  *
175  * @param bl config class.
176  * @param The scl pin state.
177  */
bl_set_scl(void * data,rt_int32_t state)178 static void bl_set_scl(void *data, rt_int32_t state)
179 {
180     struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
181     if (state)
182     {
183         rt_pin_write(cfg->scl, PIN_HIGH);
184     }
185     else
186     {
187         rt_pin_write(cfg->scl, PIN_LOW);
188     }
189 }
190 
191 /**
192  * This function gets the sda pin state.
193  *
194  * @param The sda pin state.
195  */
bl_get_sda(void * data)196 static rt_int32_t bl_get_sda(void *data)
197 {
198     struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
199     return rt_pin_read(cfg->sda);
200 }
201 
202 /**
203  * This function gets the scl pin state.
204  *
205  * @param The scl pin state.
206  */
bl_get_scl(void * data)207 static rt_int32_t bl_get_scl(void *data)
208 {
209     struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data;
210     return rt_pin_read(cfg->scl);
211 }
212 
213 /**
214  * The time delay function.
215  *
216  * @param microseconds.
217  */
bl_udelay(rt_uint32_t us)218 static void bl_udelay(rt_uint32_t us)
219 {
220     bflb_mtimer_delay_us(us);
221 }
222 
223 static const struct rt_i2c_bit_ops bl_bit_ops_default =
224 {
225     .data     = RT_NULL,
226     .pin_init = bl_i2c_pin_init,
227     .set_sda  = bl_set_sda,
228     .set_scl  = bl_set_scl,
229     .get_sda  = bl_get_sda,
230     .get_scl  = bl_get_scl,
231     .udelay   = bl_udelay,
232     .delay_us = 1,
233     .timeout  = 100,
234     .i2c_pin_init_flag = RT_FALSE
235 };
236 
237 /**
238  * if i2c is locked, this function will unlock it
239  *
240  * @param bl config class
241  *
242  * @return RT_EOK indicates successful unlock.
243  */
bl_i2c_bus_unlock(const struct bl_soft_i2c_config * cfg)244 static rt_err_t bl_i2c_bus_unlock(const struct bl_soft_i2c_config *cfg)
245 {
246     rt_int32_t i = 0;
247 
248     if (PIN_LOW == rt_pin_read(cfg->sda))
249     {
250         while (i++ < 9)
251         {
252             rt_pin_write(cfg->scl, PIN_HIGH);
253             bl_udelay(100);
254             rt_pin_write(cfg->scl, PIN_LOW);
255             bl_udelay(100);
256         }
257     }
258     if (PIN_LOW == rt_pin_read(cfg->sda))
259     {
260         return -RT_ERROR;
261     }
262 
263     return RT_EOK;
264 }
265 
266 /* I2C initialization function */
rt_hw_i2c_init(void)267 int rt_hw_i2c_init(void)
268 {
269     rt_err_t result;
270 
271     for (rt_size_t i = 0; i < sizeof(i2c_obj) / sizeof(struct bl_i2c); i++)
272     {
273         i2c_obj[i].ops = bl_bit_ops_default;
274         i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
275         i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops;
276 
277         result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, soft_i2c_config[i].bus_name);
278         RT_ASSERT(result == RT_EOK);
279         bl_i2c_bus_unlock(&soft_i2c_config[i]);
280 
281         LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
282         soft_i2c_config[i].bus_name,
283         soft_i2c_config[i].scl,
284         soft_i2c_config[i].sda);
285     }
286 
287     return RT_EOK;
288 }
289 INIT_BOARD_EXPORT(rt_hw_i2c_init);
290 
291 #endif /* BSP_USING_SOFT_I2C1 */
292