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/05/10     flyingcys    first version
9 */
10 
11 #include <rthw.h>
12 #include <rtdevice.h>
13 
14 #ifdef BSP_USING_I2C
15 #include "drv_i2c.h"
16 
17 #define DBG_TAG "DRV.I2C"
18 #define DBG_LVL DBG_WARNING
19 #include <rtdbg.h>
20 
21 struct bl_i2c_bus
22 {
23     struct rt_i2c_bus_device parent;
24     struct bflb_device_s *i2c;
25     struct rt_mutex lock;
26 };
27 
_i2c_master_xfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg * msgs,rt_uint32_t num)28 static rt_ssize_t _i2c_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msgs, rt_uint32_t num)
29 {
30     struct bl_i2c_bus *_i2c_bus = (struct bl_i2c_bus *)bus;
31     struct rt_i2c_msg *msg;
32     struct bflb_i2c_msg_s *bflb_i2c_msg;
33     int i;
34     int ret;
35 
36     bflb_i2c_msg = rt_malloc(sizeof(struct bflb_i2c_msg_s) * num);
37     if (!bflb_i2c_msg)
38     {
39         LOG_E("i2c xfer malloc(%d) failure\n", sizeof(struct bflb_i2c_msg_s) * num);
40         return -RT_ENOMEM;
41     }
42 
43     rt_memset(bflb_i2c_msg, 0, sizeof(struct bflb_i2c_msg_s) * num);
44 
45     for (i = 0; i < num; i++)
46     {
47         msg = &msgs[i];
48         if (msg->flags & RT_I2C_RD)
49         {
50             bflb_i2c_msg[i].flags = I2C_M_READ;
51         }
52         else
53         {
54             bflb_i2c_msg[i].flags = 0;
55         }
56 
57         if (_i2c_bus->parent.flags & RT_I2C_DEV_CTRL_10BIT)
58         {
59             bflb_i2c_msg[i].flags |= I2C_M_TEN;
60         }
61 
62         bflb_i2c_msg[i].addr = msg->addr;
63         bflb_i2c_msg[i].length = msg->len;
64         bflb_i2c_msg[i].buffer = msg->buf;
65     }
66 
67     rt_mutex_take(&_i2c_bus->lock, RT_WAITING_FOREVER);
68     ret = bflb_i2c_transfer(_i2c_bus->i2c, bflb_i2c_msg, num);
69     rt_mutex_release(&_i2c_bus->lock);
70 
71     rt_free(bflb_i2c_msg);
72     bflb_i2c_msg = RT_NULL;
73 
74     if (ret < 0)
75     {
76         i = 0;
77         LOG_E("i2c xfer failure %d\n", ret);
78     }
79 
80     return i;
81 }
82 
83 static const struct rt_i2c_bus_device_ops _i2c_ops =
84 {
85     _i2c_master_xfer,
86     RT_NULL,
87     RT_NULL
88 };
89 
rt_hw_i2c_init(void)90 int rt_hw_i2c_init(void)
91 {
92     struct bflb_device_s *gpio;
93     gpio = bflb_device_get_by_name("gpio");
94 
95 #ifdef BSP_USING_I2C0
96     static struct bl_i2c_bus i2c_bus0;
97 
98    /* I2C0_SCL */
99     bflb_gpio_init(gpio, I2C0_GPIO_SCL, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
100     /* I2C0_SDA */
101     bflb_gpio_init(gpio, I2C0_GPIO_SDA, GPIO_FUNC_I2C0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
102 
103     /* init i2c bus device */
104     rt_mutex_init(&i2c_bus0.lock, "i2c0_mutex", RT_IPC_FLAG_PRIO);
105 
106     i2c_bus0.parent.ops = &_i2c_ops;
107     i2c_bus0.i2c = bflb_device_get_by_name("i2c0");
108     bflb_i2c_init(i2c_bus0.i2c, I2C0_FREQUENCY);
109 
110     if (rt_i2c_bus_device_register(&i2c_bus0.parent, "i2c0") != RT_EOK)
111         LOG_E("i2c bus register:%s failure\n", "i2c0");
112 #endif
113 
114 #ifdef BSP_USING_I2C1
115     static struct bl_i2c_bus i2c_bus1;
116 
117     /* I2C1_SCL */
118     bflb_gpio_init(gpio, I2C1_GPIO_SCL, GPIO_FUNC_I2C1 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
119     /* I2C1_SDA */
120     bflb_gpio_init(gpio, I2C1_GPIO_SDA, GPIO_FUNC_I2C1 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
121 
122     /* init i2c bus device */
123     rt_mutex_init(&i2c_bus1.lock, "i2c1_mutex", RT_IPC_FLAG_PRIO);
124 
125     i2c_bus1.parent.ops = &_i2c_ops;
126     i2c_bus1.i2c = bflb_device_get_by_name("i2c1");
127     bflb_i2c_init(i2c_bus1.i2c, I2C1_FREQUENCY);
128 
129     if (rt_i2c_bus_device_register(&i2c_bus1.parent, "i2c1") != RT_EOK)
130         LOG_E("i2c bus register:%s failure\n", "i2c1");
131 #endif
132 
133 #ifdef BSP_USING_I2C2
134     static struct bl_i2c_bus i2c_bus2;
135 
136     /* I2C2_SCL */
137     bflb_gpio_init(gpio, I2C2_GPIO_SCL, GPIO_FUNC_I2C2 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
138     /* I2C2_SDA */
139     bflb_gpio_init(gpio, I2C2_GPIO_SDA, GPIO_FUNC_I2C2 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
140 
141     /* init i2c bus device */
142     rt_mutex_init(&i2c_bus2.lock, "i2c2_mutex", RT_IPC_FLAG_PRIO);
143 
144     i2c_bus2.parent.ops = &_i2c_ops;
145     i2c_bus2.i2c = bflb_device_get_by_name("i2c2");
146     bflb_i2c_init(i2c_bus2.i2c, I2C2_FREQUENCY);
147 
148     if (rt_i2c_bus_device_register(&i2c_bus2.parent, "i2c2") != RT_EOK)
149         LOG_E("i2c bus register:%s failure\n", "i2c2");
150 #endif
151 
152 #ifdef BSP_USING_I2C3
153     static struct bl_i2c_bus i2c_bus3;
154 
155     /* I2C3_SCL */
156     bflb_gpio_init(gpio, I2C3_GPIO_SCL, GPIO_FUNC_I2C3 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
157     /* I2C3_SDA */
158     bflb_gpio_init(gpio, I2C3_GPIO_SDA, GPIO_FUNC_I2C3 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
159 
160     /* init i2c bus device */
161     rt_mutex_init(&i2c_bus3.lock, "i2c3_mutex", RT_IPC_FLAG_PRIO);
162 
163     i2c_bus3.parent.ops = &_i2c_ops;
164     i2c_bus3.i2c = bflb_device_get_by_name("i2c3");
165     bflb_i2c_init(i2c_bus3.i2c, I2C3_FREQUENCY);
166 
167     if (rt_i2c_bus_device_register(&i2c_bus3.parent, "i2c3") != RT_EOK)
168         LOG_E("i2c bus register:%s failure\n", "i2c3");
169 #endif
170 
171     return 0;
172 }
173 INIT_BOARD_EXPORT(rt_hw_i2c_init);
174 
175 #endif /* BSP_USING_I2C */
176