• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3  *
4  * This file is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "i2c_bes.h"
10 #include <stdlib.h>
11 #include <securec.h>
12 #include "i2c_core.h"
13 #include "i2c_if.h"
14 #include "hdf_device_desc.h"
15 #include "hdf_log.h"
16 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
17 #include "hcs_macro.h"
18 #include "hdf_config_macro.h"
19 #else
20 #include "device_resource_if.h"
21 #endif
22 
23 #define DEC_NUM 10
24 #define GROUP_PIN_NUM 8
25 #define I2C_INVALID_ADDR 0xFFFF
26 
27 /* HdfDriverEntry method definitions */
28 static int32_t i2cDriverBind(struct HdfDeviceObject *device);
29 static int32_t i2cDriverInit(struct HdfDeviceObject *device);
30 static void i2cDriverRelease(struct HdfDeviceObject *device);
31 
32 /* HdfDriverEntry definitions */
33 struct HdfDriverEntry g_i2cDriverEntry = {
34     .moduleVersion = 1,
35     .moduleName = "BES_I2C_MODULE_HDF",
36     .Bind = i2cDriverBind,
37     .Init = i2cDriverInit,
38     .Release = i2cDriverRelease,
39 };
40 
41 // Initialize HdfDriverEntry
42 HDF_INIT(g_i2cDriverEntry);
43 
44 /* I2cHostMethod method definitions */
45 static int32_t i2cHostTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
46 
47 struct I2cMethod g_i2cHostMethod = {
48     .transfer = i2cHostTransfer,
49 };
50 
I2cDeviceIomuxInit(uint32_t i2cId,const struct I2cResource * resource)51 static void I2cDeviceIomuxInit(uint32_t i2cId, const struct I2cResource *resource)
52 {
53     if (i2cId > HAL_I2C_ID_NUM || resource == NULL) {
54         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
55         return;
56     }
57 
58     struct HAL_IOMUX_PIN_FUNCTION_MAP pinMuxI2c[] = {
59         {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENABLE},
60         {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENABLE},
61     };
62 
63 #ifdef LOSCFG_SOC_SERIES_BES2600
64     if (i2cId == 0) {
65         pinMuxI2c[0].function = HAL_IOMUX_FUNC_I2C_M0_SCL;
66         pinMuxI2c[1].function = HAL_IOMUX_FUNC_I2C_M0_SDA;
67     } else {
68         pinMuxI2c[0].function = HAL_IOMUX_FUNC_I2C_M1_SCL;
69         pinMuxI2c[1].function = HAL_IOMUX_FUNC_I2C_M1_SDA;
70     }
71 #elif defined (LOSCFG_SOC_SERIES_BES2700)
72     if (i2cId == 0) {
73         pinMuxI2c[0].function = HAL_IOMUX_FUNC_SYS_I2C_M0_SCL;
74         pinMuxI2c[1].function = HAL_IOMUX_FUNC_SYS_I2C_M0_SDA;
75     } else {
76         pinMuxI2c[0].function = HAL_IOMUX_FUNC_SYS_I2C_M1_SCL;
77         pinMuxI2c[1].function = HAL_IOMUX_FUNC_SYS_I2C_M1_SDA;
78     }
79 #endif
80     pinMuxI2c[0].pin = resource->sclPin;
81     pinMuxI2c[1].pin = resource->sdaPin;
82     hal_iomux_init(pinMuxI2c, ARRAY_SIZE(pinMuxI2c));
83 }
84 
InitI2cDevice(struct I2cDevice * device)85 static int32_t InitI2cDevice(struct I2cDevice *device)
86 {
87     int32_t ret;
88     uint32_t i2cPort;
89     struct I2cResource *resource = NULL;
90     struct HAL_I2C_CONFIG_T *i2cConfig = NULL;
91     if (device == NULL) {
92         HDF_LOGE("device is NULL\r\n");
93         return HDF_ERR_INVALID_PARAM;
94     }
95 
96     resource = &device->resource;
97     if (resource == NULL) {
98         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
99         return HDF_ERR_INVALID_PARAM;
100     }
101 
102     i2cConfig = &device->i2cCfg;
103     if (i2cConfig == NULL) {
104         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
105         return HDF_ERR_INVALID_PARAM;
106     }
107 
108     device->port = resource->port;
109     i2cPort = device->port;
110     if (i2cPort > HAL_I2C_ID_NUM) {
111         HDF_LOGE("i2c port %u not support\r\n", i2cPort);
112         return HDF_ERR_NOT_SUPPORT;
113     }
114 
115     if (OsalMutexInit(&device->mutex) != HDF_SUCCESS) {
116         HDF_LOGE("%s %d OsalMutexInit fail\r\n", __func__, __LINE__);
117         return HDF_FAILURE;
118     }
119 
120     if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
121         HDF_LOGE("%s %d osMutexWait fail\r\n", __func__, __LINE__);
122         return HDF_ERR_TIMEOUT;
123     }
124 
125     I2cDeviceIomuxInit(i2cPort, resource);
126 
127     ret = hal_i2c_open(i2cPort, i2cConfig);
128     if (ret == HDF_SUCCESS) {
129         HDF_LOGD("open %u i2c succ.\r\n", i2cPort);
130     }
131     OsalMutexUnlock(&device->mutex);
132     return ret;
133 }
134 
135 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
136 #define I2C_FIND_CONFIG(node, name, resource, result, tempPin) \
137     do { \
138         if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
139             resource->port = HCS_PROP(node, port); \
140             tempPin = HCS_PROP(node, sclPin); \
141             resource->sclPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); \
142             tempPin = HCS_PROP(node, sdaPin); \
143             resource->sdaPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); \
144             resource->speed = HCS_PROP(node, speed); \
145             resource->mode = HCS_PROP(node, mode); \
146             resource->useDma = HCS_PROP(node, useDma); \
147             resource->useSync = HCS_PROP(node, useSync); \
148             resource->asMaster = HCS_PROP(node, asMaster); \
149             result = HDF_SUCCESS; \
150             break; \
151         } \
152     } while (0)
153 #define PLATFORM_I2C_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), i2c_config)
GetI2cDeviceResource(struct I2cDevice * device,const char * deviceMatchAttr)154 static uint32_t GetI2cDeviceResource(struct I2cDevice *device,
155                                      const char *deviceMatchAttr)
156 {
157     uint32_t tempPin;
158     int32_t result = HDF_FAILURE;
159     struct I2cResource *resource = NULL;
160     if (device == NULL || deviceMatchAttr == NULL) {
161         HDF_LOGE("device or deviceMatchAttr is NULL");
162         return HDF_ERR_INVALID_PARAM;
163     }
164     resource = &device->resource;
165 #if HCS_NODE_EXISTS(PLATFORM_I2C_CONFIG)
166     HCS_FOREACH_CHILD_VARGS(PLATFORM_I2C_CONFIG, I2C_FIND_CONFIG, deviceMatchAttr, resource, result, tempPin);
167 #endif
168     if (result != HDF_SUCCESS) {
169         HDF_LOGE("resourceNode %s is NULL", deviceMatchAttr);
170     }
171     return result;
172 }
173 #else
GetI2cDeviceResource(struct I2cDevice * device,const struct DeviceResourceNode * resourceNode)174 static uint32_t GetI2cDeviceResource(struct I2cDevice *device,
175                                      const struct DeviceResourceNode *resourceNode)
176 {
177     uint32_t tempPin;
178     struct I2cResource *resource = NULL;
179     struct DeviceResourceIface *dri = NULL;
180     if (device == NULL || resourceNode == NULL) {
181         HDF_LOGE("device or resourceNode is NULL\r\n");
182         return HDF_ERR_INVALID_PARAM;
183     }
184     resource = &device->resource;
185     if (resource == NULL) {
186         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
187         return HDF_ERR_INVALID_OBJECT;
188     }
189     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
190     if (dri == NULL || dri->GetUint32 == NULL) {
191         HDF_LOGE("DeviceResourceIface is invalid\r\n");
192         return HDF_ERR_INVALID_OBJECT;
193     }
194 
195     if (dri->GetUint32(resourceNode, "port", &resource->port, 0) != HDF_SUCCESS) {
196         HDF_LOGE("i2c config port fail\r\n");
197         return HDF_FAILURE;
198     }
199 
200     if (dri->GetUint32(resourceNode, "sclPin", &tempPin, 0) != HDF_SUCCESS) {
201         HDF_LOGE("i2c config sclPin fail\r\n");
202         return HDF_FAILURE;
203     }
204     resource->sclPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM);
205 
206     if (dri->GetUint32(resourceNode, "sdaPin", &tempPin, 0) != HDF_SUCCESS) {
207         HDF_LOGE("i2c config sdaPin fail\r\n");
208         return HDF_FAILURE;
209     }
210     resource->sdaPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM);
211 
212     if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) {
213         HDF_LOGE("i2c config speed fail\r\n");
214         return HDF_FAILURE;
215     }
216 
217     if (dri->GetUint32(resourceNode, "mode", &resource->mode, 0) != HDF_SUCCESS) {
218         HDF_LOGE("i2c config mode fail\r\n");
219         return HDF_FAILURE;
220     }
221 
222     if (dri->GetUint32(resourceNode, "useDma", &resource->useDma, 0) != HDF_SUCCESS) {
223         HDF_LOGE("i2c config useDma fail\r\n");
224         return HDF_FAILURE;
225     }
226 
227     if (dri->GetUint32(resourceNode, "useSync", &resource->useSync, 0) != HDF_SUCCESS) {
228         HDF_LOGE("i2c config useSync fail\r\n");
229         return HDF_FAILURE;
230     }
231 
232     if (dri->GetUint32(resourceNode, "asMaster", &resource->asMaster, 0) != HDF_SUCCESS) {
233         HDF_LOGE("i2c config asMaster fail\r\n");
234         return HDF_FAILURE;
235     }
236     return HDF_SUCCESS;
237 }
238 #endif
AttachI2cDevice(struct I2cCntlr * host,const struct HdfDeviceObject * device)239 static int32_t AttachI2cDevice(struct I2cCntlr *host, const struct HdfDeviceObject *device)
240 {
241     int32_t ret;
242     struct I2cDevice *i2cDevice = NULL;
243     struct I2cResource *resource = NULL;
244     struct HAL_I2C_CONFIG_T *i2cConfig = NULL;
245     if (device == NULL || host == NULL) {
246         HDF_LOGE("%s: device or host is NULL\r\n", __func__);
247         return HDF_ERR_INVALID_PARAM;
248     }
249     i2cDevice = (struct I2cDevice *)OsalMemAlloc(sizeof(struct I2cDevice));
250     if (i2cDevice == NULL) {
251         HDF_LOGE("%s: OsalMemAlloc i2cDevice error\r\n", __func__);
252         return HDF_ERR_MALLOC_FAIL;
253     }
254     (void)memset_s(i2cDevice, sizeof(struct I2cDevice), 0, sizeof(struct I2cDevice));
255 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
256     ret = GetI2cDeviceResource(i2cDevice, device->deviceMatchAttr);
257 #else
258     ret = GetI2cDeviceResource(i2cDevice, device->property);
259 #endif
260     if (ret != HDF_SUCCESS) {
261         OsalMemFree(i2cDevice);
262         return HDF_FAILURE;
263     }
264     resource = &i2cDevice->resource;
265     if (resource == NULL) {
266         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
267         return HDF_ERR_INVALID_OBJECT;
268     }
269     i2cConfig = &i2cDevice->i2cCfg;
270     if (i2cConfig == NULL) {
271         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
272         return HDF_ERR_INVALID_OBJECT;
273     }
274     i2cDevice->port = resource->port;
275     i2cConfig->mode = resource->mode;
276     i2cConfig->use_sync = resource->useSync;
277     i2cConfig->use_dma = resource->useDma;
278     i2cConfig->as_master = resource->asMaster;
279     i2cConfig->speed = resource->speed;
280     i2cConfig->addr_as_slave = 0;
281     i2cConfig->rising_time_ns = 0;
282 
283     host->priv = i2cDevice;
284     host->busId = i2cDevice->port;
285 
286     return InitI2cDevice(i2cDevice);
287 }
288 
i2cDriverInit(struct HdfDeviceObject * device)289 static int32_t i2cDriverInit(struct HdfDeviceObject *device)
290 {
291     int32_t ret;
292     struct I2cCntlr *host = NULL;
293     if (device == NULL) {
294         HDF_LOGE("%s: device is NULL\r\n", __func__);
295         return HDF_ERR_INVALID_PARAM;
296     }
297 
298     host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr));
299     if (host == NULL) {
300         HDF_LOGE("%s: host is NULL\r\n", __func__);
301         return HDF_ERR_MALLOC_FAIL;
302     }
303     (void)memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr));
304     host->ops = &g_i2cHostMethod;
305     device->priv = (void *)host;
306     ret = AttachI2cDevice(host, device);
307     if (ret != HDF_SUCCESS) {
308         HDF_LOGE("%s: attach error\r\n", __func__);
309         i2cDriverRelease(device);
310         return HDF_DEV_ERR_ATTACHDEV_FAIL;
311     }
312     ret = I2cCntlrAdd(host);
313     if (ret != HDF_SUCCESS) {
314         i2cDriverRelease(device);
315         return HDF_FAILURE;
316     }
317     return ret;
318 }
319 
i2cDriverBind(struct HdfDeviceObject * device)320 static int32_t i2cDriverBind(struct HdfDeviceObject *device)
321 {
322     if (device == NULL) {
323         HDF_LOGE("%s: I2c device object is NULL\r\n", __func__);
324         return HDF_FAILURE;
325     }
326     return HDF_SUCCESS;
327 }
328 
i2cDriverRelease(struct HdfDeviceObject * device)329 static void i2cDriverRelease(struct HdfDeviceObject *device)
330 {
331     struct I2cCntlr *i2cCntrl = NULL;
332     struct I2cDevice *i2cDevice = NULL;
333 
334     if (device == NULL) {
335         HDF_LOGE("%s: device is NULL\r\n", __func__);
336         return;
337     }
338     i2cCntrl = device->priv;
339     if (i2cCntrl == NULL || i2cCntrl->priv == NULL) {
340         HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__);
341         return;
342     }
343     i2cCntrl->ops = NULL;
344     i2cDevice = (struct I2cDevice *)i2cCntrl->priv;
345     OsalMemFree(i2cCntrl);
346 
347     if (i2cDevice != NULL) {
348         OsalMutexDestroy(&i2cDevice->mutex);
349         OsalMemFree(i2cDevice);
350     }
351 }
352 
i2c_transfer(struct I2cDevice * device,struct I2cMsg * msgs,int16_t count)353 static int32_t i2c_transfer(struct I2cDevice *device, struct I2cMsg *msgs, int16_t count)
354 {
355     int ret;
356     struct I2cMsg *msg = NULL;
357     struct I2cMsg *msg2 = NULL;
358     uint32_t i2cPort;
359     if (device == NULL || msgs == NULL) {
360         HDF_LOGE("%s: device or  msgs is NULL\r\n", __func__);
361         return HDF_ERR_INVALID_PARAM;
362     }
363 
364     i2cPort = (uint32_t)device->port;
365     if (i2cPort > HAL_I2C_ID_NUM) {
366         HDF_LOGE("i2c port %u not support\r\n", i2cPort);
367         return HDF_ERR_NOT_SUPPORT;
368     }
369     if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
370         HDF_LOGE("%s %d OsalMutexTimedLock fail\r\n", __func__, __LINE__);
371         return HDF_ERR_TIMEOUT;
372     }
373     for (int32_t i = 0; i < count; i++) {
374         msg = &msgs[i];
375         if (msg->flags == I2C_FLAG_READ) {
376             ret = hal_i2c_task_recv(i2cPort, msg->addr, msg->buf, 0, msg->buf, msg->len, 0, NULL);
377             if (ret != 0) {
378                 HDF_LOGE("%s:%d,i2c recev fail, ret = %d\r\n", __func__, __LINE__, ret);
379                 OsalMutexUnlock(&device->mutex);
380                 return i;
381             }
382         } else if (msg->flags == I2C_FLAG_STOP) {
383             i++;
384             msg2 = &msgs[i];
385             ret = hal_i2c_task_recv(i2cPort, msg->addr, msg->buf, msg->len, msg2->buf, msg2->len, 0, NULL);
386             if (ret != 0) {
387                 HDF_LOGE("%s:%d,i2c recev fail, ret = %d\r\n", __func__, __LINE__, ret);
388                 OsalMutexUnlock(&device->mutex);
389                 return i;
390             }
391         } else {
392             ret = hal_i2c_task_send(i2cPort, msg->addr, msg->buf, msg->len, 0, NULL);
393             if (ret != 0) {
394                 HDF_LOGE("%s:%d,i2c send fail, ret = %d\r\n", __func__, __LINE__, ret);
395                 OsalMutexUnlock(&device->mutex);
396                 return i;
397             }
398         }
399     }
400     OsalMutexUnlock(&device->mutex);
401     return count;
402 }
403 
i2cHostTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)404 static int32_t i2cHostTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
405 {
406     struct I2cDevice *device = NULL;
407 
408     if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) {
409         HDF_LOGE("%s: I2cCntlr or msgs is NULL\r\n", __func__);
410         return HDF_ERR_INVALID_PARAM;
411     }
412     device = (struct I2cDevice *)cntlr->priv;
413     return i2c_transfer(device, msgs, count);
414 }
415