1 /*
2 * Copyright (c) 2021-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
9 #include "i3c_core.h"
10 #include "hdf_device_desc.h"
11 #include "hdf_log.h"
12 #include "osal_mem.h"
13 #include "osal_mutex.h"
14
15 #define I3C_SERVICE_NAME "HDF_PLATFORM_I3C_MANAGER"
16
17 struct I3cManager {
18 struct IDeviceIoService service;
19 struct HdfDeviceObject *device;
20 struct I3cCntlr *cntlrs[I3C_CNTLR_MAX];
21 struct OsalMutex lock;
22 };
23
24 static struct I3cManager *g_i3cManager = NULL;
25 static struct DListHead g_i3cDeviceList;
26 static OsalSpinlock g_listLock;
27
I3cCheckReservedAddr(uint16_t addr)28 int I3cCheckReservedAddr(uint16_t addr)
29 {
30 if ((addr == I3C_RESERVED_ADDR_7H00) || (addr == I3C_RESERVED_ADDR_7H01) ||
31 (addr == I3C_RESERVED_ADDR_7H02) || (addr == I3C_RESERVED_ADDR_7H3E) ||
32 (addr == I3C_RESERVED_ADDR_7H5E) || (addr == I3C_RESERVED_ADDR_7H6E) ||
33 (addr == I3C_RESERVED_ADDR_7H76) || (addr == I3C_RESERVED_ADDR_7H78) ||
34 (addr == I3C_RESERVED_ADDR_7H79) || (addr == I3C_RESERVED_ADDR_7H7A) ||
35 (addr == I3C_RESERVED_ADDR_7H7B) || (addr == I3C_RESERVED_ADDR_7H7C) ||
36 (addr == I3C_RESERVED_ADDR_7H7D) || (addr == I3C_RESERVED_ADDR_7H7E) ||
37 (addr == I3C_RESERVED_ADDR_7H7F)) {
38 return I3C_ADDR_RESERVED;
39 }
40 return I3C_ADDR_FREE;
41 }
42
I3cCntlrLockDefault(struct I3cCntlr * cntlr)43 static inline int32_t I3cCntlrLockDefault(struct I3cCntlr *cntlr)
44 {
45 if (cntlr == NULL) {
46 HDF_LOGE("I3cCntlrLockDefault: cntlr is null!");
47 return HDF_ERR_DEVICE_BUSY;
48 }
49 return OsalSpinLock(&cntlr->lock);
50 }
51
I3cCntlrUnlockDefault(struct I3cCntlr * cntlr)52 static inline void I3cCntlrUnlockDefault(struct I3cCntlr *cntlr)
53 {
54 if (cntlr == NULL) {
55 HDF_LOGE("I3cCntlrUnlockDefault: cntlr is null!");
56 return;
57 }
58 (void)OsalSpinUnlock(&cntlr->lock);
59 }
60
61 static const struct I3cLockMethod g_i3cLockOpsDefault = {
62 .lock = I3cCntlrLockDefault,
63 .unlock = I3cCntlrUnlockDefault,
64 };
65
I3cCntlrLock(struct I3cCntlr * cntlr)66 static inline int32_t I3cCntlrLock(struct I3cCntlr *cntlr)
67 {
68 if (cntlr->lockOps == NULL || cntlr->lockOps->lock == NULL) {
69 HDF_LOGE("I3cCntlrLock: lockOps or lock is null!");
70 return HDF_ERR_NOT_SUPPORT;
71 }
72 return cntlr->lockOps->lock(cntlr);
73 }
74
I3cCntlrUnlock(struct I3cCntlr * cntlr)75 static inline void I3cCntlrUnlock(struct I3cCntlr *cntlr)
76 {
77 if (cntlr->lockOps != NULL && cntlr->lockOps->unlock != NULL) {
78 cntlr->lockOps->unlock(cntlr);
79 }
80 }
81
I3cDeviceListGet(void)82 static struct DListHead *I3cDeviceListGet(void)
83 {
84 static struct DListHead *head = NULL;
85
86 head = &g_i3cDeviceList;
87 while (OsalSpinLock(&g_listLock)) { }
88
89 return head;
90 }
91
I3cDeviceListPut(void)92 static void I3cDeviceListPut(void)
93 {
94 (void)OsalSpinUnlock(&g_listLock);
95 }
96
GetAddrStatus(const struct I3cCntlr * cntlr,uint16_t addr)97 static int32_t GetAddrStatus(const struct I3cCntlr *cntlr, uint16_t addr)
98 {
99 int32_t status;
100
101 if (addr > I3C_ADDR_MAX) {
102 HDF_LOGE("GetAddrStatus: The address 0x%x exceeds the maximum address!", addr);
103 return HDF_ERR_INVALID_PARAM;
104 }
105
106 status = ADDR_STATUS_MASK & ((cntlr->addrSlot[addr / ADDRS_PER_UINT16]) >>
107 ((addr % ADDRS_PER_UINT16) * ADDRS_STATUS_BITS));
108
109 return status;
110 }
111
SetAddrStatus(struct I3cCntlr * cntlr,uint16_t addr,enum I3cAddrStatus status)112 static int32_t SetAddrStatus(struct I3cCntlr *cntlr, uint16_t addr, enum I3cAddrStatus status)
113 {
114 uint16_t temp;
115 int32_t ret;
116 uint16_t statusMask;
117
118 if (addr > I3C_ADDR_MAX) {
119 HDF_LOGE("SetAddrStatus: The address 0x%x exceeds the maximum address!", addr);
120 return HDF_ERR_INVALID_PARAM;
121 }
122
123 if (cntlr == NULL) {
124 HDF_LOGE("SetAddrStatus: cntlr is null!");
125 return HDF_ERR_INVALID_PARAM;
126 }
127
128 ret = I3cCntlrLock(cntlr);
129 if (ret != HDF_SUCCESS) {
130 HDF_LOGE("SetAddrStatus: lock cntlr fail!");
131 return ret;
132 }
133
134 statusMask = ADDR_STATUS_MASK << ((addr % ADDRS_PER_UINT16) * ADDRS_STATUS_BITS);
135 temp = (cntlr->addrSlot[addr / (uint16_t)ADDRS_PER_UINT16]) & (uint16_t)~statusMask;
136 temp |= (uint16_t)(((uint16_t)status) << ((addr % ADDRS_PER_UINT16) * ADDRS_STATUS_BITS));
137 cntlr->addrSlot[addr / ADDRS_PER_UINT16] = temp;
138
139 I3cCntlrUnlock(cntlr);
140
141 return HDF_SUCCESS;
142 }
143
I3cInitAddrStatus(struct I3cCntlr * cntlr)144 static void inline I3cInitAddrStatus(struct I3cCntlr *cntlr)
145 {
146 uint16_t addr;
147
148 for (addr = 0; addr <= I3C_ADDR_MAX; addr++) {
149 if (I3cCheckReservedAddr(addr) == I3C_ADDR_RESERVED) {
150 (void)SetAddrStatus(cntlr, addr, I3C_ADDR_RESERVED);
151 }
152 }
153 }
154
GetFreeAddr(struct I3cCntlr * cntlr)155 static int32_t GetFreeAddr(struct I3cCntlr *cntlr)
156 {
157 enum I3cAddrStatus status;
158 int16_t count;
159 int32_t ret;
160
161 if (cntlr == NULL) {
162 HDF_LOGE("GetFreeAddr: cntlr is null!");
163 return HDF_ERR_INVALID_PARAM;
164 }
165
166 ret = I3cCntlrLock(cntlr);
167 if (ret != HDF_SUCCESS) {
168 HDF_LOGE("GetFreeAddr: lock cntlr fail!");
169 return ret;
170 }
171
172 for (count = 0; count <= I3C_ADDR_MAX; count++) {
173 status = (enum I3cAddrStatus)GetAddrStatus(cntlr, count);
174 if (status == I3C_ADDR_FREE) {
175 return (int32_t)count;
176 }
177 }
178 I3cCntlrUnlock(cntlr);
179 HDF_LOGE("GetFreeAddr: no free addresses left!");
180
181 return HDF_FAILURE;
182 }
183
I3cCntlrSendCccCmd(struct I3cCntlr * cntlr,struct I3cCccCmd * ccc)184 int32_t I3cCntlrSendCccCmd(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc)
185 {
186 int32_t ret;
187
188 if (ccc == NULL) {
189 HDF_LOGE("I3cCntlrSendCccCmd: ccc is null!");
190 return HDF_ERR_INVALID_PARAM;
191 }
192
193 if (cntlr->ops == NULL || cntlr->ops->sendCccCmd == NULL) {
194 HDF_LOGE("I3cCntlrSendCccCmd: ops or sendCccCmd is null!");
195 return HDF_ERR_NOT_SUPPORT;
196 }
197
198 if (I3cCntlrLock(cntlr) != HDF_SUCCESS) {
199 HDF_LOGE("I3cCntlrSendCccCmd: lock cntlr fail!");
200 return HDF_ERR_DEVICE_BUSY;
201 }
202
203 ret = cntlr->ops->sendCccCmd(cntlr, ccc);
204 I3cCntlrUnlock(cntlr);
205
206 return ret;
207 }
208
I3cGetDeviceByAddr(const struct I3cCntlr * cntlr,uint16_t addr)209 struct I3cDevice *I3cGetDeviceByAddr(const struct I3cCntlr *cntlr, uint16_t addr)
210 {
211 struct DListHead *head = NULL;
212 struct I3cDevice *pos = NULL;
213 struct I3cDevice *tmp = NULL;
214 enum I3cAddrStatus addrStatus;
215
216 if (addr > I3C_ADDR_MAX) {
217 HDF_LOGE("I3cGetDeviceByAddr: The address 0x%x exceeds the maximum address!", addr);
218 return NULL;
219 }
220 addrStatus = GetAddrStatus(cntlr, addr);
221 if (addrStatus == I3C_ADDR_FREE) {
222 HDF_LOGE("I3cGetDeviceByAddr: The addr 0x%x is unavailable!", addr);
223 return NULL;
224 }
225 if (addrStatus == I3C_ADDR_RESERVED) {
226 HDF_LOGE("I3cGetDeviceByAddr: The addr 0x%x is reserved!", addr);
227 return NULL;
228 }
229
230 if (addrStatus == I3C_ADDR_I2C_DEVICE || addrStatus == I3C_ADDR_I3C_DEVICE) {
231 head = I3cDeviceListGet();
232 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, head, struct I3cDevice, list) {
233 if ((pos->dynaAddr == addr) && (pos->cntlr == cntlr)) {
234 I3cDeviceListPut();
235 HDF_LOGI("I3cGetDeviceByAddr: found by dynaAddr, done!");
236 return pos;
237 } else if ((!pos->dynaAddr) && (pos->addr == addr) && (pos->cntlr == cntlr)) {
238 HDF_LOGI("I3cGetDeviceByAddr: found by Addr, done!");
239 I3cDeviceListPut();
240 return pos;
241 }
242 }
243 }
244 HDF_LOGE("I3cGetDeviceByAddr: No such device found! addr: 0x%x!", addr);
245
246 return NULL;
247 }
248
I3cDeviceDefineI3cDevices(struct I3cDevice * device)249 static int32_t I3cDeviceDefineI3cDevices(struct I3cDevice *device)
250 {
251 int32_t ret;
252 int32_t addr;
253
254 ret = SetAddrStatus(device->cntlr, device->addr, I3C_ADDR_I3C_DEVICE);
255 if (ret != HDF_SUCCESS) {
256 addr = GetFreeAddr(device->cntlr);
257 if (addr <= 0) {
258 HDF_LOGE("I3cDeviceDefineI3cDevices: no free addresses left!");
259 return HDF_ERR_DEVICE_BUSY;
260 }
261 ret = SetAddrStatus(device->cntlr, (uint16_t)addr, I3C_ADDR_I3C_DEVICE);
262 if (ret != HDF_SUCCESS) {
263 HDF_LOGE("I3cDeviceDefineI3cDevices: add i3c device fail!");
264 return ret;
265 }
266 }
267
268 return HDF_SUCCESS;
269 }
270
I3cDeviceAdd(struct I3cDevice * device)271 int32_t I3cDeviceAdd(struct I3cDevice *device)
272 {
273 struct DListHead *head = NULL;
274 struct I3cDevice *pos = NULL;
275 struct I3cDevice *tmp = NULL;
276 int32_t ret;
277
278 if ((device == NULL) || (GetAddrStatus(device->cntlr, device->addr) != I3C_ADDR_FREE)) {
279 HDF_LOGE("I3cDeviceAdd: device or addr is unavailable!");
280 return HDF_ERR_INVALID_OBJECT;
281 }
282 if (device->type == I3C_CNTLR_I2C_DEVICE || device->type == I3C_CNTLR_I2C_LEGACY_DEVICE) {
283 ret = SetAddrStatus(device->cntlr, device->addr, I3C_ADDR_I2C_DEVICE);
284 if (ret != HDF_SUCCESS) {
285 HDF_LOGE("I3cDeviceAdd: add i2c device fail!");
286 return ret;
287 }
288 } else {
289 ret = I3cDeviceDefineI3cDevices(device);
290 if (ret != HDF_SUCCESS) {
291 HDF_LOGE("I3cDeviceAdd: i3c DEFSLVS error!");
292 return ret;
293 }
294 }
295 head = I3cDeviceListGet();
296 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, head, struct I3cDevice, list) {
297 if (pos == NULL) { // empty list
298 break;
299 }
300 if ((pos->pid == device->pid) && (pos->cntlr == device->cntlr)) {
301 I3cDeviceListPut();
302 HDF_LOGE("I3cDeviceAdd: device already existed!: 0x%llx!", device->pid);
303 (void)SetAddrStatus(device->cntlr, device->addr, I3C_ADDR_RESERVED);
304 return HDF_ERR_IO;
305 }
306 }
307 DListHeadInit(&device->list);
308 DListInsertTail(&device->list, head);
309 I3cDeviceListPut();
310 HDF_LOGI("I3cDeviceAdd: done!");
311
312 return HDF_SUCCESS;
313 }
314
I3cDeviceRemove(struct I3cDevice * device)315 void I3cDeviceRemove(struct I3cDevice *device)
316 {
317 int32_t ret;
318
319 if (device == NULL) {
320 HDF_LOGE("I3cDeviceRemove: device is null!");
321 return;
322 }
323
324 ret = SetAddrStatus(device->cntlr, device->addr, I3C_ADDR_RESERVED);
325 if (ret != HDF_SUCCESS) {
326 HDF_LOGE("I3cDeviceRemove: set addr status fail!");
327 return;
328 }
329 (void)I3cDeviceListGet();
330 DListRemove(&device->list);
331 I3cDeviceListPut();
332 }
333
I3cManagerAddCntlr(struct I3cCntlr * cntlr)334 static int32_t I3cManagerAddCntlr(struct I3cCntlr *cntlr)
335 {
336 int32_t ret;
337 struct I3cManager *manager = g_i3cManager;
338
339 if (cntlr->busId >= I3C_CNTLR_MAX) {
340 HDF_LOGE("I3cManagerAddCntlr: busId:%d exceed!", cntlr->busId);
341 return HDF_ERR_INVALID_PARAM;
342 }
343
344 if (manager == NULL) {
345 HDF_LOGE("I3cManagerAddCntlr: get i3c manager fail!");
346 return HDF_ERR_NOT_SUPPORT;
347 }
348
349 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
350 HDF_LOGE("I3cManagerAddCntlr: lock i3c manager fail!");
351 return HDF_ERR_DEVICE_BUSY;
352 }
353
354 if (manager->cntlrs[cntlr->busId] != NULL) {
355 HDF_LOGE("I3cManagerAddCntlr: cntlr of bus:%hd already exits!", cntlr->busId);
356 ret = HDF_FAILURE;
357 } else {
358 manager->cntlrs[cntlr->busId] = cntlr;
359 ret = HDF_SUCCESS;
360 }
361 (void)OsalMutexUnlock(&manager->lock);
362
363 return ret;
364 }
365
I3cManagerRemoveCntlr(struct I3cCntlr * cntlr)366 static void I3cManagerRemoveCntlr(struct I3cCntlr *cntlr)
367 {
368 struct I3cManager *manager = g_i3cManager;
369
370 if (cntlr->busId < 0 || cntlr->busId >= I3C_CNTLR_MAX) {
371 HDF_LOGE("I3cManagerRemoveCntlr: invalid busId:%hd!", cntlr->busId);
372 return;
373 }
374
375 if (manager == NULL) {
376 HDF_LOGE("I3cManagerRemoveCntlr: get i3c manager fail!");
377 return;
378 }
379 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
380 HDF_LOGE("I3cManagerRemoveCntlr: lock i3c manager fail!");
381 return;
382 }
383
384 if (manager->cntlrs[cntlr->busId] != cntlr) {
385 HDF_LOGE("I3cManagerRemoveCntlr: cntlr(%hd) not in manager!", cntlr->busId);
386 } else {
387 manager->cntlrs[cntlr->busId] = NULL;
388 }
389
390 (void)OsalMutexUnlock(&manager->lock);
391 }
392
I3cCntlrGet(int16_t number)393 struct I3cCntlr *I3cCntlrGet(int16_t number)
394 {
395 struct I3cCntlr *cntlr = NULL;
396 struct I3cManager *manager = g_i3cManager;
397
398 if (number < 0 || number >= I3C_CNTLR_MAX) {
399 HDF_LOGE("I3cCntlrGet: invalid busId:%hd!", number);
400 return NULL;
401 }
402
403 if (manager == NULL) {
404 HDF_LOGE("I3cCntlrGet: get i3c manager fail!");
405 return NULL;
406 }
407
408 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
409 HDF_LOGE("I3cCntlrGet: lock i3c manager fail!");
410 return NULL;
411 }
412 cntlr = manager->cntlrs[number];
413 (void)OsalMutexUnlock(&manager->lock);
414
415 return cntlr;
416 }
417
I3cCntlrPut(struct I3cCntlr * cntlr)418 void I3cCntlrPut(struct I3cCntlr *cntlr)
419 {
420 (void)cntlr;
421 }
422
I3cCntlrAdd(struct I3cCntlr * cntlr)423 int32_t I3cCntlrAdd(struct I3cCntlr *cntlr)
424 {
425 int32_t ret;
426
427 if (cntlr == NULL) {
428 HDF_LOGE("I3cCntlrAdd: cntlr is null!");
429 return HDF_ERR_INVALID_OBJECT;
430 }
431
432 if (cntlr->ops == NULL) {
433 HDF_LOGE("I3cCntlrAdd: no ops supplied!");
434 return HDF_ERR_INVALID_OBJECT;
435 }
436
437 if (cntlr->lockOps == NULL) {
438 HDF_LOGI("I3cCntlrAdd: use default lock methods!");
439 cntlr->lockOps = &g_i3cLockOpsDefault;
440 }
441
442 if (OsalSpinInit(&cntlr->lock) != HDF_SUCCESS) {
443 HDF_LOGE("I3cCntlrAdd: init lock fail!");
444 return HDF_FAILURE;
445 }
446
447 I3cInitAddrStatus(cntlr);
448 ret = I3cManagerAddCntlr(cntlr);
449 if (ret != HDF_SUCCESS) {
450 HDF_LOGE("I3cCntlrAdd: i3c manager add cntlr fail!");
451 (void)OsalSpinDestroy(&cntlr->lock);
452 return ret;
453 }
454
455 return HDF_SUCCESS;
456 }
457
I3cCntlrRemove(struct I3cCntlr * cntlr)458 void I3cCntlrRemove(struct I3cCntlr *cntlr)
459 {
460 if (cntlr == NULL) {
461 HDF_LOGE("I3cCntlrRemove: cntlr is null!");
462 return;
463 }
464 I3cManagerRemoveCntlr(cntlr);
465 (void)OsalSpinDestroy(&cntlr->lock);
466 }
467
I3cCntlrTransfer(struct I3cCntlr * cntlr,struct I3cMsg * msgs,int16_t count)468 int32_t I3cCntlrTransfer(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count)
469 {
470 int32_t ret;
471
472 if (cntlr == NULL) {
473 HDF_LOGE("I3cCntlrTransfer: cntlr is null!");
474 return HDF_ERR_INVALID_OBJECT;
475 }
476
477 if (cntlr->ops == NULL || cntlr->ops->Transfer == NULL) {
478 HDF_LOGE("I3cCntlrTransfer: ops or i3transfer is null!");
479 return HDF_ERR_NOT_SUPPORT;
480 }
481
482 if (I3cCntlrLock(cntlr) != HDF_SUCCESS) {
483 HDF_LOGE("I3cCntlrTransfer: lock cntlr fail!");
484 return HDF_ERR_DEVICE_BUSY;
485 }
486
487 ret = cntlr->ops->Transfer(cntlr, msgs, count);
488 I3cCntlrUnlock(cntlr);
489
490 return ret;
491 }
492
I3cCntlrI2cTransfer(struct I3cCntlr * cntlr,struct I3cMsg * msgs,int16_t count)493 int32_t I3cCntlrI2cTransfer(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count)
494 {
495 int32_t ret;
496
497 if (cntlr == NULL) {
498 HDF_LOGE("I3cCntlrI2cTransfer: cntlr is null!");
499 return HDF_ERR_INVALID_OBJECT;
500 }
501
502 if (cntlr->ops == NULL || cntlr->ops->i2cTransfer == NULL) {
503 HDF_LOGE("I3cCntlrI2cTransfer: ops or i2ctransfer is null!");
504 return HDF_ERR_NOT_SUPPORT;
505 }
506
507 if (I3cCntlrLock(cntlr) != HDF_SUCCESS) {
508 HDF_LOGE("I3cCntlrI2cTransfer: lock cntlr fail!");
509 return HDF_ERR_DEVICE_BUSY;
510 }
511 ret = cntlr->ops->i2cTransfer(cntlr, msgs, count);
512 I3cCntlrUnlock(cntlr);
513
514 return ret;
515 }
516
I3cCntlrSetConfig(struct I3cCntlr * cntlr,struct I3cConfig * config)517 int32_t I3cCntlrSetConfig(struct I3cCntlr *cntlr, struct I3cConfig *config)
518 {
519 int32_t ret;
520
521 if (cntlr == NULL) {
522 HDF_LOGE("I3cCntlrSetConfig: cntlr is null!");
523 return HDF_ERR_INVALID_OBJECT;
524 }
525
526 if (config == NULL) {
527 HDF_LOGE("I3cCntlrSetConfig: config is null!");
528 return HDF_ERR_INVALID_PARAM;
529 }
530
531 if (cntlr->ops == NULL || cntlr->ops->setConfig == NULL) {
532 HDF_LOGE("I3cCntlrSetConfig: ops or setConfig is null!");
533 return HDF_ERR_NOT_SUPPORT;
534 }
535
536 if (I3cCntlrLock(cntlr) != HDF_SUCCESS) {
537 HDF_LOGE("I3cCntlrSetConfig: lock cntlr fail!");
538 return HDF_ERR_DEVICE_BUSY;
539 }
540
541 ret = cntlr->ops->setConfig(cntlr, config);
542 cntlr->config = *config;
543 I3cCntlrUnlock(cntlr);
544
545 return ret;
546 }
547
I3cCntlrGetConfig(struct I3cCntlr * cntlr,struct I3cConfig * config)548 int32_t I3cCntlrGetConfig(struct I3cCntlr *cntlr, struct I3cConfig *config)
549 {
550 int32_t ret;
551
552 if (cntlr == NULL) {
553 HDF_LOGE("I3cCntlrGetConfig: cntlr is null!");
554 return HDF_ERR_INVALID_OBJECT;
555 }
556
557 if (config == NULL) {
558 HDF_LOGE("I3cCntlrGetConfig: config is null!");
559 return HDF_ERR_INVALID_PARAM;
560 }
561
562 if (cntlr->ops == NULL || cntlr->ops->getConfig == NULL) {
563 HDF_LOGE("I3cCntlrGetConfig: ops or getConfig is null!");
564 return HDF_ERR_NOT_SUPPORT;
565 }
566
567 if (I3cCntlrLock(cntlr) != HDF_SUCCESS) {
568 HDF_LOGE("I3cCntlrGetConfig: lock controller fail!");
569 return HDF_ERR_DEVICE_BUSY;
570 }
571
572 ret = cntlr->ops->getConfig(cntlr, config);
573 cntlr->config = *config;
574 I3cCntlrUnlock(cntlr);
575
576 return ret;
577 }
578
I3cCntlrRequestIbi(struct I3cCntlr * cntlr,uint16_t addr,I3cIbiFunc func,uint32_t payload)579 int32_t I3cCntlrRequestIbi(struct I3cCntlr *cntlr, uint16_t addr, I3cIbiFunc func, uint32_t payload)
580 {
581 struct I3cDevice *device = NULL;
582 struct I3cIbiInfo *ibi = NULL;
583 uint16_t ptr;
584
585 if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->requestIbi == NULL) {
586 HDF_LOGE("I3cCntlrRequestIbi: cntlr or ops or requestIbi is null!");
587 return HDF_ERR_NOT_SUPPORT;
588 }
589 if ((func == NULL) || (addr >= I3C_ADDR_MAX)) {
590 HDF_LOGE("I3cCntlrRequestIbi: invalid func or addr!");
591 return HDF_ERR_INVALID_PARAM;
592 }
593 device = I3cGetDeviceByAddr(cntlr, addr);
594 if (device == NULL) {
595 HDF_LOGE("I3cCntlrRequestIbi: get device fail!");
596 return HDF_ERR_INVALID_OBJECT;
597 }
598 if (device->supportIbi != I3C_DEVICE_SUPPORT_IBI) {
599 HDF_LOGE("I3cCntlrRequestIbi: not support!");
600 return HDF_ERR_NOT_SUPPORT;
601 }
602 if (I3cCntlrLock(cntlr) != HDF_SUCCESS) {
603 HDF_LOGE("I3cCntlrRequestIbi: lock controller fail!");
604 return HDF_ERR_DEVICE_BUSY;
605 }
606
607 for (ptr = 0; ptr < I3C_IBI_MAX; ptr++) {
608 if (cntlr->ibiSlot[ptr] != NULL) {
609 continue;
610 }
611 ibi = (struct I3cIbiInfo *)OsalMemCalloc(sizeof(*ibi));
612 if (ibi == NULL) {
613 HDF_LOGE("I3cCntlrRequestIbi: ibi is null!");
614 I3cCntlrUnlock(cntlr);
615 return HDF_ERR_MALLOC_FAIL;
616 }
617 ibi->ibiFunc = func;
618 ibi->payload = payload;
619 ibi->data = (uint8_t *)OsalMemCalloc(sizeof(uint8_t) * payload);
620 device->ibi = ibi;
621 cntlr->ibiSlot[ptr] = device->ibi;
622 int32_t ret = cntlr->ops->requestIbi(device);
623 I3cCntlrUnlock(cntlr);
624 return ret;
625 }
626 I3cCntlrUnlock(cntlr);
627
628 return HDF_ERR_DEVICE_BUSY;
629 }
630
I3cCntlrFreeIbi(struct I3cCntlr * cntlr,uint16_t addr)631 int32_t I3cCntlrFreeIbi(struct I3cCntlr *cntlr, uint16_t addr)
632 {
633 struct I3cDevice *device = NULL;
634 uint16_t ptr;
635
636 if (cntlr == NULL) {
637 HDF_LOGE("I3cCntlrFreeIbi: cntlr is null!");
638 return HDF_ERR_INVALID_OBJECT;
639 }
640
641 if (addr >= I3C_ADDR_MAX) {
642 HDF_LOGE("I3cCntlrFreeIbi: Invalid addr: %x!", addr);
643 return HDF_ERR_INVALID_PARAM;
644 }
645
646 device = I3cGetDeviceByAddr(cntlr, addr);
647 if (device == NULL || device->ibi == NULL) {
648 HDF_LOGE("I3cCntlrFreeIbi: invaild device!");
649 return HDF_ERR_INVALID_OBJECT;
650 }
651
652 for (ptr = 0; ptr < I3C_IBI_MAX; ptr++) {
653 if (cntlr->ibiSlot[ptr] == NULL || cntlr->ibiSlot[ptr] != device->ibi) {
654 continue;
655 }
656 cntlr->ibiSlot[ptr] = NULL;
657 if (device->ibi->data != NULL) {
658 OsalMemFree(device->ibi->data);
659 }
660 OsalMemFree(device->ibi);
661 device->ibi = NULL;
662 break;
663 }
664
665 return HDF_SUCCESS;
666 }
667
I3cCntlrIbiCallback(struct I3cDevice * device)668 int32_t I3cCntlrIbiCallback(struct I3cDevice *device)
669 {
670 struct I3cIbiData *ibiData = NULL;
671
672 if (device == NULL) {
673 HDF_LOGW("I3cCntlrIbiCallback: device is null!");
674 return HDF_ERR_INVALID_PARAM;
675 }
676
677 ibiData = (struct I3cIbiData *)OsalMemCalloc(sizeof(*ibiData));
678 if (ibiData == NULL) {
679 HDF_LOGE("I3cCntlrIbiCallback: memcalloc ibiData fail!");
680 return HDF_ERR_MALLOC_FAIL;
681 }
682
683 ibiData->buf = device->ibi->data;
684 ibiData->payload = device->ibi->payload;
685
686 if (device->ibi->ibiFunc == NULL) {
687 HDF_LOGW("I3cCntlrIbiCallback: device->ibi or ibiFunc is null!");
688 OsalMemFree(ibiData);
689 return HDF_ERR_NOT_SUPPORT;
690 }
691
692 if (device->dynaAddr != 0) {
693 (void)device->ibi->ibiFunc(device->cntlr, device->dynaAddr, *ibiData);
694 OsalMemFree(ibiData);
695 } else {
696 (void)device->ibi->ibiFunc(device->cntlr, device->addr, *ibiData);
697 OsalMemFree(ibiData);
698 }
699
700 return HDF_SUCCESS;
701 }
702
I3cManagerBind(struct HdfDeviceObject * device)703 static int32_t I3cManagerBind(struct HdfDeviceObject *device)
704 {
705 (void)device;
706 HDF_LOGI("I3cManagerBind: enter!");
707 return HDF_SUCCESS;
708 }
709
I3cManagerInit(struct HdfDeviceObject * device)710 static int32_t I3cManagerInit(struct HdfDeviceObject *device)
711 {
712 int32_t ret;
713 struct I3cManager *manager = NULL;
714
715 HDF_LOGI("I3cManagerInit: enter!");
716 if (device == NULL) {
717 HDF_LOGE("I3cManagerInit: device is null!");
718 return HDF_ERR_INVALID_OBJECT;
719 }
720
721 manager = (struct I3cManager *)OsalMemCalloc(sizeof(*manager));
722 if (manager == NULL) {
723 HDF_LOGE("I3cManagerInit: malloc manager fail!");
724 return HDF_ERR_MALLOC_FAIL;
725 }
726
727 ret = OsalMutexInit(&manager->lock);
728 if (ret != HDF_SUCCESS) {
729 HDF_LOGE("I3cManagerInit: mutex init fail, ret: %d!", ret);
730 OsalMemFree(manager);
731 return HDF_FAILURE;
732 }
733 manager->device = device;
734 g_i3cManager = manager;
735 DListHeadInit(&g_i3cDeviceList);
736 OsalSpinInit(&g_listLock);
737
738 return HDF_SUCCESS;
739 }
740
I3cManagerRelease(struct HdfDeviceObject * device)741 static void I3cManagerRelease(struct HdfDeviceObject *device)
742 {
743 struct I3cManager *manager = NULL;
744
745 HDF_LOGI("I3cManagerRelease: enter");
746 if (device == NULL) {
747 HDF_LOGI("I3cManagerRelease: device is null!");
748 return;
749 }
750 manager = (struct I3cManager *)device->service;
751 if (manager == NULL) {
752 HDF_LOGI("I3cManagerRelease: no service binded!");
753 return;
754 }
755 g_i3cManager = NULL;
756 (void)OsalMutexDestroy(&manager->lock);
757 OsalMemFree(manager);
758 }
759
760 struct HdfDriverEntry g_i3cManagerEntry = {
761 .moduleVersion = 1,
762 .Bind = I3cManagerBind,
763 .Init = I3cManagerInit,
764 .Release = I3cManagerRelease,
765 .moduleName = "HDF_PLATFORM_I3C_MANAGER",
766 };
767 HDF_INIT(g_i3cManagerEntry);
768