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