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