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