Merge "target: msm8974: Add support to use different sdc instances"
diff --git a/dev/pmic/pm8x41/include/pm8x41.h b/dev/pmic/pm8x41/include/pm8x41.h
index 731528c..b230549 100644
--- a/dev/pmic/pm8x41/include/pm8x41.h
+++ b/dev/pmic/pm8x41/include/pm8x41.h
@@ -61,6 +61,7 @@
 
 #define PON_PSHOLD_WARM_RESET   0x1
 #define PON_PSHOLD_SHUTDOWN     0x4
+#define PON_PSHOLD_HARD_RESET   0x7
 
 enum PM8X41_VERSIONS
 {
diff --git a/platform/msm8226/include/platform/iomap.h b/platform/msm8226/include/platform/iomap.h
index ea8bbeb..5418229 100644
--- a/platform/msm8226/include/platform/iomap.h
+++ b/platform/msm8226/include/platform/iomap.h
@@ -128,6 +128,17 @@
 #define SDCC1_N                     (CLK_CTL_BASE + 0x4DC) /* n */
 #define SDCC1_D                     (CLK_CTL_BASE + 0x4E0) /* d */
 
+/* SDCC2 */
+#define SDCC2_BCR                   (CLK_CTL_BASE + 0x500) /* block reset */
+#define SDCC2_APPS_CBCR             (CLK_CTL_BASE + 0x504) /* branch control */
+#define SDCC2_AHB_CBCR              (CLK_CTL_BASE + 0x508)
+#define SDCC2_INACTIVITY_TIMER_CBCR (CLK_CTL_BASE + 0x50C)
+#define SDCC2_CMD_RCGR              (CLK_CTL_BASE + 0x510) /* cmd */
+#define SDCC2_CFG_RCGR              (CLK_CTL_BASE + 0x514) /* cfg */
+#define SDCC2_M                     (CLK_CTL_BASE + 0x518) /* m */
+#define SDCC2_N                     (CLK_CTL_BASE + 0x51C) /* n */
+#define SDCC2_D                     (CLK_CTL_BASE + 0x520) /* d */
+
 /* UART */
 #define BLSP1_AHB_CBCR              (CLK_CTL_BASE + 0x5C4)
 #define BLSP1_UART3_APPS_CBCR       (CLK_CTL_BASE + 0x784)
@@ -144,9 +155,11 @@
 #define USB_HS_SYSTEM_CFG_RCGR      (CLK_CTL_BASE + 0x494)
 
 /* SDHCI */
-#define SDCC_MCI_HC_MODE            (PERIPH_SS_BASE + 0x00024078)
-#define SDCC_HC_PWRCTL_MASK_REG     (PERIPH_SS_BASE + 0x000240E0)
-#define SDCC_HC_PWRCTL_CTL_REG      (PERIPH_SS_BASE + 0x000240E8)
+#define SDCC_MCI_HC_MODE            (0x00000078)
+#define SDCC_HC_PWRCTL_STATUS_REG   (0x000000DC)
+#define SDCC_HC_PWRCTL_MASK_REG     (0x000000E0)
+#define SDCC_HC_PWRCTL_CLEAR_REG    (0x000000E4)
+#define SDCC_HC_PWRCTL_CTL_REG      (0x000000E8)
 
 /* DRV strength for sdcc */
 #define SDC1_HDRV_PULL_CTL           (TLMM_BASE_ADDR + 0x00002044)
diff --git a/platform/msm8226/include/platform/irqs.h b/platform/msm8226/include/platform/irqs.h
index 2e29d3a..c3abd2f 100644
--- a/platform/msm8226/include/platform/irqs.h
+++ b/platform/msm8226/include/platform/irqs.h
@@ -47,7 +47,9 @@
 #define USB1_HS_BAM_IRQ                        (GIC_SPI_START + 135)
 #define USB1_HS_IRQ                            (GIC_SPI_START + 134)
 
-#define SDCC_PWRCTRL_IRQ                       (GIC_SPI_START + 138)
+#define SDCC1_PWRCTL_IRQ                       (GIC_SPI_START + 138)
+#define SDCC2_PWRCTL_IRQ                       (GIC_SPI_START + 221)
+#define SDCC3_PWRCTL_IRQ                       (GIC_SPI_START + 224)
 
 /* Retrofit universal macro names */
 #define INT_USB_HS                             USB1_HS_IRQ
diff --git a/platform/msm8226/msm8226-clock.c b/platform/msm8226/msm8226-clock.c
index bd0a265..4c4758d 100644
--- a/platform/msm8226/msm8226-clock.c
+++ b/platform/msm8226/msm8226-clock.c
@@ -166,6 +166,46 @@
 	},
 };
 
+static struct rcg_clk sdcc2_apps_clk_src =
+{
+	.cmd_reg      = (uint32_t *) SDCC2_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) SDCC2_CFG_RCGR,
+	.m_reg        = (uint32_t *) SDCC2_M,
+	.n_reg        = (uint32_t *) SDCC2_N,
+	.d_reg        = (uint32_t *) SDCC2_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_sdcc1_2_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "sdc2_clk",
+		.ops      = &clk_ops_rcg_mnd,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC2_APPS_CBCR,
+	.parent       = &sdcc2_apps_clk_src.c,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_apps_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC2_AHB_CBCR,
+	.has_sibling  = 1,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 /* UART Clocks */
 static struct clk_freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] =
 {
@@ -487,6 +527,9 @@
 	CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
 	CLK_LOOKUP("sdc1_core_clk",  gcc_sdcc1_apps_clk.c),
 
+	CLK_LOOKUP("sdc2_iface_clk", gcc_sdcc2_ahb_clk.c),
+	CLK_LOOKUP("sdc2_core_clk",  gcc_sdcc2_apps_clk.c),
+
 	CLK_LOOKUP("uart3_iface_clk", gcc_blsp1_ahb_clk.c),
 	CLK_LOOKUP("uart3_core_clk",  gcc_blsp1_uart3_apps_clk.c),
 
diff --git a/platform/msm8974/include/platform/iomap.h b/platform/msm8974/include/platform/iomap.h
index 799fc86..3e27c3b 100644
--- a/platform/msm8974/include/platform/iomap.h
+++ b/platform/msm8974/include/platform/iomap.h
@@ -139,6 +139,17 @@
 #define SDCC1_N                     (CLK_CTL_BASE + 0x4DC) /* n */
 #define SDCC1_D                     (CLK_CTL_BASE + 0x4E0) /* d */
 
+/* SDCC2 */
+#define SDCC2_BCR                   (CLK_CTL_BASE + 0x500) /* block reset */
+#define SDCC2_APPS_CBCR             (CLK_CTL_BASE + 0x504) /* branch control */
+#define SDCC2_AHB_CBCR              (CLK_CTL_BASE + 0x508)
+#define SDCC2_INACTIVITY_TIMER_CBCR (CLK_CTL_BASE + 0x50C)
+#define SDCC2_CMD_RCGR              (CLK_CTL_BASE + 0x510) /* cmd */
+#define SDCC2_CFG_RCGR              (CLK_CTL_BASE + 0x514) /* cfg */
+#define SDCC2_M                     (CLK_CTL_BASE + 0x518) /* m */
+#define SDCC2_N                     (CLK_CTL_BASE + 0x51C) /* n */
+#define SDCC2_D                     (CLK_CTL_BASE + 0x520) /* d */
+
 /* UART */
 #define BLSP1_AHB_CBCR              (CLK_CTL_BASE + 0x5C4)
 #define BLSP2_AHB_CBCR              (CLK_CTL_BASE + 0x944)
@@ -206,7 +217,9 @@
 #define SDC1_HDRV_PULL_CTL           (TLMM_BASE_ADDR + 0x00002044)
 
 /* SDHCI */
-#define SDCC_MCI_HC_MODE            (PERIPH_SS_BASE + 0x00024078)
-#define SDCC_HC_PWRCTL_MASK_REG     (PERIPH_SS_BASE + 0x000240E0)
-#define SDCC_HC_PWRCTL_CTL_REG      (PERIPH_SS_BASE + 0x000240E8)
+#define SDCC_MCI_HC_MODE            (0x00000078)
+#define SDCC_HC_PWRCTL_STATUS_REG   (0x000000DC)
+#define SDCC_HC_PWRCTL_MASK_REG     (0x000000E0)
+#define SDCC_HC_PWRCTL_CLEAR_REG    (0x000000E4)
+#define SDCC_HC_PWRCTL_CTL_REG      (0x000000E8)
 #endif
diff --git a/platform/msm8974/include/platform/irqs.h b/platform/msm8974/include/platform/irqs.h
index 56ef1cb..e9b2d06 100644
--- a/platform/msm8974/include/platform/irqs.h
+++ b/platform/msm8974/include/platform/irqs.h
@@ -66,5 +66,8 @@
                                                ((GIC_SPI_START + 95) + qup_id):\
                                                ((GIC_SPI_START + 101) + qup_id))
 
-#define SDCC_PWRCTRL_IRQ                       (GIC_SPI_START + 138)
+#define SDCC1_PWRCTL_IRQ                       (GIC_SPI_START + 138)
+#define SDCC2_PWRCTL_IRQ                       (GIC_SPI_START + 221)
+#define SDCC3_PWRCTL_IRQ                       (GIC_SPI_START + 224)
+#define SDCC4_PWRCTL_IRQ                       (GIC_SPI_START + 227)
 #endif	/* __IRQS_COPPER_H */
diff --git a/platform/msm8974/msm8974-clock.c b/platform/msm8974/msm8974-clock.c
index 6c88589..dbba8c4 100644
--- a/platform/msm8974/msm8974-clock.c
+++ b/platform/msm8974/msm8974-clock.c
@@ -166,6 +166,46 @@
 	},
 };
 
+static struct rcg_clk sdcc2_apps_clk_src =
+{
+	.cmd_reg      = (uint32_t *) SDCC2_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) SDCC2_CFG_RCGR,
+	.m_reg        = (uint32_t *) SDCC2_M,
+	.n_reg        = (uint32_t *) SDCC2_N,
+	.d_reg        = (uint32_t *) SDCC2_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_sdcc1_2_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "sdc2_clk",
+		.ops      = &clk_ops_rcg_mnd,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC2_APPS_CBCR,
+	.parent       = &sdcc2_apps_clk_src.c,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_apps_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk =
+{
+	.cbcr_reg     = (uint32_t *) SDCC2_AHB_CBCR,
+	.has_sibling  = 1,
+
+	.c = {
+		.dbg_name = "gcc_sdcc2_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 /* UART Clocks */
 static struct clk_freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] =
 {
@@ -590,6 +630,9 @@
 	CLK_LOOKUP("sdc1_iface_clk", gcc_sdcc1_ahb_clk.c),
 	CLK_LOOKUP("sdc1_core_clk",  gcc_sdcc1_apps_clk.c),
 
+	CLK_LOOKUP("sdc2_iface_clk", gcc_sdcc2_ahb_clk.c),
+	CLK_LOOKUP("sdc2_core_clk",  gcc_sdcc2_apps_clk.c),
+
 	CLK_LOOKUP("uart2_iface_clk", gcc_blsp1_ahb_clk.c),
 	CLK_LOOKUP("uart2_core_clk",  gcc_blsp1_uart2_apps_clk.c),
 
diff --git a/platform/msm_shared/display.c b/platform/msm_shared/display.c
index 026142c..9254a78 100755
--- a/platform/msm_shared/display.c
+++ b/platform/msm_shared/display.c
@@ -283,7 +283,7 @@
 		ret = mdp_dsi_video_off();
 		if (ret)
 			goto msm_display_off_out;
-		ret = mipi_dsi_off();
+		ret = mipi_dsi_off(pinfo);
 		if (ret)
 			goto msm_display_off_out;
 		break;
@@ -292,7 +292,7 @@
 		ret = mdp_dsi_cmd_off();
 		if (ret)
 			goto msm_display_off_out;
-		ret = mipi_dsi_off();
+		ret = mipi_dsi_off(pinfo);
 		if (ret)
 			goto msm_display_off_out;
 		break;
diff --git a/platform/msm_shared/include/mipi_dsi.h b/platform/msm_shared/include/mipi_dsi.h
index 6a00efa..4f90f96 100755
--- a/platform/msm_shared/include/mipi_dsi.h
+++ b/platform/msm_shared/include/mipi_dsi.h
@@ -1000,7 +1000,7 @@
 		unsigned char eof_bllp_pwr,
 		unsigned char interleav);
 int mipi_dsi_on();
-int mipi_dsi_off();
+int mipi_dsi_off(struct msm_panel_info *pinfo);
 int mipi_dsi_cmds_tx(struct mipi_dsi_cmd *cmds, int count);
 int mipi_dsi_cmds_rx(char **rp, int len);
 #endif
diff --git a/platform/msm_shared/include/mmc_sdhci.h b/platform/msm_shared/include/mmc_sdhci.h
index 6aa323d..79d3965 100644
--- a/platform/msm_shared/include/mmc_sdhci.h
+++ b/platform/msm_shared/include/mmc_sdhci.h
@@ -143,6 +143,44 @@
 
 #define MMC_ADDR_OUT_OF_RANGE(resp)              ((resp >> 31) & 0x01)
 
+/* SD card related Macros */
+/* Arguments for commands */
+#define MMC_SD_HC_VOLT_SUPPLIED                   0x000001AA
+#define MMC_SD_OCR                                0x00FF8000
+#define MMC_SD_HC_HCS                             0x40000000
+#define MMC_SD_DEV_READY                          0x80000000
+#define MMC_CARD_TYPE_SDHC                        0x1
+#define MMC_CARD_TYPE_STD_SD                      0x0
+#define SD_CARD_RCA                               0x0
+#define MMC_SD_SWITCH_HS                          0x80FFFFF1
+
+#define SD_CMD8_MAX_RETRY                         0x3
+#define SD_ACMD41_MAX_RETRY                       0x14
+
+/* SCR(SD Card Register) related */
+#define SD_SCR_BUS_WIDTH                          16
+#define SD_SCR_SD_SPEC                            24
+#define SD_SCR_SD_SPEC3                           15
+#define SD_SCR_BUS_WIDTH_MASK                     0xf0000
+#define SD_SCR_SD_SPEC_MASK                       0x0f000000
+#define SD_SCR_SD_SPEC3_MASK                      0x8000
+#define SD_SCR_CMD23_SUPPORT                      BIT(1)
+#define SD_SCR_WIDTH_4BIT                         BIT(2)
+
+/* SSR related macros */
+#define MMC_SD_AU_SIZE_BIT                        428
+#define MMC_SD_AU_SIZE_LEN                        4
+#define MMC_SD_ERASE_SIZE_BIT                     408
+#define MMC_SD_ERASE_SIZE_LEN                     16
+
+/* Commands for SD card */
+#define CMD8_SEND_IF_COND                         8
+#define ACMD6_SET_BUS_WIDTH                       6
+#define ACMD13_SEND_SD_STATUS                     13
+#define ACMD41_SEND_OP_COND                       41
+#define ACMD51_READ_CARD_SCR                      51
+#define CMD55_APP_CMD                             55
+
 /* Can be used to unpack array of upto 32 bits data */
 #define UNPACK_BITS(array, start, len, size_of)           \
     ({                                                    \
@@ -156,6 +194,20 @@
      unpck & mask;                                        \
      })
 
+#define swap_endian32(x) \
+	((uint32_t)( \
+	(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
+	(((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) | \
+	(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) | \
+	(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) ))
+
+
+#define MMC_CARD_SD(card) ((card->type == MMC_CARD_TYPE_SDHC) || \
+						   (card->type == MMC_CARD_TYPE_STD_SD))
+
+#define MMC_CARD_MMC(card) ((card->type == MMC_TYPE_STD_MMC) || \
+							(card->type == MMC_TYPE_MMCHC))
+
 /* CSD Register.
  * Note: not all the fields have been defined here
  */
@@ -196,6 +248,20 @@
 	uint32_t year;  /* 4 bits manufacturing year */
 };
 
+/* SCR register for SD card */
+struct mmc_sd_scr {
+	uint32_t bus_widths;  /* Bus width support, 8 or 1 bit */
+	uint32_t sd_spec;     /* sd spec version */
+	uint32_t sd3_spec;    /* sd spec 3 version */
+	uint32_t cmd23_support; /* cmd23 supported or not */
+};
+
+/* SD Status Register */
+struct mmc_sd_ssr {
+	uint32_t au_size;     /* Allocation unit (AU) size */
+	uint32_t num_aus;      /* Number of AUs */
+};
+
 /* mmc card register */
 struct mmc_card {
 	uint32_t rca;            /* Relative addres of the card*/
@@ -205,14 +271,19 @@
 	uint32_t status;         /* Card status */
 	uint8_t *ext_csd;        /* Ext CSD for the card info */
 	uint32_t raw_csd[4];     /* Raw CSD for the card */
+	uint32_t raw_scr[2];     /* SCR for SD card */
 	struct mmc_cid cid;      /* CID structure */
 	struct mmc_csd csd;      /* CSD structure */
+	struct mmc_sd_scr scr;   /* SCR structure */
+	struct mmc_sd_ssr ssr;   /* SSR Register */
 };
 
 /* mmc device config data */
 struct mmc_config_data {
 	uint8_t slot;          /* Sdcc slot used */
-	uint32_t base;         /* Based address for the sdcc */
+	uint8_t pwr_irq;       /* Power Irq from card to host */
+	uint32_t sdhc_base;    /* Base address for the sdhc */
+	uint32_t pwrctl_base;  /* Base address for power control registers */
 	uint16_t bus_width;    /* Bus width used */
 	uint32_t max_clk_rate; /* Max clock rate supported */
 };
diff --git a/platform/msm_shared/include/sdhci.h b/platform/msm_shared/include/sdhci.h
index 20861fc..ef48d1d 100644
--- a/platform/msm_shared/include/sdhci.h
+++ b/platform/msm_shared/include/sdhci.h
@@ -31,6 +31,7 @@
 
 #include <reg.h>
 #include <bits.h>
+#include <kernel/event.h>
 
 /*
  * Capabilities for the host controller
@@ -55,6 +56,7 @@
 struct sdhci_host {
 	uint32_t base;         /* Base address for the host */
 	uint32_t cur_clk_rate; /* Running clock rate */
+	event_t* sdhc_event;    /* Event for power control irqs */
 	struct host_caps caps; /* Host capabilities */
 };
 
@@ -79,6 +81,7 @@
 	uint32_t resp[4];       /* 128 bit response value */
 	uint32_t trans_mode;    /* Transfer mode, read/write */
 	uint32_t cmd_retry;     /* Retry the command, if card is busy */
+	uint32_t cmd23_support; /* If card supports cmd23 */
 	struct mmc_data data;   /* Data pointer */
 };
 
@@ -239,6 +242,7 @@
 #define SDHCI_BLK_CNT_EN                          BIT(1)
 #define SDHCI_DMA_EN                              BIT(0)
 #define SDHCI_AUTO_CMD23_EN                       BIT(3)
+#define SDHCI_AUTO_CMD12_EN                       BIT(2)
 #define SDHCI_ADMA_32BIT                          BIT(4)
 
 /*
diff --git a/platform/msm_shared/include/sdhci_msm.h b/platform/msm_shared/include/sdhci_msm.h
new file mode 100644
index 0000000..1d77823
--- /dev/null
+++ b/platform/msm_shared/include/sdhci_msm.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2013, 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 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
+ * 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.
+ */
+
+#ifndef __SDHCI_MSM_H__
+#define __SDHCI_MSM_H__
+
+#include <kernel/event.h>
+
+struct sdhci_msm_data
+{
+	uint32_t pwrctl_base;
+	uint32_t pwr_irq;
+	event_t*  sdhc_event;
+};
+
+void sdhci_msm_init(struct sdhci_msm_data *data);
+
+#endif
diff --git a/platform/msm_shared/mipi_dsi.c b/platform/msm_shared/mipi_dsi.c
index bbda314..43559eb 100644
--- a/platform/msm_shared/mipi_dsi.c
+++ b/platform/msm_shared/mipi_dsi.c
@@ -1175,7 +1175,7 @@
 	return ret;
 }
 
-int mipi_dsi_off()
+int mipi_dsi_off(struct msm_panel_info *pinfo)
 {
 	if(!target_cont_splash_screen())
 	{
@@ -1189,6 +1189,8 @@
 	}
 
 	writel(0x1115501, DSI_INT_CTRL);
+	if (pinfo->mipi.broadcast)
+		writel(0x1115501, DSI_INT_CTRL + 0x600);
 
 	return NO_ERROR;
 }
diff --git a/platform/msm_shared/mmc_sdhci.c b/platform/msm_shared/mmc_sdhci.c
index d4b0bd4..cb00a3c 100644
--- a/platform/msm_shared/mmc_sdhci.c
+++ b/platform/msm_shared/mmc_sdhci.c
@@ -32,6 +32,7 @@
 #include <reg.h>
 #include <mmc_sdhci.h>
 #include <sdhci.h>
+#include <sdhci_msm.h>
 #include <partition_parser.h>
 #include <platform/iomap.h>
 #include <platform/timer.h>
@@ -85,8 +86,7 @@
 
 	mmc_csd.cmmc_structure = UNPACK_BITS(raw_csd, 126, 2, mmc_sizeof);
 
-	if ((card->type == MMC_TYPE_SDHC)
-	    || (card->type == MMC_TYPE_STD_SD)) {
+	if (MMC_CARD_SD(card)) {
 		/* Parse CSD according to SD card spec. */
 
 		/* CSD register is little bit differnet for CSD version 2.0 High
@@ -133,7 +133,7 @@
 			mmc_csd.temp_wp = UNPACK_BITS(raw_csd, 12, 1, mmc_sizeof);
 
 			/* Calculate the card capcity */
-			card->capacity = (1 + mmc_csd.c_size) * 512 * 1024;
+			card->capacity = (unsigned long long) (1 + mmc_csd.c_size) * 512 * 1024;
 		} else {
 			/* CSD Version 1.0 */
 			mmc_csd.card_cmd_class = UNPACK_BITS(raw_csd, 84, 12, mmc_sizeof);
@@ -177,7 +177,7 @@
 
 			/* Calculate the card capacity */
 			mmc_temp = (1 << (mmc_csd.c_size_mult + 2)) * (mmc_csd.c_size + 1);
-			card->capacity = mmc_temp * mmc_csd.read_blk_len;
+			card->capacity = (unsigned long long)mmc_temp * mmc_csd.read_blk_len;
 		}
 	} else {
 		/* Parse CSD according to MMC card spec. */
@@ -213,7 +213,7 @@
 		if (mmc_csd.c_size != 0xFFF) {
 			/* For cards less than or equal to 2GB */
 			mmc_temp = (1 << (mmc_csd.c_size_mult + 2)) * (mmc_csd.c_size + 1);
-			card->capacity = mmc_temp * mmc_csd.read_blk_len;
+			card->capacity = (unsigned long long) mmc_temp * mmc_csd.read_blk_len;
 		} else {
 			/* For cards greater than 2GB, Ext CSD register's SEC_COUNT
 			 * is used to calculate the size.
@@ -224,7 +224,6 @@
 						| (card->ext_csd[MMC_SEC_COUNT3] << MMC_SEC_COUNT3_SHIFT)
 						| (card->ext_csd[MMC_SEC_COUNT2] << MMC_SEC_COUNT2_SHIFT)
 						| card->ext_csd[MMC_SEC_COUNT1];
-
 			card->capacity = sec_count * MMC_BLK_SZ;
 		}
 	}
@@ -234,22 +233,22 @@
 			sizeof(struct mmc_csd));
 
 	dprintf(SPEW, "Decoded CSD fields:\n");
-	dprintf(SPEW, "cmmc_structure: %d\n", mmc_csd.cmmc_structure);
+	dprintf(SPEW, "cmmc_structure: %u\n", mmc_csd.cmmc_structure);
 	dprintf(SPEW, "card_cmd_class: %x\n", mmc_csd.card_cmd_class);
-	dprintf(SPEW, "write_blk_len: %d\n", mmc_csd.write_blk_len);
-	dprintf(SPEW, "read_blk_len: %d\n", mmc_csd.read_blk_len);
-	dprintf(SPEW, "r2w_factor: %d\n", mmc_csd.r2w_factor);
-	dprintf(SPEW, "sector_size: %d\n", mmc_csd.sector_size);
-	dprintf(SPEW, "c_size_mult:%d\n", mmc_csd.c_size_mult);
-	dprintf(SPEW, "c_size: %d\n", mmc_csd.c_size);
-	dprintf(SPEW, "nsac_clk_cycle: %d\n", mmc_csd.nsac_clk_cycle);
-	dprintf(SPEW, "taac_ns: %d\n", mmc_csd.taac_ns);
-	dprintf(SPEW, "tran_speed: %d kbps\n", mmc_csd.tran_speed);
-	dprintf(SPEW, "erase_blk_len: %d\n", mmc_csd.erase_blk_len);
-	dprintf(SPEW, "read_blk_misalign: %d\n", mmc_csd.read_blk_misalign);
-	dprintf(SPEW, "write_blk_misalign: %d\n", mmc_csd.write_blk_misalign);
-	dprintf(SPEW, "read_blk_partial: %d\n", mmc_csd.read_blk_partial);
-	dprintf(SPEW, "write_blk_partial: %d\n", mmc_csd.write_blk_partial);
+	dprintf(SPEW, "write_blk_len: %u\n", mmc_csd.write_blk_len);
+	dprintf(SPEW, "read_blk_len: %u\n", mmc_csd.read_blk_len);
+	dprintf(SPEW, "r2w_factor: %u\n", mmc_csd.r2w_factor);
+	dprintf(SPEW, "sector_size: %u\n", mmc_csd.sector_size);
+	dprintf(SPEW, "c_size_mult:%u\n", mmc_csd.c_size_mult);
+	dprintf(SPEW, "c_size: %u\n", mmc_csd.c_size);
+	dprintf(SPEW, "nsac_clk_cycle: %u\n", mmc_csd.nsac_clk_cycle);
+	dprintf(SPEW, "taac_ns: %u\n", mmc_csd.taac_ns);
+	dprintf(SPEW, "tran_speed: %u kbps\n", mmc_csd.tran_speed);
+	dprintf(SPEW, "erase_blk_len: %u\n", mmc_csd.erase_blk_len);
+	dprintf(SPEW, "read_blk_misalign: %u\n", mmc_csd.read_blk_misalign);
+	dprintf(SPEW, "write_blk_misalign: %u\n", mmc_csd.write_blk_misalign);
+	dprintf(SPEW, "read_blk_partial: %u\n", mmc_csd.read_blk_partial);
+	dprintf(SPEW, "write_blk_partial: %u\n", mmc_csd.write_blk_partial);
 	dprintf(SPEW, "Card Capacity: %llu Bytes\n", card->capacity);
 
 	return 0;
@@ -274,8 +273,7 @@
 
 	mmc_sizeof = sizeof(uint32_t) * 8;
 
-	if ((card->type == MMC_TYPE_SDHC) ||
-		(card->type == MMC_TYPE_STD_SD)) {
+	if (MMC_CARD_SD(card)) {
 		mmc_cid.mid = UNPACK_BITS(raw_cid, 120, 8, mmc_sizeof);
 		mmc_cid.oid = UNPACK_BITS(raw_cid, 104, 16, mmc_sizeof);
 
@@ -467,8 +465,7 @@
 	/* CMD3 Format:
 	 * [31:0] stuff bits
 	 */
-	if (card->type == MMC_TYPE_SDHC ||
-		card->type == MMC_TYPE_STD_SD) {
+	if (MMC_CARD_SD(card)) {
 		cmd.cmd_index = CMD3_SEND_RELATIVE_ADDR;
 		cmd.argument = 0;
 		cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
@@ -535,14 +532,13 @@
 
 /*
  * Function: mmc select card
- * Arg     : host, card structure & RCA
+ * Arg     : host, card structure
  * Return  : 0 on Success, 1 on Failure
  * Flow    : Selects a card by sending CMD7 to the card with its RCA.
  *           If RCA field is set as 0 ( or any other address ),
  *           the card will be de-selected. (CMD7)
  */
-static uint32_t mmc_select_card(struct sdhci_host *host, struct mmc_card *card,
-						 uint32_t rca)
+static uint32_t mmc_select_card(struct sdhci_host *host, struct mmc_card *card)
 {
 	struct mmc_command cmd;
 	uint32_t mmc_arg = 0;
@@ -554,16 +550,15 @@
 	 * [31:16] RCA
 	 * [15:0] stuff bits
 	 */
-	mmc_arg |= rca << 16;
+	mmc_arg |= card->rca << 16;
 
 	cmd.cmd_index = CMD7_SELECT_DESELECT_CARD;
 	cmd.argument = mmc_arg;
 	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
 
 	/* If we are deselecting card, we do not get response */
-	if (rca == card->rca && rca) {
-		if (card->type == MMC_TYPE_SDHC ||
-			card->type == MMC_TYPE_STD_SD)
+	if (card->rca) {
+		if (MMC_CARD_SD(card))
 			cmd.resp_type = SDHCI_CMD_RESP_R1B;
 		else
 			cmd.resp_type = SDHCI_CMD_RESP_R1;
@@ -896,10 +891,27 @@
 
 	struct sdhci_host *host;
 	struct mmc_config_data *cfg;
+	struct sdhci_msm_data data;
+
+	event_t sdhc_event;
 
 	host = &dev->host;
 	cfg = &dev->config;
 
+	event_init(&sdhc_event, false, EVENT_FLAG_AUTOUNSIGNAL);
+
+	host->base = cfg->sdhc_base;
+	host->sdhc_event = &sdhc_event;
+
+	data.sdhc_event = &sdhc_event;
+	data.pwrctl_base = cfg->pwrctl_base;
+	data.pwr_irq = cfg->pwr_irq;
+
+	/*
+	 * MSM specific sdhc init
+	 */
+	sdhci_msm_init(&data);
+
 	/*
 	 * Initialize the controller, read the host capabilities
 	 * set power on mode
@@ -953,7 +965,7 @@
 	}
 
 	/* Select the card (CMD7) */
-	mmc_return = mmc_select_card(host, card, card->rca);
+	mmc_return = mmc_select_card(host, card);
 	if (mmc_return) {
 		dprintf(CRITICAL, "Failure selecting the Card with RCA: %x\n",card->rca);
 		return mmc_return;
@@ -989,6 +1001,7 @@
 	 * Send CMD1 to identify and reject cards that do not match host's VDD range
 	 * profile. Cards sends its OCR register in response.
 	 */
+
 	mmc_return = mmc_send_op_cond(host, card);
 
 	/* OCR is not received, init could not complete */
@@ -1000,6 +1013,257 @@
 	return 0;
 }
 
+static uint32_t mmc_send_app_cmd(struct sdhci_host *host, struct mmc_card *card)
+{
+	struct mmc_command cmd = {0};
+
+	cmd.cmd_index = CMD55_APP_CMD;
+	cmd.argument = (card->rca << 16);
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+
+	if (sdhci_send_command(host, &cmd))
+	{
+		dprintf(CRITICAL, "Failed Sending CMD55\n");
+		return 1;
+	}
+	return 0;
+}
+
+uint32_t mmc_sd_card_init(struct sdhci_host *host, struct mmc_card *card)
+{
+	uint8_t i;
+	uint32_t mmc_ret;
+	struct mmc_command cmd;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* Use the SD card RCA 0x0 during init */
+	card->rca = SD_CARD_RCA;
+
+	/* Send CMD8 for voltage check*/
+	for (i = 0 ;i < SD_CMD8_MAX_RETRY; i++)
+	{
+		cmd.cmd_index = CMD8_SEND_IF_COND;
+		cmd.argument = MMC_SD_HC_VOLT_SUPPLIED;
+		cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd.resp_type = SDHCI_CMD_RESP_R7;
+
+		if (sdhci_send_command(host, &cmd))
+		{
+			dprintf(CRITICAL, "The response for CMD8 does not match the supplied value\n");
+			return 1;
+		}
+		else
+		{
+			/* If the command response echos the voltage back */
+			if (cmd.resp[0] == MMC_SD_HC_VOLT_SUPPLIED)
+				break;
+		}
+		/* As per SDCC the spec try for max three times with
+		 * 1 ms delay
+		 */
+		mdelay(1);
+	}
+
+	if (i == SD_CMD8_MAX_RETRY && (cmd.resp[0] != MMC_SD_HC_VOLT_SUPPLIED))
+	{
+		dprintf(CRITICAL, "Error: CMD8 response timed out\n");
+		return 1;
+	}
+
+	/* Send ACMD41 for OCR */
+	for (i = 0; i < SD_ACMD41_MAX_RETRY; i++)
+	{
+		/* Send APP_CMD before ACMD41*/
+		if (mmc_send_app_cmd(host, card))
+		{
+			dprintf(CRITICAL, "Failed sending App command\n");
+			return 1;
+		}
+
+		/* APP_CMD is successful, send ACMD41 now */
+		cmd.cmd_index = ACMD41_SEND_OP_COND;
+		cmd.argument = MMC_SD_OCR | MMC_SD_HC_HCS;
+		cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd.resp_type = SDHCI_CMD_RESP_R3;
+
+		if (sdhci_send_command(host, &cmd))
+		{
+			dprintf(CRITICAL, "Failure sending ACMD41\n");
+			return 1;
+		}
+		else
+		{
+			if (cmd.resp[0] & MMC_SD_DEV_READY)
+			{
+				if (cmd.resp[0] & (1 << 30))
+					card->type = MMC_CARD_TYPE_SDHC;
+				else
+					card->type = MMC_CARD_TYPE_STD_SD;
+
+				break;
+			}
+		}
+		/*
+		 * As per SDCC spec try for max 1 second
+		 */
+		mdelay(50);
+	}
+
+	if (i == SD_ACMD41_MAX_RETRY && !(cmd.resp[0] & MMC_SD_DEV_READY))
+	{
+		dprintf(CRITICAL, "Error: ACMD41 response timed out\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Function to read SD card information from SD status
+ */
+static uint32_t mmc_sd_get_card_ssr(struct sdhci_host *host, struct mmc_card *card)
+{
+	BUF_DMA_ALIGN(raw_sd_status, 64);
+	struct mmc_command cmd = {0};
+	uint32_t sd_status[16];
+	uint32_t *status = sd_status;
+	uint32_t au_size;
+	int i;
+	int j;
+
+	if (mmc_send_app_cmd(host, card))
+	{
+		dprintf(CRITICAL, "Failed sending App command\n");
+		return 1;
+	}
+
+	cmd.cmd_index = ACMD13_SEND_SD_STATUS;
+	cmd.argument = 0x0;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R2;
+	cmd.trans_mode = SDHCI_MMC_READ;
+	cmd.data_present = 0x1;
+	cmd.data.data_ptr = raw_sd_status;
+	cmd.data.num_blocks = 0x1;
+	cmd.data.blk_sz = 0x40;
+
+	/* send command */
+	if (sdhci_send_command(host, &cmd))
+		return 1;
+
+	memcpy(sd_status, raw_sd_status, sizeof(sd_status));
+
+	for (i = 15, j = 0; i >=0 ; i--, j++)
+		sd_status[i] = swap_endian32(sd_status[j]);
+
+	au_size = UNPACK_BITS(status, MMC_SD_AU_SIZE_BIT, MMC_SD_AU_SIZE_LEN, 32);
+	/* Card AU size in sectors */
+	card->ssr.au_size = 1 << (au_size + 4);
+	card->ssr.num_aus = UNPACK_BITS(status, MMC_SD_ERASE_SIZE_BIT, MMC_SD_ERASE_SIZE_LEN, 32);
+
+	return 0;
+}
+
+/*
+ * Function to read the SD CARD configuration register
+ */
+static uint32_t mmc_sd_get_card_scr(struct sdhci_host *host, struct mmc_card *card)
+{
+	BUF_DMA_ALIGN(scr_resp, 8);
+	struct mmc_command cmd = {0};
+	uint32_t raw_scr[2];
+
+	/* Now read the SCR register */
+	/* Send APP_CMD before ACMD51*/
+	if (mmc_send_app_cmd(host, card))
+	{
+		dprintf(CRITICAL, "Failed sending App command\n");
+		return 1;
+	}
+
+	cmd.cmd_index = ACMD51_READ_CARD_SCR;
+	cmd.argument = 0x0;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+	cmd.trans_mode = SDHCI_MMC_READ;
+	cmd.data_present = 0x1;
+	cmd.data.data_ptr = scr_resp;
+	cmd.data.num_blocks = 0x1;
+	cmd.data.blk_sz = 0x8;
+
+	/* send command */
+	if (sdhci_send_command(host, &cmd))
+		return 1;
+
+	memcpy(raw_scr, scr_resp, sizeof(raw_scr));
+
+	card->raw_scr[0] = swap_endian32(raw_scr[0]);
+	card->raw_scr[1] = swap_endian32(raw_scr[1]);
+
+	/*
+	 * Parse & Populate the SCR data as per sdcc spec
+	 */
+	card->scr.bus_widths = (card->raw_scr[0] & SD_SCR_BUS_WIDTH_MASK) >> SD_SCR_BUS_WIDTH;
+	card->scr.cmd23_support = (card->raw_scr[0] & SD_SCR_CMD23_SUPPORT);
+	card->scr.sd_spec = (card->raw_scr[0] & SD_SCR_SD_SPEC_MASK) >> SD_SCR_SD_SPEC;
+	card->scr.sd3_spec = (card->raw_scr[0] & SD_SCR_SD_SPEC3_MASK) >> SD_SCR_SD_SPEC3;
+
+	return 0;
+}
+
+/*
+ * Function: mmc_set_sd_bus_width
+ * Arg     : host, device structure & width
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Set the bus width for the card
+ */
+uint32_t mmc_sd_set_bus_width(struct sdhci_host *host, struct mmc_card *card, uint8_t width)
+{
+	struct mmc_command cmd = {0};
+
+	/* Send APP_CMD before ACMD6*/
+	if (mmc_send_app_cmd(host, card))
+	{
+		dprintf(CRITICAL, "Failed sending App command\n");
+		return 1;
+	}
+
+	cmd.cmd_index = ACMD6_SET_BUS_WIDTH;
+	cmd.argument = (width == DATA_BUS_WIDTH_4BIT) ? (1<<1) : 0;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+
+	/* send command */
+	if (sdhci_send_command(host, &cmd))
+		return 1;
+
+	return 0;
+}
+
+uint32_t mmc_sd_set_hs(struct sdhci_host *host, struct mmc_card *card)
+{
+       struct mmc_command cmd = {0};
+       BUF_DMA_ALIGN(switch_resp, 64);
+
+       cmd.cmd_index = CMD6_SWITCH_FUNC;
+       cmd.argument = MMC_SD_SWITCH_HS;
+       cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+       cmd.resp_type = SDHCI_CMD_RESP_R1;
+       cmd.trans_mode = SDHCI_MMC_READ;
+       cmd.data_present = 0x1;
+       cmd.data.data_ptr = switch_resp;
+       cmd.data.num_blocks = 0x1;
+       cmd.data.blk_sz = 0x40;
+
+       /* send command */
+       if (sdhci_send_command(host, &cmd))
+             return 1;
+
+	return 0;
+}
+
 /*
  * Function: mmc_init_card
  * Arg     : mmc device structure
@@ -1028,10 +1292,19 @@
 	/* TODO: Get the OCR params from target */
 	card->ocr = MMC_OCR_27_36 | MMC_OCR_SEC_MODE;
 
-	/* Reset the card & get the OCR */
+	/* Initialize the internal MMC */
 	mmc_return = mmc_reset_card_and_send_op(host, card);
 	if (mmc_return)
-		return mmc_return;
+	{
+		dprintf(CRITICAL, "MMC card failed to respond, try for SD card\n");
+		/* Reset the card & get the OCR */
+		mmc_return = mmc_sd_card_init(host, card);
+		if (mmc_return)
+		{
+			dprintf(CRITICAL, "Failed to initialize SD card\n");
+			return mmc_return;
+		}
+	}
 
 	/* Identify (CMD2, CMD3 & CMD9) and select the card (CMD7) */
 	mmc_return = mmc_identify_card(host, card);
@@ -1039,18 +1312,30 @@
 		return mmc_return;
 
 	/* set interface speed */
-	mmc_return = mmc_set_hs_interface(host, card);
-	if (mmc_return) {
-		dprintf(CRITICAL, "Error adjusting interface speed!\n");
-		return mmc_return;
+	if (MMC_CARD_SD(card))
+	{
+		mmc_return = mmc_sd_set_hs(host, card);
+		if (mmc_return)
+		{
+			dprintf(CRITICAL, "Failed to set HS for SD card\n");
+			return mmc_return;
+		}
+	}
+	else
+	{
+		mmc_return = mmc_set_hs_interface(host, card);
+		if (mmc_return) {
+			dprintf(CRITICAL, "Error adjusting interface speed!\n");
+			return mmc_return;
+		}
 	}
 
 	/* Set the sdcc clock to 50 MHZ */
 	sdhci_clk_supply(host, SDHCI_CLK_50MHZ);
 
 	/* Now get the extended CSD for the card */
-	if ((card->type == MMC_TYPE_STD_MMC) ||
-		(card->type == MMC_TYPE_MMCHC)) {
+	if (MMC_CARD_MMC(card))
+	{
 			/* For MMC cards, also get the extended csd */
 			mmc_return = mmc_get_ext_csd(host, card);
 
@@ -1059,6 +1344,21 @@
 				return mmc_return;
 			}
 	}
+	else
+	{
+		/*Read SCR for sd card */
+		if (mmc_sd_get_card_scr(host, card))
+		{
+			dprintf(CRITICAL, "Failure getting card's SCR register\n");
+			return 1;
+		}
+		/* Read SSR for the SD card */
+		if (mmc_sd_get_card_ssr(host, card))
+		{
+			dprintf(CRITICAL, "Failed to get SSR from the card\n");
+			return 1;
+		}
+	}
 
 	/* Decode and save the CSD register */
 	mmc_return = mmc_decode_and_save_csd(card);
@@ -1068,53 +1368,79 @@
 	}
 
 
-	/* Set the bus width based on host, target capbilities */
-	if (cfg->bus_width == DATA_BUS_WIDTH_8BIT && host->caps.bus_width_8bit)
-			bus_width = DATA_BUS_WIDTH_8BIT;
-	/*
-	 * Host contoller by default supports 4 bit & 1 bit mode.
-	 * No need to check for host support here
-	 */
-	else if (cfg->bus_width == DATA_BUS_WIDTH_4BIT)
-			bus_width = DATA_BUS_WIDTH_4BIT;
+	if (MMC_CARD_MMC(card))
+	{
+		/* Set the bus width based on host, target capbilities */
+		if (cfg->bus_width == DATA_BUS_WIDTH_8BIT && host->caps.bus_width_8bit)
+				bus_width = DATA_BUS_WIDTH_8BIT;
+		/*
+		 * Host contoller by default supports 4 bit & 1 bit mode.
+		 * No need to check for host support here
+		 */
+		else if (cfg->bus_width == DATA_BUS_WIDTH_4BIT)
+				bus_width = DATA_BUS_WIDTH_4BIT;
+		else
+				bus_width = DATA_BUS_WIDTH_1BIT;
+
+		/* Set 4/8 bit SDR bus width in controller */
+		mmc_return = sdhci_set_bus_width(host, bus_width);
+
+		if (mmc_return) {
+			dprintf(CRITICAL, "Failed to set bus width for host controller\n");
+			return 1;
+		}
+
+		/* Enable high speed mode in the follwing order:
+		 * 1. HS200 mode if supported by host & card
+		 * 2. DDR mode host, if supported by host & card
+		 * 3. Use normal speed mode with supported bus width
+		 */
+		if (mmc_card_supports_hs200_mode(card) && host->caps.sdr50_support) {
+			mmc_return = mmc_set_hs200_mode(host, card, bus_width);
+
+			if (mmc_return) {
+				dprintf(CRITICAL, "Failure to set HS200 mode for Card(RCA:%x)\n",
+								  card->rca);
+				return mmc_return;
+			}
+		} else if (mmc_card_supports_ddr_mode(card) && host->caps.ddr_support) {
+			mmc_return = mmc_set_ddr_mode(host, card);
+
+			if (mmc_return) {
+				dprintf(CRITICAL, "Failure to set DDR mode for Card(RCA:%x)\n",
+								  card->rca);
+				return mmc_return;
+			}
+		} else {
+			/* Set 4/8 bit bus width for the card */
+			mmc_return = mmc_set_bus_width(host, card, bus_width);
+			if (mmc_return) {
+				dprintf(CRITICAL, "Failure to set wide bus for Card(RCA:%x)\n",
+								  card->rca);
+				return mmc_return;
+			}
+		}
+	}
 	else
+	{
+		/* Check the supported bus width for the card from SCR register */
+		if (card->scr.bus_widths & SD_SCR_WIDTH_4BIT)
+			bus_width = DATA_BUS_WIDTH_4BIT;
+		else
 			bus_width = DATA_BUS_WIDTH_1BIT;
 
-	/* Set 4/8 bit SDR bus width in controller */
-	mmc_return = sdhci_set_bus_width(host, bus_width);
-
-	if (mmc_return) {
-		dprintf(CRITICAL, "Failed to set bus width for host controller\n");
-		return 1;
-	}
-
-	/* Enable high speed mode in the follwing order:
-	 * 1. HS200 mode if supported by host & card
-	 * 2. DDR mode host, if supported by host & card
-	 * 3. Use normal speed mode with supported bus width
-	 */
-	if (mmc_card_supports_hs200_mode(card) && host->caps.sdr50_support) {
-		mmc_return = mmc_set_hs200_mode(host, card, bus_width);
-
-		if (mmc_return) {
-			dprintf(CRITICAL, "Failure to set HS200 mode for Card(RCA:%x)\n",
-							  card->rca);
+		mmc_return = mmc_sd_set_bus_width(host, card, bus_width);
+		if (mmc_return)
+		{
+			dprintf(CRITICAL, "Failed to set bus width for the card\n");
 			return mmc_return;
 		}
-	} else if (mmc_card_supports_ddr_mode(card) && host->caps.ddr_support) {
-		mmc_return = mmc_set_ddr_mode(host, card);
 
-		if (mmc_return) {
-			dprintf(CRITICAL, "Failure to set DDR mode for Card(RCA:%x)\n",
-							  card->rca);
-			return mmc_return;
-		}
-	} else {
-		/* Set 4/8 bit bus width for the card */
-		mmc_return = mmc_set_bus_width(host, card, bus_width);
-		if (mmc_return) {
-			dprintf(CRITICAL, "Failure to set wide bus for Card(RCA:%x)\n",
-							  card->rca);
+		/* Set bit SDR bus width in controller */
+		mmc_return = sdhci_set_bus_width(host, bus_width);
+		if (mmc_return)
+		{
+			dprintf(CRITICAL, "Failed to set bus width for host controller\n");
 			return mmc_return;
 		}
 	}
@@ -1174,8 +1500,6 @@
 
 	memset((struct mmc_card *)&dev->card, 0, sizeof(struct mmc_card));
 
-	dev->host.base = data->base;
-
 	/* Initialize the host & clock */
 	dprintf(SPEW, " Initializing MMC host data structure and clock!\n");
 
@@ -1227,6 +1551,8 @@
 	cmd.resp_type = SDHCI_CMD_RESP_R1;
 	cmd.trans_mode = SDHCI_MMC_READ;
 	cmd.data_present = 0x1;
+	/* Use CMD23 If card supports cMD23 */
+	cmd.cmd23_support = dev->card.scr.cmd23_support;
 	cmd.data.data_ptr = dest;
 	cmd.data.num_blocks = num_blocks;
 
@@ -1284,6 +1610,8 @@
 	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
 	cmd.resp_type = SDHCI_CMD_RESP_R1;
 	cmd.trans_mode = SDHCI_MMC_WRITE;
+	/* Use CMD23 If card supports cMD23 */
+	cmd.cmd23_support = dev->card.scr.cmd23_support;
 	cmd.data_present = 0x1;
 	cmd.data.data_ptr = src;
 	cmd.data.num_blocks = num_blocks;
@@ -1320,10 +1648,15 @@
 static uint32_t mmc_send_erase_grp_start(struct mmc_device *dev, uint32_t erase_start)
 {
 	struct mmc_command cmd;
+	struct mmc_card *card = &dev->card;
 
 	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
 
-	cmd.cmd_index = CMD35_ERASE_GROUP_START;
+	if (MMC_CARD_MMC(card))
+		cmd.cmd_index = CMD35_ERASE_GROUP_START;
+	else
+		cmd.cmd_index = CMD32_ERASE_WR_BLK_START;
+
 	cmd.argument = erase_start;
 	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
 	cmd.resp_type = SDHCI_CMD_RESP_R1;
@@ -1350,10 +1683,15 @@
 static uint32_t mmc_send_erase_grp_end(struct mmc_device *dev, uint32_t erase_end)
 {
 	struct mmc_command cmd;
+	struct mmc_card *card = &dev->card;
 
 	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
 
-	cmd.cmd_index = CMD36_ERASE_GROUP_END;
+	if (MMC_CARD_MMC(card))
+		cmd.cmd_index = CMD36_ERASE_GROUP_END;
+	else
+		cmd.cmd_index = CMD33_ERASE_WR_BLK_END;
+
 	cmd.argument = erase_end;
 	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
 	cmd.resp_type = SDHCI_CMD_RESP_R1;
@@ -1433,14 +1771,29 @@
 	uint32_t blk_end;
 	uint32_t num_erase_grps;
 	uint32_t *out;
+	struct mmc_card *card;
+
+
+	card = &dev->card;
 
 	/*
-	 * Calculate the erase unit size as per the emmc specification v4.5
+	 * Calculate the erase unit size,
+	 * 1. Based on emmc 4.5 spec for emmc card
+	 * 2. Use SD Card Status info for SD cards
 	 */
-	if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
-		erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
+	if (MMC_CARD_MMC(card))
+	{
+		/*
+		 * Calculate the erase unit size as per the emmc specification v4.5
+		 */
+		if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
+			erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
+		else
+			erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
+	}
 	else
-		erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
+		erase_unit_sz = dev->card.ssr.au_size * dev->card.ssr.num_aus;
+
 
 	/* Convert length in blocks */
 	len = len / MMC_BLK_SZ;
diff --git a/platform/msm_shared/qtimer.c b/platform/msm_shared/qtimer.c
index bf9de81..c8d6bd7 100644
--- a/platform/msm_shared/qtimer.c
+++ b/platform/msm_shared/qtimer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -93,7 +93,7 @@
 {
 	uint64_t ticks;
 
-	ticks = (msecs * ticks_per_sec) / 1000;
+	ticks = ((uint64_t) msecs * ticks_per_sec) / 1000;
 
 	delay(ticks);
 }
@@ -102,7 +102,7 @@
 {
 	uint64_t ticks;
 
-	ticks = (usecs * ticks_per_sec) / 1000000;
+	ticks = ((uint64_t) usecs * ticks_per_sec) / 1000000;
 
 	delay(ticks);
 }
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 72982b1..1fec96b 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -19,6 +19,7 @@
 ifeq ($(ENABLE_SDHCI_SUPPORT),1)
 OBJS += \
 	$(LOCAL_DIR)/sdhci.o \
+	$(LOCAL_DIR)/sdhci_msm.o \
 	$(LOCAL_DIR)/mmc_sdhci.o \
 	$(LOCAL_DIR)/mmc_wrapper.o
 else
diff --git a/platform/msm_shared/sdhci.c b/platform/msm_shared/sdhci.c
index 417e0eb..ce54433 100644
--- a/platform/msm_shared/sdhci.c
+++ b/platform/msm_shared/sdhci.c
@@ -40,41 +40,6 @@
 
 
 /*
- * Function: sdhci int handler
- * Arg     : Event argument
- * Return  : 0
- * Flow:   : 1. Read the power control mask register
- *           2. Check if bus is ON
- *           3. Write success to ack regiser
- * Details : This is power control interrupt handler.
- *           Once we receive the interrupt, we will ack the power control
- *           register that we have successfully completed pmic transactions
- */
-enum handler_return sdhci_int_handler(void *arg)
-{
-	uint32_t ack;
-	uint32_t status;
-
-	/*
-	 * Read the mask register to check if BUS & IO level
-	 * interrupts are enabled
-	 */
-	status = readl(SDCC_HC_PWRCTL_MASK_REG);
-
-	if (status & (SDCC_HC_BUS_ON | SDCC_HC_BUS_OFF))
-		ack = SDCC_HC_BUS_ON_OFF_SUCC;
-	if (status & (SDCC_HC_IO_SIG_LOW | SDCC_HC_IO_SIG_HIGH))
-		ack |= SDCC_HC_IO_SIG_SUCC;
-
-	/* Write success to power control register */
-	writel(ack, SDCC_HC_PWRCTL_CTL_REG);
-
-	event_signal((event_t *)arg, false);
-
-	return 0;
-}
-
-/*
  * Function: sdhci error status enable
  * Arg     : Host structure
  * Return  : None
@@ -207,7 +172,7 @@
 	voltage = host->caps.voltage;
 
 	voltage <<= SDHCI_BUS_VOL_SEL;
-	REG_WRITE8(host, voltage, SDHCI_BUS_PWR_EN);
+	REG_WRITE8(host, voltage, SDHCI_PWR_CTRL_REG);
 
 	voltage |= SDHCI_BUS_PWR_EN;
 
@@ -458,6 +423,8 @@
 	if (int_status & SDHCI_ERR_INT_STAT_MASK) {
 		if (sdhci_cmd_err_status(host)) {
 			dprintf(CRITICAL, "Error: Command completed with errors\n");
+			/* Reset the command & Data line */
+			REG_WRITE8(host, (SOFT_RESET_CMD | SOFT_RESET_DATA), SDHCI_RESET_REG);
 			return 1;
 		}
 	}
@@ -712,10 +679,16 @@
 		if (cmd->trans_mode == SDHCI_MMC_READ)
 			trans_mode |= SDHCI_READ_MODE;
 
-		/* Enable auto cmd 23 for multi block transfer */
+		/* Enable auto cmd23 or cmd12 for multi block transfer
+		 * based on what command card supports
+		 */
 		if (cmd->data.num_blocks > 1) {
-			trans_mode |= SDHCI_TRANS_MULTI | SDHCI_AUTO_CMD23_EN | SDHCI_BLK_CNT_EN;
-			REG_WRITE32(host, cmd->data.num_blocks, SDHCI_ARG2_REG);
+			if (cmd->cmd23_support) {
+				trans_mode |= SDHCI_TRANS_MULTI | SDHCI_AUTO_CMD23_EN | SDHCI_BLK_CNT_EN;
+				REG_WRITE32(host, cmd->data.num_blocks, SDHCI_ARG2_REG);
+			}
+			else
+				trans_mode |= SDHCI_TRANS_MULTI | SDHCI_AUTO_CMD12_EN | SDHCI_BLK_CNT_EN;
 		}
 	}
 
@@ -763,20 +736,6 @@
 }
 
 /*
- * Function: sdhci mode enable
- * Arg     : Flag (0/1)
- * Return  : None
- * Flow:   : Enable/Disable Sdhci mode
- */
-void sdhci_mode_enable(uint8_t enable)
-{
-	if (enable)
-		writel(SDHCI_HC_MODE_EN, SDCC_MCI_HC_MODE);
-	else
-		writel(SDHCI_HC_MODE_DIS, SDCC_MCI_HC_MODE);
-}
-
-/*
  * Function: sdhci init
  * Arg     : Host structure
  * Return  : None
@@ -791,9 +750,6 @@
 void sdhci_init(struct sdhci_host *host)
 {
 	uint32_t caps[2];
-	event_t sdhc_event;
-
-	event_init(&sdhc_event, false, EVENT_FLAG_AUTOUNSIGNAL);
 
 	/*
 	 * Reset the controller
@@ -832,20 +788,11 @@
 	/* SDR50 mode support */
 	host->caps.sdr50_support = (caps[1] & SDHCI_SDR50_MODE_MASK) ? 1 : 0;
 
-	/*
-	 * Register the interrupt handler for pwr irq
-	 */
-	register_int_handler(SDCC_PWRCTRL_IRQ, sdhci_int_handler, &sdhc_event);
-	unmask_interrupt(SDCC_PWRCTRL_IRQ);
-
-	/* Enable pwr control interrupt */
-	writel(SDCC_HC_PWR_CTRL_INT, SDCC_HC_PWRCTL_MASK_REG);
-
 	/* Set bus power on */
 	sdhci_set_bus_power_on(host);
 
 	/* Wait for power interrupt to be handled */
-	event_wait(&sdhc_event);
+	event_wait(host->sdhc_event);
 
 	/* Set bus width */
 	sdhci_set_bus_width(host, SDHCI_BUS_WITDH_1BIT);
diff --git a/platform/msm_shared/sdhci_msm.c b/platform/msm_shared/sdhci_msm.c
new file mode 100644
index 0000000..1b6c8b0
--- /dev/null
+++ b/platform/msm_shared/sdhci_msm.c
@@ -0,0 +1,139 @@
+/* Copyright (c) 2013, 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 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
+ * 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 <platform/iomap.h>
+#include <platform/irqs.h>
+#include <platform/interrupts.h>
+#include <platform/timer.h>
+#include <target.h>
+#include <string.h>
+#include <stdlib.h>
+#include <bits.h>
+#include <debug.h>
+#include <sdhci.h>
+#include <sdhci_msm.h>
+
+
+/*
+ * Function: sdhci int handler
+ * Arg     : MSM specific data for sdhci
+ * Return  : 0
+ * Flow:   : 1. Read the power control mask register
+ *           2. Check if bus is ON
+ *           3. Write success to ack regiser
+ * Details : This is power control interrupt handler.
+ *           Once we receive the interrupt, we will ack the power control
+ *           register that we have successfully completed pmic transactions
+ */
+static enum handler_return sdhci_int_handler(struct sdhci_msm_data *data)
+{
+	uint32_t ack;
+	uint32_t status;
+
+	/*
+	 * Read the mask register to check if BUS & IO level
+	 * interrupts are enabled
+	 */
+	status = readl(data->pwrctl_base + SDCC_HC_PWRCTL_MASK_REG);
+
+	if (status & (SDCC_HC_BUS_ON | SDCC_HC_BUS_OFF))
+		ack = SDCC_HC_BUS_ON_OFF_SUCC;
+	if (status & (SDCC_HC_IO_SIG_LOW | SDCC_HC_IO_SIG_HIGH))
+		ack |= SDCC_HC_IO_SIG_SUCC;
+
+	/* Write success to power control register */
+	writel(ack, (data->pwrctl_base + SDCC_HC_PWRCTL_CTL_REG));
+
+	event_signal(data->sdhc_event, false);
+
+	return 0;
+}
+
+/*
+ * Function: sdhci clear pending interrupts
+ * Arg     : MSM specific data for sdhci
+ * Return  : None
+ * Flow:   : Clear pending interrupts
+ */
+static void sdhci_clear_power_ctrl_irq(struct sdhci_msm_data *data)
+{
+	uint32_t irq_ctl;
+	uint32_t irq_stat;
+
+	/*
+	 * Read the power control status register to know
+	 * the status of BUS & IO_HIGH_V
+	 */
+	irq_stat = readl(data->pwrctl_base + SDCC_HC_PWRCTL_STATUS_REG);
+
+	/* Clear the power control status */
+	writel(irq_stat, (data->pwrctl_base + SDCC_HC_PWRCTL_CLEAR_REG));
+
+	/*
+	 * Handle the pending irq by ack'ing the bus & IO switch
+	 */
+	irq_ctl = readl(data->pwrctl_base + SDCC_HC_PWRCTL_CTL_REG);
+
+	if (irq_stat & (SDCC_HC_BUS_ON | SDCC_HC_BUS_OFF))
+		irq_ctl |= SDCC_HC_BUS_ON_OFF_SUCC;
+	if (irq_stat & (SDCC_HC_IO_SIG_LOW | SDCC_HC_IO_SIG_HIGH))
+		irq_ctl |= SDCC_HC_IO_SIG_SUCC;
+
+	writel(irq_ctl, (data->pwrctl_base + SDCC_HC_PWRCTL_CTL_REG));
+}
+
+/*
+ * Function: sdhci msm init
+ * Arg     : MSM specific config data for sdhci
+ * Return  : None
+ * Flow:   : Enable sdhci mode & do msm specific init
+ */
+void sdhci_msm_init(struct sdhci_msm_data *config)
+{
+	/* Enable sdhc mode */
+	writel(SDHCI_HC_MODE_EN, (config->pwrctl_base + SDCC_MCI_HC_MODE));
+
+	/*
+	 * CORE_SW_RST may trigger power irq if previous status of PWRCTL
+	 * was either BUS_ON or IO_HIGH. So before we enable the power irq
+	 * interrupt in GIC (by registering the interrupt handler), we need to
+	 * ensure that any pending power irq interrupt status is acknowledged
+	 * otherwise power irq interrupt handler would be fired prematurely.
+	 */
+	sdhci_clear_power_ctrl_irq(config);
+
+	/*
+	 * Register the interrupt handler for pwr irq
+	 */
+	register_int_handler(config->pwr_irq, sdhci_int_handler, (void *)config);
+
+	unmask_interrupt(config->pwr_irq);
+
+	/* Enable pwr control interrupt */
+	writel(SDCC_HC_PWR_CTRL_INT, (config->pwrctl_base + SDCC_HC_PWRCTL_MASK_REG));
+}
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index 3782c12..8ebbce8 100755
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -342,6 +342,7 @@
 enum platform_subtype {
 	HW_PLATFORM_SUBTYPE_UNKNOWN = 0,
 	HW_PLATFORM_SUBTYPE_MDM = 1,
+	HW_PLATFORM_SUBTYPE_8974PRO_PM8084 = 1,
 	HW_PLATFORM_SUBTYPE_CSFB = 1,
 	HW_PLATFORM_SUBTYPE_SVLTE1 = 2,
 	HW_PLATFORM_SUBTYPE_SVLTE2A = 3,
diff --git a/target/msm8226/init.c b/target/msm8226/init.c
index d8c7031..3dcdbd5 100644
--- a/target/msm8226/init.c
+++ b/target/msm8226/init.c
@@ -28,6 +28,7 @@
 
 #include <debug.h>
 #include <platform/iomap.h>
+#include <platform/irqs.h>
 #include <reg.h>
 #include <target.h>
 #include <platform.h>
@@ -67,9 +68,15 @@
 	HW_PLATFORM_SUBTYPE_SKUAB = 3,
 };
 
+static uint32_t mmc_pwrctl_base[] =
+	{ MSM_SDC1_BASE, MSM_SDC2_BASE, MSM_SDC3_BASE };
+
 static uint32_t mmc_sdhci_base[] =
 	{ MSM_SDC1_SDHCI_BASE, MSM_SDC2_SDHCI_BASE, MSM_SDC3_SDHCI_BASE };
 
+static uint32_t mmc_sdc_pwrctl_irq[] =
+	{ SDCC1_PWRCTL_IRQ, SDCC2_PWRCTL_IRQ, SDCC3_PWRCTL_IRQ };
+
 struct mmc_device *dev;
 
 void target_early_init(void)
@@ -140,27 +147,30 @@
 
 void target_sdc_init()
 {
-	struct mmc_config_data config;
+	struct mmc_config_data config = {0};
 
 	/*
 	 * Set drive strength & pull ctrl for emmc
 	 */
 	set_sdc_power_ctrl();
 
-	/* Enable sdhci mode */
-	sdhci_mode_enable(1);
-
 	config.bus_width = DATA_BUS_WIDTH_8BIT;
 	config.max_clk_rate = MMC_CLK_200MHZ;
 
 	/* Trying Slot 1*/
 	config.slot = 1;
-	config.base = mmc_sdhci_base[config.slot - 1];
+	config.sdhc_base = mmc_sdhci_base[config.slot - 1];
+	config.pwrctl_base = mmc_pwrctl_base[config.slot - 1];
+	config.pwr_irq     = mmc_sdc_pwrctl_irq[config.slot - 1];
+
 	if (!(dev = mmc_init(&config)))
 	{
 		/* Trying Slot 2 next */
 		config.slot = 2;
-		config.base = mmc_sdhci_base[config.slot - 1];
+		config.sdhc_base = mmc_sdhci_base[config.slot - 1];
+		config.pwrctl_base = mmc_pwrctl_base[config.slot - 1];
+		config.pwr_irq     = mmc_sdc_pwrctl_irq[config.slot - 1];
+
 		if (!(dev = mmc_init(&config))) {
 			dprintf(CRITICAL, "mmc init failed!");
 			ASSERT(0);
diff --git a/target/msm8974/init.c b/target/msm8974/init.c
index 683bf5c..b5fbf82 100644
--- a/target/msm8974/init.c
+++ b/target/msm8974/init.c
@@ -80,6 +80,8 @@
 #define SSD_PARTITION_SIZE      8192
 #endif
 
+#define FASTBOOT_MODE           0x77665500
+
 #define BOARD_SOC_VERSION1(soc_rev) (soc_rev >= 0x10000 && soc_rev < 0x20000)
 
 #if MMC_SDHCI_SUPPORT
@@ -427,10 +429,8 @@
 	 */
 	switch(platform_subtype) {
 	case HW_PLATFORM_SUBTYPE_UNKNOWN:
+	case HW_PLATFORM_SUBTYPE_8974PRO_PM8084:
 		break;
-	case HW_PLATFORM_SUBTYPE_MDM:
-		board->baseband = BASEBAND_MDM;
-		return;
 	default:
 		dprintf(CRITICAL, "Platform Subtype : %u is not supported\n",platform_subtype);
 		ASSERT(0);
@@ -500,6 +500,7 @@
 void reboot_device(unsigned reboot_reason)
 {
 	uint32_t soc_ver = 0;
+	uint8_t reset_type = 0;
 
 	soc_ver = board_soc_version();
 
@@ -509,11 +510,16 @@
 	else
 		writel(reboot_reason, RESTART_REASON_ADDR_V2);
 
+	if(reboot_reason == FASTBOOT_MODE)
+		reset_type = PON_PSHOLD_WARM_RESET;
+	else
+		reset_type = PON_PSHOLD_HARD_RESET;
+
 	/* Configure PMIC for warm reset */
 	if (target_is_8974() && (pmic_ver == PM8X41_VERSION_V2))
-		pm8x41_v2_reset_configure(PON_PSHOLD_WARM_RESET);
+		pm8x41_v2_reset_configure(reset_type);
 	else
-		pm8x41_reset_configure(PON_PSHOLD_WARM_RESET);
+		pm8x41_reset_configure(reset_type);
 
 	/* Disable Watchdog Debug.
 	 * Required becuase of a H/W bug which causes the system to