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