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