Message ID | 20210331081752.23621-1-adrian.hunter@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | mmc: sdhci-pci: Fix initialization of some SD cards for Intel BYT-based controllers | expand |
On Wed, 31 Mar 2021 at 10:17, Adrian Hunter <adrian.hunter@intel.com> wrote: > > 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 Applied for next, thanks! Kind regards Uffe > --- > drivers/mmc/host/sdhci-pci-core.c | 27 +++++++++++++++++++++++++++ > 1 file changed, 27 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c > index b3caa174effe..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 @@ static int bxt_get_cd(struct mmc_host *mmc) > 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; > } > > -- > 2.17.1 >
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index b3caa174effe..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 @@ static int bxt_get_cd(struct mmc_host *mmc) 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; }
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 --- drivers/mmc/host/sdhci-pci-core.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)