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