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