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 * 2012-04-25 weety first version
9 * 2014-08-03 bernard fix some compiling warning
10 * 2021-04-20 RiceChen added support for bus clock control
11 */
12
13 #include <rtdevice.h>
14
15 #define DBG_TAG "I2C"
16 #ifdef RT_I2C_DEBUG
17 #define DBG_LVL DBG_LOG
18 #else
19 #define DBG_LVL DBG_INFO
20 #endif
21 #include <rtdbg.h>
22
i2c_bus_device_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t count)23 static rt_ssize_t i2c_bus_device_read(rt_device_t dev,
24 rt_off_t pos,
25 void *buffer,
26 rt_size_t count)
27 {
28 rt_uint16_t addr;
29 rt_uint16_t flags;
30 struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data;
31
32 RT_ASSERT(bus != RT_NULL);
33 RT_ASSERT(buffer != RT_NULL);
34
35 LOG_D("I2C bus dev [%s] reading %u bytes.", dev->parent.name, count);
36
37 addr = pos & 0xffff;
38 flags = (pos >> 16) & 0xffff;
39
40 return rt_i2c_master_recv(bus, addr, flags, (rt_uint8_t *)buffer, count);
41 }
42
i2c_bus_device_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t count)43 static rt_ssize_t i2c_bus_device_write(rt_device_t dev,
44 rt_off_t pos,
45 const void *buffer,
46 rt_size_t count)
47 {
48 rt_uint16_t addr;
49 rt_uint16_t flags;
50 struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data;
51
52 RT_ASSERT(bus != RT_NULL);
53 RT_ASSERT(buffer != RT_NULL);
54
55 LOG_D("I2C bus dev [%s] writing %u bytes.", dev->parent.name, count);
56
57 addr = pos & 0xffff;
58 flags = (pos >> 16) & 0xffff;
59
60 return rt_i2c_master_send(bus, addr, flags, (const rt_uint8_t *)buffer, count);
61 }
62
i2c_bus_device_control(rt_device_t dev,int cmd,void * args)63 static rt_err_t i2c_bus_device_control(rt_device_t dev,
64 int cmd,
65 void *args)
66 {
67 rt_err_t ret;
68 struct rt_i2c_priv_data *priv_data;
69 struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data;
70
71 RT_ASSERT(bus != RT_NULL);
72
73 switch (cmd)
74 {
75 /* set 10-bit addr mode */
76 case RT_I2C_DEV_CTRL_10BIT:
77 bus->flags |= RT_I2C_ADDR_10BIT;
78 break;
79 case RT_I2C_DEV_CTRL_TIMEOUT:
80 bus->timeout = *(rt_uint32_t *)args;
81 break;
82 case RT_I2C_DEV_CTRL_RW:
83 priv_data = (struct rt_i2c_priv_data *)args;
84 ret = rt_i2c_transfer(bus, priv_data->msgs, priv_data->number);
85 if (ret < 0)
86 {
87 return -RT_EIO;
88 }
89 break;
90 default:
91 return rt_i2c_control(bus, cmd, args);
92 }
93
94 return RT_EOK;
95 }
96
97 #ifdef RT_USING_DEVICE_OPS
98 const static struct rt_device_ops i2c_ops =
99 {
100 RT_NULL,
101 RT_NULL,
102 RT_NULL,
103 i2c_bus_device_read,
104 i2c_bus_device_write,
105 i2c_bus_device_control
106 };
107 #endif
108
rt_i2c_bus_device_device_init(struct rt_i2c_bus_device * bus,const char * name)109 rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus,
110 const char *name)
111 {
112 struct rt_device *device;
113 RT_ASSERT(bus != RT_NULL);
114
115 device = &bus->parent;
116
117 device->user_data = bus;
118
119 /* set device type */
120 device->type = RT_Device_Class_I2CBUS;
121 /* initialize device interface */
122 #ifdef RT_USING_DEVICE_OPS
123 device->ops = &i2c_ops;
124 #else
125 device->init = RT_NULL;
126 device->open = RT_NULL;
127 device->close = RT_NULL;
128 device->read = i2c_bus_device_read;
129 device->write = i2c_bus_device_write;
130 device->control = i2c_bus_device_control;
131 #endif
132
133 /* register to device manager */
134 rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
135
136 return RT_EOK;
137 }
138