summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsutosh Das <asutoshd@codeaurora.org>2013-11-08 12:31:48 +0530
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-27 10:28:57 -0700
commitdeba741527aa75d03e2d0d1f6010b5bae538a4ac (patch)
tree415a36e324e36205944e98faa1c224fb7a2dcd11
parent2c530476d3898b8ab1d3d12df02bf96faf2e43bb (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.c24
-rw-r--r--drivers/mmc/host/sdhci.h1
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);