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>
This commit is contained in:
		
							parent
							
								
									f0ecfc5e7e
								
							
						
					
					
						commit
						cd3d48807d
					
				|  | @ -572,6 +572,15 @@ config SYS_AMBAPP_PRINT_ON_STARTUP | ||||||
| 	help | 	help | ||||||
| 	  Show AMBA Plug-n-Play information on startup. | 	  Show AMBA Plug-n-Play information on startup. | ||||||
| 
 | 
 | ||||||
|  | config CMD_BKOPS_ENABLE | ||||||
|  | 	bool "mmc bkops enable" | ||||||
|  | 	depends on CMD_MMC | ||||||
|  | 	default n | ||||||
|  | 	help | ||||||
|  | 	  Enable command for setting manual background operations handshake | ||||||
|  | 	  on a eMMC device. The feature is optionally available on eMMC devices | ||||||
|  | 	  conforming to standard >= 4.41. | ||||||
|  | 
 | ||||||
| config CMD_BLOCK_CACHE | config CMD_BLOCK_CACHE | ||||||
| 	bool "blkcache - control and stats for block cache" | 	bool "blkcache - control and stats for block cache" | ||||||
| 	depends on BLOCK_CACHE | 	depends on BLOCK_CACHE | ||||||
|  |  | ||||||
							
								
								
									
										32
									
								
								cmd/mmc.c
								
								
								
								
							
							
						
						
									
										32
									
								
								cmd/mmc.c
								
								
								
								
							|  | @ -729,6 +729,31 @@ static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag, | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_CMD_BKOPS_ENABLE | ||||||
|  | static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag, | ||||||
|  | 				   int argc, char * const argv[]) | ||||||
|  | { | ||||||
|  | 	int dev; | ||||||
|  | 	struct mmc *mmc; | ||||||
|  | 
 | ||||||
|  | 	if (argc != 2) | ||||||
|  | 		return CMD_RET_USAGE; | ||||||
|  | 
 | ||||||
|  | 	dev = simple_strtoul(argv[1], NULL, 10); | ||||||
|  | 
 | ||||||
|  | 	mmc = init_mmc_device(dev, false); | ||||||
|  | 	if (!mmc) | ||||||
|  | 		return CMD_RET_FAILURE; | ||||||
|  | 
 | ||||||
|  | 	if (IS_SD(mmc)) { | ||||||
|  | 		puts("BKOPS_EN only exists on eMMC\n"); | ||||||
|  | 		return CMD_RET_FAILURE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return mmc_set_bkops_enable(mmc); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| static cmd_tbl_t cmd_mmc[] = { | static cmd_tbl_t cmd_mmc[] = { | ||||||
| 	U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), | 	U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), | ||||||
| 	U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), | 	U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), | ||||||
|  | @ -749,6 +774,9 @@ static cmd_tbl_t cmd_mmc[] = { | ||||||
| 	U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), | 	U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), | ||||||
| #endif | #endif | ||||||
| 	U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), | 	U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), | ||||||
|  | #ifdef CONFIG_CMD_BKOPS_ENABLE | ||||||
|  | 	U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""), | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | ||||||
|  | @ -813,6 +841,10 @@ U_BOOT_CMD( | ||||||
| 	"mmc rpmb counter - read the value of the write counter\n" | 	"mmc rpmb counter - read the value of the write counter\n" | ||||||
| #endif | #endif | ||||||
| 	"mmc setdsr <value> - set DSR register value\n" | 	"mmc setdsr <value> - set DSR register value\n" | ||||||
|  | #ifdef CONFIG_CMD_BKOPS_ENABLE | ||||||
|  | 	"mmc bkops-enable <dev> - enable background operations handshake on device\n" | ||||||
|  | 	"   WARNING: This is a write-once setting.\n" | ||||||
|  | #endif | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| /* Old command kept for compatibility. Same as 'mmc info' */ | /* Old command kept for compatibility. Same as 'mmc info' */ | ||||||
|  |  | ||||||
|  | @ -1817,3 +1817,37 @@ int mmc_initialize(bd_t *bis) | ||||||
| 	mmc_do_preinit(); | 	mmc_do_preinit(); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_CMD_BKOPS_ENABLE | ||||||
|  | int mmc_set_bkops_enable(struct mmc *mmc) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); | ||||||
|  | 
 | ||||||
|  | 	err = mmc_send_ext_csd(mmc, ext_csd); | ||||||
|  | 	if (err) { | ||||||
|  | 		puts("Could not get ext_csd register values\n"); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) { | ||||||
|  | 		puts("Background operations not supported on device\n"); | ||||||
|  | 		return -EMEDIUMTYPE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (ext_csd[EXT_CSD_BKOPS_EN] & 0x1) { | ||||||
|  | 		puts("Background operations already enabled\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN, 1); | ||||||
|  | 	if (err) { | ||||||
|  | 		puts("Failed to enable manual background operations\n"); | ||||||
|  | 		return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	puts("Enabled manual background operations\n"); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | @ -174,6 +174,7 @@ | ||||||
| #define EXT_CSD_MAX_ENH_SIZE_MULT	157	/* R */ | #define EXT_CSD_MAX_ENH_SIZE_MULT	157	/* R */ | ||||||
| #define EXT_CSD_PARTITIONING_SUPPORT	160	/* RO */ | #define EXT_CSD_PARTITIONING_SUPPORT	160	/* RO */ | ||||||
| #define EXT_CSD_RST_N_FUNCTION		162	/* R/W */ | #define EXT_CSD_RST_N_FUNCTION		162	/* R/W */ | ||||||
|  | #define EXT_CSD_BKOPS_EN		163	/* R/W & R/W/E */ | ||||||
| #define EXT_CSD_WR_REL_PARAM		166	/* R */ | #define EXT_CSD_WR_REL_PARAM		166	/* R */ | ||||||
| #define EXT_CSD_WR_REL_SET		167	/* R/W */ | #define EXT_CSD_WR_REL_SET		167	/* R/W */ | ||||||
| #define EXT_CSD_RPMB_MULT		168	/* RO */ | #define EXT_CSD_RPMB_MULT		168	/* RO */ | ||||||
|  | @ -188,6 +189,7 @@ | ||||||
| #define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */ | #define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */ | ||||||
| #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */ | #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */ | ||||||
| #define EXT_CSD_BOOT_MULT		226	/* RO */ | #define EXT_CSD_BOOT_MULT		226	/* RO */ | ||||||
|  | #define EXT_CSD_BKOPS_SUPPORT		502	/* RO */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * EXT_CSD field definitions |  * EXT_CSD field definitions | ||||||
|  | @ -540,6 +542,10 @@ int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk, | ||||||
| 		  unsigned short cnt, unsigned char *key); | 		  unsigned short cnt, unsigned char *key); | ||||||
| int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk, | int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk, | ||||||
| 		   unsigned short cnt, unsigned char *key); | 		   unsigned short cnt, unsigned char *key); | ||||||
|  | #ifdef CONFIG_CMD_BKOPS_ENABLE | ||||||
|  | int mmc_set_bkops_enable(struct mmc *mmc); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Start device initialization and return immediately; it does not block on |  * Start device initialization and return immediately; it does not block on | ||||||
|  * polling OCR (operation condition register) status.  Then you should call |  * polling OCR (operation condition register) status.  Then you should call | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue