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