• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdlib.h>
17 #include "hcs_macro.h"
18 #include "hdf_config_macro.h"
19 #include "hdf_device_desc.h"
20 #include "hdf_log.h"
21 #include "i2c_core.h"
22 #include "i2c_if.h"
23 #include "osal_mutex.h"
24 #include "driver/i2c.h"
25 
26 #define HDF_LOG_TAG "ESP32U4_HDF_I2C"
27 
28 struct RealI2cResource {
29     uint8_t port;    // I2C端口号
30     uint8_t mode;    // I2C主从模式  0:master 1:slave
31     uint8_t scl_pin; // SCL引脚号
32     uint8_t sda_pin; // SDA引脚号
33     uint32_t speed;  // I2C时钟频率
34 };
35 
36 static int32_t I2cDriverBind(struct HdfDeviceObject *device);
37 static int32_t I2cDriverInit(struct HdfDeviceObject *device);
38 static void I2cDriverRelease(struct HdfDeviceObject *device);
39 static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
40 
41 struct HdfDriverEntry gI2cHdfDriverEntry = {
42     .moduleVersion = 1,
43     .moduleName = "ESP32U4_HDF_I2C",
44     .Bind = I2cDriverBind,
45     .Init = I2cDriverInit,
46     .Release = I2cDriverRelease,
47 };
48 HDF_INIT(gI2cHdfDriverEntry);
49 
50 struct I2cMethod gI2cHostMethod = {
51     .transfer = I2cDataTransfer,
52 };
53 
54 #define I2C_FIND_CONFIG(node, name, resource)                       \
55     do {                                                            \
56         if (strcmp(HCS_PROP(node, match_attr), name) == 0) {        \
57             (resource)->mode = HCS_PROP(node, mode);                \
58             (resource)->port = HCS_PROP(node, port);                \
59             (resource)->scl_pin = HCS_PROP(node, scl_pin);          \
60             (resource)->sda_pin = HCS_PROP(node, sda_pin);          \
61             (resource)->speed = HCS_PROP(node, speed);              \
62             HDF_LOGE("----- I2C%d Config -----", (resource)->port); \
63             HDF_LOGE("mode = %d", (resource)->mode);                \
64             HDF_LOGE("scl_pin = %d", (resource)->scl_pin);          \
65             HDF_LOGE("sda_pin = %d", (resource)->sda_pin);          \
66             HDF_LOGE("speed = %d", (resource)->speed);              \
67             result = HDF_SUCCESS;                                   \
68         }                                                           \
69     } while (0)
70 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
71 #define PLATFORM_I2C_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), i2c_config)
GetI2cDeviceResource(struct RealI2cResource * i2cResource,const char * deviceMatchAttr)72 static uint32_t GetI2cDeviceResource(struct RealI2cResource *i2cResource, const char *deviceMatchAttr)
73 {
74     int32_t result = HDF_FAILURE;
75     struct RealI2cResource *resource = NULL;
76     if (i2cResource == NULL || deviceMatchAttr == NULL) {
77         HDF_LOGE("device or deviceMatchAttr is NULL\r\n");
78         return HDF_ERR_INVALID_PARAM;
79     }
80     resource = i2cResource;
81 #if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, i2c_config)
82     HCS_FOREACH_CHILD_VARGS(PLATFORM_I2C_CONFIG, I2C_FIND_CONFIG, deviceMatchAttr, resource);
83 #endif
84     if (result != HDF_SUCCESS) {
85         HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
86     }
87     return result;
88 }
89 #define TICKS_SECOND 1000
DeviceI2cWrite(int id,unsigned char addr,const unsigned char * data,unsigned int dataLen,int ack)90 unsigned int DeviceI2cWrite(int id, unsigned char addr, const unsigned char *data, unsigned int dataLen, int ack)
91 {
92     unsigned int ret;
93     i2c_cmd_handle_t cmd;
94     if (dataLen < 1) {
95         return 0;
96     }
97     cmd = i2c_cmd_link_create();
98     if ((ret = i2c_master_start(cmd)) != 0) {
99         HDF_LOGE("DeviceI2cWrite i2c_master_start failed ret = %x", ret);
100         return ret;
101     }
102     if ((ret = i2c_master_write_byte(cmd, addr | 0x00, ack)) != 0) {
103         HDF_LOGE("DeviceI2cWrite i2c_master_write_addr failed ret = %x", ret);
104         return ret;
105     }
106 
107     if ((ret = i2c_master_write(cmd, data, dataLen, 1)) != 0) {
108         HDF_LOGE("DeviceI2cWrite i2c_master_write failed ret = %x", ret);
109         return ret;
110     }
111 
112     if ((ret = i2c_master_stop(cmd)) != 0) {
113         HDF_LOGE("DeviceI2cWrite i2c_master_stop failed ret = %x", ret);
114         return ret;
115     }
116     if ((ret = i2c_master_cmd_begin(id, cmd, TICKS_SECOND / portTICK_RATE_MS)) != 0) {
117         HDF_LOGE("DeviceI2cWrite i2c_master_cmd_begin failed ret = %d", ret);
118         return ret;
119     }
120     i2c_cmd_link_delete(cmd);
121     return ret;
122 }
123 
DeviceI2cRead(int id,unsigned char addr,const unsigned char * data,unsigned int dataLen,int ack)124 unsigned int DeviceI2cRead(int id, unsigned char addr, const unsigned char *data, unsigned int dataLen, int ack)
125 {
126     unsigned int ret;
127     i2c_cmd_handle_t cmd;
128     if (dataLen < 1) {
129         return 0;
130     }
131     cmd = i2c_cmd_link_create();
132     if ((ret = i2c_master_start(cmd)) != 0) {
133         HDF_LOGE("DeviceI2cRead i2c_master_start failed ret = %x", ret);
134         return ret;
135     }
136 
137     if ((ret = i2c_master_write_byte(cmd, addr | 0x01, ack)) != 0) {
138         HDF_LOGE("DeviceI2cRead i2c_master_write_addr failed ret = %x", ret);
139         return ret;
140     }
141 
142     if (dataLen > 1) {
143         if ((ret = i2c_master_read(cmd, data, dataLen - 1, 0)) != 0) {
144             HDF_LOGE("DeviceI2cRead i2c_master_read failed ret = %x", ret);
145             return ret;
146         }
147     }
148 
149     if ((ret = i2c_master_read_byte(cmd, data + dataLen - 1, 1)) != 0) {
150         HDF_LOGE("DeviceI2cRead i2c_master_read_byte failed ret = %x", ret);
151         return ret;
152     }
153 
154     if ((ret = i2c_master_stop(cmd)) != 0) {
155         HDF_LOGE("DeviceI2cRead i2c_master_stop failed ret = %x", ret);
156         return ret;
157     }
158 
159     if ((ret = i2c_master_cmd_begin(id, cmd, TICKS_SECOND / portTICK_RATE_MS)) != 0) {
160         HDF_LOGE("DeviceI2cRead i2c_master_cmd_begin failed ret = %x", ret);
161         return ret;
162     }
163     i2c_cmd_link_delete(cmd);
164     return ret;
165 }
166 #define MODE2 2
167 #define MODE4 4
DeviceI2cInit(int id,int scl_pin,int sda_pin,int speed,int mode)168 static int DeviceI2cInit(int id, int scl_pin, int sda_pin, int speed, int mode)
169 {
170     i2c_config_t conf;
171     (void)memset_s(&conf, sizeof(conf), 0, sizeof(conf));
172     conf.mode = (mode & 1) ? I2C_MODE_SLAVE : I2C_MODE_MASTER;
173     conf.sda_io_num = sda_pin;
174     conf.scl_io_num = scl_pin;
175     conf.sda_pullup_en = (mode & MODE2) ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
176     conf.scl_pullup_en = (mode & MODE4) ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
177     conf.master.clk_speed = speed;
178     i2c_param_config(id, &conf);
179     return i2c_driver_install(id, conf.mode, 0, 0, 0);
180 }
181 
AttachI2cDevice(struct I2cCntlr * host,struct HdfDeviceObject * device)182 static int32_t AttachI2cDevice(struct I2cCntlr *host, struct HdfDeviceObject *device)
183 {
184     int32_t ret = HDF_FAILURE;
185 
186     if (host == NULL || device == NULL) {
187         HDF_LOGE("[%s]: param is NULL\r\n", __func__);
188         return HDF_ERR_INVALID_PARAM;
189     }
190 
191     struct RealI2cResource *i2cResource = (struct RealI2cResource *)OsalMemAlloc(sizeof(struct RealI2cResource));
192     if (i2cResource == NULL) {
193         HDF_LOGE("[%s]: OsalMemAlloc RealI2cResource fail\r\n", __func__);
194         return HDF_ERR_MALLOC_FAIL;
195     }
196     memset_s(i2cResource, sizeof(struct RealI2cResource), 0, sizeof(struct RealI2cResource));
197 
198     ret = GetI2cDeviceResource(i2cResource, device->deviceMatchAttr);
199 
200     DeviceI2cInit(i2cResource->port, i2cResource->scl_pin, i2cResource->sda_pin,
201                   i2cResource->speed, i2cResource->mode);
202 
203     if (ret != HDF_SUCCESS) {
204         OsalMemFree(i2cResource);
205         return HDF_FAILURE;
206     }
207 
208     host->busId = i2cResource->port;
209     host->priv = i2cResource;
210 
211     return HDF_SUCCESS;
212 }
213 
I2cDataTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)214 static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
215 {
216     unsigned int ret;
217     if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) {
218         HDF_LOGE("[%s]: I2cDataTransfer param is NULL\r\n", __func__);
219         return HDF_ERR_INVALID_PARAM;
220     }
221 
222     if (count <= 0) {
223         HDF_LOGE("[%s]: I2cDataTransfer count err\r\n", __func__);
224         return HDF_ERR_INVALID_PARAM;
225     }
226 
227     struct RealI2cResource *device = (struct I2cDevice *)cntlr->priv;
228     if (device == NULL) {
229         HDF_LOGE("%s: I2cDevice is NULL\r\n", __func__);
230         return HDF_DEV_ERR_NO_DEVICE;
231     }
232 
233     for (; count > 0; --count, ++msgs) {
234         if ((msgs->flags) == 0) { // write
235             if (DeviceI2cWrite(cntlr->busId, msgs->addr, msgs->buf, msgs->len, 1))
236                 break;
237         } else if ((msgs->flags) == I2C_FLAG_READ) { // read
238             if (DeviceI2cRead(cntlr->busId, msgs->addr, msgs->buf, msgs->len, 1))
239                 break;
240         }
241     }
242     return count;
243 }
244 
I2cDriverBind(struct HdfDeviceObject * device)245 static int32_t I2cDriverBind(struct HdfDeviceObject *device)
246 {
247     return HDF_SUCCESS;
248 }
249 
I2cDriverInit(struct HdfDeviceObject * device)250 static int32_t I2cDriverInit(struct HdfDeviceObject *device)
251 {
252     int32_t ret = HDF_FAILURE;
253     struct I2cCntlr *host = NULL;
254     if (device == NULL) {
255         HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__);
256         return HDF_ERR_INVALID_PARAM;
257     }
258 
259     host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr));
260     if (host == NULL) {
261         HDF_LOGE("[%s]: malloc host is NULL\r\n", __func__);
262         return HDF_ERR_MALLOC_FAIL;
263     }
264 
265     memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr));
266     host->ops = &gI2cHostMethod;
267     device->priv = (VOID *)host;
268 
269     ret = AttachI2cDevice(host, device);
270     if (ret != HDF_SUCCESS) {
271         HDF_LOGE("[%s]: AttachI2cDevice error, ret = %d\r\n", __func__, ret);
272         I2cDriverRelease(device);
273         return HDF_DEV_ERR_ATTACHDEV_FAIL;
274     }
275 
276     ret = I2cCntlrAdd(host);
277     if (ret != HDF_SUCCESS) {
278         I2cDriverRelease(device);
279         return HDF_FAILURE;
280     }
281     HDF_LOGI("I2cDriverInit success!!");
282     return HDF_SUCCESS;
283 }
284 
I2cDriverRelease(struct HdfDeviceObject * device)285 static void I2cDriverRelease(struct HdfDeviceObject *device)
286 {
287     if (device == NULL) {
288         HDF_LOGE("%s: device is NULL\r\n", __func__);
289         return;
290     }
291 
292     struct I2cCntlr *i2cCntrl = device->priv;
293     if (i2cCntrl == NULL || i2cCntrl->priv == NULL) {
294         HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__);
295         return;
296     }
297     i2cCntrl->ops = NULL;
298     struct RealI2cResource *i2cDevice = (struct I2cDevice *)i2cCntrl->priv;
299     OsalMemFree(i2cCntrl);
300 
301     if (i2cDevice != NULL) {
302         OsalMemFree(i2cDevice);
303     }
304 }
305