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