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