* [PATCH 1/2] mci: drop unused parameter from mci_switch()
@ 2018-01-19 10:50 Uwe Kleine-König
2018-01-19 10:50 ` [PATCH 2/2] mci: implement command to switch a mmc device to enhanced mode Uwe Kleine-König
0 siblings, 1 reply; 3+ messages in thread
From: Uwe Kleine-König @ 2018-01-19 10:50 UTC (permalink / raw)
To: barebox
The SWITCH command has two purposes:
a) switch the command set
b) Write to the EXT_CSD register
If the access field (bits [25:24]) in the argument are b00, we're in
case a), otherwise in b). As mci_switch() always passes
MMC_SWITCH_MODE_WRITE_BYTE (0b3) in the access field, only case b) is
relevant here. According to the eMMC specification[1] the command set
field is ignored in case b) and so the respective parameter (that is
unused already now) can be dropped.
[1] Embedded Multi-Media Card (e•MMC) Electrical Standard (5.1),
February 2015; paragraph 6.6.1
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
commands/mmc_extcsd.c | 2 +-
drivers/mci/mci-core.c | 16 ++++++----------
include/mci.h | 3 +--
3 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c
index 7a6d39075da0..acd23a466bcb 100644
--- a/commands/mmc_extcsd.c
+++ b/commands/mmc_extcsd.c
@@ -2357,7 +2357,7 @@ static void write_field(struct mci *mci, u8 *reg, u16 index, u8 value,
break;
}
- mci_switch(mci, 0, index, value);
+ mci_switch(mci, index, value);
out:
return;
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 07911d43d703..3da96f42aaf9 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -396,8 +396,7 @@ int mci_send_ext_csd(struct mci *mci, char *ext_csd)
* @param value FIXME
* @return Transaction status (0 on success)
*/
-int mci_switch(struct mci *mci, unsigned set, unsigned index,
- unsigned value)
+int mci_switch(struct mci *mci, unsigned index, unsigned value)
{
struct mci_cmd cmd;
@@ -471,7 +470,7 @@ static int mmc_change_freq(struct mci *mci)
cardtype = mci->ext_csd[EXT_CSD_DEVICE_TYPE] & EXT_CSD_CARD_TYPE_MASK;
- err = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
+ err = mci_switch(mci, EXT_CSD_HS_TIMING, 1);
if (err) {
dev_dbg(&mci->dev, "MMC frequency changing failed: %d\n", err);
@@ -1044,9 +1043,7 @@ static int mci_startup_mmc(struct mci *mci)
* 4bit transfer mode. On success set the corresponding
* bus width on the host.
*/
- err = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- ext_csd_bits[idx]);
+ err = mci_switch(mci, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx]);
if (err) {
if (idx == 0)
dev_warn(&mci->dev, "Changing MMC bus width failed: %d\n", err);
@@ -1253,8 +1250,7 @@ static int mci_blk_part_switch(struct mci_part *part)
part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
part_config |= part->part_cfg;
- ret = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_PARTITION_CONFIG, part_config);
+ ret = mci_switch(mci, EXT_CSD_PARTITION_CONFIG, part_config);
if (ret)
return ret;
@@ -1568,8 +1564,8 @@ static int mci_set_boot(struct param_d *param, void *priv)
mci->ext_csd_part_config &= ~(7 << 3);
mci->ext_csd_part_config |= mci->bootpart << 3;
- return mci_switch(mci, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_PARTITION_CONFIG, mci->ext_csd_part_config);
+ return mci_switch(mci,
+ EXT_CSD_PARTITION_CONFIG, mci->ext_csd_part_config);
}
static const char *mci_boot_names[] = {
diff --git a/include/mci.h b/include/mci.h
index d3115e8cc68f..827eecd39f8d 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -477,8 +477,7 @@ void mci_of_parse(struct mci_host *host);
void mci_of_parse_node(struct mci_host *host, struct device_node *np);
int mci_detect_card(struct mci_host *);
int mci_send_ext_csd(struct mci *mci, char *ext_csd);
-int mci_switch(struct mci *mci, unsigned set, unsigned index,
- unsigned value);
+int mci_switch(struct mci *mci, unsigned index, unsigned value);
static inline int mmc_host_is_spi(struct mci_host *host)
{
--
2.11.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 2/2] mci: implement command to switch a mmc device to enhanced mode
2018-01-19 10:50 [PATCH 1/2] mci: drop unused parameter from mci_switch() Uwe Kleine-König
@ 2018-01-19 10:50 ` Uwe Kleine-König
2018-01-19 13:26 ` Uwe Kleine-König
0 siblings, 1 reply; 3+ messages in thread
From: Uwe Kleine-König @ 2018-01-19 10:50 UTC (permalink / raw)
To: barebox
The command structure allows adding more subcommands and is designed to
match the Linux program mmc from the mmc-utils. So later more commands
can easily be added if need be.
Compared to mmc-utils'
mmc enh_area set <-y|-n|-c> <start KiB> <length KiB> <device>
the command that is implemented here (
mmc enh_area setmax <-y|-n|-c> <device>
) is easier to use (because you don't have to check the maximal allowed
size by reading some registers and calculate the available size from
them (which then must be calculated back to register values by the mmc
command)) but less flexible as it doesn't allow all the crazy
possibilities specified in the eMMC standard but just creates an
enhanced area with maximal size.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
commands/Kconfig | 5 +-
commands/Makefile | 1 +
commands/mmc.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/mci.h | 7 +++
4 files changed, 183 insertions(+), 1 deletion(-)
create mode 100644 commands/mmc.c
diff --git a/commands/Kconfig b/commands/Kconfig
index ae2dc4b0947b..ea26d430dc43 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -236,7 +236,10 @@ config CMD_VERSION
help
Pring barebox version. Example:
- 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
config CMD_MMC_EXTCSD
tristate
diff --git a/commands/Makefile b/commands/Makefile
index 37486dceb181..bcd0665cfe88 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 000000000000..2f5c7ad69a37
--- /dev/null
+++ b/commands/mmc.c
@@ -0,0 +1,171 @@
+#include <command.h>
+#include <mci.h>
+#include <stdio.h>
+#include <string.h>
+
+/* enh_area setmax <-y|-n|-c> /dev/mmcX */
+static int do_mmc_enh_area(int argc, char *argv[])
+{
+ char *devname;
+ struct mci *mci;
+ u8 *ext_csd;
+ int set_completed = 0;
+ int ret;
+
+ if (argc != 4 || strcmp(argv[1], "setmax") ||
+ argv[2][0] != '-' ||
+ (argv[2][1] != 'y' && argv[2][1] != 'n' && argv[2][1] != 'c')) {
+ printf("Usage: mmc enh_area setmax <-y|-n|-c> /dev/mmcX\n");
+ return 1;
+ }
+
+ if (argv[2][1] == 'y')
+ set_completed = 1;
+
+ devname = argv[3];
+ if (!strncmp(devname, "/dev/", 5))
+ devname += 5;
+
+ mci = mci_get_device_by_name(devname);
+ if (!mci) {
+ printf("Failure to open %s as mci device\n", devname);
+ return -ENOENT;
+ }
+ /* get extcsd */
+ ext_csd = xmalloc(512);
+
+ ret = mci_send_ext_csd(mci, ext_csd);
+ if (ret) {
+ printf("Failure to read EXT_CSD register\n");
+ goto error;
+ }
+
+ if (!(ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & EXT_CSD_ENH_ATTRIBUTE_EN_MASK)) {
+ printf("Device doesn't support enhanced area\n");
+ ret = -EIO;
+ goto error;
+ }
+
+ if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED]) {
+ printf("Partitioning already finalized\n");
+ ret = -EIO;
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ERASE_GROUP_DEF, 1);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ERASE_GROUP_DEF\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ENH_START_ADDR, 0);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ENH_START_ADDR[0]\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ENH_START_ADDR + 1, 0);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ENH_START_ADDR[1]\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ENH_START_ADDR + 2, 0);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ENH_START_ADDR[2]\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ENH_START_ADDR + 3, 0);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ENH_START_ADDR[3]\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ENH_SIZE_MULT, ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT]);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ENH_SIZE_MULT[0]\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ENH_SIZE_MULT + 1, ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT + 1]);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ENH_SIZE_MULT[1]\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_ENH_SIZE_MULT + 2, ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT + 2]);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_ENH_SIZE_MULT[2]\n");
+ goto error;
+ }
+
+ ret = mci_switch(mci, EXT_CSD_PARTITIONS_ATTRIBUTE, ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] | EXT_CSD_ENH_USR_MASK);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_PARTITIONS_ATTRIBUTE\n");
+ goto error;
+ }
+
+ if (set_completed) {
+ ret = mci_switch(mci, EXT_CSD_PARTITION_SETTING_COMPLETED, 1);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_PARTITION_SETTING_COMPLETED\n");
+error:
+ free(ext_csd);
+ } else {
+ printf("Now power cycle the device to let it reconfigure itself.\n");
+ }
+ }
+
+ return ret;
+}
+
+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, subcmdlen;
+ int (*func)(int argc, char *argv[]) = NULL;
+
+ if (argc < 2) {
+ printf("mmc: required subcommand missing\n");
+ return 1;
+ }
+
+ subcmdlen = strlen(argv[1]);
+ for (i = 0; i < ARRAY_SIZE(mmc_subcmds); ++i) {
+ if (strncmp(mmc_subcmds[i].cmd, argv[1], subcmdlen) == 0) {
+ if (subcmdlen == strlen(mmc_subcmds[i].cmd)) {
+ /* exact match */
+ func = mmc_subcmds[i].func;
+ break;
+ } else if (func) {
+ printf("mmc: ambiguously abbreviated subcommand");
+ return 1;
+ } else {
+ func = mmc_subcmds[i].func;
+ }
+ }
+ }
+
+ if (func) {
+ int ret = func(argc - 1, argv + 1);
+ return ret < 0;
+ } else {
+ printf("mmc: subcommand \"%s\" not found\n", argv[1]);
+ return 1;
+ }
+}
+
+BAREBOX_CMD_START(mmc)
+ .cmd = do_mmc,
+ BAREBOX_CMD_OPTS("enh_area setmax <-y|-n|-c> /dev/mmcX")
+BAREBOX_CMD_END
diff --git a/include/mci.h b/include/mci.h
index 827eecd39f8d..779da9c156db 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -304,6 +304,13 @@
#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
+/* register PARTITIONS_ATTRIBUTE [156] */
+#define EXT_CSD_ENH_USR_MASK (1 << 0)
+
+/* register PARTITIONING_SUPPORT [160] */
+#define EXT_CSD_ENH_ATTRIBUTE_EN_MASK (1 << 0)
+
+/* register BUS_WIDTH [183], field Bus Mode Selection [4:0] */
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
--
2.11.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-01-19 13:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-19 10:50 [PATCH 1/2] mci: drop unused parameter from mci_switch() Uwe Kleine-König
2018-01-19 10:50 ` [PATCH 2/2] mci: implement command to switch a mmc device to enhanced mode Uwe Kleine-König
2018-01-19 13:26 ` Uwe Kleine-König
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox