mmc: sdhci-pci: Fix initialization of some SD cards for Intel BYT-based controllers

Bus power may control card power, but the full reset done by SDHCI at
initialization 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.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20210331081752.23621-1-adrian.hunter@intel.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Adrian Hunter 2021-03-31 11:17:52 +03:00 committed by Ulf Hansson
parent 47805532eb
commit 2970134b92

View File

@ -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)
@ -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;
}