mmc: sdhci: Turn on controller clocks and card power at MMC_POWER_UP

Currently, the clock to the card is enabled prior to enabling
the power to card. Specification requires that the power be
supplied first and then a delay of 10ms and then clock be
provided to the card.

In this, during MMC_POWER_UP mode, the controller clocks would be
ON and the power would be supplied to the card. In the MMC_POWER_ON
mode, the clocks to the card would be enabled and the rate set.
A callback has been provided to facilitate the enabling of
controller clocks.

CRs-Fixed: 567658
Change-Id: I2d66eae1581b9b136faaba4cafc330aeb6a3f364
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
[venkatg@codeaurora.org: Fix sdhci_set_power fn signature
as it changed in 3.14 kernel]
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
[subhashj@codeaurora.org: fixed minor merge conflict]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
Asutosh Das 2013-11-08 12:31:48 +05:30 committed by Subhash Jadavani
parent 2c530476d3
commit deba741527
2 changed files with 24 additions and 1 deletions

View file

@ -1693,6 +1693,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
unsigned long flags;
u8 ctrl;
struct mmc_host *mmc = host->mmc;
int ret;
if (host->flags & SDHCI_DEVICE_DEAD) {
if (!IS_ERR(mmc->supply.vmmc) &&
@ -1706,6 +1707,25 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
sdhci_enable_preset_value(host, false);
/*
* The controller clocks may be off during power-up and we may end up
* enabling card clock before giving power to the card. Hence, during
* MMC_POWER_UP enable the controller clock and turn-on the regulators.
* The mmc_power_up would provide the necessary delay before turning on
* the clocks to the card.
*/
if (ios->power_mode & MMC_POWER_UP) {
if (host->ops->enable_controller_clock) {
ret = host->ops->enable_controller_clock(host);
if (ret) {
pr_err("%s: enabling controller clock: failed: %d\n",
mmc_hostname(host->mmc), ret);
} else {
sdhci_set_power(host, ios->power_mode, ios->vdd);
}
}
}
spin_lock_irqsave(&host->lock, flags);
if (!ios->clock || ios->clock != host->clock) {
spin_unlock_irqrestore(&host->lock, flags);
@ -1727,7 +1747,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
}
spin_unlock_irqrestore(&host->lock, flags);
if (ios->power_mode & (MMC_POWER_UP | MMC_POWER_ON))
if (!host->ops->enable_controller_clock && (ios->power_mode &
(MMC_POWER_UP |
MMC_POWER_ON)))
sdhci_set_power(host, ios->power_mode, ios->vdd);
spin_lock_irqsave(&host->lock, flags);

View file

@ -640,6 +640,7 @@ struct sdhci_ops {
int (*config_auto_tuning_cmd)(struct sdhci_host *host,
bool enable,
u32 type);
int (*enable_controller_clock)(struct sdhci_host *host);
void (*dump_vendor_regs)(struct sdhci_host *host);
void (*toggle_cdr)(struct sdhci_host *host, bool enable);
void (*voltage_switch)(struct sdhci_host *host);