diff options
author | Al Cooper <acooperx@gmail.com> | 2015-04-29 18:12:35 -0400 |
---|---|---|
committer | Chris Ball <chris@printf.net> | 2015-05-01 08:38:26 -0400 |
commit | d0b46442b50794217e53b2455c1344c548d9d088 (patch) | |
tree | 8db4e5d2acf6d6c1708fd969777fefda92526b42 | |
parent | 64c2de8b1476c42ef9e9729b7ca0e436b5d90170 (diff) | |
download | mmc-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.c | 12 | ||||
-rw-r--r-- | mmc.h | 15 | ||||
-rw-r--r-- | mmc_cmds.c | 67 | ||||
-rw-r--r-- | mmc_cmds.h | 2 |
4 files changed, 93 insertions, 3 deletions
@@ -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 } }; @@ -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) @@ -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); +} @@ -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); |