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