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