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" 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) 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 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 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) 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 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 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 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 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) 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) 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 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 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 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 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 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