mmc: msm_sdcc: Clean up clock management and add a 10us delay after enabling clocks

It appears that in some cases there may be a delay on the ARM9 in enabling our clock.
As a result, we may put the controller into a bad state. Delay 10us after enabling
clocks to let the peripheral settle. Note - this is all imperical.

Also ensure set_ios() callback grabs the host lock.

Signed-off-by: San Mehat <san@google.com>
Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 4c068e5..977932a 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -735,20 +735,42 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
+static int inline
+msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
+{
+	int rc;
+	if (enable) {
+		rc = clk_enable(host->pclk);
+		if (rc)
+			return rc;
+		rc = clk_enable(host->clk);
+		if (rc) {
+			clk_disable(host->pclk);
+			return rc;
+		}
+		host->clks_on = 1;
+		udelay(10);
+	} else {
+		clk_disable(host->clk);
+		clk_disable(host->pclk);
+		host->clks_on = 0;
+	}
+	return 0;
+}
+
 static void
 msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	u32 clk = 0, pwr = 0;
 	int rc;
+	unsigned long flags;
 
+	spin_lock_irqsave(&host->lock, flags);
 	if (ios->clock) {
 
-		if (!host->clks_on) {
-			clk_enable(host->pclk);
-			clk_enable(host->clk);
-			host->clks_on = 1;
-		}
+		if (!host->clks_on)
+			msmsdcc_enable_clocks(host, 1);
 		if (ios->clock != host->clk_rate) {
 			rc = clk_set_rate(host->clk, ios->clock);
 			if (rc < 0)
@@ -793,11 +815,9 @@
 		writel(pwr, host->base + MMCIPOWER);
 	}
 
-	if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
-		clk_disable(host->clk);
-		clk_disable(host->pclk);
-		host->clks_on = 0;
-	}
+	if (!(clk & MCI_CLK_ENABLE) && host->clks_on)
+		msmsdcc_enable_clocks(host, 0);
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -899,7 +919,6 @@
 	pr_err("%s: Command timeout (%p %p %p %p)\n",
 	       mmc_hostname(host->mmc), mrq, mrq->cmd,
 	       mrq->data, host->dma.sg);
-
 	mrq->cmd->error = -ETIMEDOUT;
 	msmsdcc_stop_data(host);
 
@@ -1031,31 +1050,21 @@
 	 */
 	msmsdcc_init_dma(host);
 
-	/*
-	 * Setup main peripheral bus clock
-	 */
+	/* Get our clocks */
 	host->pclk = clk_get(&pdev->dev, "sdc_pclk");
 	if (IS_ERR(host->pclk)) {
 		ret = PTR_ERR(host->pclk);
 		goto host_free;
 	}
 
-	ret = clk_enable(host->pclk);
-	if (ret)
-		goto pclk_put;
-
-	host->pclk_rate = clk_get_rate(host->pclk);
-
-	/*
-	 * Setup SDC MMC clock
-	 */
 	host->clk = clk_get(&pdev->dev, "sdc_clk");
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
-		goto pclk_disable;
+		goto pclk_put;
 	}
 
-	ret = clk_enable(host->clk);
+	/* Enable clocks */
+	ret = msmsdcc_enable_clocks(host, 1);
 	if (ret)
 		goto clk_put;
 
@@ -1065,10 +1074,9 @@
 		goto clk_disable;
 	}
 
+	host->pclk_rate = clk_get_rate(host->pclk);
 	host->clk_rate = clk_get_rate(host->clk);
 
-	host->clks_on = 1;
-
 	/*
 	 * Setup MMC host structure
 	 */
@@ -1187,11 +1195,9 @@
 	if (host->stat_irq)
 		free_irq(host->stat_irq, host);
  clk_disable:
-	clk_disable(host->clk);
+	msmsdcc_enable_clocks(host, 0);
  clk_put:
 	clk_put(host->clk);
- pclk_disable:
-	clk_disable(host->pclk);
  pclk_put:
 	clk_put(host->pclk);
  host_free:
@@ -1217,11 +1223,8 @@
 		if (!rc) {
 			writel(0, host->base + MMCIMASK0);
 
-			if (host->clks_on) {
-				clk_disable(host->clk);
-				clk_disable(host->pclk);
-				host->clks_on = 0;
-			}
+			if (host->clks_on)
+				msmsdcc_enable_clocks(host, 0);
 		}
 	}
 	return rc;
@@ -1238,11 +1241,8 @@
 
 		spin_lock_irqsave(&host->lock, flags);
 
-		if (!host->clks_on) {
-			clk_enable(host->pclk);
-			clk_enable(host->clk);
-			host->clks_on = 1;
-		}
+		if (!host->clks_on)
+			msmsdcc_enable_clocks(host, 1);
 
 		writel(host->saved_irq0mask, host->base + MMCIMASK0);