diff options
Diffstat (limited to 'drivers/mmc/core/sdio.c')
| -rw-r--r-- | drivers/mmc/core/sdio.c | 54 | 
1 files changed, 38 insertions, 16 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 2273ce6b6c1..aa0719a4dfd 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -157,10 +157,7 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr)  			if (ret)  				goto out; -			if (card->host->caps & -				(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | -				 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | -				 MMC_CAP_UHS_DDR50)) { +			if (mmc_host_uhs(card->host)) {  				if (data & SDIO_UHS_DDR50)  					card->sw_caps.sd3_bus_mode  						|= SD_MODE_UHS_DDR50; @@ -478,8 +475,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)  	 * If the host doesn't support any of the UHS-I modes, fallback on  	 * default speed.  	 */ -	if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | -	    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) +	if (!mmc_host_uhs(card->host))  		return 0;  	bus_speed = SDIO_SPEED_SDR12; @@ -489,23 +485,27 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)  			bus_speed = SDIO_SPEED_SDR104;  			timing = MMC_TIMING_UHS_SDR104;  			card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; +			card->sd_bus_speed = UHS_SDR104_BUS_SPEED;  	} else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&  		   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {  			bus_speed = SDIO_SPEED_DDR50;  			timing = MMC_TIMING_UHS_DDR50;  			card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; +			card->sd_bus_speed = UHS_DDR50_BUS_SPEED;  	} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |  		    MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &  		    SD_MODE_UHS_SDR50)) {  			bus_speed = SDIO_SPEED_SDR50;  			timing = MMC_TIMING_UHS_SDR50;  			card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; +			card->sd_bus_speed = UHS_SDR50_BUS_SPEED;  	} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |  		    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&  		   (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {  			bus_speed = SDIO_SPEED_SDR25;  			timing = MMC_TIMING_UHS_SDR25;  			card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR; +			card->sd_bus_speed = UHS_SDR25_BUS_SPEED;  	} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |  		    MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |  		    MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode & @@ -513,6 +513,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)  			bus_speed = SDIO_SPEED_SDR12;  			timing = MMC_TIMING_UHS_SDR12;  			card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR; +			card->sd_bus_speed = UHS_SDR12_BUS_SPEED;  	}  	err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); @@ -583,10 +584,19 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,  {  	struct mmc_card *card;  	int err; +	int retries = 10;  	BUG_ON(!host);  	WARN_ON(!host->claimed); +try_again: +	if (!retries) { +		pr_warning("%s: Skipping voltage switch\n", +				mmc_hostname(host)); +		ocr &= ~R4_18V_PRESENT; +		host->ocr &= ~R4_18V_PRESENT; +	} +  	/*  	 * Inform the card of the voltage  	 */ @@ -645,14 +655,16 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,  	 * systems that claim 1.8v signalling in fact do not support  	 * it.  	 */ -	if ((ocr & R4_18V_PRESENT) && -		(host->caps & -			(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | -			 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | -			 MMC_CAP_UHS_DDR50))) { -		err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, -				true); -		if (err) { +	if (!powered_resume && (ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) { +		err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); +		if (err == -EAGAIN) { +			sdio_reset(host); +			mmc_go_idle(host); +			mmc_send_if_cond(host, host->ocr_avail); +			mmc_remove_card(card); +			retries--; +			goto try_again; +		} else if (err) {  			ocr &= ~R4_18V_PRESENT;  			host->ocr &= ~R4_18V_PRESENT;  		} @@ -937,10 +949,12 @@ static int mmc_sdio_resume(struct mmc_host *host)  	mmc_claim_host(host);  	/* No need to reinitialize powered-resumed nonremovable cards */ -	if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) +	if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { +		sdio_reset(host); +		mmc_go_idle(host);  		err = mmc_sdio_init_card(host, host->ocr, host->card,  					mmc_card_keep_power(host)); -	else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { +	} else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {  		/* We may have switched to 1-bit mode during suspend */  		err = sdio_enable_4bit_bus(host->card);  		if (err > 0) { @@ -1020,6 +1034,10 @@ static int mmc_sdio_power_restore(struct mmc_host *host)  		goto out;  	} +	if (mmc_host_uhs(host)) +		/* to query card if 1.8V signalling is supported */ +		host->ocr |= R4_18V_PRESENT; +  	ret = mmc_sdio_init_card(host, host->ocr, host->card,  				mmc_card_keep_power(host));  	if (!ret && host->sdio_irqs) @@ -1085,6 +1103,10 @@ int mmc_attach_sdio(struct mmc_host *host)  	/*  	 * Detect and init the card.  	 */ +	if (mmc_host_uhs(host)) +		/* to query card if 1.8V signalling is supported */ +		host->ocr |= R4_18V_PRESENT; +  	err = mmc_sdio_init_card(host, host->ocr, NULL, 0);  	if (err) {  		if (err == -EAGAIN) {  |