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