summaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
Diffstat (limited to 'commands')
-rw-r--r--commands/Kconfig13
-rw-r--r--commands/Makefile1
-rw-r--r--commands/mmc.c196
-rw-r--r--commands/mmc_extcsd.c6
4 files changed, 212 insertions, 4 deletions
diff --git a/commands/Kconfig b/commands/Kconfig
index 24fd47b..ad65fec 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"
@@ -2151,7 +2162,7 @@ config CMD_SEED
config CMD_UBSAN
tristate "ubsan"
- depends on UBSAN && COMMAND_SUPPORT
+ depends on UBSAN
help
This is a test command for the undefined behavior sanitizer.
It triggers various undefined behavior, and detect it.
diff --git a/commands/Makefile b/commands/Makefile
index a619ee5..85adc32 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -120,6 +120,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 0000000..c696e7b
--- /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 ad8e9ad..4f566bc 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;