Revert "Revert "msm_shared: Fix the delays in the mmc driver.""

This reverts commit 5a4f0305fc046deb69d7b4a9ef36a789349f9685.
diff --git a/platform/copper/acpuclock.c b/platform/copper/acpuclock.c
index 28cd204..d6589dd 100644
--- a/platform/copper/acpuclock.c
+++ b/platform/copper/acpuclock.c
@@ -147,6 +147,12 @@
 	reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
 	writel(reg, MMC_BOOT_MCI_CLK);
+
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
+	/* Wait 1 ms to provide the free running SD CLK to the card. */
+	mdelay(1);
 }
 
 /* Configure UART clock based on the UART block id*/
diff --git a/platform/msm7k/acpuclock.c b/platform/msm7k/acpuclock.c
index 695f18e..0a681a0 100644
--- a/platform/msm7k/acpuclock.c
+++ b/platform/msm7k/acpuclock.c
@@ -1,30 +1,32 @@
 /*
  * Copyright (c) 2008, Google Inc.
  * All rights reserved.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 	* Redistributions of source code must retain the above copyright
+ * 	  notice, this list of conditions and the following disclaimer.
+ * 	* Redistributions in binary form must reproduce the above
+ * 	  copyright notice, this list of conditions and the following
+ * 	  disclaimer in the documentation and/or other materials provided
+ * 	  with the distribution.
+ * 	* Neither the name of The Linux Foundation nor the names of its
+ * 	  contributors may be used to endorse or promote products derived
+ * 	  from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <stdint.h>
@@ -194,6 +196,12 @@
 	reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
 	writel( reg, MMC_BOOT_MCI_CLK );
+
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
+	/* Wait 1 ms to provide the free running SD CLK to the card. */
+	mdelay(1);
 }
 
 /* Intialize MMC clock */
diff --git a/platform/msm7x27a/acpuclock.c b/platform/msm7x27a/acpuclock.c
index 96aa21d..3e7602d 100644
--- a/platform/msm7x27a/acpuclock.c
+++ b/platform/msm7x27a/acpuclock.c
@@ -1,30 +1,32 @@
 /*
  * Copyright (c) 2008, Google Inc.
  * All rights reserved.
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *	notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *	notice, this list of conditions and the following disclaimer in
- *	the documentation and/or other materials provided with the
- *	distribution.
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 	* Redistributions of source code must retain the above copyright
+ * 	  notice, this list of conditions and the following disclaimer.
+ * 	* Redistributions in binary form must reproduce the above
+ * 	  copyright notice, this list of conditions and the following
+ * 	  disclaimer in the documentation and/or other materials provided
+ * 	  with the distribution.
+ * 	* Neither the name of The Linux Foundation nor the names of its
+ * 	  contributors may be used to endorse or promote products derived
+ * 	  from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <stdint.h>
@@ -318,6 +320,12 @@
 	reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
 	writel(reg, MMC_BOOT_MCI_CLK);
+
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
+	/* Wait 1 ms to provide the free running SD CLK to the card. */
+	mdelay(1);
 }
 
 /* Intialize MMC clock */
diff --git a/platform/msm7x30/acpuclock.c b/platform/msm7x30/acpuclock.c
index 7d6687b..1bbc051 100644
--- a/platform/msm7x30/acpuclock.c
+++ b/platform/msm7x30/acpuclock.c
@@ -1,29 +1,29 @@
-/*
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *   * Neither the name of Code Aurora nor
- *     the names of its contributors may be used to endorse or promote
- *     products derived from this software without specific prior written
- *     permission.
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <stdint.h>
@@ -340,6 +340,12 @@
 	reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
 	writel(reg, MMC_BOOT_MCI_CLK);
+
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
+	/* Wait 1 ms to provide the free running SD CLK to the card. */
+	mdelay(1);
 }
 
 /* Intialize MMC clock */
diff --git a/platform/msm8960/acpuclock.c b/platform/msm8960/acpuclock.c
index b57a22b..cbe53f7 100644
--- a/platform/msm8960/acpuclock.c
+++ b/platform/msm8960/acpuclock.c
@@ -235,6 +235,12 @@
 	reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
 	writel(reg, MMC_BOOT_MCI_CLK);
+
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
+	/* Wait 1 ms to provide the free running SD CLK to the card. */
+	mdelay(1);
 }
 
 /* Configure crypto engine clock */
diff --git a/platform/msm8x60/acpuclock.c b/platform/msm8x60/acpuclock.c
index 9b75f58..2fbb4c0 100644
--- a/platform/msm8x60/acpuclock.c
+++ b/platform/msm8x60/acpuclock.c
@@ -1,29 +1,29 @@
-/*
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *   * Neither the name of Code Aurora nor
- *     the names of its contributors may be used to endorse or promote
- *     products derived from this software without specific prior written
- *     permission.
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <stdint.h>
@@ -356,6 +356,12 @@
 	reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
 	writel(reg, MMC_BOOT_MCI_CLK);
+
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
+	/* Wait 1 ms to provide the free running SD CLK to the card. */
+	mdelay(1);
 }
 
 void mdp_clock_init(void)
diff --git a/platform/msm_shared/include/mmc.h b/platform/msm_shared/include/mmc.h
index a07d169..eee414e 100644
--- a/platform/msm_shared/include/mmc.h
+++ b/platform/msm_shared/include/mmc.h
@@ -1,17 +1,17 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
-
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -248,14 +248,20 @@
 
 #define MMC_BOOT_MCI_FIFO_COUNT           MMC_BOOT_MCI_REG(0x044)
 
+#define MMC_BOOT_MCI_VERSION              MMC_BOOT_MCI_REG(0x050)
+
 #define MMC_BOOT_MCI_CCS_TIMER            MMC_BOOT_MCI_REG(0x0058)
 
+#define MMC_BOOT_MCI_STATUS2              MMC_BOOT_MCI_REG(0x06C)
+#define MMC_BOOT_MCI_MCLK_REG_WR_ACTIVE   (1 << 0)
+
 #define MMC_BOOT_MCI_FIFO                 MMC_BOOT_MCI_REG(0x080)
 
 /* Card status */
 #define MMC_BOOT_CARD_STATUS(x)          ((x>>9) & 0x0F)
 #define MMC_BOOT_TRAN_STATE              4
 #define MMC_BOOT_PROG_STATE              7
+#define MMC_BOOT_SWITCH_FUNC_ERR_FLAG    (1 << 7)
 
 /* SD Memory Card bus commands */
 #define CMD0_GO_IDLE_STATE               0
@@ -504,6 +510,7 @@
 	unsigned int mclk_rate;
 	unsigned int ocr;
 	unsigned int cmd_retry;
+	uint32_t mmc_cont_version;
 };
 
 /* MACRO used to evoke regcomp */
@@ -595,4 +602,5 @@
 
 struct mmc_boot_host *get_mmc_host(void);
 struct mmc_boot_card *get_mmc_card(void);
+void mmc_mclk_reg_wr_delay();
 #endif
diff --git a/platform/msm_shared/mmc.c b/platform/msm_shared/mmc.c
index b504c35..527ba58 100644
--- a/platform/msm_shared/mmc.c
+++ b/platform/msm_shared/mmc.c
@@ -1,17 +1,17 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
-
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  * met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -48,6 +48,8 @@
 #define NULL        0
 #endif
 
+#define USEC_PER_SEC           (1000000L)
+
 #define MMC_BOOT_DATA_READ     0
 #define MMC_BOOT_DATA_WRITE    1
 
@@ -156,6 +158,17 @@
 									 24);
 }
 
+void mmc_mclk_reg_wr_delay()
+{
+	if (mmc_host.mmc_cont_version)
+	{
+		/* Wait for the MMC_BOOT_MCI register write to go through. */
+		while(readl(MMC_BOOT_MCI_STATUS2) & MMC_BOOT_MCI_MCLK_REG_WR_ACTIVE);
+	}
+	else
+		udelay((1 + ((3 * USEC_PER_SEC) / (mmc_host.mclk_rate? mmc_host.mclk_rate : MMC_CLK_400KHZ))));
+}
+
 /* Sets a timeout for read operation.
  */
 static unsigned int
@@ -534,12 +547,6 @@
 	/* 1. Write command argument to MMC_BOOT_MCI_ARGUMENT register */
 	writel(cmd->argument, MMC_BOOT_MCI_ARGUMENT);
 
-	/* Writes to MCI port are not effective for 3 ticks of PCLK.
-	 * The min pclk is 144KHz which gives 6.94 us/tick.
-	 * Thus 21us == 3 ticks.
-	 */
-	udelay(21);
-
 	/* 2. Set appropriate fields and write MMC_BOOT_MCI_CMD */
 	/* 2a. Write command index in CMD_INDEX field */
 	cmd_index = cmd->cmd_index;
@@ -565,10 +572,8 @@
 	/* 2f. Set ENABLE bit to 1 */
 	mmc_cmd |= MMC_BOOT_MCI_CMD_ENABLE;
 
-	/* 2g. Set PROG_ENA bit to 1 for CMD12, CMD13 issued at the end of
-	   write data transfer */
-	if ((cmd_index == CMD12_STOP_TRANSMISSION ||
-	     cmd_index == CMD13_SEND_STATUS) && cmd->prg_enabled) {
+	/* 2g. Set PROG_ENA bit */
+	if (cmd->prg_enabled) {
 		mmc_cmd |= MMC_BOOT_MCI_CMD_PROG_ENA;
 	}
 
@@ -582,6 +587,9 @@
 	/* 2k. Write to MMC_BOOT_MCI_CMD register */
 	writel(mmc_cmd, MMC_BOOT_MCI_CMD);
 
+	/* Wait for the MMC_BOOT_MCI_CMD write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	dprintf(SPEW, "Command sent: CMD%d MCI_CMD_REG:%x MCI_ARG:%x\n",
 		cmd_index, mmc_cmd, cmd->argument);
 
@@ -663,6 +671,13 @@
 	}
 	while (1);
 
+
+	/* 2k. Write to MMC_BOOT_MCI_CMD register */
+	writel(0, MMC_BOOT_MCI_CMD);
+
+	/* Wait for the MMC_BOOT_MCI_CMD write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	return mmc_return;
 }
 
@@ -1114,6 +1129,9 @@
 	mmc_reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	writel(mmc_reg, MMC_BOOT_MCI_CLK);
 
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	/* Write data timeout period to MCI_DATA_TIMER register. */
 	/* Data timeout period should be in card bus clock periods */
 	mmc_reg = 0xFFFFFFFF;
@@ -1132,6 +1150,9 @@
 
 	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
 
+	/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 #if MMC_BOOT_BAM
 	/*  Setup SDCC BAM descriptors for Read operation. */
 	mmc_ret = mmc_boot_bam_setup_desc(mmc_ptr, 512, MMC_BOOT_DATA_READ);
@@ -1157,6 +1178,9 @@
 	/* Reset DPSM */
 	writel(0, MMC_BOOT_MCI_DATA_CTL);
 
+	/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	return mmc_ret;
 }
 
@@ -1170,6 +1194,7 @@
 
 	struct mmc_boot_command cmd;
 	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
+	uint32_t mmc_status;
 
 	/* basic check */
 	if (card == NULL) {
@@ -1193,13 +1218,46 @@
 	cmd.argument |= (value << 8);
 	cmd.cmd_type = MMC_BOOT_CMD_ADDRESS;
 	cmd.resp_type = MMC_BOOT_RESP_R1B;
+	cmd.prg_enabled = 1;
 
 	mmc_ret = mmc_boot_send_command(&cmd);
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
+		dprintf(CRITICAL,"Send cmd6 failed\n");
 		return mmc_ret;
 	}
 
-	return MMC_BOOT_E_SUCCESS;
+	/* Wait for interrupt or poll on PROG_DONE bit of MCI_STATUS register.
+	 * If PROG_DONE bit is set to 1 it means that the card finished it programming
+	 * and stopped driving DAT0 line to 0.
+	 */
+	do {
+		mmc_status = readl(MMC_BOOT_MCI_STATUS);
+		if (mmc_status & MMC_BOOT_MCI_STAT_PROG_DONE) {
+			break;
+		}
+	}
+	while (1);
+
+	/* Check if the card completed the switch command processing */
+	mmc_ret = mmc_boot_get_card_status(card, 0, &mmc_status);
+	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
+		dprintf(CRITICAL, "Get card status failed\n");
+		return mmc_ret;
+	}
+
+	if (MMC_BOOT_CARD_STATUS(mmc_status) != MMC_BOOT_TRAN_STATE)
+	{
+		dprintf(CRITICAL, "Switch cmd failed. Card not in tran state\n");
+		mmc_ret = MMC_BOOT_E_FAILURE;
+	}
+
+	if (mmc_status & MMC_BOOT_SWITCH_FUNC_ERR_FLAG)
+	{
+		dprintf(CRITICAL, "Switch cmd failed. Switch Error.\n");
+		mmc_ret = MMC_BOOT_E_FAILURE;
+	}
+
+	return mmc_ret;
 }
 
 /*
@@ -1211,8 +1269,6 @@
 	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
 	unsigned int mmc_reg = 0;
 	unsigned int mmc_width = 0;
-	unsigned int status;
-	unsigned int wait_count = 100;
 
 	if (width != MMC_BOOT_BUS_WIDTH_1_BIT) {
 		mmc_width = width - 1;
@@ -1222,23 +1278,10 @@
 				      MMC_BOOT_EXT_CMMC_BUS_WIDTH, mmc_width);
 
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
+		dprintf(CRITICAL, "Switch cmd failed\n");
 		return mmc_ret;
 	}
 
-	/* Wait for the card to complete the switch command processing */
-	do {
-		mmc_ret = mmc_boot_get_card_status(card, 0, &status);
-		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
-			return mmc_ret;
-		}
-
-		wait_count--;
-		if (wait_count == 0) {
-			return MMC_BOOT_E_FAILURE;
-		}
-	}
-	while (MMC_BOOT_CARD_STATUS(status) == MMC_BOOT_PROG_STATE);
-
 	/* set MCI_CLK accordingly */
 	mmc_reg = readl(MMC_BOOT_MCI_CLK);
 	mmc_reg &= ~MMC_BOOT_MCI_CLK_WIDEBUS_MODE;
@@ -1251,7 +1294,8 @@
 	}
 	writel(mmc_reg, MMC_BOOT_MCI_CLK);
 
-	mdelay(10);		// Giving some time to card to stabilize.
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
 
 	return MMC_BOOT_E_SUCCESS;
 }
@@ -1415,6 +1459,9 @@
 	mmc_reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	writel(mmc_reg, MMC_BOOT_MCI_CLK);
 
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	/* Write data timeout period to MCI_DATA_TIMER register */
 	/* Data timeout period should be in card bus clock periods */
 	/*TODO: Fix timeout value */
@@ -1458,6 +1505,9 @@
 	mmc_reg |= card->wr_block_len << MMC_BOOT_MCI_BLKSIZE_POS;
 	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
 
+	/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	/* write data to FIFO */
 	mmc_ret =
 	    mmc_boot_data_transfer(in, data_len, MMC_BOOT_DATA_WRITE);
@@ -1513,6 +1563,9 @@
 	/* Reset DPSM */
 	writel(0, MMC_BOOT_MCI_DATA_CTL);
 
+	/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	return MMC_BOOT_E_SUCCESS;
 }
 
@@ -1524,33 +1577,16 @@
 				struct mmc_boot_card *card)
 {
 	unsigned int mmc_ret = MMC_BOOT_E_SUCCESS;
-	unsigned int status;
-	unsigned int wait_count = 100;
 
 	/* Setting HS_TIMING in EXT_CSD (CMD6) */
 	mmc_ret = mmc_boot_switch_cmd(card, MMC_BOOT_ACCESS_WRITE,
 				      MMC_BOOT_EXT_CMMC_HS_TIMING, 1);
 
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
+		dprintf(CRITICAL, "Switch cmd returned failure %d\n", __LINE__);
 		return mmc_ret;
 	}
 
-	/* Wait for the card to complete the switch command processing */
-	do {
-		mmc_ret = mmc_boot_get_card_status(card, 0, &status);
-		if (mmc_ret != MMC_BOOT_E_SUCCESS) {
-			dprintf(CRITICAL, "WARNING: Failed to get card status after"
-							  "cmd6. ret = %d wait_count = %d\n",
-					mmc_ret, wait_count);
-		}
-
-		wait_count--;
-		if (wait_count == 0) {
-			return MMC_BOOT_E_FAILURE;
-		}
-	}
-	while (MMC_BOOT_CARD_STATUS(status) == MMC_BOOT_PROG_STATE);
-
 	clock_config_mmc(mmc_slot, MMC_CLK_50MHZ);
 
 	host->mclk_rate = MMC_CLK_50MHZ;
@@ -1703,6 +1739,9 @@
 	mmc_reg |= (card->rd_block_len << MMC_BOOT_MCI_BLKSIZE_POS);
 	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
 
+	/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 #if MMC_BOOT_BAM
 	/* Setup SDCC FIFO descriptors for Read operation. */
 	mmc_ret = mmc_boot_bam_setup_desc(out, data_len, MMC_BOOT_DATA_READ);
@@ -1742,6 +1781,9 @@
 	/* Reset DPSM */
 	writel(0, MMC_BOOT_MCI_DATA_CTL);
 
+	/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	return MMC_BOOT_E_SUCCESS;
 }
 
@@ -1759,6 +1801,9 @@
 	/* Initialize any clocks needed for SDC controller */
 	clock_init_mmc(mmc_slot);
 
+	/* Save the verison on the mmc controller. */
+	host->mmc_cont_version = readl(MMC_BOOT_MCI_VERSION);
+
 	/* Setup initial freq to 400KHz */
 	clock_config_mmc(mmc_slot, MMC_CLK_400KHZ);
 
@@ -1766,13 +1811,14 @@
 
 	/* set power mode */
 	/* give some time to reach minimum voltate */
-	mdelay(2);
+
 	mmc_pwr &= ~MMC_BOOT_MCI_PWR_UP;
 	mmc_pwr |= MMC_BOOT_MCI_PWR_ON;
 	mmc_pwr |= MMC_BOOT_MCI_PWR_UP;
 	writel(mmc_pwr, MMC_BOOT_MCI_POWER);
-	/* some more time to stabilize voltage */
-	mdelay(2);
+
+	/* Wait for the MMC_BOOT_MCI_POWER write to go through. */
+	mmc_mclk_reg_wr_delay();
 
 	return MMC_BOOT_E_SUCCESS;
 }
@@ -2063,7 +2109,8 @@
 	}
 	writel(sd_reg, MMC_BOOT_MCI_CLK);
 
-	mdelay(10);		// Giving some time to card to stabilize.
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
 
 	return MMC_BOOT_E_SUCCESS;
 }
@@ -2084,8 +2131,6 @@
 		return mmc_ret;
 	}
 
-	mdelay(1);
-
 	clock_config_mmc(mmc_slot, MMC_CLK_50MHZ);
 
 	host->mclk_rate = MMC_CLK_50MHZ;
@@ -2312,6 +2357,9 @@
 	mmc_reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
 	writel(mmc_reg, MMC_BOOT_MCI_CLK);
 
+	/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	/* Write data timeout period to MCI_DATA_TIMER register. */
 	/* Data timeout period should be in card bus clock periods */
 	mmc_reg = 0xFFFFFFFF;
@@ -2330,6 +2378,9 @@
 
 	writel(mmc_reg, MMC_BOOT_MCI_DATA_CTL);
 
+	/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+	mmc_mclk_reg_wr_delay();
+
 	memset((struct mmc_boot_command *)&cmd, 0,
 	       sizeof(struct mmc_boot_command));
 
@@ -2383,19 +2434,6 @@
 		return mmc_ret;
 	}
 
-	/* Sending CMD13 to check card status */
-	do {
-		mmc_ret = mmc_boot_get_card_status(card, 0, &status);
-		if (MMC_BOOT_CARD_STATUS(status) == MMC_BOOT_TRAN_STATE)
-			break;
-	}
-	while ((mmc_ret == MMC_BOOT_E_SUCCESS) &&
-	       (MMC_BOOT_CARD_STATUS(status) == MMC_BOOT_PROG_STATE));
-
-	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
-		return mmc_ret;
-	}
-
 	mmc_ret = mmc_boot_send_ext_cmd(card, ext_csd_buf);
 
 	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
@@ -2444,19 +2482,6 @@
 		return mmc_ret;
 	}
 
-	/* Sending CMD13 to check card status */
-	do {
-		mmc_ret = mmc_boot_get_card_status(card, 0, &status);
-		if (MMC_BOOT_CARD_STATUS(status) == MMC_BOOT_TRAN_STATE)
-			break;
-	}
-	while ((mmc_ret == MMC_BOOT_E_SUCCESS) &&
-	       (MMC_BOOT_CARD_STATUS(status) == MMC_BOOT_PROG_STATE));
-
-	if (mmc_ret != MMC_BOOT_E_SUCCESS) {
-		return mmc_ret;
-	}
-
 	/* Calculating the loop count for sending SET_WRITE_PROTECT (CMD28)
 	   or CLEAR_WRITE_PROTECT (CMD29).
 	   We are write protecting the partitions in blocks of write protect
@@ -3142,6 +3167,9 @@
 		/* Reset DPSM */
 		writel(0, MMC_BOOT_MCI_DATA_CTL);
 
+		/* Wait for the MMC_BOOT_MCI_DATA_CTL write to go through. */
+		mmc_mclk_reg_wr_delay();
+
 		dprintf(SPEW, "Offset value is %d \n", offset);
 	}
 	else