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