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  * 2021-04-20     RiceChen      added support for bus control api
10  */
11 
12 #include <rtdevice.h>
13 
14 #define DBG_TAG               "I2C"
15 #ifdef RT_I2C_DEBUG
16 #define DBG_LVL               DBG_LOG
17 #else
18 #define DBG_LVL               DBG_INFO
19 #endif
20 #include <rtdbg.h>
21 
rt_i2c_bus_device_register(struct rt_i2c_bus_device * bus,const char * bus_name)22 rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus,
23                                     const char               *bus_name)
24 {
25     rt_err_t res = RT_EOK;
26 
27     rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_PRIO);
28 
29     if (bus->timeout == 0) bus->timeout = RT_TICK_PER_SECOND;
30 
31     res = rt_i2c_bus_device_device_init(bus, bus_name);
32 
33     LOG_D("I2C bus [%s] registered", bus_name);
34 
35 #ifdef RT_USING_DM
36     if (!res)
37     {
38         i2c_bus_scan_clients(bus);
39     }
40 #endif
41 
42     return res;
43 }
44 
rt_i2c_bus_device_find(const char * bus_name)45 struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name)
46 {
47     struct rt_i2c_bus_device *bus;
48     rt_device_t dev = rt_device_find(bus_name);
49     if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS)
50     {
51         LOG_E("I2C bus %s not exist", bus_name);
52 
53         return RT_NULL;
54     }
55 
56     bus = (struct rt_i2c_bus_device *)dev->user_data;
57 
58     return bus;
59 }
60 
rt_i2c_transfer(struct rt_i2c_bus_device * bus,struct rt_i2c_msg msgs[],rt_uint32_t num)61 rt_ssize_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,
62                           struct rt_i2c_msg         msgs[],
63                           rt_uint32_t               num)
64 {
65     rt_ssize_t ret;
66     rt_err_t err;
67 
68     if (bus->ops->master_xfer)
69     {
70 #ifdef RT_I2C_DEBUG
71         for (ret = 0; ret < num; ret++)
72         {
73             LOG_D("msgs[%d] %c, addr=0x%02x, len=%d", ret,
74                   (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W',
75                   msgs[ret].addr, msgs[ret].len);
76         }
77 #endif
78         err = rt_mutex_take(&bus->lock, RT_WAITING_FOREVER);
79         if (err != RT_EOK)
80         {
81             return (rt_ssize_t)err;
82         }
83         ret = bus->ops->master_xfer(bus, msgs, num);
84         err = rt_mutex_release(&bus->lock);
85         if (err != RT_EOK)
86         {
87             return (rt_ssize_t)err;
88         }
89         return ret;
90     }
91     else
92     {
93         LOG_E("I2C bus operation not supported");
94         return -RT_EINVAL;
95     }
96 }
97 
rt_i2c_control(struct rt_i2c_bus_device * bus,int cmd,void * args)98 rt_err_t rt_i2c_control(struct rt_i2c_bus_device *bus,
99                         int                       cmd,
100                         void                      *args)
101 {
102     rt_err_t ret;
103 
104     if(bus->ops->i2c_bus_control)
105     {
106         ret = bus->ops->i2c_bus_control(bus, cmd, args);
107         return ret;
108     }
109     else
110     {
111         LOG_E("I2C bus operation not supported");
112         return -RT_EINVAL;
113     }
114 }
115 
rt_i2c_master_send(struct rt_i2c_bus_device * bus,rt_uint16_t addr,rt_uint16_t flags,const rt_uint8_t * buf,rt_uint32_t count)116 rt_ssize_t rt_i2c_master_send(struct rt_i2c_bus_device *bus,
117                              rt_uint16_t               addr,
118                              rt_uint16_t               flags,
119                              const rt_uint8_t         *buf,
120                              rt_uint32_t               count)
121 {
122     rt_ssize_t ret;
123     struct rt_i2c_msg msg;
124 
125     msg.addr  = addr;
126     msg.flags = flags;
127     msg.len   = count;
128     msg.buf   = (rt_uint8_t *)buf;
129 
130     ret = rt_i2c_transfer(bus, &msg, 1);
131 
132     return (ret == 1) ? count : ret;
133 }
134 
rt_i2c_master_recv(struct rt_i2c_bus_device * bus,rt_uint16_t addr,rt_uint16_t flags,rt_uint8_t * buf,rt_uint32_t count)135 rt_ssize_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus,
136                              rt_uint16_t               addr,
137                              rt_uint16_t               flags,
138                              rt_uint8_t               *buf,
139                              rt_uint32_t               count)
140 {
141     rt_ssize_t ret;
142     struct rt_i2c_msg msg;
143     RT_ASSERT(bus != RT_NULL);
144 
145     msg.addr   = addr;
146     msg.flags  = flags | RT_I2C_RD;
147     msg.len    = count;
148     msg.buf    = buf;
149 
150     ret = rt_i2c_transfer(bus, &msg, 1);
151 
152     return (ret == 1) ? count : ret;
153 }
154