1 /*
2 * Copyright (c) 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 "i3c/i3c_core.h"
10 #include "device_resource_if.h"
11 #include "osal_mem.h"
12 #include "osal_time.h"
13
14 #define HDF_LOG_TAG i3c_virtual
15
16 #define VIRTUAL_I3C_DELAY 50
17 #define VIRTUAL_I3C_HOT_JOIN_TEST_ADDR 0x3f
18
19 #define VIRTUAL_I3C_TEST_STR_LEN 11
20 #define VIRTUAL_I3C_TEST_STR "Hello I3C!"
21
22 struct VirtualI3cCntlr {
23 struct I3cCntlr cntlr;
24 OsalSpinlock spin;
25 uint16_t busId;
26 uint16_t busMode;
27 uint16_t IrqNum;
28 uint32_t i3cMaxRate;
29 uint32_t i3cRate;
30 uint32_t i2cFmRate;
31 uint32_t i2cFmPlusRate;
32 };
33
34 struct VirtualI3cTransferData {
35 struct I3cMsg *msgs;
36 int16_t index;
37 int16_t count;
38 };
39
40 struct VirtualI3cIbiSimulator {
41 uint16_t ibiAddr;
42 uint16_t deviceAddr;
43 };
44
45 static struct VirtualI3cIbiSimulator ibiSimulator;
46
VirtualI3cSetIbiSimulator(uint16_t addr,uint16_t deviceAddr)47 static inline void VirtualI3cSetIbiSimulator(uint16_t addr, uint16_t deviceAddr)
48 {
49 ibiSimulator.ibiAddr = addr;
50 ibiSimulator.deviceAddr = deviceAddr;
51 }
52
VirtualI3cGetIbiAddr(void)53 static inline uint16_t VirtualI3cGetIbiAddr(void)
54 {
55 return ibiSimulator.ibiAddr;
56 }
57
VirtualI3cGetIbiDeviceAddr(void)58 static inline uint16_t VirtualI3cGetIbiDeviceAddr(void)
59 {
60 return ibiSimulator.deviceAddr;
61 }
62
VirtualI3cXferI2cOneMsgPolling(const struct VirtualI3cCntlr * virtual,const struct VirtualI3cTransferData * td)63 static int32_t VirtualI3cXferI2cOneMsgPolling(const struct VirtualI3cCntlr *virtual,
64 const struct VirtualI3cTransferData *td)
65 {
66 struct I3cMsg *msg = &td->msgs[td->index];
67
68 (void)virtual;
69 (void)msg;
70 PLAT_LOGV("%s: msg:%p, addr:%x, flags:0x%x, len=%d", __func__, msg, msg->addr, msg->flags, msg->len);
71
72 return HDF_SUCCESS;
73 }
74
VirtualI3cCntlrInit(struct VirtualI3cCntlr * virtual)75 static inline void VirtualI3cCntlrInit(struct VirtualI3cCntlr *virtual)
76 {
77 HDF_LOGI("%s: cntlr:%u init done!", __func__, virtual->busId);
78 }
79
VirtualSendCccCmd(struct I3cCntlr * cntlr,struct I3cCccCmd * ccc)80 static int32_t VirtualSendCccCmd(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc)
81 {
82 (void)cntlr;
83 HDF_LOGI("%s: Enter, destination: %x", __func__, ccc->dest);
84
85 return HDF_SUCCESS;
86 }
87
VirtualI3cTransfer(struct I3cCntlr * cntlr,struct I3cMsg * msgs,int16_t count)88 static int32_t VirtualI3cTransfer(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count)
89 {
90 struct VirtualI3cCntlr *virtual = NULL;
91
92 (void)cntlr;
93 (void)msgs;
94 if (cntlr == NULL || cntlr->priv == NULL) {
95 HDF_LOGE("%s: cntlr or virtual is null!", __func__);
96 return HDF_ERR_INVALID_OBJECT;
97 }
98 virtual = (struct VirtualI3cCntlr *)cntlr;
99
100 if (msgs == NULL || count <= 0) {
101 HDF_LOGE("%s: err params! count:%d", __func__, count);
102 return HDF_ERR_INVALID_PARAM;
103 }
104
105 return count;
106 }
107
VirtualI3cCntlrI2cTransfer(struct I3cCntlr * cntlr,struct I3cMsg * msgs,int16_t count)108 static int32_t VirtualI3cCntlrI2cTransfer(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count)
109 {
110 int32_t ret;
111 unsigned long irqSave;
112 struct VirtualI3cCntlr *virtual = NULL;
113 struct VirtualI3cTransferData td;
114
115 if (cntlr == NULL || cntlr->priv == NULL) {
116 HDF_LOGE("%s: cntlr or virtual is null!", __func__);
117 return HDF_ERR_INVALID_OBJECT;
118 }
119 virtual = (struct VirtualI3cCntlr *)cntlr;
120
121 if (msgs == NULL || count <= 0) {
122 HDF_LOGE("%s: err params! count:%d", __func__, count);
123 return HDF_ERR_INVALID_PARAM;
124 }
125 td.msgs = msgs;
126 td.count = count;
127 td.index = 0;
128
129 irqSave = LOS_IntLock();
130 while (td.index < td.count) {
131 ret = VirtualI3cXferI2cOneMsgPolling(virtual, &td);
132 if (ret != 0) {
133 break;
134 }
135 td.index++;
136 }
137 LOS_IntRestore(irqSave);
138 return (td.index > 0) ? td.index : ret;
139 }
140
VirtualI3cSetConfig(struct I3cCntlr * cntlr,struct I3cConfig * config)141 int32_t VirtualI3cSetConfig(struct I3cCntlr *cntlr, struct I3cConfig *config)
142 {
143 (void)cntlr;
144 (void)config;
145 HDF_LOGI("%s: done!", __func__);
146 return HDF_SUCCESS;
147 }
148
VirtualI3cGetConfig(struct I3cCntlr * cntlr,struct I3cConfig * config)149 int32_t VirtualI3cGetConfig(struct I3cCntlr *cntlr, struct I3cConfig *config)
150 {
151 (void)cntlr;
152 (void)config;
153 HDF_LOGI("%s: done!", __func__);
154 return HDF_SUCCESS;
155 }
156
VirtualI3cRequestIbi(struct I3cDevice * dev)157 int32_t VirtualI3cRequestIbi(struct I3cDevice *dev)
158 {
159 (void)dev;
160 HDF_LOGI("%s: done!", __func__);
161
162 return HDF_SUCCESS;
163 }
164
VirtualI3cFreeIbi(struct I3cDevice * dev)165 static void VirtualI3cFreeIbi(struct I3cDevice *dev)
166 {
167 (void)dev;
168 HDF_LOGI("%s: done!", __func__);
169 }
170
171 static const struct I3cMethod g_method = {
172 .sendCccCmd = VirtualSendCccCmd,
173 .i2cTransfer = VirtualI3cCntlrI2cTransfer,
174 .Transfer = VirtualI3cTransfer,
175 .setConfig = VirtualI3cSetConfig,
176 .getConfig = VirtualI3cGetConfig,
177 .requestIbi = VirtualI3cRequestIbi,
178 .freeIbi = VirtualI3cFreeIbi,
179 };
180
VirtualI3cHotJoin(struct VirtualI3cCntlr * virtual)181 static void VirtualI3cHotJoin(struct VirtualI3cCntlr *virtual)
182 {
183 uint16_t deviceAddr;
184 struct I3cDevice *device = NULL;
185 int32_t ret;
186
187 deviceAddr = VirtualI3cGetIbiDeviceAddr();
188 device = (struct I3cDevice *)OsalMemCalloc(sizeof(*device));
189 if (device == NULL) {
190 HDF_LOGE("func:%s device is NULL!", __func__);
191 return;
192 }
193 device->cntlr = &virtual->cntlr;
194 device->addr = deviceAddr;
195 device->type = I3C_CNTLR_I3C_DEVICE;
196 device->supportIbi = I3C_DEVICE_SUPPORT_IBI;
197 ret = I3cDeviceAdd(device);
198 if (ret != HDF_SUCCESS) {
199 HDF_LOGE("%s: Add device failed!", __func__);
200 return;
201 }
202 HDF_LOGI("%s: done!", __func__);
203 }
204
VirtualI3cReservedAddrWorker(struct VirtualI3cCntlr * virtual,uint16_t addr)205 static int32_t VirtualI3cReservedAddrWorker(struct VirtualI3cCntlr *virtual, uint16_t addr)
206 {
207 (void)virtual;
208 switch (addr) {
209 case I3C_HOT_JOIN_ADDR:
210 VirtualI3cHotJoin(virtual);
211 break;
212 case I3C_RESERVED_ADDR_7H3E:
213 case I3C_RESERVED_ADDR_7H5E:
214 case I3C_RESERVED_ADDR_7H6E:
215 case I3C_RESERVED_ADDR_7H76:
216 case I3C_RESERVED_ADDR_7H7A:
217 case I3C_RESERVED_ADDR_7H7C:
218 case I3C_RESERVED_ADDR_7H7F:
219 /* All cases of broadcast address single bit error detect */
220 HDF_LOGW("%s: broadcast Address single bit error!", __func__);
221 break;
222 default:
223 HDF_LOGD("%s: Reserved address which is not supported!", __func__);
224 break;
225 }
226
227 return HDF_SUCCESS;
228 }
229
I3cIbiHandle(uint32_t irq,void * data)230 static int32_t I3cIbiHandle(uint32_t irq, void *data)
231 {
232 struct VirtualI3cCntlr *virtual = NULL;
233 struct I3cDevice *device = NULL;
234 uint16_t ibiAddr;
235 char *testStr = VIRTUAL_I3C_TEST_STR;
236
237 (void)irq;
238 if (data == NULL) {
239 HDF_LOGW("%s: data is NULL!", __func__);
240 return HDF_ERR_INVALID_PARAM;
241 }
242 virtual = (struct VirtualI3cCntlr *)data;
243 ibiAddr = VirtualI3cGetIbiAddr();
244 if (I3cCheckReservedAddr(ibiAddr) == I3C_ADDR_RESERVED) {
245 HDF_LOGD("%s: Calling VirtualI3cResAddrWorker...", __func__);
246 return VirtualI3cReservedAddrWorker(virtual, ibiAddr);
247 } else {
248 HDF_LOGD("%s: Calling I3cCntlrIbiCallback...", __func__);
249 device = GetDeviceByAddr(&virtual->cntlr, ibiAddr);
250 if (device == NULL) {
251 HDF_LOGE("func:%s device is NULL!", __func__);
252 return HDF_ERR_MALLOC_FAIL;
253 }
254 if (device->ibi->payload > VIRTUAL_I3C_TEST_STR_LEN) {
255 /* Put the string "Hello I3C!" into IBI buffer */
256 *device->ibi->data = *testStr;
257 }
258 return I3cCntlrIbiCallback(device);
259 }
260
261 return HDF_SUCCESS;
262 }
263
264 /* Soft calling is used here to simulate in-band interrupt */
SoftInterruptTrigger(struct VirtualI3cCntlr * virtual,uint16_t ibiDeviceAddr)265 static inline void SoftInterruptTrigger(struct VirtualI3cCntlr *virtual, uint16_t ibiDeviceAddr)
266 {
267 VirtualI3cSetIbiSimulator(I3C_HOT_JOIN_ADDR, ibiDeviceAddr);
268 HDF_LOGE("%s: IrqNum: %d", __func__, virtual->IrqNum);
269
270 /* Simulate soft interrupt through direct call */
271 if (I3cIbiHandle(virtual->IrqNum, (void *)virtual) != HDF_SUCCESS) {
272 HDF_LOGE("%s: Call I3cIbiHandle failed!", __func__);
273 }
274 }
275
VirtualI3cHotJoinSimulator(void)276 static int32_t VirtualI3cHotJoinSimulator(void)
277 {
278 uint16_t busId;
279 struct I3cCntlr *cntlr = NULL;
280 struct VirtualI3cCntlr *virtual = NULL;
281
282 for (busId = 0; busId < I3C_CNTLR_MAX; busId++) {
283 cntlr = I3cCntlrGet(busId);
284 if (cntlr == NULL) {
285 continue;
286 }
287
288 virtual = (struct VirtualI3cCntlr *)cntlr;
289 OsalMDelay(VIRTUAL_I3C_DELAY);
290 SoftInterruptTrigger(virtual, VIRTUAL_I3C_HOT_JOIN_TEST_ADDR);
291 }
292
293 return HDF_SUCCESS;
294 }
295
VirtualI3cReadDrs(struct VirtualI3cCntlr * virtual,const struct DeviceResourceNode * node)296 static int32_t VirtualI3cReadDrs(struct VirtualI3cCntlr *virtual, const struct DeviceResourceNode *node)
297 {
298 struct DeviceResourceIface *drsOps = NULL;
299
300 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
301 if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
302 HDF_LOGE("%s: Invalid drs ops fail!", __func__);
303 return HDF_FAILURE;
304 }
305 if (drsOps->GetUint16(node, "busId", &virtual->busId, 0) != HDF_SUCCESS) {
306 HDF_LOGE("%s: Read busId fail!", __func__);
307 return HDF_ERR_IO;
308 }
309 if (drsOps->GetUint16(node, "busMode", &virtual->busMode, 0) != HDF_SUCCESS) {
310 HDF_LOGE("%s: Read busMode fail!", __func__);
311 return HDF_ERR_IO;
312 }
313 if (drsOps->GetUint16(node, "IrqNum", &virtual->IrqNum, 0) != HDF_SUCCESS) {
314 HDF_LOGE("%s: Read IrqNum fail!", __func__);
315 return HDF_ERR_IO;
316 }
317 if (drsOps->GetUint32(node, "i3cMaxRate", &virtual->i3cMaxRate, 0) != HDF_SUCCESS) {
318 HDF_LOGE("%s: Read i3cMaxRate fail!", __func__);
319 return HDF_ERR_IO;
320 }
321 if (drsOps->GetUint32(node, "i3cRate", &virtual->i3cRate, 0) != HDF_SUCCESS) {
322 HDF_LOGE("%s: Read i3cRate fail!", __func__);
323 return HDF_ERR_IO;
324 }
325 if (drsOps->GetUint32(node, "i2cFmRate", &virtual->i2cFmRate, 0) != HDF_SUCCESS) {
326 HDF_LOGE("%s: Read i2cFmRate fail!", __func__);
327 return HDF_ERR_IO;
328 }
329 if (drsOps->GetUint32(node, "i2cFmPlusRate", &virtual->i2cFmPlusRate, 0) != HDF_SUCCESS) {
330 HDF_LOGE("%s: Read i2cFmPlusRate fail!", __func__);
331 return HDF_ERR_IO;
332 }
333
334 return HDF_SUCCESS;
335 }
336
VirtualI3cParseAndInit(struct HdfDeviceObject * device,const struct DeviceResourceNode * node)337 static int32_t VirtualI3cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
338 {
339 int32_t ret;
340 struct VirtualI3cCntlr *virtual = NULL;
341 (void)device;
342
343 virtual = (struct VirtualI3cCntlr *)OsalMemCalloc(sizeof(*virtual));
344 if (virtual == NULL) {
345 HDF_LOGE("%s: Malloc virtual fail!", __func__);
346 return HDF_ERR_MALLOC_FAIL;
347 }
348
349 ret = VirtualI3cReadDrs(virtual, node);
350 if (ret != HDF_SUCCESS) {
351 HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret);
352 OsalMemFree(virtual);
353 virtual = NULL;
354 return ret;
355 }
356
357 VirtualI3cCntlrInit(virtual);
358 virtual->cntlr.priv = (void *)node;
359 virtual->cntlr.busId = (int16_t)virtual->busId;
360 virtual->cntlr.ops = &g_method;
361 (void)OsalSpinInit(&virtual->spin);
362 ret = I3cCntlrAdd(&virtual->cntlr);
363 if (ret != HDF_SUCCESS) {
364 HDF_LOGE("%s: add i3c controller failed! ret = %d", __func__, ret);
365 (void)OsalSpinDestroy(&virtual->spin);
366 OsalMemFree(virtual);
367 virtual = NULL;
368 return ret;
369 }
370
371 return HDF_SUCCESS;
372 }
373
VirtualI3cInit(struct HdfDeviceObject * device)374 static int32_t VirtualI3cInit(struct HdfDeviceObject *device)
375 {
376 int32_t ret;
377 const struct DeviceResourceNode *childNode = NULL;
378
379 HDF_LOGE("%s: Enter", __func__);
380 if (device == NULL || device->property == NULL) {
381 HDF_LOGE("%s: device or property is NULL", __func__);
382 return HDF_ERR_INVALID_OBJECT;
383 }
384
385 ret = HDF_SUCCESS;
386 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
387 ret = VirtualI3cParseAndInit(device, childNode);
388 if (ret != HDF_SUCCESS) {
389 break;
390 }
391 }
392 ret = VirtualI3cHotJoinSimulator();
393
394 return ret;
395 }
396
VirtualI3cRemoveByNode(const struct DeviceResourceNode * node)397 static void VirtualI3cRemoveByNode(const struct DeviceResourceNode *node)
398 {
399 int32_t ret;
400 int16_t busId;
401 struct I3cCntlr *cntlr = NULL;
402 struct VirtualI3cCntlr *virtual = NULL;
403 struct DeviceResourceIface *drsOps = NULL;
404
405 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
406 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
407 HDF_LOGE("%s: invalid drs ops fail!", __func__);
408 return;
409 }
410
411 ret = drsOps->GetUint16(node, "busId", (uint16_t *)&busId, 0);
412 if (ret != HDF_SUCCESS) {
413 HDF_LOGE("%s: read busId fail!", __func__);
414 return;
415 }
416
417 cntlr = I3cCntlrGet(busId);
418 if (cntlr != NULL && cntlr->priv == node) {
419 I3cCntlrPut(cntlr);
420 I3cCntlrRemove(cntlr);
421 virtual = (struct VirtualI3cCntlr *)cntlr;
422 (void)OsalSpinDestroy(&virtual->spin);
423 OsalMemFree(virtual);
424 }
425 return;
426 }
427
VirtualI3cRelease(struct HdfDeviceObject * device)428 static void VirtualI3cRelease(struct HdfDeviceObject *device)
429 {
430 const struct DeviceResourceNode *childNode = NULL;
431
432 HDF_LOGI("%s: enter", __func__);
433
434 if (device == NULL || device->property == NULL) {
435 HDF_LOGE("%s: device or property is NULL", __func__);
436 return;
437 }
438
439 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
440 VirtualI3cRemoveByNode(childNode);
441 }
442 }
443
444 struct HdfDriverEntry g_i3cDriverEntry = {
445 .moduleVersion = 1,
446 .Init = VirtualI3cInit,
447 .Release = VirtualI3cRelease,
448 .moduleName = "virtual_i3c_driver",
449 };
450 HDF_INIT(g_i3cDriverEntry);
451