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