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