1 /*
2 * (C) Copyright 2019 Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.h>
8 #ifdef CONFIG_DM_RAMDISK
9 #include <boot_rkimg.h>
10 #endif
11 #include <cli.h>
12 #include <dm.h>
13 #include <environment.h>
14 #include <malloc.h>
15 #include <misc.h>
16 #ifdef CONFIG_RKIMG_BOOTLOADER
17 #include <sysmem.h>
18 #endif
19 #include <linux/ctype.h>
20 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
21 #include <asm/arch/vendor.h>
22 #endif
23 #include "test-rockchip.h"
24
25 #define DEFAULT_STORAGE_RW_PART "userdata"
blk_get_type_by_name_and_num(char * devtype,int devnum)26 static enum if_type blk_get_type_by_name_and_num(char *devtype, int devnum)
27 {
28 int type = -1;
29
30 if (!strcmp(devtype, "mmc"))
31 type = IF_TYPE_MMC;
32 #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND)
33 else if (!strcmp(devtype, "rknand"))
34 type = IF_TYPE_RKNAND;
35 #endif
36 #ifdef CONFIG_RKSFC_NAND
37 else if (!strcmp(devtype, "rksfc") && devnum == 0)
38 type = IF_TYPE_SPINAND;
39 #endif
40 #ifdef CONFIG_RKSFC_NOR
41 else if (!strcmp(devtype, "rksfc") && devnum == 1)
42 type = IF_TYPE_SPINOR;
43 #endif
44 #ifdef CONFIG_DM_RAMDISK
45 else if (!strcmp(devtype, "ramdisk"))
46 type = IF_TYPE_RAMDISK;
47 #endif
48 #ifdef CONFIG_MTD_BLK
49 else if (!strcmp(devtype, "mtd"))
50 type = IF_TYPE_MTD;
51 #endif
52 #ifdef CONFIG_SCSI
53 else if (!strcmp(devtype, "scsi"))
54 type = IF_TYPE_SCSI;
55 #endif
56 else if (!strcmp(devtype, "usb"))
57 type = IF_TYPE_USB;
58
59 return type;
60 }
61
62 #if defined(CONFIG_MMC) ||\
63 defined(CONFIG_RKNAND) ||\
64 defined(CONFIG_DM_RAMDISK) ||\
65 defined(CONFIG_USB_HOST) ||\
66 defined(CONFIG_RKNANDC_NAND) ||\
67 defined(CONFIG_RKSFC_NAND) ||\
68 defined(CONFIG_RKSFC_NOR)
do_test_storage(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],const char * devtype,const char * devnum,const char * label)69 static int do_test_storage(cmd_tbl_t *cmdtp, int flag,
70 int argc, char *const argv[],
71 const char *devtype,
72 const char *devnum,
73 const char *label)
74 {
75 struct blk_desc *dev_desc;
76 disk_partition_t part;
77 u32 blocks, round, sector;
78 char *w_buf, *r_buf;
79 char cmd[64];
80 int i, ret;
81 ulong ts;
82
83 /* 1. Switch to device type/num */
84 if (devtype && !strcmp(devtype, "usb")) {
85 if (run_command("usb start", 0)) {
86 printf("Switch to %s%s failed\n", devtype, devnum);
87 ret = -ENODEV;
88 goto err1;
89 }
90 } else if (devtype) {
91 snprintf(cmd, sizeof(cmd), "%s dev %s", devtype, devnum);
92 if (run_command(cmd, 0)) {
93 printf("Switch to %s%s failed\n", devtype, devnum);
94 ret = -ENODEV;
95 goto err1;
96 }
97 }
98 if (!devtype) {
99 /* For blk test only */
100 #ifdef CONFIG_DM_RAMDISK
101 dev_desc = rockchip_get_bootdev();
102 #else
103 printf("%s Not support devtype!\n", __func__);
104 return -EINVAL;
105 #endif
106 } else {
107 int if_type;
108 int num = simple_strtoul(devnum, NULL, 10);
109
110 if_type = blk_get_type_by_name_and_num((char *)devtype, num);
111 dev_desc = blk_get_devnum_by_type(if_type, num);
112 }
113 if (!dev_desc) {
114 ut_err("%s: failed to get blk desc\n", label);
115 return -ENODEV;
116 }
117
118 /* 2. Get test partition */
119 if (part_get_info_by_name(dev_desc,
120 DEFAULT_STORAGE_RW_PART, &part) < 0) {
121 ut_err("%s: failed to find %s partition\n", label,
122 DEFAULT_STORAGE_RW_PART);
123 return -EINVAL;
124 }
125
126 /* 32MB */
127 sector = part.start;
128 if (part.start + part.size > dev_desc->lba)
129 part.size = dev_desc->lba - part.start;
130 blocks = part.size > 0x10000 ? 0x10000 : part.size;
131 round = 4;
132
133 /* Round up */
134 if (blocks % 2)
135 blocks += 1;
136
137 printf("%s RW sectors on %s 0x%08x - 0x%08x(size: %ld MiB) for %d round\n\n",
138 label, DEFAULT_STORAGE_RW_PART,
139 sector, sector + blocks,
140 (blocks * dev_desc->blksz) >> 20, round);
141
142 /* 3. Prepare memory */
143 #ifdef CONFIG_RKIMG_BOOTLOADER
144 w_buf = sysmem_alloc_by_name("storage_w", blocks * dev_desc->blksz);
145 #else
146 w_buf = memalign(CONFIG_SYS_CACHELINE_SIZE, blocks * dev_desc->blksz);
147 #endif
148 if (!w_buf) {
149 ut_err("%s: no sysmem for w_buf\n", label);
150 ret = -ENOMEM;
151 goto err1;
152 }
153 #ifdef CONFIG_RKIMG_BOOTLOADER
154 r_buf = sysmem_alloc_by_name("storage_r", blocks * dev_desc->blksz);
155 #else
156 r_buf = memalign(CONFIG_SYS_CACHELINE_SIZE, blocks * dev_desc->blksz);
157 #endif
158 if (!r_buf) {
159 ut_err("%s: no sysmem for r_buf\n", label);
160 ret = -ENOMEM;
161 goto err2;
162 }
163
164 for (i = 0; i < blocks * dev_desc->blksz; i++) {
165 w_buf[i] = i;
166 r_buf[i] = 0;
167 }
168
169 /* 4. Write test */
170 ts = get_timer(0);
171 if (devtype) {
172 snprintf(cmd, sizeof(cmd), "%s write 0x%x 0x%x 0x%x",
173 devtype, (u32)(ulong)w_buf, sector, blocks);
174 for (i = 0; i < round; i++) {
175 if (run_command(cmd, 0)) {
176 ut_err("%s: failed to write @%d round\n", label, i);
177 ret = -EIO;
178 goto err3;
179 }
180 }
181 } else {
182 for (i = 0; i < round; i++) {
183 ret = blk_dwrite(dev_desc, sector, blocks, w_buf);
184 if (ret != blocks) {
185 ut_err("%s: failed to write @%d round\n", label, i);
186 ret = -EIO;
187 goto err3;
188 }
189 }
190 }
191
192 ts = get_timer(0) - ts;
193 printf("\n%s write: size %dMB, used %ldms, speed %ldMB/s\n",
194 label, blocks * round / 2048, ts, (blocks * round >> 1) / ts);
195
196 /* 5. Read test */
197 ts = get_timer(0);
198 if (devtype) {
199 snprintf(cmd, sizeof(cmd), "%s read 0x%x 0x%x 0x%x",
200 devtype, (u32)(ulong)r_buf, sector, blocks);
201
202 for (i = 0; i < round; i++) {
203 if (run_command(cmd, 0)) {
204 ut_err("%s: failed to read @%d round\n", label, i);
205 ret = -EIO;
206 goto err3;
207 }
208 }
209 } else {
210 for (i = 0; i < round; i++) {
211 ret = blk_dread(dev_desc, sector, blocks, r_buf);
212 if (ret != blocks) {
213 ut_err("%s: failed to read @%d round\n", label, i);
214 ret = -EIO;
215 goto err3;
216 }
217 }
218 }
219
220 ts = get_timer(0) - ts;
221 printf("\n%s read: size %dMB, used %ldms, speed %ldMB/s\n",
222 label, blocks * round / 2048, ts, (blocks * round >> 1) / ts);
223
224 /* 6. Verify the context */
225 for (i = 0; i < blocks * dev_desc->blksz; i++) {
226 if (w_buf[i] != r_buf[i]) {
227 ut_err("%s: context compare error\n", label);
228 ret = -EINVAL;
229 goto err3;
230 }
231 }
232
233 /* 7. Switch back to default system devnum */
234 if (devtype && !strcmp(devtype, "mmc") && env_get("devnum") &&
235 strcmp(devnum, env_get("devnum"))) {
236 ret = run_command(cmd, 0);
237 if (ret) {
238 ut_err("%s: failed to switch to mmc1\n", label);
239 ret = -ENODEV;
240 goto err3;
241 }
242 }
243
244 ret = 0;
245 err3:
246 #ifdef CONFIG_RKIMG_BOOTLOADER
247 sysmem_free((phys_addr_t)r_buf);
248 err2:
249 sysmem_free((phys_addr_t)w_buf);
250 #else
251 free(r_buf);
252 err2:
253 free(w_buf);
254 #endif
255 err1:
256
257 return ret;
258 }
259
260 #ifdef CONFIG_MMC
do_test_emmc(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])261 static int do_test_emmc(cmd_tbl_t *cmdtp, int flag,
262 int argc, char *const argv[])
263 {
264 return do_test_storage(cmdtp, flag, argc, argv, "mmc", "0", "MMC0");
265 }
266
do_test_sdmmc(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])267 static int do_test_sdmmc(cmd_tbl_t *cmdtp, int flag,
268 int argc, char *const argv[])
269 {
270 return do_test_storage(cmdtp, flag, argc, argv, "mmc", "1", "MMC1");
271 }
272 #endif
273
274 #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND)
do_test_rknand(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])275 static int do_test_rknand(cmd_tbl_t *cmdtp, int flag,
276 int argc, char *const argv[])
277 {
278 return do_test_storage(cmdtp, flag, argc, argv, "rknand", "0", "RKNAND0");
279 }
280 #endif
281
282 #ifdef CONFIG_RKSFC_NAND
do_test_rkflash_spinand(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])283 static int do_test_rkflash_spinand(cmd_tbl_t *cmdtp, int flag,
284 int argc, char *const argv[])
285 {
286 return do_test_storage(cmdtp, flag, argc, argv, "rksfc", "0", "RKSFC0");
287 }
288 #endif
289
290 #ifdef CONFIG_RKSFC_NOR
do_test_rkflash_spinor(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])291 static int do_test_rkflash_spinor(cmd_tbl_t *cmdtp, int flag,
292 int argc, char *const argv[])
293 {
294 return do_test_storage(cmdtp, flag, argc, argv, "rksfc", "1", "RKSFC1");
295 }
296 #endif
297
298 #ifdef CONFIG_DM_RAMDISK
do_test_blk(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])299 static int do_test_blk(cmd_tbl_t *cmdtp, int flag,
300 int argc, char *const argv[])
301 {
302 return do_test_storage(cmdtp, flag, argc, argv, NULL, NULL, "BLK");
303 }
304 #endif
305
306 #ifdef CONFIG_SCSI
do_test_scsi(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])307 static int do_test_scsi(cmd_tbl_t *cmdtp, int flag,
308 int argc, char *const argv[])
309 {
310 return do_test_storage(cmdtp, flag, argc, argv, "scsi", "0", "BLK");
311 }
312 #endif
313
314 #endif/* defined(CONFIG_MMC) ||\
315 * defined(CONFIG_RKNAND) ||\
316 * defined(CONFIG_DM_RAMDISK) ||\
317 * defined(CONFIG_USB_HOST) ||\
318 * defined(CONFIG_RKNANDC_NAND) ||\
319 * defined(CONFIG_RKSFC_NAND) ||\
320 * defined(CONFIG_RKSFC_NOR)
321 */
322
323 #if defined(CONFIG_OPTEE_CLIENT) && defined(CONFIG_MMC)
do_test_secure_storage(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])324 static int do_test_secure_storage(cmd_tbl_t *cmdtp, int flag,
325 int argc, char *const argv[])
326 {
327 return run_command("mmc testsecurestorage", 0);
328 }
329 #endif
330
331 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) && \
332 !defined(CONFIG_SPL_BUILD)
do_test_env(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])333 static int do_test_env(cmd_tbl_t *cmdtp, int flag,
334 int argc, char *const argv[])
335 {
336 int ret;
337
338 ret = env_save();
339 if (ret) {
340 ut_err("env: failed to save, ret=%d\n", ret);
341 return ret;
342 }
343
344 return env_load();
345 }
346 #endif
347
348 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
do_test_vendor(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])349 static int do_test_vendor(cmd_tbl_t *cmdtp, int flag,
350 int argc, char *const argv[])
351 {
352 return vendor_storage_test();
353 }
354 #endif
355
356 #ifdef CONFIG_ROCKCHIP_EFUSE
do_test_efuse(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])357 static int do_test_efuse(cmd_tbl_t *cmdtp, int flag,
358 int argc, char *const argv[])
359 {
360 struct udevice *dev;
361 u8 fuses[128] = {0};
362 int ret;
363
364 ret = uclass_get_device(UCLASS_MISC, 0, &dev);
365 if (ret) {
366 ut_err("efuse: failed to get device, ret=%d\n", ret);
367 return 0;
368 }
369
370 ret = misc_read(dev, 0, &fuses, sizeof(fuses));
371 if (ret) {
372 ut_err("efuse: failed to read, ret=%d\n", ret);
373 return 0;
374 }
375
376 printf("Efuse-content:\n");
377 print_buffer(0, fuses, 1, 128, 16);
378
379 return 0;
380 }
381 #endif
382
383 #ifdef CONFIG_ROCKCHIP_OTP
do_test_otp(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])384 static int do_test_otp(cmd_tbl_t *cmdtp, int flag,
385 int argc, char *const argv[])
386 {
387 struct udevice *dev;
388 u8 otps[64] = {0};
389 int ret;
390
391 /* retrieve the device */
392 ret = uclass_get_device_by_driver(UCLASS_MISC, 0, &dev);
393 if (ret) {
394 ut_err("otp: failed to get device, ret=%d\n", ret);
395 return 0;
396 }
397
398 ret = misc_read(dev, 0, &otps, sizeof(otps));
399 if (ret) {
400 ut_err("otp: failed to read, ret=%d\n", ret);
401 return 0;
402 }
403
404 printf("Otp-content:\n");
405 print_buffer(0, otps, 1, 64, 16);
406
407 return 0;
408 }
409 #endif
410
411 #ifdef CONFIG_PARTITIONS
do_test_part(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])412 static int do_test_part(cmd_tbl_t *cmdtp, int flag,
413 int argc, char *const argv[])
414 {
415 return run_command("part list ${devtype} ${devnum}", 0);
416 }
417 #endif
418
419 #ifdef CONFIG_USB_HOST
do_test_usb(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])420 static int do_test_usb(cmd_tbl_t *cmdtp, int flag,
421 int argc, char *const argv[])
422 {
423 run_command("usb start", 0);
424 return do_test_storage(cmdtp, flag, argc, argv, "usb", "0", "usb0");
425 }
426 #endif
427
428 static cmd_tbl_t sub_cmd[] = {
429 #ifdef CONFIG_DM_RAMDISK
430 UNIT_CMD_DEFINE(blk, 0),
431 #endif
432 #ifdef CONFIG_MMC
433 UNIT_CMD_DEFINE(emmc, 0),
434 #endif
435 #ifdef CONFIG_ROCKCHIP_EFUSE
436 UNIT_CMD_DEFINE(efuse, 0),
437 #endif
438 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) && \
439 !defined(CONFIG_SPL_BUILD)
440 UNIT_CMD_DEFINE(env, 0),
441 #endif
442 #ifdef CONFIG_ROCKCHIP_OTP
443 UNIT_CMD_DEFINE(otp, 0),
444 #endif
445 #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND)
446 UNIT_CMD_DEFINE(rknand, 0),
447 #endif
448 #ifdef CONFIG_RKSFC_NAND
449 UNIT_CMD_DEFINE(rkflash_spinand, 0),
450 #endif
451 #ifdef CONFIG_RKSFC_NOR
452 UNIT_CMD_DEFINE(rkflash_spinor, 0),
453 #endif
454 #if defined(CONFIG_OPTEE_CLIENT) && defined(CONFIG_MMC)
455 UNIT_CMD_DEFINE(secure_storage, 0),
456 #endif
457 #ifdef CONFIG_PARTITIONS
458 UNIT_CMD_DEFINE(part, 0),
459 #endif
460 #ifdef CONFIG_USB_HOST
461 UNIT_CMD_DEFINE(usb, 0),
462 #endif
463 #ifdef CONFIG_MMC
464 UNIT_CMD_DEFINE(sdmmc, 0),
465 #endif
466 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
467 UNIT_CMD_DEFINE(vendor, 0),
468 #endif
469 #ifdef CONFIG_SCSI
470 UNIT_CMD_DEFINE(scsi, 0),
471 #endif
472 };
473
474 static char sub_cmd_help[] =
475 #ifdef CONFIG_DM_RAMDISK
476 " [.] rktest blk - test blk layer read/write\n"
477 #endif
478 #ifdef CONFIG_MMC
479 " [.] rktest emmc - test emmc read/write speed\n"
480 " [.] rktest sdmmc - test sd card and fat fs read/write\n"
481 #endif
482 #if defined(CONFIG_RKNAND) || defined(CONFIG_RKNANDC_NAND)
483 " [.] rktest rknand - test rknand read/write speed\n"
484 #endif
485 #ifdef CONFIG_RKSFC_NAND
486 " [.] rktest rkflash_spinand - test RKFLASH DM driver spinand read/write speed\n"
487 #endif
488 #ifdef CONFIG_RKSFC_NOR
489 " [.] rktest rkflash_spinor - test RKFLASH DM driver read/write speed\n"
490 #endif
491 #if defined(CONFIG_OPTEE_CLIENT) && defined(CONFIG_MMC)
492 " [.] rktest secure_storage - test secure storage\n"
493 #endif
494 #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
495 " [.] rktest vendor - test vendor storage read/write\n"
496 #endif
497 #ifdef CONFIG_ROCKCHIP_EFUSE
498 " [.] rktest efuse - test efuse, dump content\n"
499 #endif
500 #ifdef CONFIG_ROCKCHIP_OTP
501 " [.] rktest otp - test otp, dump content\n"
502 #endif
503 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) && \
504 !defined(CONFIG_SPL_BUILD)
505 " [.] rktest env - test save env to storage\n"
506 #endif
507 #ifdef CONFIG_PARTITIONS
508 " [.] rktest part - test part list\n"
509 #endif
510 #ifdef CONFIG_USB_HOST
511 " [.] rktest usb - test usb disk\n"
512 #endif
513 #ifdef CONFIG_SCSI
514 " [.] rktest scsi - test sata disk\n"
515 #endif
516 ;
517
518 const struct cmd_group cmd_grp_storage = {
519 .id = TEST_ID_STORAGE,
520 .help = sub_cmd_help,
521 .cmd = sub_cmd,
522 .cmd_n = ARRAY_SIZE(sub_cmd),
523 };
524