xref: /rk3399_rockchip-uboot/cmd/mmc.c (revision b2858095789a25b1c699d6a281d4334c9ffe75c3)
1 /*
2  * (C) Copyright 2003
3  * Kyle Harris, kharris@nexus-tech.net
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 #include <common.h>
8 #include <command.h>
9 #include <console.h>
10 #include <mmc.h>
11 #include <optee_include/OpteeClientInterface.h>
12 #include <optee_include/OpteeClientApiLib.h>
13 #include <optee_test.h>
14 
15 DECLARE_GLOBAL_DATA_PTR;
16 
17 static int curr_device = -1;
18 
19 static void print_mmcinfo(struct mmc *mmc)
20 {
21 	int i;
22 	const char *timing[] = {
23 		"Legacy", "High Speed", "High Speed", "SDR12",
24 		"SDR25", "SDR50", "SDR104", "DDR50",
25 		"DDR52", "HS200", "HS400", "HS400 Enhanced Strobe"};
26 
27 	printf("Device: %s\n", mmc->cfg->name);
28 	printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
29 	printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
30 	printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
31 			(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
32 			(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
33 
34 	printf("Timing Interface: %s\n", timing[mmc->timing]);
35 	printf("Tran Speed: %d\n", mmc->clock);
36 	printf("Rd Block Len: %d\n", mmc->read_bl_len);
37 
38 	printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC",
39 			EXTRACT_SDMMC_MAJOR_VERSION(mmc->version),
40 			EXTRACT_SDMMC_MINOR_VERSION(mmc->version));
41 	if (EXTRACT_SDMMC_CHANGE_VERSION(mmc->version) != 0)
42 		printf(".%d", EXTRACT_SDMMC_CHANGE_VERSION(mmc->version));
43 	printf("\n");
44 
45 	printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
46 	puts("Capacity: ");
47 	print_size(mmc->capacity, "\n");
48 
49 	printf("Bus Width: %d-bit%s\n", mmc->bus_width,
50 			mmc_card_ddr(mmc) ? " DDR" : "");
51 
52 	puts("Erase Group Size: ");
53 	print_size(((u64)mmc->erase_grp_size) << 9, "\n");
54 
55 	if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) {
56 		bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0;
57 		bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR);
58 
59 		puts("HC WP Group Size: ");
60 		print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n");
61 
62 		puts("User Capacity: ");
63 		print_size(mmc->capacity_user, usr_enh ? " ENH" : "");
64 		if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_USR)
65 			puts(" WRREL\n");
66 		else
67 			putc('\n');
68 		if (usr_enh) {
69 			puts("User Enhanced Start: ");
70 			print_size(mmc->enh_user_start, "\n");
71 			puts("User Enhanced Size: ");
72 			print_size(mmc->enh_user_size, "\n");
73 		}
74 		puts("Boot Capacity: ");
75 		print_size(mmc->capacity_boot, has_enh ? " ENH\n" : "\n");
76 		puts("RPMB Capacity: ");
77 		print_size(mmc->capacity_rpmb, has_enh ? " ENH\n" : "\n");
78 
79 		for (i = 0; i < ARRAY_SIZE(mmc->capacity_gp); i++) {
80 			bool is_enh = has_enh &&
81 				(mmc->part_attr & EXT_CSD_ENH_GP(i));
82 			if (mmc->capacity_gp[i]) {
83 				printf("GP%i Capacity: ", i+1);
84 				print_size(mmc->capacity_gp[i],
85 					   is_enh ? " ENH" : "");
86 				if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_GP(i))
87 					puts(" WRREL\n");
88 				else
89 					putc('\n');
90 			}
91 		}
92 	}
93 }
94 static struct mmc *init_mmc_device(int dev, bool force_init)
95 {
96 	struct mmc *mmc;
97 	mmc = find_mmc_device(dev);
98 	if (!mmc) {
99 		printf("no mmc device at slot %x\n", dev);
100 		return NULL;
101 	}
102 
103 	if (force_init)
104 		mmc->has_init = 0;
105 	if (mmc_init(mmc))
106 		return NULL;
107 	return mmc;
108 }
109 static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
110 {
111 	struct mmc *mmc;
112 
113 	if (curr_device < 0) {
114 		if (get_mmc_num() > 0)
115 			curr_device = 0;
116 		else {
117 			puts("No MMC device available\n");
118 			return 1;
119 		}
120 	}
121 
122 	mmc = init_mmc_device(curr_device, false);
123 	if (!mmc)
124 		return CMD_RET_FAILURE;
125 
126 	print_mmcinfo(mmc);
127 	return CMD_RET_SUCCESS;
128 }
129 
130 #ifdef CONFIG_OPTEE_CLIENT
131 static int do_mmc_test_secure_storage(cmd_tbl_t *cmdtp,
132 				      int flag, int argc, char * const argv[])
133 {
134 #ifdef CONFIG_MMC
135 	struct mmc *mmc;
136 
137 	if (curr_device < 0) {
138 		if (get_mmc_num() > 0) {
139 			puts("MMC device available\n");
140 			curr_device = 0;
141 		} else {
142 			puts("No MMC device available\n");
143 			return 1;
144 		}
145 	}
146 
147 	mmc = init_mmc_device(curr_device, false);
148 	if (!mmc)
149 		printf("No mmc device\n");
150 #endif
151 
152 	int i, count = 100;
153 
154 	for (i = 1; i <= count; i++) {
155 		if (test_secure_storage_default() == 0) {
156 			printf("test_secure_storage_default success! %d/%d\n", i, count);
157 		} else {
158 			printf("test_secure_storage_default fail! %d/%d\n", i, count);
159 			break;
160 		}
161 		if (test_secure_storage_security_partition() == 0) {
162 			printf("test_secure_storage_security_partition success! %d/%d\n", i, count);
163 		} else {
164 			printf("test_secure_storage_security_partition fail! %d/%d\n", i, count);
165 			break;
166 		}
167 	}
168 
169 	return CMD_RET_SUCCESS;
170 }
171 
172 static int do_mmc_testefuse(cmd_tbl_t *cmdtp,
173 		int flag, int argc, char * const argv[])
174 {
175 	uint32_t outbuf32[8];
176 
177 	trusty_read_attribute_hash(outbuf32, 8);
178 
179 	printf(" 0x%x  0x%x  0x%x  0x%x \n",
180 		outbuf32[0], outbuf32[1], outbuf32[2], outbuf32[3]);
181 	printf(" 0x%x  0x%x  0x%x  0x%x \n",
182 		outbuf32[4], outbuf32[5], outbuf32[6], outbuf32[7]);
183 
184 	return CMD_RET_SUCCESS;
185 }
186 
187 #endif
188 
189 #ifdef CONFIG_SUPPORT_EMMC_RPMB
190 char temp_original_part;
191 int init_rpmb(void)
192 {
193 	struct mmc *mmc;
194 
195 	if (curr_device < 0) {
196 		if (get_mmc_num() > 0) {
197 			curr_device = 0;
198 		} else {
199 			printf("No MMC device available\n");
200 			return CMD_RET_FAILURE;
201 		}
202 	}
203 
204 	mmc = init_mmc_device(curr_device, false);
205 	if (!mmc)
206 		return CMD_RET_FAILURE;
207 
208 	if (!(mmc->version & MMC_VERSION_MMC)) {
209 		printf("It is not a EMMC device\n");
210 		return CMD_RET_FAILURE;
211 	}
212 	if (mmc->version < MMC_VERSION_4_41) {
213 		printf("RPMB not supported before version 4.41\n");
214 		return CMD_RET_FAILURE;
215 	}
216 
217 		/* Switch to the RPMB partition */
218 #ifndef CONFIG_BLK
219 	temp_original_part = mmc->block_dev.hwpart;
220 	debug("mmc->block_dev.hwpart\n");
221 #else
222 	temp_original_part = mmc_get_blk_desc(mmc)->hwpart;
223 	debug("mmc_get_blk_desc(mmc)->hwpart\n");
224 #endif
225 	debug("init_rpmb temp_original_part = 0x%X\n", temp_original_part);
226 	if (blk_select_hwpart_devnum
227 		(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != 0)
228 		return CMD_RET_FAILURE;
229 
230 	return CMD_RET_SUCCESS;
231 }
232 
233 int finish_rpmb(void)
234 {
235 	/* Return to original partition */
236 	debug("finish_rpmb temp_original_part = 0x%X\n", temp_original_part);
237 	if (blk_select_hwpart_devnum
238 		(IF_TYPE_MMC, curr_device, temp_original_part) != 0)
239 		return CMD_RET_FAILURE;
240 
241 	return CMD_RET_SUCCESS;
242 }
243 
244 int do_readcounter(struct s_rpmb *requestpackets)
245 {
246 	int ret;
247 	struct mmc *mmc = find_mmc_device(curr_device);
248 	if (!mmc)
249 		return -1;
250 
251 	if (init_rpmb() != 0)
252 		return -1;
253 
254 	ret = read_counter(mmc, requestpackets);
255 
256 	if (finish_rpmb() != 0)
257 		return -1;
258 
259 	return ret;
260 }
261 
262 int do_programkey(struct s_rpmb *requestpackets)
263 {
264 	int ret;
265 	struct mmc *mmc = find_mmc_device(curr_device);
266 	if (!mmc)
267 		return -1;
268 
269 	if (init_rpmb() != 0)
270 		return -1;
271 
272 	ret = program_key(mmc, requestpackets);
273 
274 	if (finish_rpmb() != 0)
275 		return -1;
276 
277 	return ret;
278 }
279 
280 int do_authenticatedread(struct s_rpmb *requestpackets, uint16_t block_count)
281 {
282 	int ret;
283 	struct mmc *mmc = find_mmc_device(curr_device);
284 	if (!mmc)
285 		return -1;
286 
287 	if (init_rpmb() != 0)
288 		return -1;
289 
290 	ret = authenticated_read(mmc, requestpackets, block_count);
291 
292 	if (finish_rpmb() != 0)
293 		return -1;
294 
295 	return ret;
296 }
297 
298 int do_authenticatedwrite(struct s_rpmb *requestpackets)
299 {
300 	int ret;
301 	struct mmc *mmc = find_mmc_device(curr_device);
302 	if (!mmc)
303 		return -1;
304 
305 	if (init_rpmb() != 0)
306 		return -1;
307 
308 	ret = authenticated_write(mmc, requestpackets);
309 
310 	if (finish_rpmb() != 0)
311 		return -1;
312 
313 	return ret;
314 }
315 
316 struct mmc *do_returnmmc(void)
317 {
318 	struct mmc *mmc;
319 
320 	if (init_rpmb() != 0)
321 		return NULL;
322 
323 	mmc = find_mmc_device(curr_device);
324 
325 	if (finish_rpmb() != 0)
326 		return NULL;
327 
328 	return mmc;
329 }
330 
331 static int confirm_key_prog(void)
332 {
333 	puts("Warning: Programming authentication key can be done only once !\n"
334 	     "         Use this command only if you are sure of what you are doing,\n"
335 	     "Really perform the key programming? <y/N> ");
336 	if (confirm_yesno())
337 		return 1;
338 
339 	puts("Authentication key programming aborted\n");
340 	return 0;
341 }
342 static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag,
343 			  int argc, char * const argv[])
344 {
345 	void *key_addr;
346 	struct mmc *mmc = find_mmc_device(curr_device);
347 
348 	if (argc != 2)
349 		return CMD_RET_USAGE;
350 
351 	key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
352 	if (!confirm_key_prog())
353 		return CMD_RET_FAILURE;
354 	if (mmc_rpmb_set_key(mmc, key_addr)) {
355 		printf("ERROR - Key already programmed ?\n");
356 		return CMD_RET_FAILURE;
357 	}
358 	return CMD_RET_SUCCESS;
359 }
360 static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag,
361 			   int argc, char * const argv[])
362 {
363 	u16 blk, cnt;
364 	void *addr;
365 	int n;
366 	void *key_addr = NULL;
367 	struct mmc *mmc = find_mmc_device(curr_device);
368 
369 	if (argc < 4)
370 		return CMD_RET_USAGE;
371 
372 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
373 	blk = simple_strtoul(argv[2], NULL, 16);
374 	cnt = simple_strtoul(argv[3], NULL, 16);
375 
376 	if (argc == 5)
377 		key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
378 
379 	printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
380 	       curr_device, blk, cnt);
381 	n =  mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
382 
383 	printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
384 	if (n != cnt)
385 		return CMD_RET_FAILURE;
386 	return CMD_RET_SUCCESS;
387 }
388 static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag,
389 			    int argc, char * const argv[])
390 {
391 	u16 blk, cnt;
392 	void *addr;
393 	int n;
394 	void *key_addr;
395 	struct mmc *mmc = find_mmc_device(curr_device);
396 
397 	if (argc != 5)
398 		return CMD_RET_USAGE;
399 
400 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
401 	blk = simple_strtoul(argv[2], NULL, 16);
402 	cnt = simple_strtoul(argv[3], NULL, 16);
403 	key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
404 
405 	printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
406 	       curr_device, blk, cnt);
407 	n =  mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
408 
409 	printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
410 	if (n != cnt)
411 		return CMD_RET_FAILURE;
412 	return CMD_RET_SUCCESS;
413 }
414 static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag,
415 			      int argc, char * const argv[])
416 {
417 	unsigned long counter;
418 	struct mmc *mmc = find_mmc_device(curr_device);
419 
420 	if (mmc_rpmb_get_counter(mmc, &counter))
421 		return CMD_RET_FAILURE;
422 	printf("RPMB Write counter= %lx\n", counter);
423 	return CMD_RET_SUCCESS;
424 }
425 
426 static cmd_tbl_t cmd_rpmb[] = {
427 	U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
428 	U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
429 	U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
430 	U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
431 };
432 
433 static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
434 		      int argc, char * const argv[])
435 {
436 	cmd_tbl_t *cp;
437 	struct mmc *mmc;
438 	char original_part;
439 	int ret;
440 
441 	cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
442 
443 	/* Drop the rpmb subcommand */
444 	argc--;
445 	argv++;
446 
447 	if (cp == NULL || argc > cp->maxargs)
448 		return CMD_RET_USAGE;
449 	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
450 		return CMD_RET_SUCCESS;
451 
452 	mmc = init_mmc_device(curr_device, false);
453 	if (!mmc)
454 		return CMD_RET_FAILURE;
455 
456 	if (!(mmc->version & MMC_VERSION_MMC)) {
457 		printf("It is not a EMMC device\n");
458 		return CMD_RET_FAILURE;
459 	}
460 	if (mmc->version < MMC_VERSION_4_41) {
461 		printf("RPMB not supported before version 4.41\n");
462 		return CMD_RET_FAILURE;
463 	}
464 	/* Switch to the RPMB partition */
465 #ifndef CONFIG_BLK
466 	original_part = mmc->block_dev.hwpart;
467 #else
468 	original_part = mmc_get_blk_desc(mmc)->hwpart;
469 #endif
470 	if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) !=
471 	    0)
472 		return CMD_RET_FAILURE;
473 	ret = cp->cmd(cmdtp, flag, argc, argv);
474 
475 	/* Return to original partition */
476 	if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) !=
477 	    0)
478 		return CMD_RET_FAILURE;
479 	return ret;
480 }
481 #endif
482 
483 static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
484 		       int argc, char * const argv[])
485 {
486 	struct mmc *mmc;
487 	u32 blk, cnt, n;
488 	void *addr;
489 
490 	if (argc != 4)
491 		return CMD_RET_USAGE;
492 
493 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
494 	blk = simple_strtoul(argv[2], NULL, 16);
495 	cnt = simple_strtoul(argv[3], NULL, 16);
496 
497 	mmc = init_mmc_device(curr_device, false);
498 	if (!mmc)
499 		return CMD_RET_FAILURE;
500 
501 	printf("\nMMC read: dev # %d, block # %d, count %d ... ",
502 	       curr_device, blk, cnt);
503 
504 	n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
505 	printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
506 
507 	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
508 }
509 static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
510 			int argc, char * const argv[])
511 {
512 	struct mmc *mmc;
513 	u32 blk, cnt, n;
514 	void *addr;
515 
516 	if (argc != 4)
517 		return CMD_RET_USAGE;
518 
519 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
520 	blk = simple_strtoul(argv[2], NULL, 16);
521 	cnt = simple_strtoul(argv[3], NULL, 16);
522 
523 	mmc = init_mmc_device(curr_device, false);
524 	if (!mmc)
525 		return CMD_RET_FAILURE;
526 
527 	printf("\nMMC write: dev # %d, block # %d, count %d ... ",
528 	       curr_device, blk, cnt);
529 
530 	if (mmc_getwp(mmc) == 1) {
531 		printf("Error: card is write protected!\n");
532 		return CMD_RET_FAILURE;
533 	}
534 	n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
535 	printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
536 
537 	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
538 }
539 static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
540 			int argc, char * const argv[])
541 {
542 	struct mmc *mmc;
543 	u32 blk, cnt, n;
544 
545 	if (argc != 3)
546 		return CMD_RET_USAGE;
547 
548 	blk = simple_strtoul(argv[1], NULL, 16);
549 	cnt = simple_strtoul(argv[2], NULL, 16);
550 
551 	mmc = init_mmc_device(curr_device, false);
552 	if (!mmc)
553 		return CMD_RET_FAILURE;
554 
555 	printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
556 	       curr_device, blk, cnt);
557 
558 	if (mmc_getwp(mmc) == 1) {
559 		printf("Error: card is write protected!\n");
560 		return CMD_RET_FAILURE;
561 	}
562 	n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
563 	printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
564 
565 	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
566 }
567 static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
568 			 int argc, char * const argv[])
569 {
570 	struct mmc *mmc;
571 
572 	mmc = init_mmc_device(curr_device, true);
573 	if (!mmc)
574 		return CMD_RET_FAILURE;
575 
576 	return CMD_RET_SUCCESS;
577 }
578 static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
579 		       int argc, char * const argv[])
580 {
581 	struct blk_desc *mmc_dev;
582 	struct mmc *mmc;
583 
584 	mmc = init_mmc_device(curr_device, false);
585 	if (!mmc)
586 		return CMD_RET_FAILURE;
587 
588 	mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device);
589 	if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
590 		part_print(mmc_dev);
591 		return CMD_RET_SUCCESS;
592 	}
593 
594 	puts("get mmc type error!\n");
595 	return CMD_RET_FAILURE;
596 }
597 static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
598 		      int argc, char * const argv[])
599 {
600 	int dev, part = 0, ret;
601 	struct mmc *mmc;
602 
603 	/* If not boot from mmc devices, init mmc devices first. */
604 	ret = mmc_initialize(gd->bd);
605 	if (ret) {
606 		printf("Could not initialize mmc. error: %d\n", ret);
607 		return ret;
608 	}
609 
610 	if (argc == 1) {
611 		dev = curr_device;
612 	} else if (argc == 2) {
613 		dev = simple_strtoul(argv[1], NULL, 10);
614 	} else if (argc == 3) {
615 		dev = (int)simple_strtoul(argv[1], NULL, 10);
616 		part = (int)simple_strtoul(argv[2], NULL, 10);
617 		if (part > PART_ACCESS_MASK) {
618 			printf("#part_num shouldn't be larger than %d\n",
619 			       PART_ACCESS_MASK);
620 			return CMD_RET_FAILURE;
621 		}
622 	} else {
623 		return CMD_RET_USAGE;
624 	}
625 
626 	mmc = init_mmc_device(dev, false);
627 	if (!mmc)
628 		return CMD_RET_FAILURE;
629 
630 	ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
631 	printf("switch to partitions #%d, %s\n",
632 	       part, (!ret) ? "OK" : "ERROR");
633 	if (ret)
634 		return 1;
635 
636 	curr_device = dev;
637 	if (mmc->part_config == MMCPART_NOAVAILABLE)
638 		printf("mmc%d is current device\n", curr_device);
639 	else
640 		printf("mmc%d(part %d) is current device\n",
641 		       curr_device, mmc_get_blk_desc(mmc)->hwpart);
642 
643 	return CMD_RET_SUCCESS;
644 }
645 static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
646 		       int argc, char * const argv[])
647 {
648 	print_mmc_devices('\n');
649 	return CMD_RET_SUCCESS;
650 }
651 
652 static int parse_hwpart_user(struct mmc_hwpart_conf *pconf,
653 			     int argc, char * const argv[])
654 {
655 	int i = 0;
656 
657 	memset(&pconf->user, 0, sizeof(pconf->user));
658 
659 	while (i < argc) {
660 		if (!strcmp(argv[i], "enh")) {
661 			if (i + 2 >= argc)
662 				return -1;
663 			pconf->user.enh_start =
664 				simple_strtoul(argv[i+1], NULL, 10);
665 			pconf->user.enh_size =
666 				simple_strtoul(argv[i+2], NULL, 10);
667 			i += 3;
668 		} else if (!strcmp(argv[i], "wrrel")) {
669 			if (i + 1 >= argc)
670 				return -1;
671 			pconf->user.wr_rel_change = 1;
672 			if (!strcmp(argv[i+1], "on"))
673 				pconf->user.wr_rel_set = 1;
674 			else if (!strcmp(argv[i+1], "off"))
675 				pconf->user.wr_rel_set = 0;
676 			else
677 				return -1;
678 			i += 2;
679 		} else {
680 			break;
681 		}
682 	}
683 	return i;
684 }
685 
686 static int parse_hwpart_gp(struct mmc_hwpart_conf *pconf, int pidx,
687 			   int argc, char * const argv[])
688 {
689 	int i;
690 
691 	memset(&pconf->gp_part[pidx], 0, sizeof(pconf->gp_part[pidx]));
692 
693 	if (1 >= argc)
694 		return -1;
695 	pconf->gp_part[pidx].size = simple_strtoul(argv[0], NULL, 10);
696 
697 	i = 1;
698 	while (i < argc) {
699 		if (!strcmp(argv[i], "enh")) {
700 			pconf->gp_part[pidx].enhanced = 1;
701 			i += 1;
702 		} else if (!strcmp(argv[i], "wrrel")) {
703 			if (i + 1 >= argc)
704 				return -1;
705 			pconf->gp_part[pidx].wr_rel_change = 1;
706 			if (!strcmp(argv[i+1], "on"))
707 				pconf->gp_part[pidx].wr_rel_set = 1;
708 			else if (!strcmp(argv[i+1], "off"))
709 				pconf->gp_part[pidx].wr_rel_set = 0;
710 			else
711 				return -1;
712 			i += 2;
713 		} else {
714 			break;
715 		}
716 	}
717 	return i;
718 }
719 
720 static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag,
721 			      int argc, char * const argv[])
722 {
723 	struct mmc *mmc;
724 	struct mmc_hwpart_conf pconf = { };
725 	enum mmc_hwpart_conf_mode mode = MMC_HWPART_CONF_CHECK;
726 	int i, r, pidx;
727 
728 	mmc = init_mmc_device(curr_device, false);
729 	if (!mmc)
730 		return CMD_RET_FAILURE;
731 
732 	if (argc < 1)
733 		return CMD_RET_USAGE;
734 	i = 1;
735 	while (i < argc) {
736 		if (!strcmp(argv[i], "user")) {
737 			i++;
738 			r = parse_hwpart_user(&pconf, argc-i, &argv[i]);
739 			if (r < 0)
740 				return CMD_RET_USAGE;
741 			i += r;
742 		} else if (!strncmp(argv[i], "gp", 2) &&
743 			   strlen(argv[i]) == 3 &&
744 			   argv[i][2] >= '1' && argv[i][2] <= '4') {
745 			pidx = argv[i][2] - '1';
746 			i++;
747 			r = parse_hwpart_gp(&pconf, pidx, argc-i, &argv[i]);
748 			if (r < 0)
749 				return CMD_RET_USAGE;
750 			i += r;
751 		} else if (!strcmp(argv[i], "check")) {
752 			mode = MMC_HWPART_CONF_CHECK;
753 			i++;
754 		} else if (!strcmp(argv[i], "set")) {
755 			mode = MMC_HWPART_CONF_SET;
756 			i++;
757 		} else if (!strcmp(argv[i], "complete")) {
758 			mode = MMC_HWPART_CONF_COMPLETE;
759 			i++;
760 		} else {
761 			return CMD_RET_USAGE;
762 		}
763 	}
764 
765 	puts("Partition configuration:\n");
766 	if (pconf.user.enh_size) {
767 		puts("\tUser Enhanced Start: ");
768 		print_size(((u64)pconf.user.enh_start) << 9, "\n");
769 		puts("\tUser Enhanced Size: ");
770 		print_size(((u64)pconf.user.enh_size) << 9, "\n");
771 	} else {
772 		puts("\tNo enhanced user data area\n");
773 	}
774 	if (pconf.user.wr_rel_change)
775 		printf("\tUser partition write reliability: %s\n",
776 		       pconf.user.wr_rel_set ? "on" : "off");
777 	for (pidx = 0; pidx < 4; pidx++) {
778 		if (pconf.gp_part[pidx].size) {
779 			printf("\tGP%i Capacity: ", pidx+1);
780 			print_size(((u64)pconf.gp_part[pidx].size) << 9,
781 				   pconf.gp_part[pidx].enhanced ?
782 				   " ENH\n" : "\n");
783 		} else {
784 			printf("\tNo GP%i partition\n", pidx+1);
785 		}
786 		if (pconf.gp_part[pidx].wr_rel_change)
787 			printf("\tGP%i write reliability: %s\n", pidx+1,
788 			       pconf.gp_part[pidx].wr_rel_set ? "on" : "off");
789 	}
790 
791 	if (!mmc_hwpart_config(mmc, &pconf, mode)) {
792 		if (mode == MMC_HWPART_CONF_COMPLETE)
793 			puts("Partitioning successful, "
794 			     "power-cycle to make effective\n");
795 		return CMD_RET_SUCCESS;
796 	} else {
797 		puts("Failed!\n");
798 		return CMD_RET_FAILURE;
799 	}
800 }
801 
802 #ifdef CONFIG_SUPPORT_EMMC_BOOT
803 static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
804 			  int argc, char * const argv[])
805 {
806 	int dev;
807 	struct mmc *mmc;
808 	u8 width, reset, mode;
809 
810 	if (argc != 5)
811 		return CMD_RET_USAGE;
812 	dev = simple_strtoul(argv[1], NULL, 10);
813 	width = simple_strtoul(argv[2], NULL, 10);
814 	reset = simple_strtoul(argv[3], NULL, 10);
815 	mode = simple_strtoul(argv[4], NULL, 10);
816 
817 	mmc = init_mmc_device(dev, false);
818 	if (!mmc)
819 		return CMD_RET_FAILURE;
820 
821 	if (IS_SD(mmc)) {
822 		puts("BOOT_BUS_WIDTH only exists on eMMC\n");
823 		return CMD_RET_FAILURE;
824 	}
825 
826 	/* acknowledge to be sent during boot operation */
827 	return mmc_set_boot_bus_width(mmc, width, reset, mode);
828 }
829 static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
830 			      int argc, char * const argv[])
831 {
832 	int dev;
833 	struct mmc *mmc;
834 	u32 bootsize, rpmbsize;
835 
836 	if (argc != 4)
837 		return CMD_RET_USAGE;
838 	dev = simple_strtoul(argv[1], NULL, 10);
839 	bootsize = simple_strtoul(argv[2], NULL, 10);
840 	rpmbsize = simple_strtoul(argv[3], NULL, 10);
841 
842 	mmc = init_mmc_device(dev, false);
843 	if (!mmc)
844 		return CMD_RET_FAILURE;
845 
846 	if (IS_SD(mmc)) {
847 		printf("It is not a EMMC device\n");
848 		return CMD_RET_FAILURE;
849 	}
850 
851 	if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
852 		printf("EMMC boot partition Size change Failed.\n");
853 		return CMD_RET_FAILURE;
854 	}
855 
856 	printf("EMMC boot partition Size %d MB\n", bootsize);
857 	printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
858 	return CMD_RET_SUCCESS;
859 }
860 
861 static int mmc_partconf_print(struct mmc *mmc)
862 {
863 	u8 ack, access, part;
864 
865 	if (mmc->part_config == MMCPART_NOAVAILABLE) {
866 		printf("No part_config info for ver. 0x%x\n", mmc->version);
867 		return CMD_RET_FAILURE;
868 	}
869 
870 	access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config);
871 	ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config);
872 	part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
873 
874 	printf("EXT_CSD[179], PARTITION_CONFIG:\n"
875 		"BOOT_ACK: 0x%x\n"
876 		"BOOT_PARTITION_ENABLE: 0x%x\n"
877 		"PARTITION_ACCESS: 0x%x\n", ack, part, access);
878 
879 	return CMD_RET_SUCCESS;
880 }
881 
882 static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
883 			   int argc, char * const argv[])
884 {
885 	int dev;
886 	struct mmc *mmc;
887 	u8 ack, part_num, access;
888 
889 	if (argc != 2 && argc != 5)
890 		return CMD_RET_USAGE;
891 
892 	dev = simple_strtoul(argv[1], NULL, 10);
893 
894 	mmc = init_mmc_device(dev, false);
895 	if (!mmc)
896 		return CMD_RET_FAILURE;
897 
898 	if (IS_SD(mmc)) {
899 		puts("PARTITION_CONFIG only exists on eMMC\n");
900 		return CMD_RET_FAILURE;
901 	}
902 
903 	if (argc == 2)
904 		return mmc_partconf_print(mmc);
905 
906 	ack = simple_strtoul(argv[2], NULL, 10);
907 	part_num = simple_strtoul(argv[3], NULL, 10);
908 	access = simple_strtoul(argv[4], NULL, 10);
909 
910 	/* acknowledge to be sent during boot operation */
911 	return mmc_set_part_conf(mmc, ack, part_num, access);
912 }
913 static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag,
914 			   int argc, char * const argv[])
915 {
916 	int dev;
917 	struct mmc *mmc;
918 	u8 enable;
919 
920 	/*
921 	 * Set the RST_n_ENABLE bit of RST_n_FUNCTION
922 	 * The only valid values are 0x0, 0x1 and 0x2 and writing
923 	 * a value of 0x1 or 0x2 sets the value permanently.
924 	 */
925 	if (argc != 3)
926 		return CMD_RET_USAGE;
927 
928 	dev = simple_strtoul(argv[1], NULL, 10);
929 	enable = simple_strtoul(argv[2], NULL, 10);
930 
931 	if (enable > 2) {
932 		puts("Invalid RST_n_ENABLE value\n");
933 		return CMD_RET_USAGE;
934 	}
935 
936 	mmc = init_mmc_device(dev, false);
937 	if (!mmc)
938 		return CMD_RET_FAILURE;
939 
940 	if (IS_SD(mmc)) {
941 		puts("RST_n_FUNCTION only exists on eMMC\n");
942 		return CMD_RET_FAILURE;
943 	}
944 
945 	return mmc_set_rst_n_function(mmc, enable);
946 }
947 #endif
948 static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag,
949 			 int argc, char * const argv[])
950 {
951 	struct mmc *mmc;
952 	u32 val;
953 	int ret;
954 
955 	if (argc != 2)
956 		return CMD_RET_USAGE;
957 	val = simple_strtoul(argv[1], NULL, 16);
958 
959 	mmc = find_mmc_device(curr_device);
960 	if (!mmc) {
961 		printf("no mmc device at slot %x\n", curr_device);
962 		return CMD_RET_FAILURE;
963 	}
964 	ret = mmc_set_dsr(mmc, val);
965 	printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
966 	if (!ret) {
967 		mmc->has_init = 0;
968 		if (mmc_init(mmc))
969 			return CMD_RET_FAILURE;
970 		else
971 			return CMD_RET_SUCCESS;
972 	}
973 	return ret;
974 }
975 
976 #ifdef CONFIG_CMD_BKOPS_ENABLE
977 static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag,
978 				   int argc, char * const argv[])
979 {
980 	int dev;
981 	struct mmc *mmc;
982 
983 	if (argc != 2)
984 		return CMD_RET_USAGE;
985 
986 	dev = simple_strtoul(argv[1], NULL, 10);
987 
988 	mmc = init_mmc_device(dev, false);
989 	if (!mmc)
990 		return CMD_RET_FAILURE;
991 
992 	if (IS_SD(mmc)) {
993 		puts("BKOPS_EN only exists on eMMC\n");
994 		return CMD_RET_FAILURE;
995 	}
996 
997 	return mmc_set_bkops_enable(mmc);
998 }
999 #endif
1000 
1001 static cmd_tbl_t cmd_mmc[] = {
1002 	U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
1003 	U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
1004 	U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
1005 	U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
1006 	U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
1007 	U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
1008 	U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
1009 	U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
1010 	U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""),
1011 #ifdef CONFIG_SUPPORT_EMMC_BOOT
1012 	U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
1013 	U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),
1014 	U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
1015 	U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
1016 #endif
1017 #ifdef CONFIG_OPTEE_CLIENT
1018 	U_BOOT_CMD_MKENT(testsecurestorage, 1, 0, do_mmc_test_secure_storage, "", ""),
1019 	U_BOOT_CMD_MKENT(testefuse, 1, 0, do_mmc_testefuse, "", ""),
1020 #endif
1021 #ifdef CONFIG_SUPPORT_EMMC_RPMB
1022 	U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
1023 #endif
1024 	U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
1025 #ifdef CONFIG_CMD_BKOPS_ENABLE
1026 	U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""),
1027 #endif
1028 };
1029 
1030 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1031 {
1032 	cmd_tbl_t *cp;
1033 
1034 	cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
1035 
1036 	/* Drop the mmc command */
1037 	argc--;
1038 	argv++;
1039 
1040 	if (cp == NULL || argc > cp->maxargs)
1041 		return CMD_RET_USAGE;
1042 	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
1043 		return CMD_RET_SUCCESS;
1044 
1045 	if (curr_device < 0) {
1046 		if (get_mmc_num() > 0) {
1047 			curr_device = 0;
1048 		} else {
1049 			puts("No MMC device available\n");
1050 			return CMD_RET_FAILURE;
1051 		}
1052 	}
1053 	return cp->cmd(cmdtp, flag, argc, argv);
1054 }
1055 
1056 U_BOOT_CMD(
1057 	mmc, 29, 1, do_mmcops,
1058 	"MMC sub system",
1059 	"info - display info of the current MMC device\n"
1060 	"mmc read addr blk# cnt\n"
1061 	"mmc write addr blk# cnt\n"
1062 	"mmc erase blk# cnt\n"
1063 	"mmc rescan\n"
1064 	"mmc part - lists available partition on current mmc device\n"
1065 	"mmc dev [dev] [part] - show or set current mmc device [partition]\n"
1066 	"mmc list - lists available devices\n"
1067 	"mmc hwpartition [args...] - does hardware partitioning\n"
1068 	"  arguments (sizes in 512-byte blocks):\n"
1069 	"    [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n"
1070 	"    [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n"
1071 	"    [check|set|complete] - mode, complete set partitioning completed\n"
1072 	"  WARNING: Partitioning is a write-once setting once it is set to complete.\n"
1073 	"  Power cycling is required to initialize partitions after set to complete.\n"
1074 #ifdef CONFIG_SUPPORT_EMMC_BOOT
1075 	"mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
1076 	" - Set the BOOT_BUS_WIDTH field of the specified device\n"
1077 	"mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
1078 	" - Change sizes of boot and RPMB partitions of specified device\n"
1079 	"mmc partconf dev [boot_ack boot_partition partition_access]\n"
1080 	" - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
1081 	"mmc rst-function dev value\n"
1082 	" - Change the RST_n_FUNCTION field of the specified device\n"
1083 	"   WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
1084 #endif
1085 #ifdef CONFIG_OPTEE_CLIENT
1086 	"mmc testsecurestorage - test CA call static TA to store data in security\n"
1087 	"mmc testefuse - test CA call static TA,and TA read or write efuse\n"
1088 #endif
1089 #ifdef CONFIG_SUPPORT_EMMC_RPMB
1090 	"mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
1091 	"mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
1092 	"mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
1093 	"mmc rpmb counter - read the value of the write counter\n"
1094 #endif
1095 	"mmc setdsr <value> - set DSR register value\n"
1096 #ifdef CONFIG_CMD_BKOPS_ENABLE
1097 	"mmc bkops-enable <dev> - enable background operations handshake on device\n"
1098 	"   WARNING: This is a write-once setting.\n"
1099 #endif
1100 	);
1101 
1102 /* Old command kept for compatibility. Same as 'mmc info' */
1103 U_BOOT_CMD(
1104 	mmcinfo, 1, 0, do_mmcinfo,
1105 	"display MMC info",
1106 	"- display info of the current MMC device"
1107 );
1108 
1109