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