• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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