mmc: msm_sdcc: Wrap readl/writel calls with appropriate clk delays

As it turns out, all sdcc register writes must be delayed by at
least 3 core clock cycles for the writes to take effect. *sigh*

    Also removes the 30us constant delay on clock enable in favor
of a 3 core clock delay.

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 b4b6372..3b096f6 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -62,6 +62,7 @@
 msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
 {
 	int rc;
+
 	WARN_ON(enable == host->clks_on);
 	if (enable) {
 		rc = clk_enable(host->pclk);
@@ -72,7 +73,8 @@
 			clk_disable(host->pclk);
 			return rc;
 		}
-		udelay(30);
+		udelay(1 + ((3 * USEC_PER_SEC) /
+		       (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
 		host->clks_on = 1;
 	} else {
 		clk_disable(host->clk);
@@ -82,6 +84,20 @@
 	return 0;
 }
 
+static inline unsigned int
+msmsdcc_readl(struct msmsdcc_host *host, unsigned int reg)
+{
+	return readl(host->base + reg);
+}
+
+static inline void
+msmsdcc_writel(struct msmsdcc_host *host, u32 data, unsigned int reg)
+{
+	writel(data, host->base + reg);
+	/* 3 clk delay required! */
+	udelay(1 + ((3 * USEC_PER_SEC) /
+	       (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
+}
 
 static void
 msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
@@ -90,7 +106,7 @@
 static void
 msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
 {
-	writel(0, host->base + MMCICOMMAND);
+	msmsdcc_writel(host, 0, MMCICOMMAND);
 
 	BUG_ON(host->curr.data);
 
@@ -116,7 +132,7 @@
 static void
 msmsdcc_stop_data(struct msmsdcc_host *host)
 {
-	writel(0, host->base + MMCIDATACTRL);
+	msmsdcc_writel(host, 0, MMCIDATACTRL);
 	host->curr.data = NULL;
 	host->curr.got_dataend = host->curr.got_datablkend = 0;
 }
@@ -200,7 +216,7 @@
 		if (!mrq->data->error)
 			host->curr.data_xfered = host->curr.xfer_size;
 		if (!mrq->data->stop || mrq->cmd->error) {
-			writel(0, host->base + MMCICOMMAND);
+			msmsdcc_writel(host, 0, MMCICOMMAND);
 			host->curr.mrq = NULL;
 			host->curr.cmd = NULL;
 			mrq->data->bytes_xfered = host->curr.data_xfered;
@@ -337,7 +353,6 @@
 {
 	unsigned int datactrl, timeout;
 	unsigned long long clks;
-	void __iomem *base = host->base;
 	unsigned int pio_irqmask = 0;
 
 	host->curr.data = data;
@@ -352,9 +367,9 @@
 	clks = (unsigned long long)data->timeout_ns * host->clk_rate;
 	do_div(clks, NSEC_PER_SEC);
 	timeout = data->timeout_clks + (unsigned int)clks;
-	writel(timeout, base + MMCIDATATIMER);
+	msmsdcc_writel(host, timeout, MMCIDATATIMER);
 
-	writel(host->curr.xfer_size, base + MMCIDATALENGTH);
+	msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH);
 
 	datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
 
@@ -376,8 +391,8 @@
 	if (data->flags & MMC_DATA_READ)
 		datactrl |= MCI_DPSM_DIRECTION;
 
-	writel(pio_irqmask, base + MMCIMASK1);
-	writel(datactrl, base + MMCIDATACTRL);
+	msmsdcc_writel(host, pio_irqmask, MMCIMASK1);
+	msmsdcc_writel(host, datactrl, MMCIDATACTRL);
 
 	if (datactrl & MCI_DPSM_DMAENABLE) {
 		host->dma.busy = 1;
@@ -398,12 +413,8 @@
 static void
 msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
 {
-	void __iomem *base = host->base;
-
-	if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
-		writel(0, base + MMCICOMMAND);
-		udelay(2 + ((5 * 1000000) / host->clk_rate));
-	}
+	if (msmsdcc_readl(host, MMCICOMMAND) & MCI_CPSM_ENABLE)
+		msmsdcc_writel(host, 0, MMCICOMMAND);
 
 	c |= cmd->opcode | MCI_CPSM_ENABLE;
 
@@ -428,8 +439,8 @@
 
 	host->stats.cmds++;
 
-	writel(cmd->arg, base + MMCIARGUMENT);
-	writel(c, base + MMCICOMMAND);
+	msmsdcc_writel(host, cmd->arg, MMCIARGUMENT);
+	msmsdcc_writel(host, c, MMCICOMMAND);
 }
 
 static void
@@ -463,13 +474,11 @@
 static int
 msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
 {
-	void __iomem	*base = host->base;
 	uint32_t	*ptr = (uint32_t *) buffer;
 	int		count = 0;
 
-	while (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
-
-		*ptr = readl(base + MMCIFIFO + (count % MCI_FIFOSIZE));
+	while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) {
+		*ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE));
 		ptr++;
 		count += sizeof(uint32_t);
 
@@ -501,7 +510,7 @@
 		if (remain == 0)
 			break;
 
-		status = readl(base + MMCISTATUS);
+		status = msmsdcc_readl(host, MMCISTATUS);
 	} while (status & MCI_TXFIFOHALFEMPTY);
 
 	return ptr - buffer;
@@ -511,7 +520,7 @@
 msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin)
 {
 	while (maxspin) {
-		if ((readl(host->base + MMCISTATUS) & mask))
+		if ((msmsdcc_readl(host, MMCISTATUS) & mask))
 			return 0;
 		udelay(1);
 		--maxspin;
@@ -523,10 +532,9 @@
 msmsdcc_pio_irq(int irq, void *dev_id)
 {
 	struct msmsdcc_host	*host = dev_id;
-	void __iomem		*base = host->base;
 	uint32_t		status;
 
-	status = readl(base + MMCISTATUS);
+	status = msmsdcc_readl(host, MMCISTATUS);
 
 	do {
 		unsigned long flags;
@@ -581,14 +589,14 @@
 			host->pio.sg_off = 0;
 		}
 
-		status = readl(base + MMCISTATUS);
+		status = msmsdcc_readl(host, MMCISTATUS);
 	} while (1);
 
 	if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
-		writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
+		msmsdcc_writel(host, MCI_RXDATAAVLBLMASK, MMCIMASK1);
 
 	if (!host->curr.xfer_remain)
-		writel(0, base + MMCIMASK1);
+		msmsdcc_writel(host, 0, MMCIMASK1);
 
 	return IRQ_HANDLED;
 }
@@ -596,13 +604,12 @@
 static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
 {
 	struct mmc_command *cmd = host->curr.cmd;
-	void __iomem	   *base = host->base;
 
 	host->curr.cmd = NULL;
-	cmd->resp[0] = readl(base + MMCIRESPONSE0);
-	cmd->resp[1] = readl(base + MMCIRESPONSE1);
-	cmd->resp[2] = readl(base + MMCIRESPONSE2);
-	cmd->resp[3] = readl(base + MMCIRESPONSE3);
+	cmd->resp[0] = msmsdcc_readl(host, MMCIRESPONSE0);
+	cmd->resp[1] = msmsdcc_readl(host, MMCIRESPONSE1);
+	cmd->resp[2] = msmsdcc_readl(host, MMCIRESPONSE2);
+	cmd->resp[3] = msmsdcc_readl(host, MMCIRESPONSE3);
 
 	del_timer(&host->command_timer);
 	if (status & MCI_CMDTIMEOUT) {
@@ -699,10 +706,11 @@
 	spin_lock(&host->lock);
 
 	do {
-		status = readl(base + MMCISTATUS);
-
-		status &= (readl(base + MMCIMASK0) | MCI_DATABLOCKENDMASK);
-		writel(status, base + MMCICLEAR);
+		struct mmc_data *data;
+		status = msmsdcc_readl(host, MMCISTATUS);
+		status &= (msmsdcc_readl(host, MMCIMASK0) |
+					      MCI_DATABLOCKENDMASK);
+		msmsdcc_writel(host, status, MMCICLEAR);
 
 		if (status & MCI_SDIOINTR)
 			status &= ~MCI_SDIOINTR;
@@ -774,10 +782,11 @@
 	if (host->cmdpoll && !msmsdcc_spin_on_status(host,
 				MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT,
 				CMD_SPINMAX)) {
-		uint32_t status = readl(host->base + MMCISTATUS);
+		uint32_t status = msmsdcc_readl(host, MMCISTATUS);
 		msmsdcc_do_cmdirq(host, status);
-		writel(MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT,
-		       host->base + MMCICLEAR);
+		msmsdcc_writel(host,
+			       MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT,
+			       MMCICLEAR);
 		host->stats.cmdpoll_hits++;
 	} else {
 		host->stats.cmdpoll_misses++;
@@ -836,11 +845,11 @@
 	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
 		pwr |= MCI_OD;
 
-	writel(clk, host->base + MMCICLOCK);
+	msmsdcc_writel(host, clk, MMCICLOCK);
 
 	if (host->pwr != pwr) {
 		host->pwr = pwr;
-		writel(pwr, host->base + MMCIPOWER);
+		msmsdcc_writel(host, pwr, MMCIPOWER);
 	}
 	if (host->clks_on)
 		msmsdcc_enable_clocks(host, 0);
@@ -855,13 +864,13 @@
 
 	spin_lock_irqsave(&host->lock, flags);
 	if (msmsdcc_sdioirq == 1) {
-		status = readl(host->base + MMCIMASK0);
+		status = msmsdcc_readl(host, MMCIMASK0);
 		if (enable)
 			status |= MCI_SDIOINTOPERMASK;
 		else
 			status &= ~MCI_SDIOINTOPERMASK;
 		host->saved_irq0mask = status;
-		writel(status, host->base + MMCIMASK0);
+		msmsdcc_writel(host, status, MMCIMASK0);
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
 }
@@ -950,19 +959,16 @@
 	mrq = host->curr.mrq;
 
 	if (!mrq) {
-		pr_info("%s: Command expiry misfire\n",
-			mmc_hostname(host->mmc));
 		spin_unlock_irqrestore(&host->lock, flags);
 		return;
 	}
 
-	pr_err("%s: Command timeout (%p %p %p %p)\n",
-	       mmc_hostname(host->mmc), mrq, mrq->cmd,
-	       mrq->data, host->dma.sg);
+	pr_err("%s: Controller lockup detected\n",
+	       mmc_hostname(host->mmc));
 	mrq->cmd->error = -ETIMEDOUT;
 	msmsdcc_stop_data(host);
 
-	writel(0, host->base + MMCICOMMAND);
+	msmsdcc_writel(host, 0, MMCICOMMAND);
 
 	host->curr.mrq = NULL;
 	host->curr.cmd = NULL;
@@ -1143,10 +1149,10 @@
 	mmc->max_req_size = 33554432;	/* MCI_DATA_LENGTH is 25 bits */
 	mmc->max_seg_size = mmc->max_req_size;
 
-	writel(0, host->base + MMCIMASK0);
-	writel(0x5e007ff, host->base + MMCICLEAR); /* Add: 1 << 25 */
+	msmsdcc_writel(host, 0, MMCIMASK0);
+	msmsdcc_writel(host, 0x5e007ff, MMCICLEAR);
 
-	writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+	msmsdcc_writel(host, MCI_IRQENABLE, MMCIMASK0);
 	host->saved_irq0mask = MCI_IRQENABLE;
 
 	/*
@@ -1269,7 +1275,7 @@
 		if (mmc->card && mmc->card->type != MMC_TYPE_SDIO)
 			rc = mmc_suspend_host(mmc, state);
 		if (!rc) {
-			writel(0, host->base + MMCIMASK0);
+			msmsdcc_writel(host, 0, MMCIMASK0);
 
 			if (host->clks_on)
 				msmsdcc_enable_clocks(host, 0);
@@ -1292,7 +1298,7 @@
 		if (!host->clks_on)
 			msmsdcc_enable_clocks(host, 1);
 
-		writel(host->saved_irq0mask, host->base + MMCIMASK0);
+		msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0);
 
 		spin_unlock_irqrestore(&host->lock, flags);