• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2023 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 #include "i2c_core.h"
9 #include "hdf_device_desc.h"
10 #include "hdf_log.h"
11 #include "i2c_msg.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         HDF_LOGE("I2cCntlrLockDefault: cntlr is null!");
34         return HDF_ERR_INVALID_OBJECT;
35     }
36     return OsalMutexLock(&cntlr->lock);
37 }
38 
I2cCntlrUnlockDefault(struct I2cCntlr * cntlr)39 static void I2cCntlrUnlockDefault(struct I2cCntlr *cntlr)
40 {
41     if (cntlr == NULL) {
42         HDF_LOGE("I2cCntlrUnlockDefault: cntlr is null!");
43         return;
44     }
45     (void)OsalMutexUnlock(&cntlr->lock);
46 }
47 
48 static const struct I2cLockMethod g_i2cLockOpsDefault = {
49     .lock = I2cCntlrLockDefault,
50     .unlock = I2cCntlrUnlockDefault,
51 };
52 
I2cManagerAddCntlr(struct I2cCntlr * cntlr)53 static int32_t I2cManagerAddCntlr(struct I2cCntlr *cntlr)
54 {
55     int32_t ret;
56     struct I2cManager *manager = g_i2cManager;
57 
58     if (cntlr->busId >= I2C_BUS_MAX) {
59         HDF_LOGE("I2cManagerAddCntlr: busId:%hd exceed!", cntlr->busId);
60         return HDF_ERR_INVALID_PARAM;
61     }
62 
63     if (manager == NULL) {
64         HDF_LOGE("I2cManagerAddCntlr: get i2c manager fail!");
65         return HDF_ERR_NOT_SUPPORT;
66     }
67     if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
68         HDF_LOGE("I2cManagerAddCntlr: lock i2c manager fail!");
69         return HDF_ERR_DEVICE_BUSY;
70     }
71 
72     if (manager->cntlrs[cntlr->busId] != NULL) {
73         HDF_LOGE("I2cManagerAddCntlr: cntlr of bus:%hd already exits!", cntlr->busId);
74         ret = HDF_FAILURE;
75     } else {
76         manager->cntlrs[cntlr->busId] = cntlr;
77         ret = HDF_SUCCESS;
78     }
79 
80     (void)OsalMutexUnlock(&manager->lock);
81     return ret;
82 }
83 
I2cManagerRemoveCntlr(struct I2cCntlr * cntlr)84 static void I2cManagerRemoveCntlr(struct I2cCntlr *cntlr)
85 {
86     struct I2cManager *manager = g_i2cManager;
87 
88     if (cntlr->busId < 0 || cntlr->busId >= I2C_BUS_MAX) {
89         HDF_LOGE("I2cManagerRemoveCntlr: invalid busId:%hd!", cntlr->busId);
90         return;
91     }
92 
93     if (manager == NULL) {
94         HDF_LOGE("I2cManagerRemoveCntlr: get i2c manager fail!");
95         return;
96     }
97     if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
98         HDF_LOGE("I2cManagerRemoveCntlr: lock i2c manager fail!");
99         return;
100     }
101 
102     if (manager->cntlrs[cntlr->busId] != cntlr) {
103         HDF_LOGE("I2cManagerRemoveCntlr: cntlr(%hd) not in manager!", cntlr->busId);
104     } else {
105         manager->cntlrs[cntlr->busId] = NULL;
106     }
107 
108     (void)OsalMutexUnlock(&manager->lock);
109 }
110 
111 /*
112  * Find an i2c controller by bus number, without ref count
113  */
I2cManagerFindCntlr(int16_t number)114 static struct I2cCntlr *I2cManagerFindCntlr(int16_t number)
115 {
116     struct I2cCntlr *cntlr = NULL;
117     struct I2cManager *manager = g_i2cManager;
118 
119     if (number < 0 || number >= I2C_BUS_MAX) {
120         HDF_LOGE("I2cManagerFindCntlr: invalid busId:%hd!", number);
121         return NULL;
122     }
123 
124     if (manager == NULL) {
125         HDF_LOGE("I2cManagerFindCntlr: get i2c manager fail!");
126         return NULL;
127     }
128 
129     if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
130         HDF_LOGE("I2cManagerFindCntlr: lock i2c manager fail!");
131         return NULL;
132     }
133     cntlr = manager->cntlrs[number];
134     (void)OsalMutexUnlock(&manager->lock);
135     return cntlr;
136 }
137 
138 /*
139  * Find and return an i2c controller by number, with ref count
140  */
I2cCntlrGet(int16_t number)141 struct I2cCntlr *I2cCntlrGet(int16_t number)
142 {
143     return I2cManagerFindCntlr(number);
144 }
145 
146 /*
147  * Put back the i2c controller, with ref count
148  */
I2cCntlrPut(struct I2cCntlr * cntlr)149 void I2cCntlrPut(struct I2cCntlr *cntlr)
150 {
151     (void)cntlr;
152 }
153 
I2cCntlrAdd(struct I2cCntlr * cntlr)154 int32_t I2cCntlrAdd(struct I2cCntlr *cntlr)
155 {
156     int32_t ret;
157 
158     if (cntlr == NULL) {
159         return HDF_ERR_INVALID_OBJECT;
160     }
161 
162     if (cntlr->ops == NULL) {
163         HDF_LOGE("I2cCntlrAdd: no ops supplied!");
164         return HDF_ERR_INVALID_OBJECT;
165     }
166 
167     if (cntlr->lockOps == NULL) {
168         HDF_LOGD("I2cCntlrAdd: use default lock methods!");
169         cntlr->lockOps = &g_i2cLockOpsDefault;
170     }
171 
172     if (OsalMutexInit(&cntlr->lock) != HDF_SUCCESS) {
173         HDF_LOGE("I2cCntlrAdd: init lock fail!");
174         return HDF_FAILURE;
175     }
176 
177     ret = I2cManagerAddCntlr(cntlr);
178     if (ret != HDF_SUCCESS) {
179         (void)OsalMutexDestroy(&cntlr->lock);
180         return ret;
181     }
182     return HDF_SUCCESS;
183 }
184 
I2cCntlrRemove(struct I2cCntlr * cntlr)185 void I2cCntlrRemove(struct I2cCntlr *cntlr)
186 {
187     if (cntlr == NULL) {
188         return;
189     }
190     I2cManagerRemoveCntlr(cntlr);
191     (void)OsalMutexDestroy(&cntlr->lock);
192 }
193 
I2cCntlrLock(struct I2cCntlr * cntlr)194 static inline int32_t I2cCntlrLock(struct I2cCntlr *cntlr)
195 {
196     if (cntlr->lockOps == NULL || cntlr->lockOps->lock == NULL) {
197         return HDF_ERR_NOT_SUPPORT;
198     }
199     return cntlr->lockOps->lock(cntlr);
200 }
201 
I2cCntlrUnlock(struct I2cCntlr * cntlr)202 static inline void I2cCntlrUnlock(struct I2cCntlr *cntlr)
203 {
204     if (cntlr->lockOps != NULL && cntlr->lockOps->unlock != NULL) {
205         cntlr->lockOps->unlock(cntlr);
206     }
207 }
208 
I2cCntlrTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)209 int32_t I2cCntlrTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
210 {
211     int32_t ret;
212 
213     if (cntlr == NULL) {
214         HDF_LOGE("I2cCntlrTransfer: cntlr is null!");
215         return HDF_ERR_INVALID_OBJECT;
216     }
217 
218     if (cntlr->ops == NULL || cntlr->ops->transfer == NULL) {
219         HDF_LOGE("I2cCntlrTransfer: ops or transfer is null!");
220         return HDF_ERR_NOT_SUPPORT;
221     }
222 
223     if (I2cCntlrLock(cntlr) != HDF_SUCCESS) {
224         HDF_LOGE("I2cCntlrTransfer: lock controller fail!");
225         return HDF_ERR_DEVICE_BUSY;
226     }
227     ret = cntlr->ops->transfer(cntlr, msgs, count);
228     I2cCntlrUnlock(cntlr);
229     return ret;
230 }
231 
232 #if defined(LOSCFG_USER_I2C_SUPPORT) || defined(CONFIG_USER_I2C_SUPPORT)
I2cIoDoTransfer(struct I2cCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)233 static int32_t I2cIoDoTransfer(struct I2cCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
234 {
235     struct I2cMsg *msgs = NULL;
236     int16_t count = 0;
237     int16_t transCnt = 0;
238     int32_t ret = HDF_SUCCESS;
239 
240     if (I2cMsgsRebuildFromSbuf(data, &msgs, &count) != HDF_SUCCESS) {
241         HDF_LOGE("I2cIoDoTransfer: fail to rebuild i2c msg!");
242         return HDF_ERR_INVALID_PARAM;
243     }
244 
245     transCnt = I2cCntlrTransfer(cntlr, msgs, count);
246     if (transCnt != count) {
247         I2cMsgsFree(msgs, count);
248         HDF_LOGE("I2cIoDoTransfer: i2c transfer fail!");
249         return HDF_ERR_IO;
250     }
251 
252     if (I2cMsgsWriteToSbuf(msgs, count, reply) != HDF_SUCCESS) {
253         HDF_LOGE("I2cIoDoTransfer: fail to write i2c msg!");
254         ret = HDF_ERR_INVALID_PARAM;
255     }
256     I2cMsgsFree(msgs, count);
257 
258     return ret;
259 }
260 
261 // user data format:handle---count---count data records of I2cUserMsg;
I2cManagerIoTransfer(struct HdfSBuf * data,struct HdfSBuf * reply)262 static int32_t I2cManagerIoTransfer(struct HdfSBuf *data, struct HdfSBuf *reply)
263 {
264     int16_t number;
265     uint32_t handle;
266     struct I2cCntlr *cntlr = NULL;
267 
268     if (data == NULL || reply == NULL) {
269         HDF_LOGE("I2cManagerIoTransfer: data or reply is null!");
270         return HDF_ERR_INVALID_PARAM;
271     }
272     if (!HdfSbufReadUint32(data, &handle)) {
273         HDF_LOGE("I2cManagerIoTransfer: read handle fail!");
274         return HDF_ERR_IO;
275     }
276 
277     number = (int16_t)(handle - I2C_HANDLE_SHIFT);
278     cntlr = I2cManagerFindCntlr(number);
279     if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->transfer == NULL) {
280         HDF_LOGE("I2cManagerIoTransfer: invalid cntlr num %d!", number);
281         return HDF_ERR_NOT_SUPPORT;
282     }
283 
284     return I2cIoDoTransfer(cntlr, data, reply);
285 }
286 
I2cManagerIoOpen(struct HdfSBuf * data,struct HdfSBuf * reply)287 static int32_t I2cManagerIoOpen(struct HdfSBuf *data, struct HdfSBuf *reply)
288 {
289     int16_t number;
290     uint32_t handle;
291 
292     if (!HdfSbufReadUint16(data, (uint16_t *)&number)) {
293         HDF_LOGE("I2cManagerIoOpen: read nuber fail!");
294         return HDF_ERR_IO;
295     }
296 
297     if (number < 0 || number >= I2C_BUS_MAX || reply == NULL) {
298         HDF_LOGE("I2cManagerIoOpen: number is invalid or reply is null!");
299         return HDF_ERR_INVALID_PARAM;
300     }
301 
302     if (I2cCntlrGet(number) == NULL) {
303         HDF_LOGE("I2cManagerIoOpen: i2c cnltr get fail!");
304         return HDF_ERR_NOT_SUPPORT;
305     }
306 
307     handle = (uint32_t)(number + I2C_HANDLE_SHIFT);
308     if (!HdfSbufWriteUint32(reply, handle)) {
309         HDF_LOGE("I2cManagerIoOpen: write handle fail!");
310         return HDF_ERR_IO;
311     }
312     return HDF_SUCCESS;
313 }
314 
I2cManagerIoClose(struct HdfSBuf * data,struct HdfSBuf * reply)315 static int32_t I2cManagerIoClose(struct HdfSBuf *data, struct HdfSBuf *reply)
316 {
317     int16_t number;
318     uint32_t handle;
319 
320     (void)reply;
321     if (!HdfSbufReadUint32(data, &handle)) {
322         HDF_LOGE("I2cManagerIoClose: read handle fail!");
323         return HDF_ERR_IO;
324     }
325 
326     number = (int16_t)(handle - I2C_HANDLE_SHIFT);
327     if (number < 0 || number >= I2C_BUS_MAX) {
328         HDF_LOGE("I2cManagerIoClose: number is invalid!");
329         return HDF_ERR_INVALID_PARAM;
330     }
331     I2cCntlrPut(I2cManagerFindCntlr(number));
332     return HDF_SUCCESS;
333 }
334 
I2cManagerDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)335 static int32_t I2cManagerDispatch(
336     struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
337 {
338     int32_t ret;
339 
340     (void)client;
341     switch (cmd) {
342         case I2C_IO_OPEN:
343             return I2cManagerIoOpen(data, reply);
344         case I2C_IO_CLOSE:
345             return I2cManagerIoClose(data, reply);
346         case I2C_IO_TRANSFER:
347             return I2cManagerIoTransfer(data, reply);
348         default:
349             HDF_LOGE("I2cManagerDispatch: cmd %d is not support!", cmd);
350             ret = HDF_ERR_NOT_SUPPORT;
351             break;
352     }
353     return ret;
354 }
355 #endif // USER_I2C_SUPPORT
I2cManagerBind(struct HdfDeviceObject * device)356 static int32_t I2cManagerBind(struct HdfDeviceObject *device)
357 {
358     int32_t ret;
359     struct I2cManager *manager = NULL;
360 
361     HDF_LOGI("I2cManagerBind: enter!");
362     if (device == NULL) {
363         HDF_LOGE("I2cManagerBind: device is null!");
364         return HDF_ERR_INVALID_OBJECT;
365     }
366 
367     manager = (struct I2cManager *)OsalMemCalloc(sizeof(*manager));
368     if (manager == NULL) {
369         HDF_LOGE("I2cManagerBind: malloc manager fail!");
370         return HDF_ERR_MALLOC_FAIL;
371     }
372 
373     ret = OsalMutexInit(&manager->lock);
374     if (ret != HDF_SUCCESS) {
375         HDF_LOGE("I2cManagerBind: mutex init fail, ret: %d!", ret);
376         OsalMemFree(manager);
377         return HDF_FAILURE;
378     }
379 
380     manager->device = device;
381 #if defined(LOSCFG_USER_I2C_SUPPORT) || defined(CONFIG_USER_I2C_SUPPORT)
382     device->service = &manager->service;
383     device->service->Dispatch = I2cManagerDispatch;
384 #endif // USER_I2C_SUPPORT
385     g_i2cManager = manager;
386     return HDF_SUCCESS;
387 }
388 
I2cManagerInit(struct HdfDeviceObject * device)389 static int32_t I2cManagerInit(struct HdfDeviceObject *device)
390 {
391     (void)device;
392     return HDF_SUCCESS;
393 }
394 
I2cManagerRelease(struct HdfDeviceObject * device)395 static void I2cManagerRelease(struct HdfDeviceObject *device)
396 {
397     struct I2cManager *manager = NULL;
398 
399     HDF_LOGI("I2cManagerRelease: enter!");
400     if (device == NULL) {
401         HDF_LOGI("I2cManagerRelease: device is null!");
402         return;
403     }
404     manager = (struct I2cManager *)device->service;
405     if (manager == NULL) {
406         HDF_LOGI("I2cManagerRelease: no service binded!");
407         return;
408     }
409     g_i2cManager = NULL;
410     OsalMemFree(manager);
411 }
412 
413 struct HdfDriverEntry g_i2cManagerEntry = {
414     .moduleVersion = 1,
415     .Bind = I2cManagerBind,
416     .Init = I2cManagerInit,
417     .Release = I2cManagerRelease,
418     .moduleName = "HDF_PLATFORM_I2C_MANAGER",
419 };
420 HDF_INIT(g_i2cManagerEntry);
421