summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2013-05-28 18:21:57 +0530
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-27 10:28:41 -0700
commitcec2ab9ba3a05f03fa390c66cc77ef0e8ef36529 (patch)
treef87565d4cfd0493c0e6886fa5b7ccf49437c3484 /drivers
parent5af7b3e981b3211eb80652aa1bcc224a43582888 (diff)
mmc: sdhci-msm: fix pwrsave bit handling
SDCC controller provides the PWRSAVE control bit to automatically disable the clock to card when there is no activity with card. During the SDCC DLL tuning, PWRSAVE is disabled to make sure that clock is always running but once the DLL tuning is completed, currently we enable the PWRSAVE unconditionally irrespective of its previous state. This change ensures that we always check if the previous state of pwrsave before really enabling it. Change-Id: I464ab1e0db41af50550bb5a9ea9b909ee0d27dd9 Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci-msm.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index b76bc6b617c8..d08a2bb718d5 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -483,19 +483,25 @@ static int msm_init_cm_dll(struct sdhci_host *host)
int rc = 0;
unsigned long flags;
u32 wait_cnt;
+ bool prev_pwrsave, curr_pwrsave;
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
spin_lock_irqsave(&host->lock, flags);
-
+ prev_pwrsave = !!(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
+ CORE_CLK_PWRSAVE);
+ curr_pwrsave = prev_pwrsave;
/*
* Make sure that clock is always enabled when DLL
* tuning is in progress. Keeping PWRSAVE ON may
* turn off the clock. So let's disable the PWRSAVE
* here and re-enable it once tuning is completed.
*/
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- & ~CORE_CLK_PWRSAVE),
- host->ioaddr + CORE_VENDOR_SPEC);
+ if (prev_pwrsave) {
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+ & ~CORE_CLK_PWRSAVE),
+ host->ioaddr + CORE_VENDOR_SPEC);
+ curr_pwrsave = false;
+ }
/* Write 1 to DLL_RST bit of DLL_CONFIG register */
writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
@@ -538,10 +544,18 @@ static int msm_init_cm_dll(struct sdhci_host *host)
}
out:
- /* re-enable PWRSAVE */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) |
- CORE_CLK_PWRSAVE),
- host->ioaddr + CORE_VENDOR_SPEC);
+ /* Restore the correct PWRSAVE state */
+ if (prev_pwrsave ^ curr_pwrsave) {
+ u32 reg = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+ if (prev_pwrsave)
+ reg |= CORE_CLK_PWRSAVE;
+ else
+ reg &= ~CORE_CLK_PWRSAVE;
+
+ writel_relaxed(reg, host->ioaddr + CORE_VENDOR_SPEC);
+ }
+
spin_unlock_irqrestore(&host->lock, flags);
pr_debug("%s: Exit %s\n", mmc_hostname(mmc), __func__);
return rc;