• 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,struct I2cResource * resource)51 static int32_t I2cDeviceIomuxInit(uint32_t i2cId, 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 HDF_ERR_INVALID_PARAM;
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     return HDF_SUCCESS;
84 }
85 
InitI2cDevice(struct I2cDevice * device)86 int32_t InitI2cDevice(struct I2cDevice *device)
87 {
88     int32_t ret;
89     uint32_t i2cPort;
90     struct I2cResource *resource = NULL;
91     struct HAL_I2C_CONFIG_T *i2cConfig = NULL;
92     if (device == NULL) {
93         HDF_LOGE("%s %d:device is NULL\r\n", __func__, __LINE__);
94         return HDF_ERR_INVALID_PARAM;
95     }
96 
97     resource = &device->resource;
98     if (resource == NULL) {
99         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
100         return HDF_ERR_INVALID_PARAM;
101     }
102 
103     i2cConfig = &device->i2cCfg;
104     if (i2cConfig == NULL) {
105         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
106         return HDF_ERR_INVALID_PARAM;
107     }
108 
109     device->port = resource->port;
110     i2cPort = device->port;
111     if (i2cPort > HAL_I2C_ID_NUM) {
112         HDF_LOGE("i2c port %u not support\r\n", i2cPort);
113         return HDF_ERR_NOT_SUPPORT;
114     }
115 
116     if (OsalMutexInit(&device->mutex) != HDF_SUCCESS) {
117         HDF_LOGE("%s %d OsalMutexInit fail\r\n", __func__, __LINE__);
118         return HDF_FAILURE;
119     }
120 
121     if (OsalMutexLock(&device->mutex) != HDF_SUCCESS) {
122         HDF_LOGE("%s %d osMutexWait fail\r\n", __func__, __LINE__);
123         return HDF_ERR_TIMEOUT;
124     }
125 
126     ret = I2cDeviceIomuxInit(i2cPort, resource);
127     if (ret != HDF_SUCCESS) {
128         HDF_LOGD("I2C iomux init failed.\r\n");
129         OsalMutexUnlock(&device->mutex);
130         return ret;
131     }
132 
133     ret = hal_i2c_open(i2cPort, i2cConfig);
134     if (ret == HDF_SUCCESS) {
135         HDF_LOGD("open %u i2c succ.\r\n", i2cPort);
136     }
137     OsalMutexUnlock(&device->mutex);
138     return ret;
139 }
140 
GetI2cDeviceIomuxConfig(struct I2cResource * resource,const struct DeviceResourceNode * resourceNode)141 static int32_t GetI2cDeviceIomuxConfig(struct I2cResource *resource, const struct DeviceResourceNode *resourceNode)
142 {
143     struct DeviceResourceIface *dri = NULL;
144     if (resource == NULL || resourceNode == NULL) {
145         HDF_LOGE("%s %d:resource or resourceNode is NULL\r\n", __func__, __LINE__);
146         return HDF_ERR_INVALID_PARAM;
147     }
148 
149     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
150     if (dri == NULL || dri->GetUint32 == NULL) {
151         HDF_LOGE("DeviceResourceIface is invalid\r\n");
152         return HDF_ERR_INVALID_OBJECT;
153     }
154 
155     if (dri->GetUint32(resourceNode, "sclPin", &resource->sclPin, 0) != HDF_SUCCESS) {
156         HDF_LOGE("i2c config sclPin fail\r\n");
157         return HDF_FAILURE;
158     }
159 
160     if (dri->GetUint32(resourceNode, "sdaPin", &resource->sdaPin, 0) != HDF_SUCCESS) {
161         HDF_LOGE("i2c config sdaPin fail\r\n");
162         return HDF_FAILURE;
163     }
164     resource->sclPin = ((resource->sclPin / DEC_NUM) * GROUP_PIN_NUM) + (resource->sclPin % DEC_NUM);
165 
166     resource->sdaPin = ((resource->sdaPin / DEC_NUM) * GROUP_PIN_NUM) + (resource->sdaPin % DEC_NUM);
167     return HDF_SUCCESS;
168 }
169 
GetI2cDeviceResource(struct I2cDevice * device,const struct DeviceResourceNode * resourceNode)170 static int32_t GetI2cDeviceResource(struct I2cDevice *device, const struct DeviceResourceNode *resourceNode)
171 {
172     struct I2cResource *resource = NULL;
173     struct DeviceResourceIface *dri = NULL;
174     if (device == NULL || resourceNode == NULL) {
175         HDF_LOGE("%s %d:device or resourceNode is NULL\r\n", __func__, __LINE__);
176         return HDF_ERR_INVALID_PARAM;
177     }
178     resource = &device->resource;
179     if (resource == NULL) {
180         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
181         return HDF_ERR_INVALID_OBJECT;
182     }
183     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
184     if (dri == NULL || dri->GetUint32 == NULL) {
185         HDF_LOGE("DeviceResourceIface is invalid\r\n");
186         return HDF_ERR_INVALID_OBJECT;
187     }
188 
189     if (dri->GetUint32(resourceNode, "port", &resource->port, 0) != HDF_SUCCESS) {
190         HDF_LOGE("i2c config port fail\r\n");
191         return HDF_FAILURE;
192     }
193 
194     if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) {
195         HDF_LOGE("i2c config speed fail\r\n");
196         return HDF_FAILURE;
197     }
198 
199     if (dri->GetUint32(resourceNode, "mode", &resource->mode, 0) != HDF_SUCCESS) {
200         HDF_LOGE("i2c config mode fail\r\n");
201         return HDF_FAILURE;
202     }
203 
204     if (dri->GetUint32(resourceNode, "useDma", &resource->useDma, 0) != HDF_SUCCESS) {
205         HDF_LOGE("i2c config useDma fail\r\n");
206         return HDF_FAILURE;
207     }
208 
209     if (dri->GetUint32(resourceNode, "useSync", &resource->useSync, 0) != HDF_SUCCESS) {
210         HDF_LOGE("i2c config useSync fail\r\n");
211         return HDF_FAILURE;
212     }
213 
214     if (dri->GetUint32(resourceNode, "asMaster", &resource->asMaster, 0) != HDF_SUCCESS) {
215         HDF_LOGE("i2c config asMaster fail\r\n");
216         return HDF_FAILURE;
217     }
218 
219     return GetI2cDeviceIomuxConfig(resource, resourceNode);
220 }
221 
AttachI2cDevice(struct I2cCntlr * host,struct HdfDeviceObject * device)222 static int32_t AttachI2cDevice(struct I2cCntlr *host, struct HdfDeviceObject *device)
223 {
224     int32_t ret;
225     struct I2cDevice *i2cDevice = NULL;
226     struct I2cResource *resource = NULL;
227     struct HAL_I2C_CONFIG_T *i2cConfig = NULL;
228     if (device == NULL || host == NULL) {
229         HDF_LOGE("%s: device or host is NULL\r\n", __func__);
230         return HDF_ERR_INVALID_PARAM;
231     }
232     i2cDevice = (struct I2cDevice *)OsalMemAlloc(sizeof(struct I2cDevice));
233     if (i2cDevice == NULL) {
234         HDF_LOGE("%s: OsalMemAlloc i2cDevice error\r\n", __func__);
235         return HDF_ERR_MALLOC_FAIL;
236     }
237     (void)memset_s(i2cDevice, sizeof(struct I2cDevice), 0, sizeof(struct I2cDevice));
238 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
239     ret = GetI2cDeviceResource(i2cDevice, device->deviceMatchAttr);
240 #else
241     ret = GetI2cDeviceResource(i2cDevice, device->property);
242 #endif
243     if (ret != HDF_SUCCESS) {
244         OsalMemFree(i2cDevice);
245         return HDF_FAILURE;
246     }
247     resource = &i2cDevice->resource;
248     if (resource == NULL) {
249         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
250         OsalMemFree(i2cDevice);
251         return HDF_ERR_INVALID_OBJECT;
252     }
253     i2cConfig = &i2cDevice->i2cCfg;
254     if (i2cConfig == NULL) {
255         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
256         OsalMemFree(i2cDevice);
257         return HDF_ERR_INVALID_OBJECT;
258     }
259     i2cDevice->port = resource->port;
260     i2cConfig->mode = resource->mode;
261     i2cConfig->use_sync = resource->useSync;
262     i2cConfig->use_dma = resource->useDma;
263     i2cConfig->as_master = resource->asMaster;
264     i2cConfig->speed = resource->speed;
265     i2cConfig->addr_as_slave = 0;
266     i2cConfig->rising_time_ns = 0;
267 
268     host->priv = i2cDevice;
269     host->busId = i2cDevice->port;
270 
271     return InitI2cDevice(i2cDevice);
272 }
273 
i2cDriverInit(struct HdfDeviceObject * device)274 static int32_t i2cDriverInit(struct HdfDeviceObject *device)
275 {
276     int32_t ret;
277     struct I2cCntlr *host = NULL;
278     if (device == NULL) {
279         HDF_LOGE("%s: device is NULL\r\n", __func__);
280         return HDF_ERR_INVALID_PARAM;
281     }
282 
283     host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr));
284     if (host == NULL) {
285         HDF_LOGE("%s: host is NULL\r\n", __func__);
286         return HDF_ERR_MALLOC_FAIL;
287     }
288     (void)memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr));
289     host->ops = &g_i2cHostMethod;
290     device->priv = (void *)host;
291     ret = AttachI2cDevice(host, device);
292     if (ret != HDF_SUCCESS) {
293         HDF_LOGE("%s: attach error\r\n", __func__);
294         return HDF_DEV_ERR_ATTACHDEV_FAIL;
295     }
296     ret = I2cCntlrAdd(host);
297     if (ret != HDF_SUCCESS) {
298         return HDF_FAILURE;
299     }
300     return ret;
301 }
302 
i2cDriverBind(struct HdfDeviceObject * device)303 static int32_t i2cDriverBind(struct HdfDeviceObject *device)
304 {
305     if (device == NULL) {
306         HDF_LOGE("%s: I2c device object is NULL\r\n", __func__);
307         return HDF_FAILURE;
308     }
309     return HDF_SUCCESS;
310 }
311 
i2cDriverRelease(struct HdfDeviceObject * device)312 static void i2cDriverRelease(struct HdfDeviceObject *device)
313 {
314     struct I2cCntlr *i2cCntrl = NULL;
315     struct I2cDevice *i2cDevice = NULL;
316 
317     if (device == NULL) {
318         HDF_LOGE("%s: device is NULL\r\n", __func__);
319         return;
320     }
321     i2cCntrl = device->priv;
322     if (i2cCntrl == NULL || i2cCntrl->priv == NULL) {
323         HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__);
324         return;
325     }
326     i2cCntrl->ops = NULL;
327     i2cDevice = (struct I2cDevice *)i2cCntrl->priv;
328     OsalMemFree(i2cCntrl);
329 
330     if (i2cDevice != NULL) {
331         OsalMutexDestroy(&i2cDevice->mutex);
332         OsalMemFree(i2cDevice);
333     }
334 }
335 
i2c_transfer(struct I2cDevice * device,struct I2cMsg * msgs,int16_t count)336 static int32_t i2c_transfer(struct I2cDevice *device, struct I2cMsg *msgs, int16_t count)
337 {
338     int ret;
339     struct I2cMsg *msg = NULL;
340     struct I2cMsg *msg2 = NULL;
341     uint32_t i2cPort;
342     if (device == NULL || msgs == NULL) {
343         HDF_LOGE("%s: device or  msgs is NULL\r\n", __func__);
344         return HDF_ERR_INVALID_PARAM;
345     }
346 
347     i2cPort = (uint32_t)device->port;
348     if (i2cPort > HAL_I2C_ID_NUM) {
349         HDF_LOGE("i2c port %u not support\r\n", i2cPort);
350         return HDF_ERR_NOT_SUPPORT;
351     }
352     if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
353         HDF_LOGE("%s %d OsalMutexTimedLock fail\r\n", __func__, __LINE__);
354         return HDF_ERR_TIMEOUT;
355     }
356     for (int32_t i = 0; i < count; i++) {
357         msg = &msgs[i];
358         if (msg->flags == I2C_FLAG_READ) {
359             ret = hal_i2c_task_recv(i2cPort, msg->addr, msg->buf, 0, msg->buf, msg->len, 0, NULL);
360             if (ret) {
361                 HDF_LOGE("%s:%d,i2c recev fail, dev_addr = 0x%x, ret = %d\r\n", __func__, __LINE__, msg->addr, ret);
362                 OsalMutexUnlock(&device->mutex);
363                 return i;
364             }
365         } else if (msg->flags == I2C_FLAG_STOP) {
366             i++;
367             msg2 = &msgs[i];
368             ret = hal_i2c_task_recv(i2cPort, msg->addr, msg->buf, msg->len, msg2->buf, msg2->len, 0, NULL);
369             if (ret) {
370                 HDF_LOGE("%s:%d,i2c recev fail, dev_addr = 0x%x, ret = %d\r\n", __func__, __LINE__, msg->addr, ret);
371                 OsalMutexUnlock(&device->mutex);
372                 return i;
373             }
374         } else {
375             ret = hal_i2c_task_send(i2cPort, msg->addr, msg->buf, msg->len, 0, NULL);
376             if (ret) {
377                 HDF_LOGE("%s:%d,i2c send fail, dev_addr = 0x%x, ret = %d\r\n", __func__, __LINE__, msg->addr, ret);
378                 OsalMutexUnlock(&device->mutex);
379                 return i;
380             }
381         }
382     }
383     OsalMutexUnlock(&device->mutex);
384     return count;
385 }
386 
i2cHostTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)387 static int32_t i2cHostTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
388 {
389     struct I2cDevice *device = NULL;
390     if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) {
391         HDF_LOGE("%s: I2cCntlr or msgs is NULL\r\n", __func__);
392         return HDF_ERR_INVALID_PARAM;
393     }
394 
395     device = (struct I2cDevice *)cntlr->priv;
396     if (device == NULL) {
397         HDF_LOGE("%s: I2cDevice is NULL\r\n", __func__);
398         return HDF_DEV_ERR_NO_DEVICE;
399     }
400 
401     return i2c_transfer(device, msgs, count);
402 }
403