mmc: extend the mmc hardware partitioning API with write reliability
The eMMC partition write reliability settings are to be set while partitioning a device, as per the eMMC spec, so changes to these attributes needs to be done in the hardware partitioning API. This commit adds such support. Signed-off-by: Diego Santa Cruz <Diego.SantaCruz@spinetix.com>
This commit is contained in:
		
							parent
							
								
									c599f53b57
								
							
						
					
					
						commit
						8dda5b0e60
					
				|  | @ -615,6 +615,7 @@ int mmc_hwpart_config(struct mmc *mmc, | ||||||
| 	u32 gp_size_mult[4]; | 	u32 gp_size_mult[4]; | ||||||
| 	u32 max_enh_size_mult; | 	u32 max_enh_size_mult; | ||||||
| 	u32 tot_enh_size_mult = 0; | 	u32 tot_enh_size_mult = 0; | ||||||
|  | 	u8 wr_rel_set; | ||||||
| 	int i, pidx, err; | 	int i, pidx, err; | ||||||
| 	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); | 	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); | ||||||
| 
 | 
 | ||||||
|  | @ -689,6 +690,33 @@ int mmc_hwpart_config(struct mmc *mmc, | ||||||
| 		return -EMEDIUMTYPE; | 		return -EMEDIUMTYPE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* The default value of EXT_CSD_WR_REL_SET is device
 | ||||||
|  | 	 * dependent, the values can only be changed if the | ||||||
|  | 	 * EXT_CSD_HS_CTRL_REL bit is set. The values can be | ||||||
|  | 	 * changed only once and before partitioning is completed. */ | ||||||
|  | 	wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET]; | ||||||
|  | 	if (conf->user.wr_rel_change) { | ||||||
|  | 		if (conf->user.wr_rel_set) | ||||||
|  | 			wr_rel_set |= EXT_CSD_WR_DATA_REL_USR; | ||||||
|  | 		else | ||||||
|  | 			wr_rel_set &= ~EXT_CSD_WR_DATA_REL_USR; | ||||||
|  | 	} | ||||||
|  | 	for (pidx = 0; pidx < 4; pidx++) { | ||||||
|  | 		if (conf->gp_part[pidx].wr_rel_change) { | ||||||
|  | 			if (conf->gp_part[pidx].wr_rel_set) | ||||||
|  | 				wr_rel_set |= EXT_CSD_WR_DATA_REL_GP(pidx); | ||||||
|  | 			else | ||||||
|  | 				wr_rel_set &= ~EXT_CSD_WR_DATA_REL_GP(pidx); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET] && | ||||||
|  | 	    !(ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_HS_CTRL_REL)) { | ||||||
|  | 		puts("Card does not support host controlled partition write " | ||||||
|  | 		     "reliability settings\n"); | ||||||
|  | 		return -EMEDIUMTYPE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (ext_csd[EXT_CSD_PARTITION_SETTING] & | 	if (ext_csd[EXT_CSD_PARTITION_SETTING] & | ||||||
| 	    EXT_CSD_PARTITION_SETTING_COMPLETED) { | 	    EXT_CSD_PARTITION_SETTING_COMPLETED) { | ||||||
| 		printf("Card already partitioned\n"); | 		printf("Card already partitioned\n"); | ||||||
|  | @ -746,6 +774,17 @@ int mmc_hwpart_config(struct mmc *mmc, | ||||||
| 	if (mode == MMC_HWPART_CONF_SET) | 	if (mode == MMC_HWPART_CONF_SET) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
|  | 	/* The WR_REL_SET is a write-once register but shall be
 | ||||||
|  | 	 * written before setting PART_SETTING_COMPLETED. As it is | ||||||
|  | 	 * write-once we can only write it when completing the | ||||||
|  | 	 * partitioning. */ | ||||||
|  | 	if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET]) { | ||||||
|  | 		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, | ||||||
|  | 				 EXT_CSD_WR_REL_SET, wr_rel_set); | ||||||
|  | 		if (err) | ||||||
|  | 			return err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* Setting PART_SETTING_COMPLETED confirms the partition
 | 	/* Setting PART_SETTING_COMPLETED confirms the partition
 | ||||||
| 	 * configuration but it only becomes effective after power | 	 * configuration but it only becomes effective after power | ||||||
| 	 * cycle, so we do not adjust the partition related settings | 	 * cycle, so we do not adjust the partition related settings | ||||||
|  |  | ||||||
|  | @ -155,6 +155,8 @@ | ||||||
| #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_WR_REL_PARAM		166	/* R */ | ||||||
|  | #define EXT_CSD_WR_REL_SET		167	/* R/W */ | ||||||
| #define EXT_CSD_RPMB_MULT		168	/* RO */ | #define EXT_CSD_RPMB_MULT		168	/* RO */ | ||||||
| #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */ | #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */ | ||||||
| #define EXT_CSD_BOOT_BUS_WIDTH		177 | #define EXT_CSD_BOOT_BUS_WIDTH		177 | ||||||
|  | @ -207,6 +209,11 @@ | ||||||
| #define EXT_CSD_ENH_USR		(1 << 0)	/* user data area is enhanced */ | #define EXT_CSD_ENH_USR		(1 << 0)	/* user data area is enhanced */ | ||||||
| #define EXT_CSD_ENH_GP(x)	(1 << ((x)+1))	/* GP part (x+1) is enhanced */ | #define EXT_CSD_ENH_GP(x)	(1 << ((x)+1))	/* GP part (x+1) is enhanced */ | ||||||
| 
 | 
 | ||||||
|  | #define EXT_CSD_HS_CTRL_REL	(1 << 0)	/* host controlled WR_REL_SET */ | ||||||
|  | 
 | ||||||
|  | #define EXT_CSD_WR_DATA_REL_USR		(1 << 0)	/* user data area WR_REL */ | ||||||
|  | #define EXT_CSD_WR_DATA_REL_GP(x)	(1 << ((x)+1))	/* GP part (x+1) WR_REL */ | ||||||
|  | 
 | ||||||
| #define R1_ILLEGAL_COMMAND		(1 << 22) | #define R1_ILLEGAL_COMMAND		(1 << 22) | ||||||
| #define R1_APP_CMD			(1 << 5) | #define R1_APP_CMD			(1 << 5) | ||||||
| 
 | 
 | ||||||
|  | @ -337,10 +344,14 @@ struct mmc_hwpart_conf { | ||||||
| 	struct { | 	struct { | ||||||
| 		uint enh_start;	/* in 512-byte sectors */ | 		uint enh_start;	/* in 512-byte sectors */ | ||||||
| 		uint enh_size;	/* in 512-byte sectors, if 0 no enh area */ | 		uint enh_size;	/* in 512-byte sectors, if 0 no enh area */ | ||||||
|  | 		unsigned wr_rel_change : 1; | ||||||
|  | 		unsigned wr_rel_set : 1; | ||||||
| 	} user; | 	} user; | ||||||
| 	struct { | 	struct { | ||||||
| 		uint size;	/* in 512-byte sectors */ | 		uint size;	/* in 512-byte sectors */ | ||||||
| 		int enhanced; | 		unsigned enhanced : 1; | ||||||
|  | 		unsigned wr_rel_change : 1; | ||||||
|  | 		unsigned wr_rel_set : 1; | ||||||
| 	} gp_part[4]; | 	} gp_part[4]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue