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