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