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