]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_mmc.c
mmc: show hardware partition sizes in mmcinfo output
[karo-tx-uboot.git] / common / 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 <mmc.h>
11
12 static int curr_device = -1;
13 #ifndef CONFIG_GENERIC_MMC
14 int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
15 {
16         int dev;
17
18         if (argc < 2)
19                 return CMD_RET_USAGE;
20
21         if (strcmp(argv[1], "init") == 0) {
22                 if (argc == 2) {
23                         if (curr_device < 0)
24                                 dev = 1;
25                         else
26                                 dev = curr_device;
27                 } else if (argc == 3) {
28                         dev = (int)simple_strtoul(argv[2], NULL, 10);
29                 } else {
30                         return CMD_RET_USAGE;
31                 }
32
33                 if (mmc_legacy_init(dev) != 0) {
34                         puts("No MMC card found\n");
35                         return 1;
36                 }
37
38                 curr_device = dev;
39                 printf("mmc%d is available\n", curr_device);
40         } else if (strcmp(argv[1], "device") == 0) {
41                 if (argc == 2) {
42                         if (curr_device < 0) {
43                                 puts("No MMC device available\n");
44                                 return 1;
45                         }
46                 } else if (argc == 3) {
47                         dev = (int)simple_strtoul(argv[2], NULL, 10);
48
49 #ifdef CONFIG_SYS_MMC_SET_DEV
50                         if (mmc_set_dev(dev) != 0)
51                                 return 1;
52 #endif
53                         curr_device = dev;
54                 } else {
55                         return CMD_RET_USAGE;
56                 }
57
58                 printf("mmc%d is current device\n", curr_device);
59         } else {
60                 return CMD_RET_USAGE;
61         }
62
63         return 0;
64 }
65
66 U_BOOT_CMD(
67         mmc, 3, 1, do_mmc,
68         "MMC sub-system",
69         "init [dev] - init MMC sub system\n"
70         "mmc device [dev] - show or set current device"
71 );
72 #else /* !CONFIG_GENERIC_MMC */
73
74 static void print_mmcinfo(struct mmc *mmc)
75 {
76         int i;
77
78         printf("Device: %s\n", mmc->cfg->name);
79         printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
80         printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
81         printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
82                         (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
83                         (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
84
85         printf("Tran Speed: %d\n", mmc->tran_speed);
86         printf("Rd Block Len: %d\n", mmc->read_bl_len);
87
88         printf("%s version %d.%d\n", IS_SD(mmc) ? "SD" : "MMC",
89                         (mmc->version >> 8) & 0xf, mmc->version & 0xff);
90
91         printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
92         puts("Capacity: ");
93         print_size(mmc->capacity, "\n");
94
95         printf("Bus Width: %d-bit%s\n", mmc->bus_width,
96                         mmc->ddr_mode ? " DDR" : "");
97
98         if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4) {
99                 puts("User Capacity: ");
100                 print_size(mmc->capacity_user, "\n");
101                 puts("Boot Capacity: ");
102                 print_size(mmc->capacity_boot, "\n");
103                 puts("RPMB Capacity: ");
104                 print_size(mmc->capacity_rpmb, "\n");
105                 for (i = 0; i < ARRAY_SIZE(mmc->capacity_gp); i++) {
106                         if (mmc->capacity_gp[i]) {
107                                 printf("GP%i Capacity: ", i);
108                                 print_size(mmc->capacity_gp[i], "\n");
109                         }
110                 }
111         }
112 }
113 static struct mmc *init_mmc_device(int dev, bool force_init)
114 {
115         struct mmc *mmc;
116         mmc = find_mmc_device(dev);
117         if (!mmc) {
118                 printf("no mmc device at slot %x\n", dev);
119                 return NULL;
120         }
121         if (force_init)
122                 mmc->has_init = 0;
123         if (mmc_init(mmc))
124                 return NULL;
125         return mmc;
126 }
127 static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
128 {
129         struct mmc *mmc;
130
131         if (curr_device < 0) {
132                 if (get_mmc_num() > 0)
133                         curr_device = 0;
134                 else {
135                         puts("No MMC device available\n");
136                         return 1;
137                 }
138         }
139
140         mmc = init_mmc_device(curr_device, false);
141         if (!mmc)
142                 return CMD_RET_FAILURE;
143
144         print_mmcinfo(mmc);
145         return CMD_RET_SUCCESS;
146 }
147
148 #ifdef CONFIG_SUPPORT_EMMC_RPMB
149 static int confirm_key_prog(void)
150 {
151         puts("Warning: Programming authentication key can be done only once !\n"
152              "         Use this command only if you are sure of what you are doing,\n"
153              "Really perform the key programming? <y/N> ");
154         if (confirm_yesno())
155                 return 1;
156
157         puts("Authentication key programming aborted\n");
158         return 0;
159 }
160 static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag,
161                           int argc, char * const argv[])
162 {
163         void *key_addr;
164         struct mmc *mmc = find_mmc_device(curr_device);
165
166         if (argc != 2)
167                 return CMD_RET_USAGE;
168
169         key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
170         if (!confirm_key_prog())
171                 return CMD_RET_FAILURE;
172         if (mmc_rpmb_set_key(mmc, key_addr)) {
173                 printf("ERROR - Key already programmed ?\n");
174                 return CMD_RET_FAILURE;
175         }
176         return CMD_RET_SUCCESS;
177 }
178 static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag,
179                            int argc, char * const argv[])
180 {
181         u16 blk, cnt;
182         void *addr;
183         int n;
184         void *key_addr = NULL;
185         struct mmc *mmc = find_mmc_device(curr_device);
186
187         if (argc < 4)
188                 return CMD_RET_USAGE;
189
190         addr = (void *)simple_strtoul(argv[1], NULL, 16);
191         blk = simple_strtoul(argv[2], NULL, 16);
192         cnt = simple_strtoul(argv[3], NULL, 16);
193
194         if (argc == 5)
195                 key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
196
197         printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
198                curr_device, blk, cnt);
199         n =  mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
200
201         printf("%d RPMB blocks read: %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_write(cmd_tbl_t *cmdtp, int flag,
207                             int argc, char * const argv[])
208 {
209         u16 blk, cnt;
210         void *addr;
211         int n;
212         void *key_addr;
213         struct mmc *mmc = find_mmc_device(curr_device);
214
215         if (argc != 5)
216                 return CMD_RET_USAGE;
217
218         addr = (void *)simple_strtoul(argv[1], NULL, 16);
219         blk = simple_strtoul(argv[2], NULL, 16);
220         cnt = simple_strtoul(argv[3], NULL, 16);
221         key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
222
223         printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
224                curr_device, blk, cnt);
225         n =  mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
226
227         printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
228         if (n != cnt)
229                 return CMD_RET_FAILURE;
230         return CMD_RET_SUCCESS;
231 }
232 static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag,
233                               int argc, char * const argv[])
234 {
235         unsigned long counter;
236         struct mmc *mmc = find_mmc_device(curr_device);
237
238         if (mmc_rpmb_get_counter(mmc, &counter))
239                 return CMD_RET_FAILURE;
240         printf("RPMB Write counter= %lx\n", counter);
241         return CMD_RET_SUCCESS;
242 }
243
244 static cmd_tbl_t cmd_rpmb[] = {
245         U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
246         U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
247         U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
248         U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
249 };
250
251 static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
252                       int argc, char * const argv[])
253 {
254         cmd_tbl_t *cp;
255         struct mmc *mmc;
256         char original_part;
257         int ret;
258
259         cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
260
261         /* Drop the rpmb subcommand */
262         argc--;
263         argv++;
264
265         if (cp == NULL || argc > cp->maxargs)
266                 return CMD_RET_USAGE;
267         if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
268                 return CMD_RET_SUCCESS;
269
270         mmc = init_mmc_device(curr_device, false);
271         if (!mmc)
272                 return CMD_RET_FAILURE;
273
274         if (!(mmc->version & MMC_VERSION_MMC)) {
275                 printf("It is not a EMMC device\n");
276                 return CMD_RET_FAILURE;
277         }
278         if (mmc->version < MMC_VERSION_4_41) {
279                 printf("RPMB not supported before version 4.41\n");
280                 return CMD_RET_FAILURE;
281         }
282         /* Switch to the RPMB partition */
283         original_part = mmc->part_num;
284         if (mmc->part_num != MMC_PART_RPMB) {
285                 if (mmc_switch_part(curr_device, MMC_PART_RPMB) != 0)
286                         return CMD_RET_FAILURE;
287                 mmc->part_num = MMC_PART_RPMB;
288         }
289         ret = cp->cmd(cmdtp, flag, argc, argv);
290
291         /* Return to original partition */
292         if (mmc->part_num != original_part) {
293                 if (mmc_switch_part(curr_device, original_part) != 0)
294                         return CMD_RET_FAILURE;
295                 mmc->part_num = original_part;
296         }
297         return ret;
298 }
299 #endif
300
301 static int do_mmc_read(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 read: dev # %d, block # %d, count %d ... ",
320                curr_device, blk, cnt);
321
322         n = mmc->block_dev.block_read(curr_device, blk, cnt, addr);
323         /* flush cache after read */
324         flush_cache((ulong)addr, cnt * 512); /* FIXME */
325         printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
326
327         return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
328 }
329 static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
330                         int argc, char * const argv[])
331 {
332         struct mmc *mmc;
333         u32 blk, cnt, n;
334         void *addr;
335
336         if (argc != 4)
337                 return CMD_RET_USAGE;
338
339         addr = (void *)simple_strtoul(argv[1], NULL, 16);
340         blk = simple_strtoul(argv[2], NULL, 16);
341         cnt = simple_strtoul(argv[3], NULL, 16);
342
343         mmc = init_mmc_device(curr_device, false);
344         if (!mmc)
345                 return CMD_RET_FAILURE;
346
347         printf("\nMMC write: 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 = mmc->block_dev.block_write(curr_device, blk, cnt, addr);
355         printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
356
357         return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
358 }
359 static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
360                         int argc, char * const argv[])
361 {
362         struct mmc *mmc;
363         u32 blk, cnt, n;
364
365         if (argc != 3)
366                 return CMD_RET_USAGE;
367
368         blk = simple_strtoul(argv[1], NULL, 16);
369         cnt = simple_strtoul(argv[2], NULL, 16);
370
371         mmc = init_mmc_device(curr_device, false);
372         if (!mmc)
373                 return CMD_RET_FAILURE;
374
375         printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
376                curr_device, blk, cnt);
377
378         if (mmc_getwp(mmc) == 1) {
379                 printf("Error: card is write protected!\n");
380                 return CMD_RET_FAILURE;
381         }
382         n = mmc->block_dev.block_erase(curr_device, blk, cnt);
383         printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
384
385         return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
386 }
387 static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
388                          int argc, char * const argv[])
389 {
390         struct mmc *mmc;
391
392         mmc = init_mmc_device(curr_device, true);
393         if (!mmc)
394                 return CMD_RET_FAILURE;
395
396         return CMD_RET_SUCCESS;
397 }
398 static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
399                        int argc, char * const argv[])
400 {
401         block_dev_desc_t *mmc_dev;
402         struct mmc *mmc;
403
404         mmc = init_mmc_device(curr_device, false);
405         if (!mmc)
406                 return CMD_RET_FAILURE;
407
408         mmc_dev = mmc_get_dev(curr_device);
409         if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
410                 print_part(mmc_dev);
411                 return CMD_RET_SUCCESS;
412         }
413
414         puts("get mmc type error!\n");
415         return CMD_RET_FAILURE;
416 }
417 static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
418                       int argc, char * const argv[])
419 {
420         int dev, part = 0, ret;
421         struct mmc *mmc;
422
423         if (argc == 1) {
424                 dev = curr_device;
425         } else if (argc == 2) {
426                 dev = simple_strtoul(argv[1], NULL, 10);
427         } else if (argc == 3) {
428                 dev = (int)simple_strtoul(argv[1], NULL, 10);
429                 part = (int)simple_strtoul(argv[2], NULL, 10);
430                 if (part > PART_ACCESS_MASK) {
431                         printf("#part_num shouldn't be larger than %d\n",
432                                PART_ACCESS_MASK);
433                         return CMD_RET_FAILURE;
434                 }
435         } else {
436                 return CMD_RET_USAGE;
437         }
438
439         mmc = init_mmc_device(dev, true);
440         if (!mmc)
441                 return CMD_RET_FAILURE;
442
443         ret = mmc_select_hwpart(dev, part);
444         printf("switch to partitions #%d, %s\n",
445                part, (!ret) ? "OK" : "ERROR");
446         if (ret)
447                 return 1;
448
449         curr_device = dev;
450         if (mmc->part_config == MMCPART_NOAVAILABLE)
451                 printf("mmc%d is current device\n", curr_device);
452         else
453                 printf("mmc%d(part %d) is current device\n",
454                        curr_device, mmc->part_num);
455
456         return CMD_RET_SUCCESS;
457 }
458 static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
459                        int argc, char * const argv[])
460 {
461         print_mmc_devices('\n');
462         return CMD_RET_SUCCESS;
463 }
464 #ifdef CONFIG_SUPPORT_EMMC_BOOT
465 static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
466                           int argc, char * const argv[])
467 {
468         int dev;
469         struct mmc *mmc;
470         u8 width, reset, mode;
471
472         if (argc != 5)
473                 return CMD_RET_USAGE;
474         dev = simple_strtoul(argv[1], NULL, 10);
475         width = simple_strtoul(argv[2], NULL, 10);
476         reset = simple_strtoul(argv[3], NULL, 10);
477         mode = simple_strtoul(argv[4], NULL, 10);
478
479         mmc = init_mmc_device(dev, false);
480         if (!mmc)
481                 return CMD_RET_FAILURE;
482
483         if (IS_SD(mmc)) {
484                 puts("BOOT_BUS_WIDTH only exists on eMMC\n");
485                 return CMD_RET_FAILURE;
486         }
487
488         /* acknowledge to be sent during boot operation */
489         return mmc_set_boot_bus_width(mmc, width, reset, mode);
490 }
491 static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
492                               int argc, char * const argv[])
493 {
494         int dev;
495         struct mmc *mmc;
496         u32 bootsize, rpmbsize;
497
498         if (argc != 4)
499                 return CMD_RET_USAGE;
500         dev = simple_strtoul(argv[1], NULL, 10);
501         bootsize = simple_strtoul(argv[2], NULL, 10);
502         rpmbsize = simple_strtoul(argv[3], NULL, 10);
503
504         mmc = init_mmc_device(dev, false);
505         if (!mmc)
506                 return CMD_RET_FAILURE;
507
508         if (IS_SD(mmc)) {
509                 printf("It is not a EMMC device\n");
510                 return CMD_RET_FAILURE;
511         }
512
513         if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
514                 printf("EMMC boot partition Size change Failed.\n");
515                 return CMD_RET_FAILURE;
516         }
517
518         printf("EMMC boot partition Size %d MB\n", bootsize);
519         printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
520         return CMD_RET_SUCCESS;
521 }
522 static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
523                            int argc, char * const argv[])
524 {
525         int dev;
526         struct mmc *mmc;
527         u8 ack, part_num, access;
528
529         if (argc != 5)
530                 return CMD_RET_USAGE;
531
532         dev = simple_strtoul(argv[1], NULL, 10);
533         ack = simple_strtoul(argv[2], NULL, 10);
534         part_num = simple_strtoul(argv[3], NULL, 10);
535         access = simple_strtoul(argv[4], NULL, 10);
536
537         mmc = init_mmc_device(dev, false);
538         if (!mmc)
539                 return CMD_RET_FAILURE;
540
541         if (IS_SD(mmc)) {
542                 puts("PARTITION_CONFIG only exists on eMMC\n");
543                 return CMD_RET_FAILURE;
544         }
545
546         /* acknowledge to be sent during boot operation */
547         return mmc_set_part_conf(mmc, ack, part_num, access);
548 }
549 static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag,
550                            int argc, char * const argv[])
551 {
552         int dev;
553         struct mmc *mmc;
554         u8 enable;
555
556         /*
557          * Set the RST_n_ENABLE bit of RST_n_FUNCTION
558          * The only valid values are 0x0, 0x1 and 0x2 and writing
559          * a value of 0x1 or 0x2 sets the value permanently.
560          */
561         if (argc != 3)
562                 return CMD_RET_USAGE;
563
564         dev = simple_strtoul(argv[1], NULL, 10);
565         enable = simple_strtoul(argv[2], NULL, 10);
566
567         if (enable > 2 || enable < 0) {
568                 puts("Invalid RST_n_ENABLE value\n");
569                 return CMD_RET_USAGE;
570         }
571
572         mmc = init_mmc_device(dev, false);
573         if (!mmc)
574                 return CMD_RET_FAILURE;
575
576         if (IS_SD(mmc)) {
577                 puts("RST_n_FUNCTION only exists on eMMC\n");
578                 return CMD_RET_FAILURE;
579         }
580
581         return mmc_set_rst_n_function(mmc, enable);
582 }
583 #endif
584 static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag,
585                          int argc, char * const argv[])
586 {
587         struct mmc *mmc;
588         u32 val;
589         int ret;
590
591         if (argc != 2)
592                 return CMD_RET_USAGE;
593         val = simple_strtoul(argv[2], NULL, 16);
594
595         mmc = find_mmc_device(curr_device);
596         if (!mmc) {
597                 printf("no mmc device at slot %x\n", curr_device);
598                 return CMD_RET_FAILURE;
599         }
600         ret = mmc_set_dsr(mmc, val);
601         printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
602         if (!ret) {
603                 mmc->has_init = 0;
604                 if (mmc_init(mmc))
605                         return CMD_RET_FAILURE;
606                 else
607                         return CMD_RET_SUCCESS;
608         }
609         return ret;
610 }
611
612 static cmd_tbl_t cmd_mmc[] = {
613         U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
614         U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
615         U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
616         U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
617         U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
618         U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
619         U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
620         U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
621 #ifdef CONFIG_SUPPORT_EMMC_BOOT
622         U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
623         U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),
624         U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
625         U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
626 #endif
627 #ifdef CONFIG_SUPPORT_EMMC_RPMB
628         U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
629 #endif
630         U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
631 };
632
633 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
634 {
635         cmd_tbl_t *cp;
636
637         cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
638
639         /* Drop the mmc command */
640         argc--;
641         argv++;
642
643         if (cp == NULL || argc > cp->maxargs)
644                 return CMD_RET_USAGE;
645         if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
646                 return CMD_RET_SUCCESS;
647
648         if (curr_device < 0) {
649                 if (get_mmc_num() > 0) {
650                         curr_device = 0;
651                 } else {
652                         puts("No MMC device available\n");
653                         return CMD_RET_FAILURE;
654                 }
655         }
656         return cp->cmd(cmdtp, flag, argc, argv);
657 }
658
659 U_BOOT_CMD(
660         mmc, 7, 1, do_mmcops,
661         "MMC sub system",
662         "info - display info of the current MMC device\n"
663         "mmc read addr blk# cnt\n"
664         "mmc write addr blk# cnt\n"
665         "mmc erase blk# cnt\n"
666         "mmc rescan\n"
667         "mmc part - lists available partition on current mmc device\n"
668         "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
669         "mmc list - lists available devices\n"
670 #ifdef CONFIG_SUPPORT_EMMC_BOOT
671         "mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
672         " - Set the BOOT_BUS_WIDTH field of the specified device\n"
673         "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
674         " - Change sizes of boot and RPMB partitions of specified device\n"
675         "mmc partconf dev boot_ack boot_partition partition_access\n"
676         " - Change the bits of the PARTITION_CONFIG field of the specified device\n"
677         "mmc rst-function dev value\n"
678         " - Change the RST_n_FUNCTION field of the specified device\n"
679         "   WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
680 #endif
681 #ifdef CONFIG_SUPPORT_EMMC_RPMB
682         "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
683         "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
684         "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
685         "mmc rpmb counter - read the value of the write counter\n"
686 #endif
687         "mmc setdsr <value> - set DSR register value\n"
688         );
689
690 /* Old command kept for compatibility. Same as 'mmc info' */
691 U_BOOT_CMD(
692         mmcinfo, 1, 0, do_mmcinfo,
693         "display MMC info",
694         "- display info of the current MMC device"
695 );
696
697 #endif /* !CONFIG_GENERIC_MMC */