]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
mmc: core: Skip host clk gating during voltage switch
authorAnubhav Jain <anubhavj@nvidia.com>
Fri, 15 Jul 2016 07:48:15 +0000 (13:18 +0530)
committerAnubhav Jain <anubhavj@nvidia.com>
Fri, 15 Jul 2016 13:37:01 +0000 (06:37 -0700)
Skip host clk gating during voltage switching to avoid hangs related
to register accesses without clock.

Bug 200203279

Change-Id: If5c723cd38eec3366c696e7d5405e7ffeb8b0b7c
Signed-off-by: Anubhav Jain <anubhavj@nvidia.com>
Signed-off-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Reviewed-on: http://git-master/r/1181921
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
drivers/mmc/core/core.c
drivers/mmc/host/sdhci.c
include/linux/mmc/host.h

index 5ee0020b268112724237030d54ccff2332c94230..efc3f212135bb186b017c95d74729bbdf793d73c 100644 (file)
@@ -1821,6 +1821,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
         * for 5 ms according to the SD spec
         */
        clock = host->ios.clock;
+       host->skip_host_clkgate = true;
        host->ios.clock = 0;
        mmc_set_ios(host);
 
@@ -1830,12 +1831,14 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
                 * sent CMD11, so a power cycle is required anyway
                 */
                err = -EAGAIN;
+               host->skip_host_clkgate = false;
                goto power_cycle;
        }
 
        /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
        mmc_delay(10);
        host->ios.clock = clock;
+       host->skip_host_clkgate = false;
        mmc_set_ios(host);
 
        /* Wait for at least 1 ms according to spec */
index 513dfa1b51f415780ab94b44f5d0175690f67763..69064d4bf97903a4f6ea8b35f41749d10236260c 100644 (file)
@@ -1794,7 +1794,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 
        mmiowb();
        spin_unlock_irqrestore(&host->lock, flags);
-       if (!ios->clock && ios->clock != host->clock) {
+
+       if (!ios->clock && !host->mmc->skip_host_clkgate &&
+               (ios->clock != host->clock)) {
                host->ops->set_clock(host, ios->clock);
                host->clock = ios->clock;
        }
index 5d755dfb0406e63704928e613a143c6677cb29d0..b09601391efb72d1a99d3e8f77d78f566671bd01 100644 (file)
@@ -373,6 +373,7 @@ struct mmc_host {
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
 
+       bool                    skip_host_clkgate;
        /* host specific block data */
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
        unsigned short          max_segs;       /* see blk_queue_max_segments */