diff options
Diffstat (limited to 'drivers/mmc/core/sd.c')
| -rw-r--r-- | drivers/mmc/core/sd.c | 65 | 
1 files changed, 43 insertions, 22 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 8eba697d3d86..ec02067f03c5 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -455,7 +455,7 @@ static void sd_update_bus_speed_mode(struct mmc_card *card)  	 * If the host doesn't support any of the UHS-I modes, fallback on  	 * default speed.  	 */ -	if (!mmc_host_uhs(card->host)) { +	if (!mmc_host_can_uhs(card->host)) {  		card->sd_bus_speed = 0;  		return;  	} @@ -618,6 +618,29 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status)  }  /* + * Determine if the card should tune or not. + */ +static bool mmc_sd_use_tuning(struct mmc_card *card) +{ +	/* +	 * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and +	 * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. +	 */ +	if (mmc_host_is_spi(card->host)) +		return false; + +	switch (card->host->ios.timing) { +	case MMC_TIMING_UHS_SDR50: +	case MMC_TIMING_UHS_SDR104: +		return true; +	case MMC_TIMING_UHS_DDR50: +		return !mmc_card_no_uhs_ddr50_tuning(card); +	} + +	return false; +} + +/*   * UHS-I specific initialization procedure   */  static int mmc_sd_init_uhs_card(struct mmc_card *card) @@ -660,14 +683,7 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)  	if (err)  		goto out; -	/* -	 * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and -	 * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. -	 */ -	if (!mmc_host_is_spi(card->host) && -		(card->host->ios.timing == MMC_TIMING_UHS_SDR50 || -		 card->host->ios.timing == MMC_TIMING_UHS_DDR50 || -		 card->host->ios.timing == MMC_TIMING_UHS_SDR104)) { +	if (mmc_sd_use_tuning(card)) {  		err = mmc_execute_tuning(card);  		/* @@ -851,7 +867,7 @@ try_again:  	 * to switch to 1.8V signaling level. If the card has failed  	 * repeatedly to switch however, skip this.  	 */ -	if (retries && mmc_host_uhs(host)) +	if (retries && mmc_host_can_uhs(host))  		ocr |= SD_OCR_S18R;  	/* @@ -1493,7 +1509,7 @@ retry:  	 * signaling. Detect that situation and try to initialize a UHS-I (1.8V)  	 * transfer mode.  	 */ -	if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) && +	if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_can_uhs(host) &&  	    mmc_sd_card_using_v18(card) &&  	    host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) {  		if (mmc_host_set_uhs_voltage(host) || @@ -1508,7 +1524,7 @@ retry:  	}  	/* Initialization sequence for UHS-I cards */ -	if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { +	if (rocr & SD_ROCR_S18A && mmc_host_can_uhs(host)) {  		err = mmc_sd_init_uhs_card(card);  		if (err)  			goto free_card; @@ -1597,15 +1613,6 @@ free_card:  }  /* - * Host is being removed. Free up the current card. - */ -static void mmc_sd_remove(struct mmc_host *host) -{ -	mmc_remove_card(host->card); -	host->card = NULL; -} - -/*   * Card detection - card is alive.   */  static int mmc_sd_alive(struct mmc_host *host) @@ -1630,7 +1637,8 @@ static void mmc_sd_detect(struct mmc_host *host)  	mmc_put_card(host->card, NULL);  	if (err) { -		mmc_sd_remove(host); +		mmc_remove_card(host->card); +		host->card = NULL;  		mmc_claim_host(host);  		mmc_detach_bus(host); @@ -1731,6 +1739,19 @@ out:  }  /* + * Host is being removed. Free up the current card and do a graceful power-off. + */ +static void mmc_sd_remove(struct mmc_host *host) +{ +	get_device(&host->card->dev); +	mmc_remove_card(host->card); + +	_mmc_sd_suspend(host); + +	put_device(&host->card->dev); +	host->card = NULL; +} +/*   * Callback for suspend   */  static int mmc_sd_suspend(struct mmc_host *host)  | 
