Skip to content

Commit

Permalink
mmc: sdhci: Improve external VDD regulator support
Browse files Browse the repository at this point in the history
A standard compliant SDHCI can itself supply VDD at 1.8, 3.0, or 3.3v.
Several vendors ignore this and instead rely upon external regulators
to supply VDD.  While the external regulators typically can supply one
of the standard SDHCI voltage levels, there is no real reason for this
to be a hard requirement.

This patch alters the SDHCI driver such that external VDD regulators
that provide voltages other than the three mentioned above may be used
so long as they can supply a voltage that meets the needs of the card.

In the case that an external VDD regulator is provided, it is reasonable
to ignore the voltage capabilities of the host controller and allow the
external regulator to set the OCR mask.  Additionally, there is no need
to convert a VDD voltage request into one of the standard SDHCI voltage
levels or program it in the host controller's power control register.

Signed-off-by: Tim Kryger <tim.kryger@gmail.com>
Tested-by: Sachin Kamat <spk.linux@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
  • Loading branch information
Tim Kryger authored and Ulf Hansson committed Jul 9, 2014
1 parent 87a0f46 commit 5222161
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,13 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
struct mmc_host *mmc = host->mmc;
u8 pwr = 0;

if (!IS_ERR(mmc->supply.vmmc)) {
spin_unlock_irq(&host->lock);
mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, vdd);
spin_lock_irq(&host->lock);
return;
}

if (mode != MMC_POWER_OFF) {
switch (1 << vdd) {
case MMC_VDD_165_195:
Expand Down Expand Up @@ -1284,12 +1291,6 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
mdelay(10);
}

if (!IS_ERR(mmc->supply.vmmc)) {
spin_unlock_irq(&host->lock);
mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, vdd);
spin_lock_irq(&host->lock);
}
}

/*****************************************************************************\
Expand Down Expand Up @@ -3092,8 +3093,9 @@ int sdhci_add_host(struct sdhci_host *host)
SDHCI_MAX_CURRENT_MULTIPLIER;
}

/* If OCR set by external regulators, use it instead */
if (mmc->ocr_avail)
ocr_avail &= mmc->ocr_avail;
ocr_avail = mmc->ocr_avail;

if (host->ocr_mask)
ocr_avail &= host->ocr_mask;
Expand Down

0 comments on commit 5222161

Please sign in to comment.