summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Cooper <acooperx@gmail.com>2015-04-29 18:12:35 -0400
committerChris Ball <chris@printf.net>2015-05-01 08:38:26 -0400
commitd0b46442b50794217e53b2455c1344c548d9d088 (patch)
tree8db4e5d2acf6d6c1708fd969777fefda92526b42
parent64c2de8b1476c42ef9e9729b7ca0e436b5d90170 (diff)
downloadmmc-utils-d0b46442b50794217e53b2455c1344c548d9d088.tar.gz
mmc-utils: add ability to enable/disable optional eMMC cache
The MMC4.5 specification added an optional cache for eMMC devices. This change will add the ability to enable/disable the cache. Signed-off-by: Al Cooper <acooperx@gmail.com> Signed-off-by: Chris Ball <chris@printf.net>
-rw-r--r--mmc.c12
-rw-r--r--mmc.h15
-rw-r--r--mmc_cmds.c67
-rw-r--r--mmc_cmds.h2
4 files changed, 93 insertions, 3 deletions
diff --git a/mmc.c b/mmc.c
index 2adf15c..a13d9ae 100644
--- a/mmc.c
+++ b/mmc.c
@@ -163,6 +163,18 @@ static struct Command commands[] = {
" mmc rpmb write-block /dev/mmcblk0rpmb 0x02 - -",
NULL
},
+ { do_cache_en, -1,
+ "cache enable", "<device>\n"
+ "Enable the eMMC cache feature on <device>.\n"
+ "NOTE! The cache is an optional feature on devices >= eMMC4.5.",
+ NULL
+ },
+ { do_cache_dis, -1,
+ "cache disable", "<device>\n"
+ "Disable the eMMC cache feature on <device>.\n"
+ "NOTE! The cache is an optional feature on devices >= eMMC4.5.",
+ NULL
+ },
{ 0, 0, 0, 0 }
};
diff --git a/mmc.h b/mmc.h
index d57cad5..b7063fb 100644
--- a/mmc.h
+++ b/mmc.h
@@ -42,12 +42,17 @@
#define EXT_CSD_S_CMD_SET 504
#define EXT_CSD_HPI_FEATURE 503
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
+#define EXT_CSD_CACHE_SIZE_3 252
+#define EXT_CSD_CACHE_SIZE_2 251
+#define EXT_CSD_CACHE_SIZE_1 250
+#define EXT_CSD_CACHE_SIZE_0 249
#define EXT_CSD_BOOT_INFO 228 /* R/W */
#define EXT_CSD_SEC_COUNT_3 215
#define EXT_CSD_SEC_COUNT_2 214
#define EXT_CSD_SEC_COUNT_1 213
#define EXT_CSD_SEC_COUNT_0 212
#define EXT_CSD_PART_SWITCH_TIME 199
+#define EXT_CSD_REV 192
#define EXT_CSD_BOOT_CFG 179
#define EXT_CSD_PART_CONFIG 179
#define EXT_CSD_BOOT_BUS_CONDITIONS 177
@@ -88,6 +93,7 @@
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
#define EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_1 53
#define EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_0 52
+#define EXT_CSD_CACHE_CTRL 33
/*
* WR_REL_PARAM field definitions
@@ -131,6 +137,15 @@
#define EXT_CSD_ENH_2 (1<<2)
#define EXT_CSD_ENH_1 (1<<1)
#define EXT_CSD_ENH_USR (1<<0)
+#define EXT_CSD_REV_V5_1 8
+#define EXT_CSD_REV_V5_0 7
+#define EXT_CSD_REV_V4_5 6
+#define EXT_CSD_REV_V4_4_1 5
+#define EXT_CSD_REV_V4_3 3
+#define EXT_CSD_REV_V4_2 2
+#define EXT_CSD_REV_V4_1 1
+#define EXT_CSD_REV_V4_0 0
+
/* From kernel linux/mmc/core.h */
#define MMC_RSP_PRESENT (1 << 0)
diff --git a/mmc_cmds.c b/mmc_cmds.c
index bf3ff78..4aa0a11 100644
--- a/mmc_cmds.c
+++ b/mmc_cmds.c
@@ -98,7 +98,7 @@ int send_status(int fd, __u32 *response)
void print_writeprotect_status(__u8 *ext_csd)
{
__u8 reg;
- __u8 ext_csd_rev = ext_csd[192];
+ __u8 ext_csd_rev = ext_csd[EXT_CSD_REV];
/* A43: reserved [174:0] */
if (ext_csd_rev >= 5) {
@@ -1014,7 +1014,7 @@ int do_read_extcsd(int nargs, char **argv)
exit(1);
}
- ext_csd_rev = ext_csd[192];
+ ext_csd_rev = ext_csd[EXT_CSD_REV];
switch (ext_csd_rev) {
case 7:
@@ -1218,7 +1218,7 @@ int do_read_extcsd(int nargs, char **argv)
if (reg & 0x01) printf(" HS eMMC @26MHz - at rated device voltage(s)\n");
printf("CSD structure version [CSD_STRUCTURE: 0x%02x]\n", ext_csd[194]);
- /* ext_csd_rev = ext_csd[192] (already done!!!) */
+ /* ext_csd_rev = ext_csd[EXT_CSD_REV] (already done!!!) */
printf("Command set [CMD_SET: 0x%02x]\n", ext_csd[191]);
printf("Command set revision [CMD_SET_REV: 0x%02x]\n", ext_csd[189]);
printf("Power class [POWER_CLASS: 0x%02x]\n", ext_csd[187]);
@@ -1971,3 +1971,64 @@ int do_rpmb_write_block(int nargs, char **argv)
return ret;
}
+
+int do_cache_ctrl(int value, int nargs, char **argv)
+{
+ __u8 ext_csd[512];
+ int fd, ret;
+ char *device;
+
+ CHECK(nargs != 2, "Usage: mmc cache enable </path/to/mmcblkX>\n",
+ exit(1));
+
+ device = argv[1];
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ ret = read_extcsd(fd, ext_csd);
+ if (ret) {
+ fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
+ exit(1);
+ }
+
+ if (ext_csd[EXT_CSD_REV] < EXT_CSD_REV_V4_5) {
+ fprintf(stderr,
+ "The CACHE option is only availabe on devices >= "
+ "MMC 4.5 %s\n", device);
+ exit(1);
+ }
+
+ /* If the cache size is zero, this device does not have a cache */
+ if (!(ext_csd[EXT_CSD_CACHE_SIZE_3] ||
+ ext_csd[EXT_CSD_CACHE_SIZE_2] ||
+ ext_csd[EXT_CSD_CACHE_SIZE_1] ||
+ ext_csd[EXT_CSD_CACHE_SIZE_0])) {
+ fprintf(stderr,
+ "The CACHE option is not available on %s\n",
+ device);
+ exit(1);
+ }
+ ret = write_extcsd_value(fd, EXT_CSD_CACHE_CTRL, value);
+ if (ret) {
+ fprintf(stderr,
+ "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
+ value, EXT_CSD_CACHE_CTRL, device);
+ exit(1);
+ }
+
+ return ret;
+}
+
+int do_cache_en(int nargs, char **argv)
+{
+ return do_cache_ctrl(1, nargs, argv);
+}
+
+int do_cache_dis(int nargs, char **argv)
+{
+ return do_cache_ctrl(0, nargs, argv);
+}
diff --git a/mmc_cmds.h b/mmc_cmds.h
index ab181d4..75d8f8c 100644
--- a/mmc_cmds.h
+++ b/mmc_cmds.h
@@ -34,3 +34,5 @@ int do_rpmb_write_key(int nargs, char **argv);
int do_rpmb_read_counter(int nargs, char **argv);
int do_rpmb_read_block(int nargs, char **argv);
int do_rpmb_write_block(int nargs, char **argv);
+int do_cache_en(int nargs, char **argv);
+int do_cache_dis(int nargs, char **argv);