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