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