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