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