diff options
author | Terry Lv <r65388@freescale.com> | 2011-08-12 12:54:58 +0800 |
---|---|---|
committer | Terry Lv <r65388@freescale.com> | 2011-09-01 11:45:02 +0800 |
commit | 72ac6998a7700c2c64a4a7f4d6d44bbc980558f6 (patch) | |
tree | 1c07090998bd507e3cde3c481e0fa859ec25a3d5 /common | |
parent | d187eb3675f1408d206e9013bcde38793f5d1ca8 (diff) | |
download | u-boot-imx-72ac6998a7700c2c64a4a7f4d6d44bbc980558f6.zip u-boot-imx-72ac6998a7700c2c64a4a7f4d6d44bbc980558f6.tar.gz u-boot-imx-72ac6998a7700c2c64a4a7f4d6d44bbc980558f6.tar.bz2 |
ENGR00154666-3: Align u-boot mmc command with community
This patch will enhance mmc command.
1. Add erase command.
2. Abandon dev_no in mmc command. User need to switch slot with "mmc
dev" command.
3. Add mmc part switch command. Enhance partition switch support.
4. Add mmc bootpart. Boot partition support is more flexible.
Signed-off-by: Terry Lv <r65388@freescale.com>
Diffstat (limited to 'common')
-rw-r--r-- | common/cmd_mmc.c | 412 |
1 files changed, 230 insertions, 182 deletions
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 31a4f05..d82f2db 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -27,17 +27,14 @@ #include <command.h> #include <mmc.h> -#ifndef CONFIG_GENERIC_MMC static int curr_device = -1; - -int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +#ifndef CONFIG_GENERIC_MMC +int do_mmc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int dev; - if (argc < 2) { - cmd_usage(cmdtp); - return 1; - } + if (argc < 2) + return cmd_usage(cmdtp); if (strcmp(argv[1], "init") == 0) { if (argc == 2) { @@ -48,8 +45,7 @@ int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } else if (argc == 3) { dev = (int)simple_strtoul(argv[2], NULL, 10); } else { - cmd_usage(cmdtp); - return 1; + return cmd_usage(cmdtp); } if (mmc_legacy_init(dev) != 0) { @@ -74,14 +70,12 @@ int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #endif curr_device = dev; } else { - cmd_usage(cmdtp); - return 1; + return cmd_usage(cmdtp); } printf("mmc%d is current device\n", curr_device); } else { - cmd_usage(cmdtp); - return 1; + return cmd_usage(cmdtp); } return 0; @@ -95,32 +89,12 @@ U_BOOT_CMD( ); #else /* !CONFIG_GENERIC_MMC */ -#ifdef CONFIG_BOOT_PARTITION_ACCESS -#define MMC_PARTITION_SWITCH(mmc, part, enable_boot) \ - do { \ - if (IS_SD(mmc)) { \ - if (part > 1) {\ - printf( \ - "\nError: SD partition can only be 0 or 1\n");\ - return 1; \ - } \ - if (sd_switch_partition(mmc, part) < 0) { \ - if (part > 0) { \ - printf("\nError: Unable to switch SD "\ - "partition\n");\ - return 1; \ - } \ - } \ - } else { \ - if (mmc_switch_partition(mmc, part, enable_boot) \ - < 0) { \ - printf("Error: Fail to switch " \ - "partition to %d\n", part); \ - return 1; \ - } \ - } \ - } while (0) -#endif +enum mmc_state { + MMC_INVALID, + MMC_READ, + MMC_WRITE, + MMC_ERASE, +}; static void print_mmcinfo(struct mmc *mmc) { @@ -138,22 +112,19 @@ static void print_mmcinfo(struct mmc *mmc) (mmc->version >> 4) & 0xf, mmc->version & 0xf); printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No"); - printf("Capacity: %lld\n", mmc->capacity); + puts("Capacity: "); + print_size(mmc->capacity, "\n"); - if (mmc->bus_width == EMMC_MODE_4BIT_DDR || - mmc->bus_width == EMMC_MODE_8BIT_DDR) - printf("Bus Width: %d-bit DDR\n", (mmc->bus_width >> 8)); - else - printf("Bus Width: %d-bit\n", mmc->bus_width); + printf("Bus Width: %d-bit %s\n", mmc->bus_width, + (mmc->card_caps & EMMC_MODE_4BIT_DDR || + mmc->card_caps & EMMC_MODE_8BIT_DDR) ? "DDR" : ""); -#ifdef CONFIG_BOOT_PARTITION_ACCESS - if (mmc->boot_size_mult == 0) { - printf("Boot Partition Size: %s\n", "No boot partition available"); + if (mmc->part_config == MMCPART_NOAVAILABLE) { + printf("Boot Partition for boot: %s\n", + "No boot partition available"); } else { - printf("Boot Partition Size: %5dKB\n", mmc->boot_size_mult * 128); - printf("Current Partition for boot: "); - switch (mmc->boot_config & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) { + switch (mmc->part_config & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) { case EXT_CSD_BOOT_PARTITION_DISABLE: printf("Not bootable\n"); break; @@ -171,185 +142,262 @@ static void print_mmcinfo(struct mmc *mmc) break; } } -#endif } -int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct mmc *mmc; - int dev_num; - if (argc < 2) - dev_num = 0; - else - dev_num = simple_strtoul(argv[1], NULL, 0); + if (curr_device < 0) { + if (get_mmc_num() > 0) + curr_device = 0; + else { + puts("No MMC device available\n"); + return 1; + } + } - mmc = find_mmc_device(dev_num); + mmc = find_mmc_device(curr_device); if (mmc) { - if (mmc_init(mmc)) - puts("MMC card init failed!\n"); - else - print_mmcinfo(mmc); - } + mmc_init(mmc); - return 0; + print_mmcinfo(mmc); + return 0; + } else { + printf("no mmc device at slot %x\n", curr_device); + return 1; + } } -U_BOOT_CMD(mmcinfo, 2, 0, do_mmcinfo, - "mmcinfo <dev num>-- display MMC info", +U_BOOT_CMD( + mmcinfo, 1, 0, do_mmcinfo, + "display MMC info", + " - device number of the device to dislay info of\n" "" ); -int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - int rc = 0; -#ifdef CONFIG_BOOT_PARTITION_ACCESS - u32 part = 0; -#endif + enum mmc_state state; - switch (argc) { - case 3: - if (strcmp(argv[1], "rescan") == 0) { - int dev = simple_strtoul(argv[2], NULL, 10); - struct mmc *mmc = find_mmc_device(dev); + if (argc < 2) + return cmd_usage(cmdtp); - if (!mmc) - return 1; + if (curr_device < 0) { + if (get_mmc_num() > 0) + curr_device = 0; + else { + puts("No MMC device available\n"); + return 1; + } + } - mmc_init(mmc); + if (strcmp(argv[1], "rescan") == 0) { + struct mmc *mmc = find_mmc_device(curr_device); - return 0; + if (!mmc) { + printf("no mmc device at slot %x\n", curr_device); + return 1; } - case 0: - case 1: - case 4: - printf("Usage:\n%s\n", cmdtp->usage); - return 1; + mmc->has_init = 0; - case 2: - if (!strcmp(argv[1], "list")) { - print_mmc_devices('\n'); + if (mmc_init(mmc)) + return 1; + else return 0; + } else if (strncmp(argv[1], "part", 4) == 0) { + block_dev_desc_t *mmc_dev; + struct mmc *mmc = find_mmc_device(curr_device); + + if (!mmc) { + printf("no mmc device at slot %x\n", curr_device); + return 1; } + mmc_init(mmc); + mmc_dev = mmc_get_dev(curr_device); + if (mmc_dev != NULL && + mmc_dev->type != DEV_TYPE_UNKNOWN) { + print_part(mmc_dev); + return 0; + } + + puts("get mmc type error!\n"); return 1; -#ifdef CONFIG_BOOT_PARTITION_ACCESS - case 7: /* Fall through */ - part = simple_strtoul(argv[6], NULL, 10); -#endif - default: /* at least 5 args */ - if (strcmp(argv[1], "read") == 0) { - int dev = simple_strtoul(argv[2], NULL, 10); - void *addr = (void *)simple_strtoul(argv[3], NULL, 16); - u32 cnt = simple_strtoul(argv[5], NULL, 16); - u32 n; - u32 blk = simple_strtoul(argv[4], NULL, 16); + } else if (strncmp(argv[1], "bootpart", 8) == 0) { + int dev, part = -1; + struct mmc *mmc; - struct mmc *mmc = find_mmc_device(dev); + if (argc == 2) { + dev = curr_device; + } else if (argc == 3) { + dev = (int)simple_strtoul(argv[2], NULL, 10); + } else if (argc == 4) { + dev = (int)simple_strtoul(argv[2], NULL, 10); + part = (int)simple_strtoul(argv[3], NULL, 10); + } else + return cmd_usage(cmdtp); - if (!mmc) - return 1; + mmc = find_mmc_device(dev); + if (!mmc) { + printf("no mmc device at slot %x\n", dev); + return 1; + } -#ifdef CONFIG_BOOT_PARTITION_ACCESS - printf("\nMMC read: dev # %d, block # %d, " - "count %d partition # %d ... \n", - dev, blk, cnt, part); -#else - printf("\nMMC read: dev # %d, block # %d," - "count %d ... \n", dev, blk, cnt); -#endif + mmc_init(mmc); - mmc_init(mmc); - -#ifdef CONFIG_BOOT_PARTITION_ACCESS - if (((mmc->boot_config & - EXT_CSD_BOOT_PARTITION_ACCESS_MASK) != part) - || IS_SD(mmc)) { - /* - * After mmc_init, we now know whether - * this is a eSD/eMMC which support boot - * partition - */ - MMC_PARTITION_SWITCH(mmc, part, 0); - } -#endif + if (mmc->part_config == MMCPART_NOAVAILABLE) { + printf("Card doesn't support boot partition feature\n"); + return 0; + } - n = mmc->block_dev.block_read(dev, blk, cnt, addr); + if (part != -1) { + int ret; - /* flush cache after read */ - flush_cache((ulong)addr, cnt * 512); /* FIXME */ + if (part != mmc->boot_part_num) { + if (IS_SD(mmc)) + ret = sd_switch_boot_part(dev, part); + else + ret = mmc_switch_boot_part(dev, part); - printf("%d blocks read: %s\n", - n, (n==cnt) ? "OK" : "ERROR"); - return (n == cnt) ? 0 : 1; - } else if (strcmp(argv[1], "write") == 0) { - int dev = simple_strtoul(argv[2], NULL, 10); - void *addr = (void *)simple_strtoul(argv[3], NULL, 16); - u32 cnt = simple_strtoul(argv[5], NULL, 16); - u32 n; + if (!ret) + mmc->boot_part_num = part; + printf("Switch boot partition to partition #%d, %s\n", + part, (!ret) ? "OK" : "ERROR"); + } + } - struct mmc *mmc = find_mmc_device(dev); + printf("Device %d: boot partition %d is for boot\n", + dev, mmc->boot_part_num); + + return 0; + } else if (strcmp(argv[1], "list") == 0) { + print_mmc_devices('\n'); + return 0; + } else if (strcmp(argv[1], "dev") == 0) { + int dev, part = -1; + struct mmc *mmc; + + if (argc == 2) + dev = curr_device; + else if (argc == 3) + dev = simple_strtoul(argv[2], NULL, 10); + else if (argc == 4) { + dev = (int)simple_strtoul(argv[2], NULL, 10); + part = (int)simple_strtoul(argv[3], NULL, 10); + if (part > PART_ACCESS_MASK) { + printf("#part_num shouldn't be larger" + " than %d\n", PART_ACCESS_MASK); + return 1; + } + } else + return cmd_usage(cmdtp); - int blk = simple_strtoul(argv[4], NULL, 16); + mmc = find_mmc_device(dev); + if (!mmc) { + printf("no mmc device at slot %x\n", dev); + return 1; + } - if (!mmc) + mmc_init(mmc); + if (part != -1) { + int ret; + if (mmc->part_config == MMCPART_NOAVAILABLE) { + printf("Card doesn't support part_switch\n"); return 1; + } -#ifdef CONFIG_BOOT_PARTITION_ACCESS - printf("\nMMC write: dev # %d, block # %d, " - "count %d, partition # %d ... \n", - dev, blk, cnt, part); -#else - printf("\nMMC write: dev # %d, block # %d, " - "count %d ... \n", - dev, blk, cnt); -#endif + if (part != mmc->part_num) { + if (IS_SD(mmc)) + ret = sd_switch_part(dev, part); + else + ret = mmc_switch_part(dev, part); + if (!ret) + mmc->part_num = part; - mmc_init(mmc); - -#ifdef CONFIG_BOOT_PARTITION_ACCESS - if (((mmc->boot_config & - EXT_CSD_BOOT_PARTITION_ACCESS_MASK) != part) - || IS_SD(mmc)) { - /* - * After mmc_init, we now know whether this is a - * eSD/eMMC which support boot partition - */ - MMC_PARTITION_SWITCH(mmc, part, 1); + printf("switch to partition #%d, %s\n", + part, (!ret) ? "OK" : "ERROR"); } -#endif + } + curr_device = dev; + if (mmc->part_config == MMCPART_NOAVAILABLE) + printf("mmc%d is current device\n", curr_device); + else + printf("mmc%d(part %d) is current device\n", + curr_device, mmc->part_num); - n = mmc->block_dev.block_write(dev, blk, cnt, addr); + return 0; + } - printf("%d blocks written: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); - return (n == cnt) ? 0 : 1; - } else { - printf("Usage:\n%s\n", cmdtp->usage); - rc = 1; + if (strcmp(argv[1], "read") == 0) + state = MMC_READ; + else if (strcmp(argv[1], "write") == 0) + state = MMC_WRITE; + else if (strcmp(argv[1], "erase") == 0) + state = MMC_ERASE; + else + state = MMC_INVALID; + + if (state != MMC_INVALID) { + struct mmc *mmc = find_mmc_device(curr_device); + int idx = 2; + u32 blk, cnt, n; + void *addr; + + if (state != MMC_ERASE) { + addr = (void *)simple_strtoul(argv[idx], NULL, 16); + ++idx; + } else + addr = 0; + blk = simple_strtoul(argv[idx], NULL, 16); + cnt = simple_strtoul(argv[idx + 1], NULL, 16); + + if (!mmc) { + printf("no mmc device at slot %x\n", curr_device); + return 1; + } + + printf("\nMMC %s: dev # %d, block # %d, count %d ... ", + argv[1], curr_device, blk, cnt); + + mmc_init(mmc); + + switch (state) { + case MMC_READ: + n = mmc->block_dev.block_read(curr_device, blk, + cnt, addr); + /* flush cache after read */ + flush_cache((ulong)addr, cnt * 512); /* FIXME */ + break; + case MMC_WRITE: + n = mmc->block_dev.block_write(curr_device, blk, + cnt, addr); + break; + case MMC_ERASE: + n = mmc->block_dev.block_erase(curr_device, blk, cnt); + break; + default: + BUG(); } - return rc; + printf("%d blocks %s: %s\n", + n, argv[1], (n == cnt) ? "OK" : "ERROR"); + return (n == cnt) ? 0 : 1; } + + return cmd_usage(cmdtp); } -#ifndef CONFIG_BOOT_PARTITION_ACCESS U_BOOT_CMD( mmc, 6, 1, do_mmcops, "MMC sub system", - "mmc read <device num> addr blk# cnt\n" - "mmc write <device num> addr blk# cnt\n" - "mmc rescan <device num>\n" - "mmc list - lists available devices"); -#else -U_BOOT_CMD( - mmc, 7, 1, do_mmcops, - "MMC sub system", - "mmc read <device num> addr blk# cnt [partition]\n" - "mmc write <device num> addr blk# cnt [partition]\n" - "mmc rescan <device num>\n" + "read addr blk# cnt\n" + "mmc write addr blk# cnt\n" + "mmc erase blk# cnt\n" + "mmc rescan\n" + "mmc part - lists available partition on current mmc device\n" + "mmc dev [dev] [part] - show or set current mmc device [partition]\n" + "mmc bootpart [dev] [part] - show or set boot partition\n" "mmc list - lists available devices"); #endif -#endif - |