1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Email: opensource_embedded@phytium.com.cn
7  *
8  * Change Logs:
9  * Date           Author       Notes
10  * 2023-10-23     zhangyan     first version
11  *
12  */
13 #include "rtconfig.h"
14 #include <rtdevice.h>
15 #include <string.h>
16 #define LOG_TAG      "i2c_drv"
17 #include "drv_log.h"
18 #include "drv_i2c.h"
19 #include "fi2c.h"
20 #include "fi2c_hw.h"
21 #include "fio_mux.h"
22 #include "drivers/dev_i2c.h"
23 #include "fparameters.h"
24 #ifdef RT_USING_SMART
25     #include <ioremap.h>
26 #endif
27 
28 /*Please define the length of the mem_addr of the device*/
29 #ifndef FI2C_DEVICE_MEMADDR_LEN
30     #define FI2C_DEVICE_MEMADDR_LEN 2
31 #endif
32 #define FI2C_DEFAULT_ID 0
33 #if defined(I2C_USE_MIO)
34     #include "fmio_hw.h"
35     #include "fmio.h"
36     static FMioCtrl mio_handle;
37 #endif
38 
39 struct phytium_i2c_bus
40 {
41     struct rt_i2c_bus_device device;
42     FI2c i2c_handle;
43     struct rt_i2c_msg *msg;
44     const char *name;
45 };
46 
47 #if defined(I2C_USE_CONTROLLER)
i2c_config(struct phytium_i2c_bus * i2c_bus)48 static rt_err_t i2c_config(struct phytium_i2c_bus *i2c_bus)
49 {
50     RT_ASSERT(i2c_bus);
51     FI2cConfig input_cfg;
52     const FI2cConfig *config_p = NULL;
53     FI2c *instance_p = &i2c_bus->i2c_handle;
54     FError ret = FI2C_SUCCESS;
55 
56     /* Lookup default configs by instance id */
57     config_p = FI2cLookupConfig(instance_p->config.instance_id);
58     input_cfg = *config_p;
59 #ifdef RT_USING_SMART
60     input_cfg.base_addr = (uintptr)rt_ioremap((void *)input_cfg.base_addr, 0x1000);
61 #endif
62     input_cfg.speed_rate = FI2C_SPEED_STANDARD_RATE;
63     input_cfg.work_mode = FI2C_MASTER;
64     FI2cDeInitialize(&i2c_bus->i2c_handle);
65     /* Initialization */
66     ret = FI2cCfgInitialize(instance_p, &input_cfg);
67     if (ret != FI2C_SUCCESS)
68     {
69         LOG_E("Init master I2c failed, ret: 0x%x", ret);
70         return -RT_ERROR;
71     }
72         ret = FI2cSetAddress(&i2c_bus->i2c_handle, FI2C_MASTER, i2c_bus->i2c_handle.config.slave_addr);
73     if (FI2C_SUCCESS != ret)
74     {
75         return -RT_ERROR;
76     }
77     ret = FI2cSetSpeed(&i2c_bus->i2c_handle, FI2C_SPEED_STANDARD_RATE, TRUE);
78     if (FI2C_SUCCESS != ret)
79     {
80         return -RT_ERROR;
81     }
82 
83     return RT_EOK;
84 }
85 #endif
86 
87 #if defined(I2C_USE_MIO)
i2c_mio_config(struct phytium_i2c_bus * i2c_bus)88 static rt_err_t i2c_mio_config(struct phytium_i2c_bus *i2c_bus)
89 {
90     RT_ASSERT(i2c_bus);
91     FError ret = FI2C_SUCCESS;
92     FI2cConfig i2c_config;
93     FI2c *instance_p = &i2c_bus->i2c_handle;
94     FIOPadSetMioMux(instance_p->config.instance_id);
95 
96     mio_handle.config = *FMioLookupConfig(instance_p->config.instance_id);
97 #ifdef RT_USING_SMART
98     mio_handle.config.func_base_addr = (uintptr)rt_ioremap((void *)mio_handle.config.func_base_addr, 0x1200);
99     mio_handle.config.mio_base_addr = (uintptr)rt_ioremap((void *)mio_handle.config.mio_base_addr, 0x200);
100 #endif
101     ret = FMioFuncInit(&mio_handle, FMIO_FUNC_SET_I2C);
102     if (ret != FT_SUCCESS)
103     {
104         LOG_E("MIO initialize error.");
105         return -RT_ERROR;
106     }
107 
108     /* Modify i2c configuration */
109     rt_memset(&i2c_config, 0, sizeof(i2c_config));
110     i2c_config.base_addr = FMioFuncGetAddress(&mio_handle, FMIO_FUNC_SET_I2C);
111     i2c_config.irq_num = FMioFuncGetIrqNum(&mio_handle, FMIO_FUNC_SET_I2C);
112     i2c_config.irq_prority = 0;
113     i2c_config.ref_clk_hz = FMIO_CLK_FREQ_HZ;
114     i2c_config.work_mode = FI2C_MASTER;
115     i2c_config.use_7bit_addr = TRUE;
116     i2c_config.speed_rate = FI2C_SPEED_STANDARD_RATE;
117     i2c_config.auto_calc = TRUE;
118 
119     ret = FI2cCfgInitialize(instance_p, &i2c_config);
120 
121     if (FI2C_SUCCESS != ret)
122     {
123         LOG_E("Init mio master failed, ret: 0x%x", ret);
124         return -RT_ERROR;
125     }
126     ret = FI2cSetAddress(instance_p, FI2C_MASTER, instance_p->config.slave_addr);
127     if (FI2C_SUCCESS != ret)
128     {
129         return -RT_ERROR;
130     }
131     ret = FI2cSetSpeed(instance_p, FI2C_SPEED_STANDARD_RATE, TRUE);
132     if (FI2C_SUCCESS != ret)
133     {
134         return -RT_ERROR;
135     }
136 
137     mio_handle.is_ready = 0;
138     rt_memset(&mio_handle, 0, sizeof(mio_handle));
139 
140     return RT_EOK;
141 }
142 #endif
143 
phytium_i2c_set_speed(struct phytium_i2c_bus * i2c_bus,rt_uint32_t speed)144 static rt_err_t phytium_i2c_set_speed(struct phytium_i2c_bus *i2c_bus, rt_uint32_t speed)
145 {
146     RT_ASSERT(i2c_bus);
147     u32 ret;
148 
149     ret = FI2cSetSpeed(&i2c_bus->i2c_handle, speed, TRUE);
150     if (ret != FI2C_SUCCESS)
151     {
152         LOG_E("Set i2c speed failed!\n");
153         return -RT_ERROR;
154     }
155 
156     return RT_EOK;
157 }
158 
i2c_bus_control(struct rt_i2c_bus_device * device,int cmd,void * args)159 static rt_err_t i2c_bus_control(struct rt_i2c_bus_device *device, int cmd, void *args)
160 {
161     RT_ASSERT(device);
162     struct phytium_i2c_bus *i2c_bus;
163     i2c_bus = (struct phytium_i2c_bus *)(device);
164     FI2cConfig *config_p;
165 
166     switch (cmd)
167     {
168         case RT_I2C_DEV_CTRL_CLK:
169             phytium_i2c_set_speed(i2c_bus, *(rt_uint32_t *)args);
170             break;
171         case RT_I2C_DEV_CTRL_10BIT:
172             config_p = &i2c_bus->i2c_handle.config;
173             config_p->use_7bit_addr = FALSE;
174             FI2cCfgInitialize(&i2c_bus->i2c_handle, config_p);
175             break;
176         default:
177             return -RT_EIO;
178     }
179 
180     return RT_EOK;
181 }
182 
i2c_master_xfer(struct rt_i2c_bus_device * device,struct rt_i2c_msg msgs[],rt_uint32_t num)183 static rt_ssize_t i2c_master_xfer(struct rt_i2c_bus_device *device, struct rt_i2c_msg msgs[], rt_uint32_t num)
184 {
185     RT_ASSERT(device);
186     u32 ret;
187     struct rt_i2c_msg *pmsg;
188     rt_ssize_t i;
189     struct phytium_i2c_bus *i2c_bus;
190     i2c_bus = (struct phytium_i2c_bus *)(device);
191     uintptr mem_addr = 0;
192 
193     for (i = 0; i < num; i++)
194     {
195         pmsg = &msgs[i];
196         for (u32 j = 0; j <FI2C_DEVICE_MEMADDR_LEN; j++)
197         {
198             mem_addr |= msgs[i].buf[j] << (8 * (FI2C_DEVICE_MEMADDR_LEN - 1 - j));
199         }
200 
201         i2c_bus->i2c_handle.config.slave_addr = pmsg->addr;
202         if (pmsg->flags & RT_I2C_RD)
203         {
204             rt_thread_delay(100);
205             ret = FI2cMasterReadPoll(&i2c_bus->i2c_handle, mem_addr, FI2C_DEVICE_MEMADDR_LEN, &pmsg->buf[0], pmsg->len - FI2C_DEVICE_MEMADDR_LEN);
206             if (ret != FI2C_SUCCESS)
207             {
208                 LOG_E("I2C master read failed!\n");
209                 return -RT_ERROR;
210             }
211         }
212         else
213         {
214             rt_thread_delay(100);
215             ret = FI2cMasterWritePoll(&i2c_bus->i2c_handle, mem_addr, FI2C_DEVICE_MEMADDR_LEN, &pmsg->buf[FI2C_DEVICE_MEMADDR_LEN], pmsg->len - FI2C_DEVICE_MEMADDR_LEN);
216             if (ret != FI2C_SUCCESS)
217             {
218                 LOG_E("I2C master write failed!\n");
219                 return -RT_ERROR;
220             }
221         }
222     }
223 
224     return i;
225 }
226 
227 static const struct rt_i2c_bus_device_ops _i2c_ops =
228 {
229     .master_xfer        = i2c_master_xfer,
230     .slave_xfer         = NULL,
231     .i2c_bus_control    = i2c_bus_control
232 };
233 
234 #if defined(I2C_USE_CONTROLLER)
i2c_controller_init(struct phytium_i2c_bus * i2c_controller_bus)235 static int i2c_controller_init(struct phytium_i2c_bus *i2c_controller_bus)
236 {
237     rt_err_t ret = RT_EOK;
238     ret = i2c_config(i2c_controller_bus);
239     if (ret != RT_EOK)
240     {
241         LOG_E("I2C config failed.\n");
242 
243         return -RT_ERROR;
244     }
245     i2c_controller_bus->device.ops = &_i2c_ops;
246     ret = rt_i2c_bus_device_register(&i2c_controller_bus->device, i2c_controller_bus->name);
247     RT_ASSERT(RT_EOK == ret);
248     LOG_D("I2C bus reg success.\n");
249 
250     return ret;
251 }
252 #endif
253 
254 #if defined(I2C_USE_MIO)
i2c_mio_init(struct phytium_i2c_bus * i2c_mio_bus)255 static int i2c_mio_init(struct phytium_i2c_bus *i2c_mio_bus)
256 {
257     rt_err_t ret = RT_EOK;
258     ret = i2c_mio_config(i2c_mio_bus);
259     if (ret != RT_EOK)
260     {
261         LOG_E("I2C mio config failed.\n");
262 
263         return -RT_ERROR;
264     }
265     i2c_mio_bus->device.ops = &_i2c_ops;
266     ret = rt_i2c_bus_device_register(&i2c_mio_bus->device, i2c_mio_bus->name);
267     RT_ASSERT(RT_EOK == ret);
268     LOG_D("I2C mio bus reg success.\n");
269 
270     return ret;
271 }
272 #endif
273 
274 #if defined(RT_USING_I2C0)
275     static struct phytium_i2c_bus i2c_controller0_bus;
276 #endif
277 #if defined(RT_USING_I2C1)
278     static struct phytium_i2c_bus i2c_controller1_bus;
279 #endif
280 #if defined(RT_USING_I2C2)
281     static struct phytium_i2c_bus i2c_controller2_bus;
282 #endif
283 #if defined(RT_USING_I2C3)
284     static struct phytium_i2c_bus i2c_controller3_bus;
285 #endif
286 
287 #if defined(RT_USING_MIO0)
288     static struct phytium_i2c_bus i2c_mio0_bus;
289 #endif
290 #if defined(RT_USING_MIO1)
291     static struct phytium_i2c_bus i2c_mio1_bus;
292 #endif
293 #if defined(RT_USING_MIO2)
294     static struct phytium_i2c_bus i2c_mio2_bus;
295 #endif
296 #if defined(RT_USING_MIO3)
297     static struct phytium_i2c_bus i2c_mio3_bus;
298 #endif
299 #if defined(RT_USING_MIO4)
300     static struct phytium_i2c_bus i2c_mio4_bus;
301 #endif
302 #if defined(RT_USING_MIO5)
303     static struct phytium_i2c_bus i2c_mio5_bus;
304 #endif
305 #if defined(RT_USING_MIO6)
306     static struct phytium_i2c_bus i2c_mio6_bus;
307 #endif
308 #if defined(RT_USING_MIO7)
309     static struct phytium_i2c_bus i2c_mio7_bus;
310 #endif
311 #if defined(RT_USING_MIO8)
312     static struct phytium_i2c_bus i2c_mio8_bus;
313 #endif
314 #if defined(RT_USING_MIO9)
315     static struct phytium_i2c_bus i2c_mio9_bus;
316 #endif
317 #if defined(RT_USING_MIO10)
318     static struct phytium_i2c_bus i2c_mio10_bus;
319 #endif
320 #if defined(RT_USING_MIO11)
321     static struct phytium_i2c_bus i2c_mio11_bus;
322 #endif
323 #if defined(RT_USING_MIO12)
324     static struct phytium_i2c_bus i2c_mio12_bus;
325 #endif
326 #if defined(RT_USING_MIO13)
327     static struct phytium_i2c_bus i2c_mio13_bus;
328 #endif
329 #if defined(RT_USING_MIO14)
330     static struct phytium_i2c_bus i2c_mio14_bus;
331 #endif
332 #if defined(RT_USING_MIO15)
333     static struct phytium_i2c_bus i2c_mio15_bus;
334 #endif
335 
rt_hw_i2c_init(void)336 int rt_hw_i2c_init(void)
337 {
338 #if defined(RT_USING_I2C0)
339     i2c_controller0_bus.name = "I2C0";
340     i2c_controller0_bus.i2c_handle.config.instance_id = FI2C0_ID;
341     i2c_controller_init(&i2c_controller0_bus);
342 #endif
343 #if defined(RT_USING_I2C1)
344     i2c_controller1_bus.name = "I2C1";
345     i2c_controller1_bus.i2c_handle.config.instance_id = FI2C1_ID;
346     i2c_controller_init(&i2c_controller1_bus);
347 #endif
348 #if defined(RT_USING_I2C2)
349     i2c_controller2_bus.name = "I2C2";
350     i2c_controller2_bus.i2c_handle.config.instance_id = FI2C2_ID;
351     i2c_controller_init(&i2c_controller2_bus);
352 #endif
353 #if defined(RT_USING_I2C3)
354     i2c_controller3_bus.name = "I2C3";
355     i2c_controller3_bus.i2c_handle.config.instance_id = FI2C3_ID;
356     i2c_controller_init(&i2c_controller3_bus);
357 #endif
358 
359 #if defined(RT_USING_MIO0)
360     i2c_mio0_bus.name = "MIO0";
361     i2c_mio0_bus.i2c_handle.config.instance_id = FMIO0_ID;
362     i2c_mio_init(&i2c_mio0_bus);
363 #endif
364 #if defined(RT_USING_MIO1)
365     i2c_mio1_bus.name = "MIO1";
366     i2c_mio1_bus.i2c_handle.config.instance_id = FMIO1_ID;
367     i2c_mio_init(&i2c_mio1_bus);
368 #endif
369 #if defined(RT_USING_MIO2)
370     i2c_mio2_bus.name = "MIO2";
371     i2c_mio2_bus.i2c_handle.config.instance_id = FMIO2_ID;
372     i2c_mio_init(&i2c_mio2_bus);
373 #endif
374 #if defined(RT_USING_MIO3)
375     i2c_mio3_bus.name = "MIO3";
376     i2c_mio3_bus.i2c_handle.config.instance_id = FMIO3_ID;
377     i2c_mio_init(&i2c_mio3_bus);
378 #endif
379 #if defined(RT_USING_MIO4)
380     i2c_mio4_bus.name = "MIO4";
381     i2c_mio4_bus.i2c_handle.config.instance_id = FMIO4_ID;
382     i2c_mio_init(&i2c_mio4_bus);
383 #endif
384 #if defined(RT_USING_MIO5)
385     i2c_mio5_bus.name = "MIO5";
386     i2c_mio5_bus.i2c_handle.config.instance_id = FMIO5_ID;
387     i2c_mio_init(&i2c_mio5_bus);
388 #endif
389 #if defined(RT_USING_MIO6)
390     i2c_mio6_bus.name = "MIO6";
391     i2c_mio6_bus.i2c_handle.config.instance_id = FMIO6_ID;
392     i2c_mio_init(&i2c_mio6_bus);
393 #endif
394 #if defined(RT_USING_MIO7)
395     i2c_mio7_bus.name = "MIO2";
396     i2c_mio7_bus.i2c_handle.config.instance_id = FMIO7_ID;
397     i2c_mio_init(&i2c_mio7_bus);
398 #endif
399 #if defined(RT_USING_MIO8)
400     i2c_mio8_bus.name = "MIO8";
401     i2c_mio8_bus.i2c_handle.config.instance_id = FMIO8_ID;
402     i2c_mio_init(&i2c_mio8_bus);
403 #endif
404 #if defined(RT_USING_MIO9)
405     i2c_mio9_bus.name = "MIO9";
406     i2c_mio9_bus.i2c_handle.config.instance_id = FMIO9_ID;
407     i2c_mio_init(&i2c_mio9_bus);
408 #endif
409 #if defined(RT_USING_MIO10)
410     i2c_mio10_bus.name = "MIO10";
411     i2c_mio10_bus.i2c_handle.config.instance_id = FMIO10_ID;
412     i2c_mio_init(&i2c_mio10_bus);
413 #endif
414 #if defined(RT_USING_MIO11)
415     i2c_mio11_bus.name = "MIO11";
416     i2c_mio11_bus.i2c_handle.config.instance_id = FMIO11_ID;
417     i2c_mio_init(&i2c_mio11_bus);
418 #endif
419 #if defined(RT_USING_MIO12)
420     i2c_mio12_bus.name = "MIO12";
421     i2c_mio12_bus.i2c_handle.config.instance_id = FMIO12_ID;
422     i2c_mio_init(&i2c_mio12_bus);
423 #endif
424 #if defined(RT_USING_MIO13)
425     i2c_mio13_bus.name = "MIO13";
426     i2c_mio13_bus.i2c_handle.config.instance_id = FMIO13_ID;
427     i2c_mio_init(&i2c_mio13_bus);
428 #endif
429 #if defined(RT_USING_MIO14)
430     i2c_mio14_bus.name = "MIO14";
431     i2c_mio14_bus.i2c_handle.config.instance_id = FMIO14_ID;
432     i2c_mio_init(&i2c_mio14_bus);
433 #endif
434 #if defined(RT_USING_MIO15)
435     i2c_mio15_bus.name = "MIO15";
436     i2c_mio15_bus.i2c_handle.config.instance_id = FMIO15_ID;
437     i2c_mio_init(&i2c_mio15_bus);
438 #endif
439 
440     return 0;
441 }
442 INIT_DEVICE_EXPORT(rt_hw_i2c_init);
443