• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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