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