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