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