diff options
| author | Asutosh Das <asutoshd@codeaurora.org> | 2013-11-08 12:31:48 +0530 |
|---|---|---|
| committer | Subhash Jadavani <subhashj@codeaurora.org> | 2016-05-27 10:28:57 -0700 |
| commit | deba741527aa75d03e2d0d1f6010b5bae538a4ac (patch) | |
| tree | 415a36e324e36205944e98faa1c224fb7a2dcd11 | |
| parent | 2c530476d3898b8ab1d3d12df02bf96faf2e43bb (diff) | |
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>
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 24 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 1 |
2 files changed, 24 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 0394eaf50d86..abde70324954 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -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); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 1430ca98dd94..f6c1ce0b0475 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -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); |
