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