Commit 2970134b authored by Adrian Hunter's avatar Adrian Hunter Committed by Ulf Hansson
Browse files

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: default avatarAdrian 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: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 47805532
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -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;
}