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