diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 1c0974a51f65..c343f056a1b0 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -732,6 +732,7 @@ int mmc_init_clk_scaling(struct mmc_host *host) host->ios.clock); host->clk_scaling.enable = true; + host->clk_scaling.is_suspended = false; return err; } diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 0823d3f1e643..98c686736020 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1472,10 +1472,16 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode) struct sdhci_host *host = mmc_priv(mmc); int tuning_seq_cnt = 3; u8 phase, tuned_phases[16], tuned_phase_cnt = 0; - int rc; + int rc = 0; struct mmc_ios ios = host->mmc->ios; + u32 core_vendor_spec; struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); + const struct sdhci_msm_offset *msm_offset = + sdhci_priv_msm_offset(host); + + core_vendor_spec = readl_relaxed(host->ioaddr + + msm_offset->core_vendor_spec); if (!sdhci_msm_is_tuning_needed(host)) { msm_host->use_cdr = false; @@ -1503,19 +1509,23 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode) host->flags &= ~SDHCI_HS400_TUNING; } + /* Make sure that PWRSAVE bit is set to '0' during tuning */ + writel_relaxed((core_vendor_spec & ~CORE_CLK_PWRSAVE), + host->ioaddr + + msm_offset->core_vendor_spec); + retry: /* First of all reset the tuning block */ rc = msm_init_cm_dll(host, DLL_INIT_NORMAL); if (rc) - return rc; + goto out; phase = 0; do { /* Set the phase in delay line hw block */ rc = msm_config_cm_dll_phase(host, phase); if (rc) - return rc; - + goto out; rc = mmc_send_tuning(mmc, opcode, NULL); if (!rc) { /* Tuning is successful at this tuning point */ @@ -1529,7 +1539,7 @@ retry: rc = msm_find_most_appropriate_phase(host, tuned_phases, tuned_phase_cnt); if (rc < 0) - return rc; + goto out; else phase = rc; @@ -1539,7 +1549,7 @@ retry: */ rc = msm_config_cm_dll_phase(host, phase); if (rc) - return rc; + goto out; msm_host->saved_tuning_phase = phase; dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", mmc_hostname(mmc), phase); @@ -1554,6 +1564,15 @@ retry: if (!rc) msm_host->tuning_done = true; +out: + /* Set PWRSAVE bit to '1' after completion of tuning as needed */ + if (core_vendor_spec & CORE_CLK_PWRSAVE) { + writel_relaxed((readl_relaxed(host->ioaddr + + msm_offset->core_vendor_spec) + | CORE_CLK_PWRSAVE), host->ioaddr + + msm_offset->core_vendor_spec); + } + return rc; }