diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2019-10-17 08:10:23 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-10-17 08:10:23 +0200 |
commit | 41be2a023dc9b8e4a790ca129b72cfa9e58be865 (patch) | |
tree | 66188250d8cc5de2c778350844d5db82a7939a40 /commands | |
parent | ee6d4a74eb6efa643e7b834b32e04d01c6b29b7f (diff) | |
parent | f3db31188849c0f7f603789d125eb60e5f139061 (diff) | |
download | barebox-41be2a023dc9b8e4a790ca129b72cfa9e58be865.tar.gz barebox-41be2a023dc9b8e4a790ca129b72cfa9e58be865.tar.xz |
Merge branch 'for-next/mmc'
Diffstat (limited to 'commands')
-rw-r--r-- | commands/Kconfig | 11 | ||||
-rw-r--r-- | commands/Makefile | 1 | ||||
-rw-r--r-- | commands/mmc.c | 196 | ||||
-rw-r--r-- | commands/mmc_extcsd.c | 6 |
4 files changed, 211 insertions, 3 deletions
diff --git a/commands/Kconfig b/commands/Kconfig index 6847a55e61..30d02264c9 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -233,6 +233,17 @@ config CMD_VERSION barebox 2014.05.0-00142-gb289373 #177 Mon May 12 20:35:55 CEST 2014 +config CMD_MMC + tristate + prompt "mmc command allowing to set enhanced area" + depends on MCI + help + Configure mmc cards similar to the userspace mmc utility. Compared to + mmc_extcsd it works on a higher abstraction level. + + Currently only the enh_area subcommand is implemented to configure + the "Enhanced Area" of an mmc device. + config CMD_MMC_EXTCSD tristate prompt "read/write eMMC ext. CSD register" diff --git a/commands/Makefile b/commands/Makefile index 5cd35b78a7..62fbf1aa27 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -119,6 +119,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o obj-$(CONFIG_CMD_BOOTCHOOSER) += bootchooser.o obj-$(CONFIG_CMD_DHRYSTONE) += dhrystone.o obj-$(CONFIG_CMD_SPD_DECODE) += spd_decode.o +obj-$(CONFIG_CMD_MMC) += mmc.o obj-$(CONFIG_CMD_MMC_EXTCSD) += mmc_extcsd.o obj-$(CONFIG_CMD_NAND_BITFLIP) += nand-bitflip.o obj-$(CONFIG_CMD_SEED) += seed.o diff --git a/commands/mmc.c b/commands/mmc.c new file mode 100644 index 0000000000..c696e7b881 --- /dev/null +++ b/commands/mmc.c @@ -0,0 +1,196 @@ +#include <command.h> +#include <mci.h> +#include <stdio.h> +#include <string.h> +#include <getopt.h> + +static int mmc_enh_area_setmax(struct mci *mci, u8 *ext_csd) +{ + unsigned i; + struct { + unsigned index; + unsigned value; + } regval[] = { + { + .index = EXT_CSD_ERASE_GROUP_DEF, + .value = 1, + }, { + .index = EXT_CSD_ENH_START_ADDR, + .value = 0, + }, { + .index = EXT_CSD_ENH_START_ADDR + 1, + .value = 0, + }, { + .index = EXT_CSD_ENH_START_ADDR + 2, + .value = 0, + }, { + .index = EXT_CSD_ENH_START_ADDR + 3, + .value = 0, + }, { + .index = EXT_CSD_ENH_SIZE_MULT, + .value = ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT], + }, { + .index = EXT_CSD_ENH_SIZE_MULT + 1, + .value = ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT + 1], + }, { + .index = EXT_CSD_ENH_SIZE_MULT + 2, + .value = ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT + 2], + }, { + .index = EXT_CSD_PARTITIONS_ATTRIBUTE, + .value = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] | EXT_CSD_ENH_USR_MASK, + } + }; + + for (i = 0; i < ARRAY_SIZE(regval); ++i) { + int ret = mci_switch(mci, regval[i].index, regval[i].value); + if (ret) { + printf("Failure to write to register %u", regval[i].index); + return ret; + } + } + + return 0; +} + +static int mmc_partitioning_complete(struct mci *mci) +{ + int ret; + + ret = mci_switch(mci, EXT_CSD_PARTITION_SETTING_COMPLETED, 1); + if (ret) + printf("Failure to write to EXT_CSD_PARTITION_SETTING_COMPLETED\n"); + + return ret; +} + +static u8 *mci_get_ext_csd(struct mci *mci) +{ + u8 *ext_csd; + int ret; + + ext_csd = xmalloc(512); + + ret = mci_send_ext_csd(mci, ext_csd); + if (ret) { + printf("Failure to read EXT_CSD register\n"); + free(ext_csd); + return ERR_PTR(-EIO); + } + + return ext_csd; +} + +/* enh_area [-c] /dev/mmcX */ +static int do_mmc_enh_area(int argc, char *argv[]) +{ + const char *devpath; + struct mci *mci; + u8 *ext_csd; + int set_completed = 0; + int opt; + int ret; + + while ((opt = getopt(argc, argv, "c")) > 0) { + switch (opt) { + case 'c': + set_completed = 1; + break; + } + } + + if (argc - optind != 1) { + printf("Usage: mmc enh_area [-c] /dev/mmcX\n"); + return COMMAND_ERROR_USAGE; + } + + devpath = argv[optind]; + + mci = mci_get_device_by_devpath(devpath); + if (!mci) { + printf("Failure to open %s as mci device\n", devpath); + return COMMAND_ERROR; + } + + ext_csd = mci_get_ext_csd(mci); + if (IS_ERR(ext_csd)) + return COMMAND_ERROR; + + if (!(ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & EXT_CSD_ENH_ATTRIBUTE_EN_MASK)) { + printf("Device doesn't support enhanced area\n"); + goto error; + } + + if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED]) { + printf("Partitioning already finalized\n"); + goto error; + } + + ret = mmc_enh_area_setmax(mci, ext_csd); + if (ret) + goto error; + + free(ext_csd); + + if (set_completed) { + ret = mmc_partitioning_complete(mci); + if (ret) + return COMMAND_ERROR; + printf("Now power cycle the device to let it reconfigure itself.\n"); + } + + return COMMAND_SUCCESS; + +error: + free(ext_csd); + return COMMAND_ERROR; +} + +static struct { + const char *cmd; + int (*func)(int argc, char *argv[]); +} mmc_subcmds[] = { + { + .cmd = "enh_area", + .func = do_mmc_enh_area, + } +}; + +static int do_mmc(int argc, char *argv[]) +{ + size_t i; + int (*func)(int argc, char *argv[]) = NULL; + + if (argc < 2) { + printf("mmc: required subcommand missing\n"); + return 1; + } + + for (i = 0; i < ARRAY_SIZE(mmc_subcmds); ++i) { + if (strcmp(mmc_subcmds[i].cmd, argv[1]) == 0) { + func = mmc_subcmds[i].func; + break; + } + } + + if (func) { + return func(argc - 1, argv + 1); + } else { + printf("mmc: subcommand \"%s\" not found\n", argv[1]); + return COMMAND_ERROR_USAGE; + } +} + +BAREBOX_CMD_HELP_START(mmc) +BAREBOX_CMD_HELP_TEXT("Modifies mmc properties.") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("The subcommand enh_area creates an enhanced area of") +BAREBOX_CMD_HELP_TEXT("maximal size.") +BAREBOX_CMD_HELP_TEXT("Note, with -c this is an irreversible action.") +BAREBOX_CMD_HELP_OPT("-c", "complete partitioning") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(mmc) + .cmd = do_mmc, + BAREBOX_CMD_OPTS("enh_area [-c] /dev/mmcX") + BAREBOX_CMD_HELP(cmd_mmc_help) +BAREBOX_CMD_END diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c index ad8e9ad19f..4f566bc805 100644 --- a/commands/mmc_extcsd.c +++ b/commands/mmc_extcsd.c @@ -2373,7 +2373,7 @@ static int do_mmc_extcsd(int argc, char *argv[]) u8 *dst; int retval = 0; int opt; - char *devname; + char *devpath; int index = 0; int value = 0; int write_operation = 0; @@ -2411,9 +2411,9 @@ static int do_mmc_extcsd(int argc, char *argv[]) if (optind == argc) return COMMAND_ERROR_USAGE; - devname = argv[optind]; + devpath = argv[optind]; - mci = mci_get_device_by_name(devpath_to_name(devname)); + mci = mci_get_device_by_devpath(devpath); if (mci == NULL) { retval = -ENOENT; goto error; |