mmc: msm_sdcc: Turn off clocks if there is no active request

Turn off SDCC clocks when there is no active request posted to
the driver. This saves power and allows TCXO shutdown
in idle power collapse. This is useful when CONFIG_PM_RUNTIME
is disabled, otherwise the same it is taken care by runtime PM
functionality. The disable delay is set to 200msecs as not to be
aggressive which can impact performance.

Change-Id: Iaa91a02ad9b146c0fea98ba2d4880dc80c4d1ace
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b46bee6..eeca25a 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2501,8 +2501,38 @@
 	return rc;
 }
 #else
-#define msmsdcc_enable NULL
-#define msmsdcc_disable NULL
+static int msmsdcc_enable(struct mmc_host *mmc)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->clks_on) {
+		msmsdcc_setup_clocks(host, true);
+		host->clks_on = 1;
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int msmsdcc_disable(struct mmc_host *mmc, int lazy)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	if (mmc->card && mmc_card_sdio(mmc->card))
+		return -ENOTSUPP;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (host->clks_on) {
+		msmsdcc_setup_clocks(host, false);
+		host->clks_on = 0;
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
 #endif
 
 static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
@@ -4102,6 +4132,9 @@
 		pm_runtime_enable(&(pdev)->dev);
 	}
 #endif
+#ifndef CONFIG_PM_RUNTIME
+	mmc_set_disable_delay(mmc, MSM_MMC_DISABLE_TIMEOUT);
+#endif
 	setup_timer(&host->req_tout_timer, msmsdcc_req_tout_timer_hdlr,
 			(unsigned long)host);
 
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index ca3eed8..a8332e51 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -216,6 +216,7 @@
  * bad cards/controller to respond.
  */
 #define MSM_MMC_REQ_TIMEOUT	10000 /* msecs */
+#define MSM_MMC_DISABLE_TIMEOUT        200 /* msecs */
 
 /*
  * Controller HW limitations