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 
9 #include "device_resource_if.h"
10 #include "hdf_base.h"
11 #include "hdf_log.h"
12 #include "osal_mem.h"
13 #include "osal_time.h"
14 #include "sdio_if.h"
15 #include "sdio_test.h"
16 
17 #define HDF_LOG_TAG sdio_test_c
18 
19 #define TEST_DATA_LEN 3
20 #define TEST_BLOCKSIZE 512
21 #ifdef CONFIG_IMX8MM_SDIO_TEST
22 #define TEST_SDIO_BASE_ADDR 0x10000
23 #define TEST_FUNC_NUM 1
24 #define TEST_ADDR_OFFSET 0x0D
25 #define TEST_FIXED_OFFSET 0x09
26 #else
27 #define TEST_SDIO_BASE_ADDR 0x100
28 #define TEST_FUNC_NUM 1
29 #define TEST_ADDR_OFFSET 0x10
30 #define TEST_FIXED_OFFSET 0x09
31 #endif
32 #define TEST_TIME_OUT 1000
33 #define TEST_ADDR_ADD 1
34 #define TEST_FUNC0_ADDR 0xFE
35 
36 struct SdioTestFunc {
37     enum SdioTestCmd type;
38     int32_t (*Func)(struct SdioTester *tester);
39 };
40 
SdioTestGetHandle(struct SdioTester * tester)41 static DevHandle SdioTestGetHandle(struct SdioTester *tester)
42 {
43     if (tester == NULL) {
44         HDF_LOGE("SdioTestGetHandle: tester is null!");
45         return NULL;
46     }
47     return SdioOpen((int16_t)(tester->busNum), &(tester->config));
48 }
49 
SdioTestReleaseHandle(DevHandle handle)50 static void SdioTestReleaseHandle(DevHandle handle)
51 {
52     if (handle == NULL) {
53         HDF_LOGE("SdioTestReleaseHandle: sdio handle is null!");
54         return;
55     }
56     SdioClose(handle);
57 }
58 
TestSdioIncrAddrReadAndWriteOtherBytes(struct SdioTester * tester)59 static int32_t TestSdioIncrAddrReadAndWriteOtherBytes(struct SdioTester *tester)
60 {
61     int32_t ret;
62     uint8_t data[TEST_DATA_LEN] = {0};
63     const uint32_t addr = TEST_SDIO_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET + TEST_ADDR_ADD;
64 
65     ret = SdioReadBytes(tester->handle, &data[0], addr, 1);
66     if (ret != HDF_SUCCESS) {
67         HDF_LOGE("TestSdioIncrAddrReadAndWriteOtherBytes: SdioReadBytes fail! ret = %d!", ret);
68         return HDF_FAILURE;
69     }
70     HDF_LOGE("TestSdioIncrAddrReadAndWriteOtherBytes: read, data[0]:%d\n", data[0]);
71     ret = SdioWriteBytes(tester->handle, &data[0], addr, 1);
72     if (ret != HDF_SUCCESS) {
73         HDF_LOGE("TestSdioIncrAddrReadAndWriteOtherBytes: SdioWriteBytes fail! ret = %d!", ret);
74         return HDF_FAILURE;
75     }
76     HDF_LOGD("TestSdioIncrAddrReadAndWriteOtherBytes: write, data[0]:%u!\n", data[0]);
77     return HDF_SUCCESS;
78 }
79 
TestSdioIncrAddrReadAndWriteOneByte(struct SdioTester * tester)80 static int32_t TestSdioIncrAddrReadAndWriteOneByte(struct SdioTester *tester)
81 {
82     int32_t ret;
83     uint8_t val;
84     uint32_t addr;
85 
86     addr = TEST_SDIO_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET;
87     /* read 1 bits */
88     ret = SdioReadBytes(tester->handle, &val, addr, 1);
89     if (ret != HDF_SUCCESS) {
90         HDF_LOGE("TestSdioIncrAddrReadAndWriteOneByte: SdioReadBytes fail, ret = %d!", ret);
91         return HDF_FAILURE;
92     }
93     HDF_LOGD("TestSdioIncrAddrReadAndWriteOneByte: read, val:%d!\n", val);
94     /* write 1 bits */
95     ret = SdioWriteBytes(tester->handle, &val, addr, 1);
96     if (ret != HDF_SUCCESS) {
97         HDF_LOGE("TestSdioIncrAddrReadAndWriteOneByte: SdioWriteBytes fail, ret = %d!", ret);
98         return HDF_FAILURE;
99     }
100     HDF_LOGD("TestSdioIncrAddrReadAndWriteOneByte: write, val:%d!\n", val);
101     /* read 1 bits */
102     addr++;
103     ret = SdioReadBytes(tester->handle, &val, addr, 1);
104     if (ret != HDF_SUCCESS) {
105         HDF_LOGE("TestSdioIncrAddrReadAndWriteOneByte: SdioReadBytes fail, ret = %d!", ret);
106         return HDF_FAILURE;
107     }
108     HDF_LOGD("TestSdioIncrAddrReadAndWriteOneByte: read, val:%u!", val);
109     /* read 1 bits */
110     addr++;
111     ret = SdioReadBytes(tester->handle, &val, addr, 1);
112     if (ret != HDF_SUCCESS) {
113         HDF_LOGE("TestSdioIncrAddrReadAndWriteOneByte: SdioReadBytes fail! ret = %d!", ret);
114         return HDF_FAILURE;
115     }
116     HDF_LOGE("TestSdioIncrAddrReadAndWriteOneByte: read, val:%u!", val);
117     return HDF_SUCCESS;
118 }
119 
TestSdioIncrAddrReadAndWriteBytes(struct SdioTester * tester)120 static int32_t TestSdioIncrAddrReadAndWriteBytes(struct SdioTester *tester)
121 {
122     int32_t ret;
123 
124     SdioClaimHost(tester->handle);
125     ret = TestSdioIncrAddrReadAndWriteOneByte(tester);
126     if (ret != HDF_SUCCESS) {
127         HDF_LOGE("TestSdioIncrAddrReadAndWriteBytes: TestSdioIncrAddrReadAndWriteOneByte fail, ret = %d!", ret);
128         SdioReleaseHost(tester->handle);
129         return HDF_FAILURE;
130     }
131     ret = TestSdioIncrAddrReadAndWriteOtherBytes(tester);
132     if (ret != HDF_SUCCESS) {
133         HDF_LOGE("TestSdioIncrAddrReadAndWriteBytes: TestSdioIncrAddrReadAndWriteOtherBytes fail, ret = %d!", ret);
134         SdioReleaseHost(tester->handle);
135         return HDF_FAILURE;
136     }
137     SdioReleaseHost(tester->handle);
138 
139     return ret;
140 }
141 
TestSdioFixedAddrReadAndWriteOtherBytes(struct SdioTester * tester)142 static int32_t TestSdioFixedAddrReadAndWriteOtherBytes(struct SdioTester *tester)
143 {
144     int32_t ret;
145     uint8_t data[TEST_DATA_LEN] = {0};
146     const uint32_t addr = TEST_SDIO_BASE_ADDR * TEST_FUNC_NUM + TEST_FIXED_OFFSET + TEST_ADDR_ADD;
147 
148     /* read bits */
149     ret = SdioReadBytes(tester->handle, &data[0], addr, 1);
150     if (ret != HDF_SUCCESS) {
151         HDF_LOGE("TestSdioFixedAddrReadAndWriteOtherBytes: SdioReadBytesFromFixedAddr fail, ret = %d!", ret);
152         return HDF_FAILURE;
153     }
154     HDF_LOGD("TestSdioFixedAddrReadAndWriteOtherBytes: read, data[0]:%u, data[1]:%u!\n", data[0], data[1]);
155     /* write bits */
156     ret = SdioWriteBytes(tester->handle, &data[0], addr, 1);
157     if (ret != HDF_SUCCESS) {
158         HDF_LOGE("TestSdioFixedAddrReadAndWriteOtherBytes: SdioWriteBytesToFixedAddr fail, ret = %d!", ret);
159         return HDF_FAILURE;
160     }
161     HDF_LOGD("TestSdioFixedAddrReadAndWriteOtherBytes: write, data[0]:%u, data[1]:%u!", data[0], data[1]);
162     return ret;
163 }
164 
TestSdioFixedAddrReadAndWriteOneByte(struct SdioTester * tester)165 static int32_t TestSdioFixedAddrReadAndWriteOneByte(struct SdioTester *tester)
166 {
167     int32_t ret;
168     uint32_t addr;
169     uint8_t val;
170 
171     addr = TEST_SDIO_BASE_ADDR * TEST_FUNC_NUM + TEST_FIXED_OFFSET;
172     /* read 1 bits */
173     ret = SdioReadBytes(tester->handle, &val, addr, 1);
174     if (ret != HDF_SUCCESS) {
175         HDF_LOGE("TestSdioFixedAddrReadAndWriteOneByte: SdioReadBytesFromFixedAddr fail, ret = %d!", ret);
176         return HDF_FAILURE;
177     }
178     HDF_LOGD("TestSdioFixedAddrReadAndWriteOneByte: read, val:%d\n", val);
179     /* write 1 bits */
180     ret = SdioWriteBytes(tester->handle, &val, addr, 1);
181     if (ret != HDF_SUCCESS) {
182         HDF_LOGE("TestSdioFixedAddrReadAndWriteOneByte: SdioWriteBytesToFixedAddr fail, ret = %d!", ret);
183         return HDF_FAILURE;
184     }
185     HDF_LOGD("TestSdioFixedAddrReadAndWriteOneByte: write, val:%d.", val);
186     /* read 1 bits */
187     addr++;
188     ret = SdioReadBytes(tester->handle, &val, addr, 1);
189     if (ret != HDF_SUCCESS) {
190         HDF_LOGE("TestSdioFixedAddrReadAndWriteOneByte: SdioReadBytesFromFixedAddr fail, ret = %d!", ret);
191         return HDF_FAILURE;
192     }
193     HDF_LOGD("TestSdioFixedAddrReadAndWriteOneByte: read, val:%d.", val);
194     /* read 1 bits */
195     addr++;
196     ret = SdioWriteBytes(tester->handle, &val, addr, 1);
197     if (ret != HDF_SUCCESS) {
198         HDF_LOGE("TestSdioFixedAddrReadAndWriteOneByte: SdioReadBytesFromFixedAddr fail, ret = %d!", ret);
199         return HDF_FAILURE;
200     }
201     HDF_LOGD("TestSdioFixedAddrReadAndWriteOneByte: read, val:%d!", val);
202 
203     return ret;
204 }
205 
TestSdioFixedAddrReadAndWriteBytes(struct SdioTester * tester)206 static int32_t TestSdioFixedAddrReadAndWriteBytes(struct SdioTester *tester)
207 {
208     int32_t ret;
209 
210     SdioClaimHost(tester->handle);
211     ret = TestSdioFixedAddrReadAndWriteOtherBytes(tester);
212     if (ret != HDF_SUCCESS) {
213         HDF_LOGE("TestSdioFixedAddrReadAndWriteBytes: TestSdioFixedAddrReadAndWriteOtherBytes fail, ret = %d!", ret);
214         SdioReleaseHost(tester->handle);
215         return HDF_FAILURE;
216     }
217     ret = TestSdioFixedAddrReadAndWriteOneByte(tester);
218     if (ret != HDF_SUCCESS) {
219         HDF_LOGE("TestSdioFixedAddrReadAndWriteBytes: TestSdioFixedAddrReadAndWriteOneByte fail, ret = %d!", ret);
220         SdioReleaseHost(tester->handle);
221         return HDF_FAILURE;
222     }
223     SdioReleaseHost(tester->handle);
224 
225     return ret;
226 }
227 
TestSdioFunc0ReadAndWriteBytes(struct SdioTester * tester)228 static int32_t TestSdioFunc0ReadAndWriteBytes(struct SdioTester *tester)
229 {
230     int32_t ret;
231     uint8_t val;
232 
233     SdioClaimHost(tester->handle);
234     /* read sdio rev */
235     ret = SdioReadBytesFromFunc0(tester->handle, &val, TEST_FUNC0_ADDR, 1);
236     if (ret != HDF_SUCCESS) {
237         HDF_LOGE("TestSdioFunc0ReadAndWriteBytes: SdioReadBytesFromFunc0 fail, ret = %d!", ret);
238         SdioReleaseHost(tester->handle);
239         return HDF_FAILURE;
240     }
241     HDF_LOGD("TestSdioFunc0ReadAndWriteBytes: Func0 Read, val :%d.", val);
242 
243     /* write sdio rev */
244     ret = SdioWriteBytesToFunc0(tester->handle, &val, TEST_FUNC0_ADDR, 1);
245     if (ret != HDF_SUCCESS) {
246         HDF_LOGE("TestSdioFunc0ReadAndWriteBytes: SdioWriteBytesToFunc0 fail, ret = %d!", ret);
247         SdioReleaseHost(tester->handle);
248         return HDF_FAILURE;
249     }
250 
251     /* read sdio rev again */
252     ret = SdioReadBytesFromFunc0(tester->handle, &val, TEST_FUNC0_ADDR, 1);
253     if (ret != HDF_SUCCESS) {
254         HDF_LOGE("TestSdioFunc0ReadAndWriteBytes: SdioReadBytesFromFunc0 fail, ret = %d!", ret);
255         SdioReleaseHost(tester->handle);
256         return HDF_FAILURE;
257     }
258     SdioReleaseHost(tester->handle);
259 
260     HDF_LOGD("TestSdioFunc0ReadAndWriteBytes: Func0 Read, val:%u!", val);
261     return ret;
262 }
263 
TestSdioSetAndGetFuncInfo(struct SdioTester * tester)264 static int32_t TestSdioSetAndGetFuncInfo(struct SdioTester *tester)
265 {
266     int32_t ret;
267     SdioCommonInfo info = {0};
268 
269     ret = SdioGetCommonInfo(tester->handle, &info, SDIO_FUNC_INFO);
270     if (ret != HDF_SUCCESS) {
271         HDF_LOGE("TestSdioSetAndGetFuncInfo: SdioGetCommonInfo fail, ret = %d!", ret);
272         return ret;
273     }
274     HDF_LOGE("TestSdioSetAndGetFuncInfo: success! Timeout = %u!", info.funcInfo.enTimeout);
275 
276     info.funcInfo.enTimeout = TEST_TIME_OUT;
277     ret = SdioSetCommonInfo(tester->handle, &info, SDIO_FUNC_INFO);
278     if (ret != HDF_SUCCESS) {
279         HDF_LOGE("TestSdioSetAndGetFuncInfo: SdioSetCommonInfo fail! ret = %d!", ret);
280         return ret;
281     }
282 
283     ret = SdioGetCommonInfo(tester->handle, &info, SDIO_FUNC_INFO);
284     if (ret != HDF_SUCCESS) {
285         HDF_LOGE("TestSdioSetAndGetFuncInfo: SdioGetCommonInfo fail, ret = %d!", ret);
286         return ret;
287     }
288     HDF_LOGD("TestSdioSetAndGetFuncInfo: again success, Timeout = %u!", info.funcInfo.enTimeout);
289 
290     return HDF_SUCCESS;
291 }
292 
TestSdioSetAndGetCommonInfo(struct SdioTester * tester)293 static int32_t TestSdioSetAndGetCommonInfo(struct SdioTester *tester)
294 {
295     int32_t ret;
296 
297     SdioClaimHost(tester->handle);
298     ret = TestSdioSetAndGetFuncInfo(tester);
299     if (ret != HDF_SUCCESS) {
300         HDF_LOGE("TestSdioSetAndGetCommonInfo: TestSdioSetAndGetFuncInfo fail, ret = %d!", ret);
301         SdioReleaseHost(tester->handle);
302         return HDF_FAILURE;
303     }
304     SdioReleaseHost(tester->handle);
305     return ret;
306 }
307 
TestSdioSetBlockSize(struct SdioTester * tester)308 static int32_t TestSdioSetBlockSize(struct SdioTester *tester)
309 {
310     int32_t ret;
311     SdioClaimHost(tester->handle);
312     ret = SdioSetBlockSize(tester->handle, TEST_BLOCKSIZE);
313     if (ret != HDF_SUCCESS) {
314         HDF_LOGE("TestSdioSetBlockSize: SdioSetBlockSize fail, ret = %d!", ret);
315         SdioReleaseHost(tester->handle);
316         return HDF_FAILURE;
317     }
318     SdioReleaseHost(tester->handle);
319     return ret;
320 }
321 
TestSdioEnableFunc(struct SdioTester * tester)322 static int32_t TestSdioEnableFunc(struct SdioTester *tester)
323 {
324     int32_t ret;
325 
326     SdioClaimHost(tester->handle);
327     ret = SdioEnableFunc(tester->handle);
328     if (ret != HDF_SUCCESS) {
329         HDF_LOGE("TestSdioEnableFunc: SdioEnableFunc fail, ret = %d!", ret);
330         SdioReleaseHost(tester->handle);
331         return HDF_FAILURE;
332     }
333     SdioReleaseHost(tester->handle);
334     return ret;
335 }
336 
TestSdioDisableFunc(struct SdioTester * tester)337 static int32_t TestSdioDisableFunc(struct SdioTester *tester)
338 {
339     int32_t ret;
340 
341     SdioClaimHost(tester->handle);
342     ret = SdioDisableFunc(tester->handle);
343     if (ret != HDF_SUCCESS) {
344         HDF_LOGE("TestSdioDisableFunc: SdioDisableFunc fail, ret = %d!", ret);
345         SdioReleaseHost(tester->handle);
346         return HDF_FAILURE;
347     }
348     SdioReleaseHost(tester->handle);
349     return ret;
350 }
351 
352 struct SdioTestFunc g_sdioTestFunc[] = {
353     { SDIO_DISABLE_FUNC_01, TestSdioDisableFunc },
354     { SDIO_ENABLE_FUNC_01, TestSdioEnableFunc },
355     { SDIO_SET_BLOCK_SIZE_01, TestSdioSetBlockSize },
356     { SDIO_INCR_ADDR_READ_AND_WRITE_BYTES_01, TestSdioIncrAddrReadAndWriteBytes },
357     { SDIO_FIXED_ADDR_READ_AND_WRITE_BYTES_01, TestSdioFixedAddrReadAndWriteBytes },
358     { SDIO_FUNC0_READ_AND_WRITE_BYTES_01, TestSdioFunc0ReadAndWriteBytes },
359     { SDIO_SET_AND_GET_COMMON_INFO_01, TestSdioSetAndGetCommonInfo },
360 };
361 
SdioTestEntry(struct SdioTester * tester,int32_t cmd)362 static int32_t SdioTestEntry(struct SdioTester *tester, int32_t cmd)
363 {
364     int32_t i;
365     int32_t ret = HDF_SUCCESS;
366     bool isFind = false;
367 
368     if (tester == NULL) {
369         HDF_LOGE("SdioTestEntry: tester is null!");
370         return HDF_ERR_INVALID_OBJECT;
371     }
372     tester->handle = SdioTestGetHandle(tester);
373     if (tester->handle == NULL) {
374         HDF_LOGE("SdioTestEntry: sdio test get handle fail!");
375         return HDF_FAILURE;
376     }
377     for (i = 0; i < sizeof(g_sdioTestFunc) / sizeof(g_sdioTestFunc[0]); i++) {
378         if (cmd == g_sdioTestFunc[i].type && g_sdioTestFunc[i].Func != NULL) {
379             ret = g_sdioTestFunc[i].Func(tester);
380             isFind = true;
381             break;
382         }
383     }
384     if (!isFind) {
385         ret = HDF_ERR_NOT_SUPPORT;
386         HDF_LOGE("SdioTestEntry: cmd %d is not support!", cmd);
387     }
388     SdioTestReleaseHandle(tester->handle);
389     return ret;
390 }
391 
SdioTestFillConfig(struct SdioTester * tester,const struct DeviceResourceNode * node)392 static int32_t SdioTestFillConfig(struct SdioTester *tester, const struct DeviceResourceNode *node)
393 {
394     int32_t ret;
395     struct DeviceResourceIface *drsOps = NULL;
396 
397     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
398     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
399         HDF_LOGE("SdioTestFillConfig: invalid drs ops fail!");
400         return HDF_FAILURE;
401     }
402 
403     ret = drsOps->GetUint32(node, "busNum", &(tester->busNum), 0);
404     if (ret != HDF_SUCCESS) {
405         HDF_LOGE("SdioTestFillConfig: fill bus num fail, ret: %d", ret);
406         return ret;
407     }
408 
409     ret = drsOps->GetUint32(node, "funcNum", &(tester->config.funcNr), 0);
410     if (ret != HDF_SUCCESS) {
411         HDF_LOGE("SdioTestFillConfig: fill funcNum fail, ret: %d", ret);
412         return ret;
413     }
414     ret = drsOps->GetUint16(node, "vendorId", &(tester->config.vendorId), 0);
415     if (ret != HDF_SUCCESS) {
416         HDF_LOGE("SdioTestFillConfig: fill vendorId fail, ret: %d", ret);
417         return ret;
418     }
419     ret = drsOps->GetUint16(node, "deviceId", &(tester->config.deviceId), 0);
420     if (ret != HDF_SUCCESS) {
421         HDF_LOGE("SdioTestFillConfig: fill deviceId fail, ret: %d", ret);
422         return ret;
423     }
424 
425     HDF_LOGE("SdioTestFillConfig: busNum:%u, funcNum:%u, vendorId:0x%x, deviceId:0x%x!",
426         tester->busNum, tester->config.funcNr, tester->config.vendorId, tester->config.deviceId);
427     return HDF_SUCCESS;
428 }
429 
SdioTestBind(struct HdfDeviceObject * device)430 static int32_t SdioTestBind(struct HdfDeviceObject *device)
431 {
432     static struct SdioTester tester;
433 
434     if (device == NULL) {
435         HDF_LOGE("SdioTestBind: device is null!");
436         return HDF_ERR_IO;
437     }
438 
439     device->service = &tester.service;
440     HDF_LOGE("SdioTestBind: Sdio_TEST service init success!");
441     return HDF_SUCCESS;
442 }
443 
SdioTestInit(struct HdfDeviceObject * device)444 static int32_t SdioTestInit(struct HdfDeviceObject *device)
445 {
446     struct SdioTester *tester = NULL;
447     int32_t ret;
448 
449     if (device == NULL || device->service == NULL || device->property == NULL) {
450         HDF_LOGE("SdioTestInit: invalid parameter!");
451         return HDF_ERR_INVALID_PARAM;
452     }
453 
454     tester = (struct SdioTester *)device->service;
455     ret = SdioTestFillConfig(tester, device->property);
456     if (ret != HDF_SUCCESS) {
457         HDF_LOGE("SdioTestInit: read config fail, ret: %d!", ret);
458         return ret;
459     }
460     tester->TestEntry = SdioTestEntry;
461     HDF_LOGE("SdioTestInit: success!");
462     return HDF_SUCCESS;
463 }
464 
SdioTestRelease(struct HdfDeviceObject * device)465 static void SdioTestRelease(struct HdfDeviceObject *device)
466 {
467     if (device != NULL) {
468         device->service = NULL;
469     }
470 }
471 
472 struct HdfDriverEntry g_sdioTestEntry = {
473     .moduleVersion = 1,
474     .Bind = SdioTestBind,
475     .Init = SdioTestInit,
476     .Release = SdioTestRelease,
477     .moduleName = "PLATFORM_SDIO_TEST",
478 };
479 HDF_INIT(g_sdioTestEntry);
480