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