xref: /rk3399_rockchip-uboot/cmd/mmc.c (revision d1e7b9e1d9259b6a26a1dc310b724936b8d5e55e)
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 
248 	if (init_rpmb() != 0)
249 		return -1;
250 
251 	struct mmc *mmc = find_mmc_device(curr_device);
252 	if (!mmc)
253 		return -1;
254 
255 	ret = read_counter(mmc, requestpackets);
256 
257 	if (finish_rpmb() != 0)
258 		return -1;
259 
260 	return ret;
261 }
262 
263 int do_programkey(struct s_rpmb *requestpackets)
264 {
265 	int ret;
266 	struct mmc *mmc = find_mmc_device(curr_device);
267 	if (!mmc)
268 		return -1;
269 
270 	if (init_rpmb() != 0)
271 		return -1;
272 
273 	ret = program_key(mmc, requestpackets);
274 
275 	if (finish_rpmb() != 0)
276 		return -1;
277 
278 	return ret;
279 }
280 
281 int do_authenticatedread(struct s_rpmb *requestpackets, uint16_t block_count)
282 {
283 	int ret;
284 	struct mmc *mmc = find_mmc_device(curr_device);
285 	if (!mmc)
286 		return -1;
287 
288 	if (init_rpmb() != 0)
289 		return -1;
290 
291 	ret = authenticated_read(mmc, requestpackets, block_count);
292 
293 	if (finish_rpmb() != 0)
294 		return -1;
295 
296 	return ret;
297 }
298 
299 int do_authenticatedwrite(struct s_rpmb *requestpackets)
300 {
301 	int ret;
302 	struct mmc *mmc = find_mmc_device(curr_device);
303 	if (!mmc)
304 		return -1;
305 
306 	if (init_rpmb() != 0)
307 		return -1;
308 
309 	ret = authenticated_write(mmc, requestpackets);
310 
311 	if (finish_rpmb() != 0)
312 		return -1;
313 
314 	return ret;
315 }
316 
317 struct mmc *do_returnmmc(void)
318 {
319 	struct mmc *mmc;
320 
321 	if (init_rpmb() != 0)
322 		return NULL;
323 
324 	mmc = find_mmc_device(curr_device);
325 
326 	if (finish_rpmb() != 0)
327 		return NULL;
328 
329 	return mmc;
330 }
331 
332 static int confirm_key_prog(void)
333 {
334 	puts("Warning: Programming authentication key can be done only once !\n"
335 	     "         Use this command only if you are sure of what you are doing,\n"
336 	     "Really perform the key programming? <y/N> ");
337 	if (confirm_yesno())
338 		return 1;
339 
340 	puts("Authentication key programming aborted\n");
341 	return 0;
342 }
343 static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag,
344 			  int argc, char * const argv[])
345 {
346 	void *key_addr;
347 	struct mmc *mmc = find_mmc_device(curr_device);
348 
349 	if (argc != 2)
350 		return CMD_RET_USAGE;
351 
352 	key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
353 	if (!confirm_key_prog())
354 		return CMD_RET_FAILURE;
355 	if (mmc_rpmb_set_key(mmc, key_addr)) {
356 		printf("ERROR - Key already programmed ?\n");
357 		return CMD_RET_FAILURE;
358 	}
359 	return CMD_RET_SUCCESS;
360 }
361 static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag,
362 			   int argc, char * const argv[])
363 {
364 	u16 blk, cnt;
365 	void *addr;
366 	int n;
367 	void *key_addr = NULL;
368 	struct mmc *mmc = find_mmc_device(curr_device);
369 
370 	if (argc < 4)
371 		return CMD_RET_USAGE;
372 
373 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
374 	blk = simple_strtoul(argv[2], NULL, 16);
375 	cnt = simple_strtoul(argv[3], NULL, 16);
376 
377 	if (argc == 5)
378 		key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
379 
380 	printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
381 	       curr_device, blk, cnt);
382 	n =  mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
383 
384 	printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
385 	if (n != cnt)
386 		return CMD_RET_FAILURE;
387 	return CMD_RET_SUCCESS;
388 }
389 static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag,
390 			    int argc, char * const argv[])
391 {
392 	u16 blk, cnt;
393 	void *addr;
394 	int n;
395 	void *key_addr;
396 	struct mmc *mmc = find_mmc_device(curr_device);
397 
398 	if (argc != 5)
399 		return CMD_RET_USAGE;
400 
401 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
402 	blk = simple_strtoul(argv[2], NULL, 16);
403 	cnt = simple_strtoul(argv[3], NULL, 16);
404 	key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
405 
406 	printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
407 	       curr_device, blk, cnt);
408 	n =  mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
409 
410 	printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
411 	if (n != cnt)
412 		return CMD_RET_FAILURE;
413 	return CMD_RET_SUCCESS;
414 }
415 static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag,
416 			      int argc, char * const argv[])
417 {
418 	unsigned long counter;
419 	struct mmc *mmc = find_mmc_device(curr_device);
420 
421 	if (mmc_rpmb_get_counter(mmc, &counter))
422 		return CMD_RET_FAILURE;
423 	printf("RPMB Write counter= %lx\n", counter);
424 	return CMD_RET_SUCCESS;
425 }
426 
427 static cmd_tbl_t cmd_rpmb[] = {
428 	U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
429 	U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
430 	U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
431 	U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
432 };
433 
434 static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
435 		      int argc, char * const argv[])
436 {
437 	cmd_tbl_t *cp;
438 	struct mmc *mmc;
439 	char original_part;
440 	int ret;
441 
442 	cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
443 
444 	/* Drop the rpmb subcommand */
445 	argc--;
446 	argv++;
447 
448 	if (cp == NULL || argc > cp->maxargs)
449 		return CMD_RET_USAGE;
450 	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
451 		return CMD_RET_SUCCESS;
452 
453 	mmc = init_mmc_device(curr_device, false);
454 	if (!mmc)
455 		return CMD_RET_FAILURE;
456 
457 	if (!(mmc->version & MMC_VERSION_MMC)) {
458 		printf("It is not a EMMC device\n");
459 		return CMD_RET_FAILURE;
460 	}
461 	if (mmc->version < MMC_VERSION_4_41) {
462 		printf("RPMB not supported before version 4.41\n");
463 		return CMD_RET_FAILURE;
464 	}
465 	/* Switch to the RPMB partition */
466 #ifndef CONFIG_BLK
467 	original_part = mmc->block_dev.hwpart;
468 #else
469 	original_part = mmc_get_blk_desc(mmc)->hwpart;
470 #endif
471 	if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) !=
472 	    0)
473 		return CMD_RET_FAILURE;
474 	ret = cp->cmd(cmdtp, flag, argc, argv);
475 
476 	/* Return to original partition */
477 	if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) !=
478 	    0)
479 		return CMD_RET_FAILURE;
480 	return ret;
481 }
482 #endif
483 
484 static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
485 		       int argc, char * const argv[])
486 {
487 	struct mmc *mmc;
488 	u32 blk, cnt, n;
489 	void *addr;
490 
491 	if (argc != 4)
492 		return CMD_RET_USAGE;
493 
494 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
495 	blk = simple_strtoul(argv[2], NULL, 16);
496 	cnt = simple_strtoul(argv[3], NULL, 16);
497 
498 	mmc = init_mmc_device(curr_device, false);
499 	if (!mmc)
500 		return CMD_RET_FAILURE;
501 
502 	printf("\nMMC read: dev # %d, block # %d, count %d ... ",
503 	       curr_device, blk, cnt);
504 
505 	n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
506 	printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
507 
508 	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
509 }
510 static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
511 			int argc, char * const argv[])
512 {
513 	struct mmc *mmc;
514 	u32 blk, cnt, n;
515 	void *addr;
516 
517 	if (argc != 4)
518 		return CMD_RET_USAGE;
519 
520 	addr = (void *)simple_strtoul(argv[1], NULL, 16);
521 	blk = simple_strtoul(argv[2], NULL, 16);
522 	cnt = simple_strtoul(argv[3], NULL, 16);
523 
524 	mmc = init_mmc_device(curr_device, false);
525 	if (!mmc)
526 		return CMD_RET_FAILURE;
527 
528 	printf("\nMMC write: dev # %d, block # %d, count %d ... ",
529 	       curr_device, blk, cnt);
530 
531 	if (mmc_getwp(mmc) == 1) {
532 		printf("Error: card is write protected!\n");
533 		return CMD_RET_FAILURE;
534 	}
535 	n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
536 	printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
537 
538 	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
539 }
540 static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
541 			int argc, char * const argv[])
542 {
543 	struct mmc *mmc;
544 	u32 blk, cnt, n;
545 
546 	if (argc != 3)
547 		return CMD_RET_USAGE;
548 
549 	blk = simple_strtoul(argv[1], NULL, 16);
550 	cnt = simple_strtoul(argv[2], NULL, 16);
551 
552 	mmc = init_mmc_device(curr_device, false);
553 	if (!mmc)
554 		return CMD_RET_FAILURE;
555 
556 	printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
557 	       curr_device, blk, cnt);
558 
559 	if (mmc_getwp(mmc) == 1) {
560 		printf("Error: card is write protected!\n");
561 		return CMD_RET_FAILURE;
562 	}
563 	n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
564 	printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
565 
566 	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
567 }
568 static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
569 			 int argc, char * const argv[])
570 {
571 	struct mmc *mmc;
572 
573 	mmc = init_mmc_device(curr_device, true);
574 	if (!mmc)
575 		return CMD_RET_FAILURE;
576 
577 	return CMD_RET_SUCCESS;
578 }
579 static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
580 		       int argc, char * const argv[])
581 {
582 	struct blk_desc *mmc_dev;
583 	struct mmc *mmc;
584 
585 	mmc = init_mmc_device(curr_device, false);
586 	if (!mmc)
587 		return CMD_RET_FAILURE;
588 
589 	mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device);
590 	if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
591 		part_print(mmc_dev);
592 		return CMD_RET_SUCCESS;
593 	}
594 
595 	puts("get mmc type error!\n");
596 	return CMD_RET_FAILURE;
597 }
598 static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
599 		      int argc, char * const argv[])
600 {
601 	int dev, part = 0, ret;
602 	struct mmc *mmc;
603 
604 	/* If not boot from mmc devices, init mmc devices first. */
605 	ret = mmc_initialize(gd->bd);
606 	if (ret) {
607 		printf("Could not initialize mmc. error: %d\n", ret);
608 		return ret;
609 	}
610 
611 	if (argc == 1) {
612 		dev = curr_device;
613 	} else if (argc == 2) {
614 		dev = simple_strtoul(argv[1], NULL, 10);
615 	} else if (argc == 3) {
616 		dev = (int)simple_strtoul(argv[1], NULL, 10);
617 		part = (int)simple_strtoul(argv[2], NULL, 10);
618 		if (part > PART_ACCESS_MASK) {
619 			printf("#part_num shouldn't be larger than %d\n",
620 			       PART_ACCESS_MASK);
621 			return CMD_RET_FAILURE;
622 		}
623 	} else {
624 		return CMD_RET_USAGE;
625 	}
626 
627 	mmc = init_mmc_device(dev, false);
628 	if (!mmc)
629 		return CMD_RET_FAILURE;
630 
631 	ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
632 	printf("switch to partitions #%d, %s\n",
633 	       part, (!ret) ? "OK" : "ERROR");
634 	if (ret)
635 		return 1;
636 
637 	curr_device = dev;
638 	if (mmc->part_config == MMCPART_NOAVAILABLE)
639 		printf("mmc%d is current device\n", curr_device);
640 	else
641 		printf("mmc%d(part %d) is current device\n",
642 		       curr_device, mmc_get_blk_desc(mmc)->hwpart);
643 
644 	return CMD_RET_SUCCESS;
645 }
646 static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
647 		       int argc, char * const argv[])
648 {
649 	print_mmc_devices('\n');
650 	do_mmc_rescan(cmdtp, flag, argc, argv);
651 	return CMD_RET_SUCCESS;
652 }
653 
654 static int parse_hwpart_user(struct mmc_hwpart_conf *pconf,
655 			     int argc, char * const argv[])
656 {
657 	int i = 0;
658 
659 	memset(&pconf->user, 0, sizeof(pconf->user));
660 
661 	while (i < argc) {
662 		if (!strcmp(argv[i], "enh")) {
663 			if (i + 2 >= argc)
664 				return -1;
665 			pconf->user.enh_start =
666 				simple_strtoul(argv[i+1], NULL, 10);
667 			pconf->user.enh_size =
668 				simple_strtoul(argv[i+2], NULL, 10);
669 			i += 3;
670 		} else if (!strcmp(argv[i], "wrrel")) {
671 			if (i + 1 >= argc)
672 				return -1;
673 			pconf->user.wr_rel_change = 1;
674 			if (!strcmp(argv[i+1], "on"))
675 				pconf->user.wr_rel_set = 1;
676 			else if (!strcmp(argv[i+1], "off"))
677 				pconf->user.wr_rel_set = 0;
678 			else
679 				return -1;
680 			i += 2;
681 		} else {
682 			break;
683 		}
684 	}
685 	return i;
686 }
687 
688 static int parse_hwpart_gp(struct mmc_hwpart_conf *pconf, int pidx,
689 			   int argc, char * const argv[])
690 {
691 	int i;
692 
693 	memset(&pconf->gp_part[pidx], 0, sizeof(pconf->gp_part[pidx]));
694 
695 	if (1 >= argc)
696 		return -1;
697 	pconf->gp_part[pidx].size = simple_strtoul(argv[0], NULL, 10);
698 
699 	i = 1;
700 	while (i < argc) {
701 		if (!strcmp(argv[i], "enh")) {
702 			pconf->gp_part[pidx].enhanced = 1;
703 			i += 1;
704 		} else if (!strcmp(argv[i], "wrrel")) {
705 			if (i + 1 >= argc)
706 				return -1;
707 			pconf->gp_part[pidx].wr_rel_change = 1;
708 			if (!strcmp(argv[i+1], "on"))
709 				pconf->gp_part[pidx].wr_rel_set = 1;
710 			else if (!strcmp(argv[i+1], "off"))
711 				pconf->gp_part[pidx].wr_rel_set = 0;
712 			else
713 				return -1;
714 			i += 2;
715 		} else {
716 			break;
717 		}
718 	}
719 	return i;
720 }
721 
722 static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag,
723 			      int argc, char * const argv[])
724 {
725 	struct mmc *mmc;
726 	struct mmc_hwpart_conf pconf = { };
727 	enum mmc_hwpart_conf_mode mode = MMC_HWPART_CONF_CHECK;
728 	int i, r, pidx;
729 
730 	mmc = init_mmc_device(curr_device, false);
731 	if (!mmc)
732 		return CMD_RET_FAILURE;
733 
734 	if (argc < 1)
735 		return CMD_RET_USAGE;
736 	i = 1;
737 	while (i < argc) {
738 		if (!strcmp(argv[i], "user")) {
739 			i++;
740 			r = parse_hwpart_user(&pconf, argc-i, &argv[i]);
741 			if (r < 0)
742 				return CMD_RET_USAGE;
743 			i += r;
744 		} else if (!strncmp(argv[i], "gp", 2) &&
745 			   strlen(argv[i]) == 3 &&
746 			   argv[i][2] >= '1' && argv[i][2] <= '4') {
747 			pidx = argv[i][2] - '1';
748 			i++;
749 			r = parse_hwpart_gp(&pconf, pidx, argc-i, &argv[i]);
750 			if (r < 0)
751 				return CMD_RET_USAGE;
752 			i += r;
753 		} else if (!strcmp(argv[i], "check")) {
754 			mode = MMC_HWPART_CONF_CHECK;
755 			i++;
756 		} else if (!strcmp(argv[i], "set")) {
757 			mode = MMC_HWPART_CONF_SET;
758 			i++;
759 		} else if (!strcmp(argv[i], "complete")) {
760 			mode = MMC_HWPART_CONF_COMPLETE;
761 			i++;
762 		} else {
763 			return CMD_RET_USAGE;
764 		}
765 	}
766 
767 	puts("Partition configuration:\n");
768 	if (pconf.user.enh_size) {
769 		puts("\tUser Enhanced Start: ");
770 		print_size(((u64)pconf.user.enh_start) << 9, "\n");
771 		puts("\tUser Enhanced Size: ");
772 		print_size(((u64)pconf.user.enh_size) << 9, "\n");
773 	} else {
774 		puts("\tNo enhanced user data area\n");
775 	}
776 	if (pconf.user.wr_rel_change)
777 		printf("\tUser partition write reliability: %s\n",
778 		       pconf.user.wr_rel_set ? "on" : "off");
779 	for (pidx = 0; pidx < 4; pidx++) {
780 		if (pconf.gp_part[pidx].size) {
781 			printf("\tGP%i Capacity: ", pidx+1);
782 			print_size(((u64)pconf.gp_part[pidx].size) << 9,
783 				   pconf.gp_part[pidx].enhanced ?
784 				   " ENH\n" : "\n");
785 		} else {
786 			printf("\tNo GP%i partition\n", pidx+1);
787 		}
788 		if (pconf.gp_part[pidx].wr_rel_change)
789 			printf("\tGP%i write reliability: %s\n", pidx+1,
790 			       pconf.gp_part[pidx].wr_rel_set ? "on" : "off");
791 	}
792 
793 	if (!mmc_hwpart_config(mmc, &pconf, mode)) {
794 		if (mode == MMC_HWPART_CONF_COMPLETE)
795 			puts("Partitioning successful, "
796 			     "power-cycle to make effective\n");
797 		return CMD_RET_SUCCESS;
798 	} else {
799 		puts("Failed!\n");
800 		return CMD_RET_FAILURE;
801 	}
802 }
803 
804 #ifdef CONFIG_SUPPORT_EMMC_BOOT
805 static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
806 			  int argc, char * const argv[])
807 {
808 	int dev;
809 	struct mmc *mmc;
810 	u8 width, reset, mode;
811 
812 	if (argc != 5)
813 		return CMD_RET_USAGE;
814 	dev = simple_strtoul(argv[1], NULL, 10);
815 	width = simple_strtoul(argv[2], NULL, 10);
816 	reset = simple_strtoul(argv[3], NULL, 10);
817 	mode = simple_strtoul(argv[4], NULL, 10);
818 
819 	mmc = init_mmc_device(dev, false);
820 	if (!mmc)
821 		return CMD_RET_FAILURE;
822 
823 	if (IS_SD(mmc)) {
824 		puts("BOOT_BUS_WIDTH only exists on eMMC\n");
825 		return CMD_RET_FAILURE;
826 	}
827 
828 	/* acknowledge to be sent during boot operation */
829 	return mmc_set_boot_bus_width(mmc, width, reset, mode);
830 }
831 static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
832 			      int argc, char * const argv[])
833 {
834 	int dev;
835 	struct mmc *mmc;
836 	u32 bootsize, rpmbsize;
837 
838 	if (argc != 4)
839 		return CMD_RET_USAGE;
840 	dev = simple_strtoul(argv[1], NULL, 10);
841 	bootsize = simple_strtoul(argv[2], NULL, 10);
842 	rpmbsize = simple_strtoul(argv[3], NULL, 10);
843 
844 	mmc = init_mmc_device(dev, false);
845 	if (!mmc)
846 		return CMD_RET_FAILURE;
847 
848 	if (IS_SD(mmc)) {
849 		printf("It is not a EMMC device\n");
850 		return CMD_RET_FAILURE;
851 	}
852 
853 	if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
854 		printf("EMMC boot partition Size change Failed.\n");
855 		return CMD_RET_FAILURE;
856 	}
857 
858 	printf("EMMC boot partition Size %d MB\n", bootsize);
859 	printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
860 	return CMD_RET_SUCCESS;
861 }
862 
863 static int mmc_partconf_print(struct mmc *mmc)
864 {
865 	u8 ack, access, part;
866 
867 	if (mmc->part_config == MMCPART_NOAVAILABLE) {
868 		printf("No part_config info for ver. 0x%x\n", mmc->version);
869 		return CMD_RET_FAILURE;
870 	}
871 
872 	access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config);
873 	ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config);
874 	part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
875 
876 	printf("EXT_CSD[179], PARTITION_CONFIG:\n"
877 		"BOOT_ACK: 0x%x\n"
878 		"BOOT_PARTITION_ENABLE: 0x%x\n"
879 		"PARTITION_ACCESS: 0x%x\n", ack, part, access);
880 
881 	return CMD_RET_SUCCESS;
882 }
883 
884 static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
885 			   int argc, char * const argv[])
886 {
887 	int dev;
888 	struct mmc *mmc;
889 	u8 ack, part_num, access;
890 
891 	if (argc != 2 && argc != 5)
892 		return CMD_RET_USAGE;
893 
894 	dev = simple_strtoul(argv[1], NULL, 10);
895 
896 	mmc = init_mmc_device(dev, false);
897 	if (!mmc)
898 		return CMD_RET_FAILURE;
899 
900 	if (IS_SD(mmc)) {
901 		puts("PARTITION_CONFIG only exists on eMMC\n");
902 		return CMD_RET_FAILURE;
903 	}
904 
905 	if (argc == 2)
906 		return mmc_partconf_print(mmc);
907 
908 	ack = simple_strtoul(argv[2], NULL, 10);
909 	part_num = simple_strtoul(argv[3], NULL, 10);
910 	access = simple_strtoul(argv[4], NULL, 10);
911 
912 	/* acknowledge to be sent during boot operation */
913 	return mmc_set_part_conf(mmc, ack, part_num, access);
914 }
915 static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag,
916 			   int argc, char * const argv[])
917 {
918 	int dev;
919 	struct mmc *mmc;
920 	u8 enable;
921 
922 	/*
923 	 * Set the RST_n_ENABLE bit of RST_n_FUNCTION
924 	 * The only valid values are 0x0, 0x1 and 0x2 and writing
925 	 * a value of 0x1 or 0x2 sets the value permanently.
926 	 */
927 	if (argc != 3)
928 		return CMD_RET_USAGE;
929 
930 	dev = simple_strtoul(argv[1], NULL, 10);
931 	enable = simple_strtoul(argv[2], NULL, 10);
932 
933 	if (enable > 2) {
934 		puts("Invalid RST_n_ENABLE value\n");
935 		return CMD_RET_USAGE;
936 	}
937 
938 	mmc = init_mmc_device(dev, false);
939 	if (!mmc)
940 		return CMD_RET_FAILURE;
941 
942 	if (IS_SD(mmc)) {
943 		puts("RST_n_FUNCTION only exists on eMMC\n");
944 		return CMD_RET_FAILURE;
945 	}
946 
947 	return mmc_set_rst_n_function(mmc, enable);
948 }
949 #endif
950 static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag,
951 			 int argc, char * const argv[])
952 {
953 	struct mmc *mmc;
954 	u32 val;
955 	int ret;
956 
957 	if (argc != 2)
958 		return CMD_RET_USAGE;
959 	val = simple_strtoul(argv[1], NULL, 16);
960 
961 	mmc = find_mmc_device(curr_device);
962 	if (!mmc) {
963 		printf("no mmc device at slot %x\n", curr_device);
964 		return CMD_RET_FAILURE;
965 	}
966 	ret = mmc_set_dsr(mmc, val);
967 	printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
968 	if (!ret) {
969 		mmc->has_init = 0;
970 		if (mmc_init(mmc))
971 			return CMD_RET_FAILURE;
972 		else
973 			return CMD_RET_SUCCESS;
974 	}
975 	return ret;
976 }
977 
978 #ifdef CONFIG_CMD_BKOPS_ENABLE
979 static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag,
980 				   int argc, char * const argv[])
981 {
982 	int dev;
983 	struct mmc *mmc;
984 
985 	if (argc != 2)
986 		return CMD_RET_USAGE;
987 
988 	dev = simple_strtoul(argv[1], NULL, 10);
989 
990 	mmc = init_mmc_device(dev, false);
991 	if (!mmc)
992 		return CMD_RET_FAILURE;
993 
994 	if (IS_SD(mmc)) {
995 		puts("BKOPS_EN only exists on eMMC\n");
996 		return CMD_RET_FAILURE;
997 	}
998 
999 	return mmc_set_bkops_enable(mmc);
1000 }
1001 #endif
1002 
1003 static cmd_tbl_t cmd_mmc[] = {
1004 	U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
1005 	U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
1006 	U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
1007 	U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
1008 	U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
1009 	U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
1010 	U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
1011 	U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
1012 	U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""),
1013 #ifdef CONFIG_SUPPORT_EMMC_BOOT
1014 	U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
1015 	U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),
1016 	U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
1017 	U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
1018 #endif
1019 #ifdef CONFIG_OPTEE_CLIENT
1020 	U_BOOT_CMD_MKENT(testsecurestorage, 1, 0, do_mmc_test_secure_storage, "", ""),
1021 	U_BOOT_CMD_MKENT(testefuse, 1, 0, do_mmc_testefuse, "", ""),
1022 #endif
1023 #ifdef CONFIG_SUPPORT_EMMC_RPMB
1024 	U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
1025 #endif
1026 	U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
1027 #ifdef CONFIG_CMD_BKOPS_ENABLE
1028 	U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""),
1029 #endif
1030 };
1031 
1032 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1033 {
1034 	cmd_tbl_t *cp;
1035 
1036 	cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
1037 
1038 	/* Drop the mmc command */
1039 	argc--;
1040 	argv++;
1041 
1042 	if (cp == NULL || argc > cp->maxargs)
1043 		return CMD_RET_USAGE;
1044 	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
1045 		return CMD_RET_SUCCESS;
1046 
1047 	if (curr_device < 0) {
1048 		if (get_mmc_num() > 0) {
1049 			curr_device = 0;
1050 		} else {
1051 			puts("No MMC device available\n");
1052 			return CMD_RET_FAILURE;
1053 		}
1054 	}
1055 	return cp->cmd(cmdtp, flag, argc, argv);
1056 }
1057 
1058 U_BOOT_CMD(
1059 	mmc, 29, 1, do_mmcops,
1060 	"MMC sub system",
1061 	"info - display info of the current MMC device\n"
1062 	"mmc read addr blk# cnt\n"
1063 	"mmc write addr blk# cnt\n"
1064 	"mmc erase blk# cnt\n"
1065 	"mmc rescan\n"
1066 	"mmc part - lists available partition on current mmc device\n"
1067 	"mmc dev [dev] [part] - show or set current mmc device [partition]\n"
1068 	"mmc list - lists available devices\n"
1069 	"mmc hwpartition [args...] - does hardware partitioning\n"
1070 	"  arguments (sizes in 512-byte blocks):\n"
1071 	"    [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n"
1072 	"    [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n"
1073 	"    [check|set|complete] - mode, complete set partitioning completed\n"
1074 	"  WARNING: Partitioning is a write-once setting once it is set to complete.\n"
1075 	"  Power cycling is required to initialize partitions after set to complete.\n"
1076 #ifdef CONFIG_SUPPORT_EMMC_BOOT
1077 	"mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
1078 	" - Set the BOOT_BUS_WIDTH field of the specified device\n"
1079 	"mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
1080 	" - Change sizes of boot and RPMB partitions of specified device\n"
1081 	"mmc partconf dev [boot_ack boot_partition partition_access]\n"
1082 	" - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
1083 	"mmc rst-function dev value\n"
1084 	" - Change the RST_n_FUNCTION field of the specified device\n"
1085 	"   WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
1086 #endif
1087 #ifdef CONFIG_OPTEE_CLIENT
1088 	"mmc testsecurestorage - test CA call static TA to store data in security\n"
1089 	"mmc testefuse - test CA call static TA,and TA read or write efuse\n"
1090 #endif
1091 #ifdef CONFIG_SUPPORT_EMMC_RPMB
1092 	"mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
1093 	"mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
1094 	"mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
1095 	"mmc rpmb counter - read the value of the write counter\n"
1096 #endif
1097 	"mmc setdsr <value> - set DSR register value\n"
1098 #ifdef CONFIG_CMD_BKOPS_ENABLE
1099 	"mmc bkops-enable <dev> - enable background operations handshake on device\n"
1100 	"   WARNING: This is a write-once setting.\n"
1101 #endif
1102 	);
1103 
1104 /* Old command kept for compatibility. Same as 'mmc info' */
1105 U_BOOT_CMD(
1106 	mmcinfo, 1, 0, do_mmcinfo,
1107 	"display MMC info",
1108 	"- display info of the current MMC device"
1109 );
1110 
1111