diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pci-core.c')
| -rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 31 | 
1 files changed, 30 insertions, 1 deletions
| diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 9552708846ca..be19785227fe 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -516,6 +516,7 @@ struct intel_host {  	int	drv_strength;  	bool	d3_retune;  	bool	rpm_retune_ok; +	bool	needs_pwr_off;  	u32	glk_rx_ctrl1;  	u32	glk_tun_val;  	u32	active_ltr; @@ -643,9 +644,25 @@ out:  static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,  				  unsigned short vdd)  { +	struct sdhci_pci_slot *slot = sdhci_priv(host); +	struct intel_host *intel_host = sdhci_pci_priv(slot);  	int cntr;  	u8 reg; +	/* +	 * Bus power may control card power, but a full reset still may not +	 * reset the power, whereas a direct write to SDHCI_POWER_CONTROL can. +	 * That might be needed to initialize correctly, if the card was left +	 * powered on previously. +	 */ +	if (intel_host->needs_pwr_off) { +		intel_host->needs_pwr_off = false; +		if (mode != MMC_POWER_OFF) { +			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); +			usleep_range(10000, 12500); +		} +	} +  	sdhci_set_power(host, mode, vdd);  	if (mode == MMC_POWER_OFF) @@ -958,7 +975,7 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)  		slot->host->mmc->caps2 |= MMC_CAP2_CQE;  	if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) { -		slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES, +		slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;  		slot->host->mmc_host_ops.hs400_enhanced_strobe =  						intel_hs400_enhanced_strobe;  		slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; @@ -1135,6 +1152,14 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)  	return 0;  } +static void byt_needs_pwr_off(struct sdhci_pci_slot *slot) +{ +	struct intel_host *intel_host = sdhci_pci_priv(slot); +	u8 reg = sdhci_readb(slot->host, SDHCI_POWER_CONTROL); + +	intel_host->needs_pwr_off = reg  & SDHCI_POWER_ON; +} +  static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)  {  	byt_probe_slot(slot); @@ -1152,6 +1177,8 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)  	    slot->chip->pdev->subsystem_device == PCI_SUBDEVICE_ID_NI_78E3)  		slot->host->mmc->caps2 |= MMC_CAP2_AVOID_3_3V; +	byt_needs_pwr_off(slot); +  	return 0;  } @@ -1903,6 +1930,8 @@ static const struct pci_device_id pci_ids[] = {  	SDHCI_PCI_DEVICE(INTEL, CMLH_SD,   intel_byt_sd),  	SDHCI_PCI_DEVICE(INTEL, JSL_EMMC,  intel_glk_emmc),  	SDHCI_PCI_DEVICE(INTEL, JSL_SD,    intel_byt_sd), +	SDHCI_PCI_DEVICE(INTEL, LKF_EMMC,  intel_glk_emmc), +	SDHCI_PCI_DEVICE(INTEL, LKF_SD,    intel_byt_sd),  	SDHCI_PCI_DEVICE(O2, 8120,     o2),  	SDHCI_PCI_DEVICE(O2, 8220,     o2),  	SDHCI_PCI_DEVICE(O2, 8221,     o2), | 
