Commit cd3d48807dfb64f521fcbc30034d4e921d842a5b

Authored by Tomas Melin
Committed by Jaehoon Chung
1 parent f0ecfc5e7e

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

... ... @@ -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
... ... @@ -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' */
... ... @@ -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
... ... @@ -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