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