1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * 2021-11-19 xieyangrun first version
8 */
9
10 #include <rthw.h>
11 #include <rtdevice.h>
12
13 #include "sunxi_hal_twi.h"
14
15 #define DBG_LVL DBG_WARNING
16 #define DBG_TAG "drv/i2c"
17 #include <rtdbg.h>
18
19 struct hal_i2c_bus
20 {
21 struct rt_i2c_bus_device parent;
22 twi_port_t id;
23 struct rt_mutex lock;
24 };
25
26 //connect am drv to rt drv.
_i2c_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg * msgs,rt_uint32_t num)27 static rt_ssize_t _i2c_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msgs, rt_uint32_t num)
28 {
29 struct hal_i2c_bus *_i2c_bus = (struct hal_i2c_bus *)bus;
30 struct rt_i2c_msg *msg;
31 twi_msg_t *twi_msg;
32 int i;
33 twi_status_t status;
34 extern twi_status_t hal_twi_xfer(twi_port_t port, twi_msg_t *msgs, int32_t num);
35
36
37 twi_msg = rt_malloc(sizeof(*twi_msg) * num);
38 if (!twi_msg)
39 {
40 LOG_E("i2c xfer malloc(%d) failure\n", sizeof(*twi_msg) * num);
41 return -RT_ENOMEM;
42 }
43
44 for (i = 0; i < num; i++)
45 {
46 msg = &msgs[i];
47 if (msg->flags == RT_I2C_RD)
48 {
49 twi_msg[i].flags = TWI_M_RD;
50 }
51 else if(msg->flags == RT_I2C_WR)
52 {
53 twi_msg[i].flags = 0;
54 }
55
56 if (_i2c_bus->parent.flags & RT_I2C_DEV_CTRL_10BIT)
57 {
58 twi_msg[i].flags |= TWI_M_TEN;
59 }
60
61 twi_msg[i].addr = msg->addr;
62 twi_msg[i].len = msg->len;
63 twi_msg[i].buf = msg->buf;
64 }
65
66 rt_mutex_take(&_i2c_bus->lock, RT_WAITING_FOREVER);
67 status = hal_twi_xfer(_i2c_bus->id, twi_msg, i);
68 rt_mutex_release(&_i2c_bus->lock);
69
70 if (status != TWI_STATUS_OK)
71 {
72 i = 0;
73 LOG_E("i2c xfer failure\n");
74 }
75
76 rt_free(twi_msg);
77
78 return i;
79 }
80
81 static const struct rt_i2c_bus_device_ops _i2c_ops =
82 {
83 _i2c_master_xfer,
84 RT_NULL,
85 RT_NULL
86 };
87
88 #ifdef BSP_USING_I2C0
89 static struct hal_i2c_bus _i2c_bus_0 = {
90 .id = TWI_MASTER_0
91 };
92 #endif
93
94 #ifdef BSP_USING_I2C1
95 static struct hal_i2c_bus _i2c_bus_1 = {
96 .id = TWI_MASTER_1,
97 };
98 #endif
99
100 #ifdef BSP_USING_I2C2
101 static struct hal_i2c_bus _i2c_bus_2 = {
102 .id = TWI_MASTER_2,
103 };
104 #endif
105
106 #ifdef BSP_USING_I2C3
107 static struct hal_i2c_bus _i2c_bus_3 = {
108 .id = TWI_MASTER_3,
109 };
110 #endif
111
112 #define CFG_GPIO_PORT(p) ((p) - 'A' + 1)
113
114 static const user_gpio_set_t _i2c_gpio_cfg[][2] = {
115 {// twi0
116 {
117 .gpio_name = "twi0.sck",
118 .port = CFG_GPIO_PORT('B'),
119 .port_num = 3, // PB3
120 .mul_sel = 4,
121 .pull = 1, // pull up
122 .drv_level = 3,
123 .data = 1,
124 },
125 {
126 .gpio_name = "twi0.sda",
127 .port = CFG_GPIO_PORT('B'),
128 .port_num = 2, // PB2
129 .mul_sel = 4,
130 .pull = 1, // pull up
131 .drv_level = 3,
132 .data = 1,
133 }
134 },
135 {// twi1
136 {
137 .gpio_name = "twi1.sck",
138 .port = CFG_GPIO_PORT('B'),
139 .port_num = 4, // PB4
140 .mul_sel = 4,
141 .pull = 1, // pull up
142 .drv_level = 3,
143 .data = 1,
144 },
145 {
146 .gpio_name = "twi1.sda",
147 .port = CFG_GPIO_PORT('B'),
148 .port_num = 5, // PB5
149 .mul_sel = 4,
150 .pull = 1, // pull up
151 .drv_level = 3,
152 .data = 1,
153 }
154 },
155 #ifdef BSP_USING_MANGOPI // mango board
156 {// twi2
157 {
158 .gpio_name = "twi2.sck",
159 .port = CFG_GPIO_PORT('E'),
160 .port_num = 12, // PE12
161 .mul_sel = 2,
162 .pull = 1, // pull up
163 .drv_level = 3,
164 .data = 1,
165 },
166 {
167 .gpio_name = "twi2.sda",
168 .port = CFG_GPIO_PORT('E'),
169 .port_num = 13, // PE13
170 .mul_sel = 2,
171 .pull = 1, // pull up
172 .drv_level = 3,
173 .data = 1,
174 }
175 },
176 #elif defined(BSP_USING_M7)
177 {// twi2
178 {
179 .gpio_name = "twi2.sck",
180 .port = CFG_GPIO_PORT('G'),
181 .port_num = 6, // PG6
182 .mul_sel = 3,
183 .pull = 1, // pull up
184 .drv_level = 3,
185 .data = 1,
186 },
187 {
188 .gpio_name = "twi2.sda",
189 .port = CFG_GPIO_PORT('G'),
190 .port_num = 7, // PG7
191 .mul_sel = 3,
192 .pull = 1, // pull up
193 .drv_level = 3,
194 .data = 1,
195 }
196 },
197 #endif
198 {// twi3
199 {
200 .gpio_name = "twi3.sck",
201 .port = CFG_GPIO_PORT('B'),
202 .port_num = 6, // PB6
203 .mul_sel = 4,
204 .pull = 1, // pull up
205 .drv_level = 3,
206 .data = 1,
207 },
208 {
209 .gpio_name = "twi3.sda",
210 .port = CFG_GPIO_PORT('B'),
211 .port_num = 7, // PB7
212 .mul_sel = 4,
213 .pull = 1, // pull up
214 .drv_level = 3,
215 .data = 1,
216 }
217 },
218 };
219
hal_i2c_gpio_cfg_load(user_gpio_set_t * gpio_cfg,int32_t GPIONum,int id)220 int hal_i2c_gpio_cfg_load(user_gpio_set_t *gpio_cfg, int32_t GPIONum, int id)
221 {
222 int i;
223
224 if (id > sizeof(_i2c_gpio_cfg) / sizeof(_i2c_gpio_cfg[0]))
225 {
226 rt_kprintf("twi id %d>%d\n", id, sizeof(_i2c_gpio_cfg) / sizeof(_i2c_gpio_cfg[0]));
227 return -1;
228 }
229
230 /* twi0 */
231 for (i = 0; i < GPIONum; i++)
232 {
233 memcpy(gpio_cfg, &_i2c_gpio_cfg[id][i], sizeof(user_gpio_set_t));
234 gpio_cfg++;
235 }
236
237 return 0;
238 }
239
_i2c_dev_register(struct hal_i2c_bus * bus,const char * name)240 static int _i2c_dev_register(struct hal_i2c_bus* bus, const char* name)
241 {
242 rt_mutex_init(&bus->lock, name, RT_IPC_FLAG_PRIO);
243
244 hal_twi_init(bus->id);
245 bus->parent.ops = &_i2c_ops;
246
247 if (rt_i2c_bus_device_register(&bus->parent, name) != RT_EOK)
248 {
249 LOG_E("i2c bus register:%s failure\n", name);
250 return -1;
251 }
252
253 return 0;
254 }
255
rt_hw_i2c_init(void)256 int rt_hw_i2c_init(void)
257 {
258 #ifdef BSP_USING_I2C0
259 /* init i2c bus device */
260 _i2c_dev_register(&_i2c_bus_0, "i2c0");
261 #endif
262
263 #ifdef BSP_USING_I2C1
264 /* init i2c bus device */
265 _i2c_dev_register(&_i2c_bus_1, "i2c1");
266 #endif
267
268 #ifdef BSP_USING_I2C2
269 _i2c_dev_register(&_i2c_bus_2, "i2c2");
270 #endif
271
272 #ifdef BSP_USING_I2C3
273 _i2c_dev_register(&_i2c_bus_3, "i2c3");
274 #endif
275
276 //rt_kprintf("i2c_init!\n");
277
278 return 0;
279 }
280 // #ifdef RT_USING_COMPONENTS_INIT
281 INIT_BOARD_EXPORT(rt_hw_i2c_init);
282 // #endif
283
_i2c_test(int argc,char * args[])284 static void _i2c_test(int argc, char *args[])
285 {
286 struct rt_i2c_bus_device *i2c_bus;
287 struct rt_i2c_msg msg[2];
288 uint8_t buf[3] = {0x12, 0x34, 0x56};
289
290 if (argc < 2) return;
291
292 i2c_bus = (struct rt_i2c_bus_device*)rt_device_find("i2c2");
293 if (!i2c_bus)
294 {
295 rt_kprintf("i2c2 not found\n");
296 return;
297 }
298
299 msg[0].addr = 0x36;
300 msg[0].flags = 0;
301 msg[0].buf = buf;
302 msg[0].len = sizeof(buf);
303
304 msg[1].addr = 0x36;
305 msg[1].flags = RT_I2C_RD;
306 msg[1].buf = buf;
307 msg[1].len = sizeof(buf);
308
309 if (atoi(args[1]) == 0)
310 {
311 rt_i2c_transfer(i2c_bus, &msg[0], 1);
312 }
313 else
314 {
315 rt_i2c_transfer(i2c_bus, &msg[0], 2);
316 }
317 }
318 MSH_CMD_EXPORT_ALIAS(_i2c_test, i2c_test, i2c bus test);
319
_pin_test(void)320 static void _pin_test(void)
321 {
322 int i;
323 rt_base_t pin;
324
325 pin = GPIO_PE10;
326
327 rt_pin_mode(pin, PIN_MODE_OUTPUT);
328
329 for (i = 0; i < 20; i++)
330 {
331 rt_pin_write(pin, !!(i & 1));
332 rt_thread_mdelay(2);
333 }
334 }
335 MSH_CMD_EXPORT_ALIAS(_pin_test, pin_test, gpio pin test);
336
337 /*@}*/
338
339
340
341
342
343