mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	mmc: core: Support UHS-II card control and access
Embed UHS-II access/control functionality into the MMC request processing flow. Signed-off-by: Jason Lai <jason.lai@genesyslogic.com.tw> Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw> Message-ID: <20241018105333.4569-2-victorshihgli@gmail.com> [Ulf: A couple of cleanups and fixed sd_uhs2_power_off()] Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
		
							parent
							
								
									328bda09cc
								
							
						
					
					
						commit
						9a9f7e1395
					
				
					 8 changed files with 1103 additions and 37 deletions
				
			
		|  | @ -354,6 +354,9 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | |||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (host->uhs2_sd_tran) | ||||
| 		mmc_uhs2_prepare_cmd(host, mrq); | ||||
| 
 | ||||
| 	led_trigger_event(host->led, LED_FULL); | ||||
| 	__mmc_start_request(host, mrq); | ||||
| 
 | ||||
|  | @ -453,6 +456,9 @@ int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq) | |||
| 	if (err) | ||||
| 		goto out_err; | ||||
| 
 | ||||
| 	if (host->uhs2_sd_tran) | ||||
| 		mmc_uhs2_prepare_cmd(host, mrq); | ||||
| 
 | ||||
| 	err = host->cqe_ops->cqe_request(host, mrq); | ||||
| 	if (err) | ||||
| 		goto out_err; | ||||
|  | @ -1135,7 +1141,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) | |||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { | ||||
| 	if (!mmc_card_uhs2(host) && host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { | ||||
| 		bit = ffs(ocr) - 1; | ||||
| 		ocr &= 3 << bit; | ||||
| 		mmc_power_cycle(host, ocr); | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ static int mmc_decode_csd(struct mmc_card *card, bool is_sduc) | |||
| /*
 | ||||
|  * Given a 64-bit response, decode to our card SCR structure. | ||||
|  */ | ||||
| static int mmc_decode_scr(struct mmc_card *card) | ||||
| int mmc_decode_scr(struct mmc_card *card) | ||||
| { | ||||
| 	struct sd_scr *scr = &card->scr; | ||||
| 	unsigned int scr_struct; | ||||
|  | @ -903,7 +903,7 @@ int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int mmc_sd_get_ro(struct mmc_host *host) | ||||
| int mmc_sd_get_ro(struct mmc_host *host) | ||||
| { | ||||
| 	int ro; | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ struct mmc_card; | |||
| 
 | ||||
| int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr); | ||||
| int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc); | ||||
| int mmc_decode_scr(struct mmc_card *card); | ||||
| int mmc_sd_get_ro(struct mmc_host *host); | ||||
| void mmc_decode_cid(struct mmc_card *card); | ||||
| int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, | ||||
| 	bool reinit); | ||||
|  |  | |||
|  | @ -42,6 +42,15 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) | |||
| 	if (WARN_ON(card && card->host != host)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * UHS2 packet has APP bit so only set APP_CMD flag here. | ||||
| 	 * Will set the APP bit when assembling UHS2 packet. | ||||
| 	 */ | ||||
| 	if (host->uhs2_sd_tran) { | ||||
| 		host->uhs2_app_cmd = true; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	cmd.opcode = MMC_APP_CMD; | ||||
| 
 | ||||
| 	if (card) { | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| 
 | ||||
| struct mmc_card; | ||||
| struct mmc_host; | ||||
| struct mmc_request; | ||||
| 
 | ||||
| int mmc_app_set_bus_width(struct mmc_card *card, int width); | ||||
| int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); | ||||
|  | @ -22,6 +23,7 @@ int mmc_app_send_scr(struct mmc_card *card); | |||
| int mmc_app_sd_status(struct mmc_card *card, void *ssr); | ||||
| int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); | ||||
| int mmc_send_ext_addr(struct mmc_host *host, u32 addr); | ||||
| void mmc_uhs2_prepare_cmd(struct mmc_host *host, struct mmc_request *mrq); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -11,6 +11,20 @@ | |||
| struct mmc_data; | ||||
| struct mmc_request; | ||||
| 
 | ||||
| #define UHS2_MAX_PAYLOAD_LEN 2 | ||||
| #define UHS2_MAX_RESP_LEN 20 | ||||
| 
 | ||||
| struct uhs2_command { | ||||
| 	u16	header; | ||||
| 	u16	arg; | ||||
| 	__be32	payload[UHS2_MAX_PAYLOAD_LEN]; | ||||
| 	u8	payload_len; | ||||
| 	u8	packet_len; | ||||
| 	u8	tmode_half_duplex; | ||||
| 	u8	uhs2_resp[UHS2_MAX_RESP_LEN];	/* UHS2 native cmd resp */ | ||||
| 	u8	uhs2_resp_len;			/* UHS2 native cmd resp len */ | ||||
| }; | ||||
| 
 | ||||
| struct mmc_command { | ||||
| 	u32			opcode; | ||||
| 	u32			arg; | ||||
|  | @ -97,6 +111,8 @@ struct mmc_command { | |||
| 	struct mmc_data		*data;		/* data segment associated with cmd */ | ||||
| 	struct mmc_request	*mrq;		/* associated request */ | ||||
| 
 | ||||
| 	struct uhs2_command	*uhs2_cmd;	/* UHS2 command */ | ||||
| 
 | ||||
| 	/* for SDUC */ | ||||
| 	bool has_ext_addr; | ||||
| 	u8 ext_addr; | ||||
|  | @ -158,6 +174,7 @@ struct mmc_request { | |||
| 	const struct bio_crypt_ctx *crypto_ctx; | ||||
| 	int			crypto_key_slot; | ||||
| #endif | ||||
| 	struct uhs2_command	uhs2_cmd; | ||||
| }; | ||||
| 
 | ||||
| struct mmc_card; | ||||
|  |  | |||
|  | @ -127,6 +127,13 @@ struct sd_uhs2_caps { | |||
| }; | ||||
| 
 | ||||
| enum sd_uhs2_operation { | ||||
| 	UHS2_PHY_INIT = 0, | ||||
| 	UHS2_SET_CONFIG, | ||||
| 	UHS2_ENABLE_INT, | ||||
| 	UHS2_DISABLE_INT, | ||||
| 	UHS2_ENABLE_CLK, | ||||
| 	UHS2_DISABLE_CLK, | ||||
| 	UHS2_CHECK_DORMANT, | ||||
| 	UHS2_SET_IOS, | ||||
| }; | ||||
| 
 | ||||
|  | @ -453,6 +460,8 @@ struct mmc_host { | |||
| #endif | ||||
| #define MMC_CAP2_ALT_GPT_TEGRA	(1 << 28)	/* Host with eMMC that has GPT entry at a non-standard location */ | ||||
| 
 | ||||
| 	bool			uhs2_sd_tran;	/* UHS-II flag for SD_TRAN state */ | ||||
| 	bool			uhs2_app_cmd;	/* UHS-II flag for APP command */ | ||||
| 	struct sd_uhs2_caps	uhs2_caps;	/* Host UHS-II capabilities */ | ||||
| 
 | ||||
| 	int			fixed_drv_type;	/* fixed driver type for non-removable media */ | ||||
|  | @ -714,6 +723,12 @@ static inline void mmc_debugfs_err_stats_inc(struct mmc_host *host, | |||
| 	host->err_stats[stat] += 1; | ||||
| } | ||||
| 
 | ||||
| static inline int mmc_card_uhs2_hd_mode(struct mmc_host *host) | ||||
| { | ||||
| 	return host->ios.timing == MMC_TIMING_UHS2_SPEED_A_HD || | ||||
| 	       host->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD; | ||||
| } | ||||
| 
 | ||||
| int mmc_sd_switch(struct mmc_card *card, bool mode, int group, | ||||
| 		u8 value, u8 *resp); | ||||
| int mmc_send_status(struct mmc_card *card, u32 *status); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Victor Shih
						Victor Shih