msm_shared: Fix the delays in the mmc driver.

Use the new mmc controller register interface to check
if the writes to mci ports are active.

Fix the switch cmd to wait for R1b response.

CRs-Fixed: 429975
Change-Id: Ib51397a08c3d02a3eab1872fb8bb525d9fc47e47
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 0635b81..478b4ce 100644
--- a/platform/msm8960/acpuclock.c
+++ b/platform/msm8960/acpuclock.c
@@ -233,6 +233,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