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