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