1 /*
2 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3 *
4 * HDF 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_core.h"
10 #include "hdf_device_desc.h"
11 #include "hdf_log.h"
12 #include "i2c_service.h"
13 #include "osal_mem.h"
14 #include "osal_time.h"
15 #include "platform_core.h"
16
17 #define HDF_LOG_TAG i2c_core
18 #define LOCK_WAIT_SECONDS_M 1
19 #define I2C_HANDLE_SHIFT ((uintptr_t)(-1) << 16)
20
21 struct I2cManager {
22 struct IDeviceIoService service;
23 struct HdfDeviceObject *device;
24 struct I2cCntlr *cntlrs[I2C_BUS_MAX];
25 struct OsalMutex lock;
26 };
27
28 static struct I2cManager *g_i2cManager = NULL;
29
I2cCntlrLockDefault(struct I2cCntlr * cntlr)30 static int32_t I2cCntlrLockDefault(struct I2cCntlr *cntlr)
31 {
32 if (cntlr == NULL) {
33 return HDF_ERR_INVALID_OBJECT;
34 }
35 return OsalMutexLock(&cntlr->lock);
36 }
37
I2cCntlrUnlockDefault(struct I2cCntlr * cntlr)38 static void I2cCntlrUnlockDefault(struct I2cCntlr *cntlr)
39 {
40 if (cntlr == NULL) {
41 return;
42 }
43 (void)OsalMutexUnlock(&cntlr->lock);
44 }
45
46 static const struct I2cLockMethod g_i2cLockOpsDefault = {
47 .lock = I2cCntlrLockDefault,
48 .unlock = I2cCntlrUnlockDefault,
49 };
50
I2cManagerAddCntlr(struct I2cCntlr * cntlr)51 static int32_t I2cManagerAddCntlr(struct I2cCntlr *cntlr)
52 {
53 int32_t ret;
54 struct I2cManager *manager = g_i2cManager;
55
56 if (cntlr->busId >= I2C_BUS_MAX) {
57 HDF_LOGE("I2cManagerAddCntlr: busId:%hd exceed!", cntlr->busId);
58 return HDF_ERR_INVALID_PARAM;
59 }
60
61 if (manager == NULL) {
62 HDF_LOGE("I2cManagerAddCntlr: get i2c manager fail!");
63 return HDF_ERR_NOT_SUPPORT;
64 }
65 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
66 HDF_LOGE("I2cManagerAddCntlr: lock i2c manager fail!");
67 return HDF_ERR_DEVICE_BUSY;
68 }
69
70 if (manager->cntlrs[cntlr->busId] != NULL) {
71 HDF_LOGE("I2cManagerAddCntlr: cntlr of bus:%hd already exits!", cntlr->busId);
72 ret = HDF_FAILURE;
73 } else {
74 manager->cntlrs[cntlr->busId] = cntlr;
75 ret = HDF_SUCCESS;
76 }
77
78 (void)OsalMutexUnlock(&manager->lock);
79 return ret;
80 }
81
I2cManagerRemoveCntlr(struct I2cCntlr * cntlr)82 static void I2cManagerRemoveCntlr(struct I2cCntlr *cntlr)
83 {
84 struct I2cManager *manager = g_i2cManager;
85
86 if (cntlr->busId < 0 || cntlr->busId >= I2C_BUS_MAX) {
87 HDF_LOGE("I2cManagerRemoveCntlr: invalid busId:%hd!", cntlr->busId);
88 return;
89 }
90
91 if (manager == NULL) {
92 HDF_LOGE("I2cManagerRemoveCntlr: get i2c manager fail!");
93 return;
94 }
95 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
96 HDF_LOGE("I2cManagerRemoveCntlr: lock i2c manager fail!");
97 return;
98 }
99
100 if (manager->cntlrs[cntlr->busId] != cntlr) {
101 HDF_LOGE("I2cManagerRemoveCntlr: cntlr(%hd) not in manager!", cntlr->busId);
102 } else {
103 manager->cntlrs[cntlr->busId] = NULL;
104 }
105
106 (void)OsalMutexUnlock(&manager->lock);
107 }
108
109 /*
110 * Find an i2c controller by bus number, without ref count
111 */
I2cManagerFindCntlr(int16_t number)112 static struct I2cCntlr *I2cManagerFindCntlr(int16_t number)
113 {
114 struct I2cCntlr *cntlr = NULL;
115 struct I2cManager *manager = g_i2cManager;
116
117 if (number < 0 || number >= I2C_BUS_MAX) {
118 HDF_LOGE("I2cManagerFindCntlr: invalid busId:%hd!", number);
119 return NULL;
120 }
121
122 if (manager == NULL) {
123 HDF_LOGE("I2cManagerFindCntlr: get i2c manager fail!");
124 return NULL;
125 }
126
127 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
128 HDF_LOGE("I2cManagerFindCntlr: lock i2c manager fail!");
129 return NULL;
130 }
131 cntlr = manager->cntlrs[number];
132 (void)OsalMutexUnlock(&manager->lock);
133 return cntlr;
134 }
135
136 /*
137 * Find and return an i2c controller by number, with ref count
138 */
I2cCntlrGet(int16_t number)139 struct I2cCntlr *I2cCntlrGet(int16_t number)
140 {
141 return I2cManagerFindCntlr(number);
142 }
143
144 /*
145 * Put back the i2c controller, with ref count
146 */
I2cCntlrPut(struct I2cCntlr * cntlr)147 void I2cCntlrPut(struct I2cCntlr *cntlr)
148 {
149 (void)cntlr;
150 }
151
I2cCntlrAdd(struct I2cCntlr * cntlr)152 int32_t I2cCntlrAdd(struct I2cCntlr *cntlr)
153 {
154 int32_t ret;
155
156 if (cntlr == NULL) {
157 return HDF_ERR_INVALID_OBJECT;
158 }
159
160 if (cntlr->ops == NULL) {
161 HDF_LOGE("I2cCntlrAdd: no ops supplied!");
162 return HDF_ERR_INVALID_OBJECT;
163 }
164
165 if (cntlr->lockOps == NULL) {
166 HDF_LOGI("I2cCntlrAdd: use default lock methods!");
167 cntlr->lockOps = &g_i2cLockOpsDefault;
168 }
169
170 if (OsalMutexInit(&cntlr->lock) != HDF_SUCCESS) {
171 HDF_LOGE("I2cCntlrAdd: init lock fail!");
172 return HDF_FAILURE;
173 }
174
175 ret = I2cManagerAddCntlr(cntlr);
176 if (ret != HDF_SUCCESS) {
177 (void)OsalMutexDestroy(&cntlr->lock);
178 return ret;
179 }
180 return HDF_SUCCESS;
181 }
182
I2cCntlrRemove(struct I2cCntlr * cntlr)183 void I2cCntlrRemove(struct I2cCntlr *cntlr)
184 {
185 if (cntlr == NULL) {
186 return;
187 }
188 I2cManagerRemoveCntlr(cntlr);
189 (void)OsalMutexDestroy(&cntlr->lock);
190 }
191
I2cCntlrLock(struct I2cCntlr * cntlr)192 static inline int32_t I2cCntlrLock(struct I2cCntlr *cntlr)
193 {
194 if (cntlr->lockOps == NULL || cntlr->lockOps->lock == NULL) {
195 return HDF_ERR_NOT_SUPPORT;
196 }
197 return cntlr->lockOps->lock(cntlr);
198 }
199
I2cCntlrUnlock(struct I2cCntlr * cntlr)200 static inline void I2cCntlrUnlock(struct I2cCntlr *cntlr)
201 {
202 if (cntlr->lockOps != NULL && cntlr->lockOps->unlock != NULL) {
203 cntlr->lockOps->unlock(cntlr);
204 }
205 }
206
I2cCntlrTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)207 int32_t I2cCntlrTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
208 {
209 int32_t ret;
210
211 if (cntlr == NULL) {
212 HDF_LOGE("I2cCntlrTransfer: cntlr is null");
213 return HDF_ERR_INVALID_OBJECT;
214 }
215
216 if (cntlr->ops == NULL || cntlr->ops->transfer == NULL) {
217 HDF_LOGE("I2cCntlrTransfer: ops or transfer is null");
218 return HDF_ERR_NOT_SUPPORT;
219 }
220
221 if (I2cCntlrLock(cntlr) != HDF_SUCCESS) {
222 HDF_LOGE("I2cCntlrTransfer: lock controller fail!");
223 return HDF_ERR_DEVICE_BUSY;
224 }
225 ret = cntlr->ops->transfer(cntlr, msgs, count);
226 I2cCntlrUnlock(cntlr);
227 return ret;
228 }
229
I2cTransferRebuildMsgs(struct HdfSBuf * data,int16_t count,struct I2cMsg * msgs,uint8_t ** ppbuf)230 static int32_t I2cTransferRebuildMsgs(struct HdfSBuf *data, int16_t count, struct I2cMsg *msgs, uint8_t **ppbuf)
231 {
232 int16_t i;
233 uint32_t len;
234 uint32_t lenReply = 0;
235 uint8_t *bufReply = NULL;
236 uint8_t *buf = NULL;
237 struct I2cUserMsg *userMsgs = NULL;
238
239 for (i = 0; i < count; i++) {
240 if (!HdfSbufReadBuffer(data, (const void **)&userMsgs, &len) || (userMsgs == NULL) ||
241 (len != sizeof(struct I2cUserMsg))) {
242 HDF_LOGE("I2cTransferRebuildMsgs: read userMsgs fail!");
243 return HDF_ERR_IO;
244 }
245 msgs[i].addr = userMsgs->addr;
246 msgs[i].len = userMsgs->len;
247 msgs[i].buf = NULL;
248 msgs[i].flags = userMsgs->flags;
249 if ((msgs[i].flags & I2C_FLAG_READ) != 0) {
250 lenReply += msgs[i].len;
251 } else if ((!HdfSbufReadBuffer(data, (const void **)&buf, &len)) || (buf == NULL)) {
252 HDF_LOGE("I2cTransferRebuildMsgs: read msg[%d] buf fail!", i);
253 } else {
254 msgs[i].len = len;
255 msgs[i].buf = buf;
256 }
257 }
258
259 if (lenReply > 0) {
260 bufReply = OsalMemCalloc(lenReply);
261 if (bufReply == NULL) {
262 return HDF_ERR_MALLOC_FAIL;
263 }
264 for (i = 0, buf = bufReply; i < count && buf < (bufReply + lenReply); i++) {
265 if ((msgs[i].flags & I2C_FLAG_READ) != 0) {
266 msgs[i].buf = buf;
267 buf += msgs[i].len;
268 }
269 }
270 }
271
272 *ppbuf = bufReply;
273 return HDF_SUCCESS;
274 }
275
I2cTransferWriteBackMsgs(struct HdfSBuf * reply,struct I2cMsg * msgs,int16_t count)276 static int32_t I2cTransferWriteBackMsgs(struct HdfSBuf *reply, struct I2cMsg *msgs, int16_t count)
277 {
278 int16_t i;
279
280 for (i = 0; i < count; i++) {
281 if ((msgs[i].flags & I2C_FLAG_READ) == 0) {
282 continue;
283 }
284 if (!HdfSbufWriteBuffer(reply, msgs[i].buf, msgs[i].len)) {
285 HDF_LOGE("I2cTransferWriteBackMsgs: write msg[%hd] reply fail!", i);
286 return HDF_ERR_IO;
287 }
288 }
289
290 return HDF_SUCCESS;
291 }
292
I2cTransferHeadRead(struct HdfSBuf * data,uint32_t * handle,int16_t * count)293 static int32_t I2cTransferHeadRead(struct HdfSBuf *data, uint32_t *handle, int16_t *count)
294 {
295 if (!HdfSbufReadUint32(data, handle)) {
296 HDF_LOGE("I2cTransferHeadRead: read handle fail!");
297 return HDF_ERR_IO;
298 }
299 if (!HdfSbufReadInt16(data, count) || (count == 0)) {
300 HDF_LOGE("I2cTransferHeadRead: read count fail!");
301 return HDF_ERR_IO;
302 }
303
304 return HDF_SUCCESS;
305 }
306
307 // user data format:handle---count---count data records of I2cUserMsg;
I2cManagerIoTransfer(struct HdfSBuf * data,struct HdfSBuf * reply)308 static int32_t I2cManagerIoTransfer(struct HdfSBuf *data, struct HdfSBuf *reply)
309 {
310 int32_t ret;
311 int16_t count;
312 int16_t number;
313 uint32_t handle;
314 uint8_t *bufReply = NULL;
315 struct I2cMsg *msgs = NULL;
316
317 if (data == NULL || reply == NULL) {
318 return HDF_ERR_INVALID_PARAM;
319 }
320
321 if (I2cTransferHeadRead(data, &handle, &count) != HDF_SUCCESS) {
322 return HDF_FAILURE;
323 }
324
325 msgs = (struct I2cMsg *)OsalMemAlloc(sizeof(struct I2cMsg) * count);
326 if (msgs == NULL) {
327 HDF_LOGE("I2cManagerIoTransfer: OsalMemAlloc I2cMsg failure");
328 return HDF_ERR_IO;
329 }
330 ret = I2cTransferRebuildMsgs(data, count, msgs, &bufReply);
331 if (ret != HDF_SUCCESS) {
332 HDF_LOGE("I2cManagerIoTransfer: rebuild msgs fail:%d", ret);
333 OsalMemFree(msgs);
334 return ret;
335 }
336
337 number = (int16_t)(handle - I2C_HANDLE_SHIFT);
338 ret = I2cCntlrTransfer(I2cManagerFindCntlr(number), msgs, count);
339 if (ret != count) {
340 HDF_LOGE("I2cManagerIoTransfer: I2cCntlrTransfer msgs fail:%d", ret);
341 OsalMemFree(msgs);
342 OsalMemFree(bufReply);
343 return ret;
344 }
345
346 ret = I2cTransferWriteBackMsgs(reply, msgs, count);
347 OsalMemFree(msgs);
348 OsalMemFree(bufReply);
349 return ret;
350 }
351
I2cManagerIoOpen(struct HdfSBuf * data,struct HdfSBuf * reply)352 static int32_t I2cManagerIoOpen(struct HdfSBuf *data, struct HdfSBuf *reply)
353 {
354 int16_t number;
355 uint32_t handle;
356
357 if (!HdfSbufReadUint16(data, (uint16_t *)&number)) {
358 return HDF_ERR_IO;
359 }
360
361 if (number < 0 || number >= I2C_BUS_MAX || reply == NULL) {
362 return HDF_ERR_INVALID_PARAM;
363 }
364
365 if (I2cCntlrGet(number) == NULL) {
366 return HDF_ERR_NOT_SUPPORT;
367 }
368
369 handle = (uint32_t)(number + I2C_HANDLE_SHIFT);
370 if (!HdfSbufWriteUint32(reply, handle)) {
371 return HDF_ERR_IO;
372 }
373 return HDF_SUCCESS;
374 }
375
I2cManagerIoClose(struct HdfSBuf * data,struct HdfSBuf * reply)376 static int32_t I2cManagerIoClose(struct HdfSBuf *data, struct HdfSBuf *reply)
377 {
378 int16_t number;
379 uint32_t handle;
380
381 (void)reply;
382 if (!HdfSbufReadUint32(data, &handle)) {
383 return HDF_ERR_IO;
384 }
385
386 number = (int16_t)(handle - I2C_HANDLE_SHIFT);
387 if (number < 0 || number >= I2C_BUS_MAX) {
388 return HDF_ERR_INVALID_PARAM;
389 }
390 I2cCntlrPut(I2cManagerFindCntlr(number));
391 return HDF_SUCCESS;
392 }
393
I2cManagerDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)394 static int32_t I2cManagerDispatch(
395 struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
396 {
397 int32_t ret;
398
399 (void)client;
400 switch (cmd) {
401 case I2C_IO_OPEN:
402 return I2cManagerIoOpen(data, reply);
403 case I2C_IO_CLOSE:
404 return I2cManagerIoClose(data, reply);
405 case I2C_IO_TRANSFER:
406 return I2cManagerIoTransfer(data, reply);
407 default:
408 ret = HDF_ERR_NOT_SUPPORT;
409 break;
410 }
411 return ret;
412 }
413
I2cManagerBind(struct HdfDeviceObject * device)414 static int32_t I2cManagerBind(struct HdfDeviceObject *device)
415 {
416 int32_t ret;
417 struct I2cManager *manager = NULL;
418
419 HDF_LOGI("I2cManagerBind: Enter!");
420 if (device == NULL) {
421 HDF_LOGE("I2cManagerBind: device is NULL");
422 return HDF_ERR_INVALID_OBJECT;
423 }
424
425 manager = (struct I2cManager *)OsalMemCalloc(sizeof(*manager));
426 if (manager == NULL) {
427 HDF_LOGE("I2cManagerBind: malloc manager fail!");
428 return HDF_ERR_MALLOC_FAIL;
429 }
430
431 ret = OsalMutexInit(&manager->lock);
432 if (ret != HDF_SUCCESS) {
433 HDF_LOGE("I2cManagerBind: mutex init fail:%d", ret);
434 OsalMemFree(manager);
435 return HDF_FAILURE;
436 }
437
438 manager->device = device;
439 device->service = &manager->service;
440 device->service->Dispatch = I2cManagerDispatch;
441 g_i2cManager = manager;
442 return HDF_SUCCESS;
443 }
444
I2cManagerInit(struct HdfDeviceObject * device)445 static int32_t I2cManagerInit(struct HdfDeviceObject *device)
446 {
447 (void)device;
448 return HDF_SUCCESS;
449 }
450
I2cManagerRelease(struct HdfDeviceObject * device)451 static void I2cManagerRelease(struct HdfDeviceObject *device)
452 {
453 struct I2cManager *manager = NULL;
454
455 HDF_LOGI("I2cManagerRelease: enter");
456 if (device == NULL) {
457 HDF_LOGI("I2cManagerRelease: device is null");
458 return;
459 }
460 manager = (struct I2cManager *)device->service;
461 if (manager == NULL) {
462 HDF_LOGI("I2cManagerRelease: no service binded!");
463 return;
464 }
465 g_i2cManager = NULL;
466 OsalMemFree(manager);
467 }
468
469 struct HdfDriverEntry g_i2cManagerEntry = {
470 .moduleVersion = 1,
471 .Bind = I2cManagerBind,
472 .Init = I2cManagerInit,
473 .Release = I2cManagerRelease,
474 .moduleName = "HDF_PLATFORM_I2C_MANAGER",
475 };
476 HDF_INIT(g_i2cManagerEntry);
477