Commit ae628903 authored by Pierre Ossman's avatar Pierre Ossman

sdhci: avoid changing voltage needlessly

Because of granularity issues, sometimes we told the hardware to change
to the voltage we were already at. Rework the logic so this doesn't
happen.
Signed-off-by: default avatarPierre Ossman <pierre@ossman.eu>
parent 7ceeb6a4
......@@ -1005,50 +1005,53 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
{
u8 pwr;
if (host->power == power)
return;
if (power == (unsigned short)-1) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
goto out;
}
/*
* Spec says that we should clear the power reg before setting
* a new value. Some controllers don't seem to like this though.
*/
if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
pwr = SDHCI_POWER_ON;
if (power == (unsigned short)-1)
pwr = 0;
else {
switch (1 << power) {
case MMC_VDD_165_195:
pwr |= SDHCI_POWER_180;
pwr = SDHCI_POWER_180;
break;
case MMC_VDD_29_30:
case MMC_VDD_30_31:
pwr |= SDHCI_POWER_300;
pwr = SDHCI_POWER_300;
break;
case MMC_VDD_32_33:
case MMC_VDD_33_34:
pwr |= SDHCI_POWER_330;
pwr = SDHCI_POWER_330;
break;
default:
BUG();
}
}
if (host->pwr == pwr)
return;
host->pwr = pwr;
if (pwr == 0) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
return;
}
/*
* Spec says that we should clear the power reg before setting
* a new value. Some controllers don't seem to like this though.
*/
if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
/*
* At least the Marvell CaFe chip gets confused if we set the voltage
* and set turn on power at the same time, so set the voltage first.
*/
if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
sdhci_writeb(host, pwr & ~SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
out:
host->power = power;
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}
/*****************************************************************************\
......
......@@ -255,7 +255,7 @@ struct sdhci_host {
unsigned int timeout_clk; /* Timeout freq (KHz) */
unsigned int clock; /* Current clock (MHz) */
unsigned short power; /* Current voltage */
u8 pwr; /* Current voltage */
struct mmc_request *mrq; /* Current request */
struct mmc_command *cmd; /* Current command */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment