Commit cd3d48807dfb64f521fcbc30034d4e921d842a5b
Committed by
Jaehoon Chung
1 parent
f0ecfc5e7e
Exists in
v2017.01-smarct4x
and in
25 other branches
mmc: add bkops-enable command
Add new command that provides possibility to enable the background operations handshake functionality (BKOPS_EN, EXT_CSD byte [163]) on eMMC devices. This is an optional feature of eMMCs, the setting is write-once. The command must be explicitly taken into use with CONFIG_CMD_BKOPS_ENABLE. Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
Showing 4 changed files with 81 additions and 0 deletions Side-by-side Diff
cmd/Kconfig
... | ... | @@ -572,6 +572,15 @@ |
572 | 572 | help |
573 | 573 | Show AMBA Plug-n-Play information on startup. |
574 | 574 | |
575 | +config CMD_BKOPS_ENABLE | |
576 | + bool "mmc bkops enable" | |
577 | + depends on CMD_MMC | |
578 | + default n | |
579 | + help | |
580 | + Enable command for setting manual background operations handshake | |
581 | + on a eMMC device. The feature is optionally available on eMMC devices | |
582 | + conforming to standard >= 4.41. | |
583 | + | |
575 | 584 | config CMD_BLOCK_CACHE |
576 | 585 | bool "blkcache - control and stats for block cache" |
577 | 586 | depends on BLOCK_CACHE |
cmd/mmc.c
... | ... | @@ -729,6 +729,31 @@ |
729 | 729 | return ret; |
730 | 730 | } |
731 | 731 | |
732 | +#ifdef CONFIG_CMD_BKOPS_ENABLE | |
733 | +static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag, | |
734 | + int argc, char * const argv[]) | |
735 | +{ | |
736 | + int dev; | |
737 | + struct mmc *mmc; | |
738 | + | |
739 | + if (argc != 2) | |
740 | + return CMD_RET_USAGE; | |
741 | + | |
742 | + dev = simple_strtoul(argv[1], NULL, 10); | |
743 | + | |
744 | + mmc = init_mmc_device(dev, false); | |
745 | + if (!mmc) | |
746 | + return CMD_RET_FAILURE; | |
747 | + | |
748 | + if (IS_SD(mmc)) { | |
749 | + puts("BKOPS_EN only exists on eMMC\n"); | |
750 | + return CMD_RET_FAILURE; | |
751 | + } | |
752 | + | |
753 | + return mmc_set_bkops_enable(mmc); | |
754 | +} | |
755 | +#endif | |
756 | + | |
732 | 757 | static cmd_tbl_t cmd_mmc[] = { |
733 | 758 | U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), |
734 | 759 | U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), |
... | ... | @@ -749,6 +774,9 @@ |
749 | 774 | U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), |
750 | 775 | #endif |
751 | 776 | U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), |
777 | +#ifdef CONFIG_CMD_BKOPS_ENABLE | |
778 | + U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""), | |
779 | +#endif | |
752 | 780 | }; |
753 | 781 | |
754 | 782 | static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
... | ... | @@ -813,6 +841,10 @@ |
813 | 841 | "mmc rpmb counter - read the value of the write counter\n" |
814 | 842 | #endif |
815 | 843 | "mmc setdsr <value> - set DSR register value\n" |
844 | +#ifdef CONFIG_CMD_BKOPS_ENABLE | |
845 | + "mmc bkops-enable <dev> - enable background operations handshake on device\n" | |
846 | + " WARNING: This is a write-once setting.\n" | |
847 | +#endif | |
816 | 848 | ); |
817 | 849 | |
818 | 850 | /* Old command kept for compatibility. Same as 'mmc info' */ |
drivers/mmc/mmc.c
... | ... | @@ -1817,4 +1817,38 @@ |
1817 | 1817 | mmc_do_preinit(); |
1818 | 1818 | return 0; |
1819 | 1819 | } |
1820 | + | |
1821 | +#ifdef CONFIG_CMD_BKOPS_ENABLE | |
1822 | +int mmc_set_bkops_enable(struct mmc *mmc) | |
1823 | +{ | |
1824 | + int err; | |
1825 | + ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); | |
1826 | + | |
1827 | + err = mmc_send_ext_csd(mmc, ext_csd); | |
1828 | + if (err) { | |
1829 | + puts("Could not get ext_csd register values\n"); | |
1830 | + return err; | |
1831 | + } | |
1832 | + | |
1833 | + if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) { | |
1834 | + puts("Background operations not supported on device\n"); | |
1835 | + return -EMEDIUMTYPE; | |
1836 | + } | |
1837 | + | |
1838 | + if (ext_csd[EXT_CSD_BKOPS_EN] & 0x1) { | |
1839 | + puts("Background operations already enabled\n"); | |
1840 | + return 0; | |
1841 | + } | |
1842 | + | |
1843 | + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN, 1); | |
1844 | + if (err) { | |
1845 | + puts("Failed to enable manual background operations\n"); | |
1846 | + return err; | |
1847 | + } | |
1848 | + | |
1849 | + puts("Enabled manual background operations\n"); | |
1850 | + | |
1851 | + return 0; | |
1852 | +} | |
1853 | +#endif |
include/mmc.h
... | ... | @@ -174,6 +174,7 @@ |
174 | 174 | #define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* R */ |
175 | 175 | #define EXT_CSD_PARTITIONING_SUPPORT 160 /* RO */ |
176 | 176 | #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ |
177 | +#define EXT_CSD_BKOPS_EN 163 /* R/W & R/W/E */ | |
177 | 178 | #define EXT_CSD_WR_REL_PARAM 166 /* R */ |
178 | 179 | #define EXT_CSD_WR_REL_SET 167 /* R/W */ |
179 | 180 | #define EXT_CSD_RPMB_MULT 168 /* RO */ |
... | ... | @@ -188,6 +189,7 @@ |
188 | 189 | #define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ |
189 | 190 | #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ |
190 | 191 | #define EXT_CSD_BOOT_MULT 226 /* RO */ |
192 | +#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ | |
191 | 193 | |
192 | 194 | /* |
193 | 195 | * EXT_CSD field definitions |
... | ... | @@ -540,6 +542,10 @@ |
540 | 542 | unsigned short cnt, unsigned char *key); |
541 | 543 | int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk, |
542 | 544 | unsigned short cnt, unsigned char *key); |
545 | +#ifdef CONFIG_CMD_BKOPS_ENABLE | |
546 | +int mmc_set_bkops_enable(struct mmc *mmc); | |
547 | +#endif | |
548 | + | |
543 | 549 | /** |
544 | 550 | * Start device initialization and return immediately; it does not block on |
545 | 551 | * polling OCR (operation condition register) status. Then you should call |