Merge "platform: msm8974: Add platform changes for sdhci"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 78bfd44..6047ecb 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -35,6 +35,7 @@
 #include <arch/arm.h>
 #include <dev/udc.h>
 #include <string.h>
+#include <stdlib.h>
 #include <kernel/thread.h>
 #include <arch/ops.h>
 
@@ -158,23 +159,10 @@
 static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr)
 {
 	/* overwrite the destination of specified for the project */
-	/*
-	 * Update the value to sane values only when the boot image
-	 * header does not have sane values, this is added to make sure
-	 * that we always use values from boot.img header and use the
-	 * force values when boot image header has default values.
-	 */
-#ifdef ABOOT_FORCE_KERNEL_ADDR
-	if (hdr->kernel_addr == ABOOT_DEFAULT_KERNEL_ADDR)
-		hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
-#endif
-#ifdef ABOOT_FORCE_RAMDISK_ADDR
-	if (hdr->ramdisk_addr == ABOOT_DEFAULT_RAMDISK_ADDR)
-		hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
-#endif
-#ifdef ABOOT_FORCE_TAGS_ADDR
-	if (hdr->tags_addr == ABOOT_DEFAULT_TAGS_ADDR)
-		hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
+#ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
+	hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
+	hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
+	hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
 #endif
 }
 
@@ -498,9 +486,9 @@
 
 #define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
 
-static unsigned char buf[4096]; //Equal to max-supported pagesize
+BUF_DMA_ALIGN(buf, 4096); //Equal to max-supported pagesize
 #if DEVICE_TREE
-static unsigned char dt_buf[4096];
+BUF_DMA_ALIGN(dt_buf, 4096);
 #endif
 
 int boot_linux_from_mmc(void)
@@ -1013,7 +1001,7 @@
 	return 0;
 }
 
-unsigned char info_buf[4096];
+BUF_DMA_ALIGN(info_buf, 4096);
 void write_device_info_mmc(device_info *dev)
 {
 	struct device_info *info = (void*) info_buf;
@@ -1340,8 +1328,8 @@
 
 void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
 {
+	BUF_DMA_ALIGN(out, 512);
 	unsigned long long ptn = 0;
-	unsigned int out[512] = {0};
 	int index = INVALID_PTN;
 
 	index = partition_get_index(arg);
@@ -1540,7 +1528,7 @@
 	{
 		if(major_version >= 2)
 		{
-			if( !strcmp(arg,"ssd") || !strcmp(arg,"tqs") )
+			if( !strcmp(arg, "ssd") || !strcmp(arg, "tqs") )
 			{
 				ret = encrypt_scm((uint32 **) &data, &sz);
 				if (ret != 0) {
@@ -1548,10 +1536,13 @@
 					return;
 				}
 
-				ret = scm_protect_keystore((uint32 *) data, sz);
-				if (ret != 0) {
-					dprintf(CRITICAL, "ERROR: scm_protect_keystore Failed\n");
-					return;
+				/* Protect only for SSD */
+				if (!strcmp(arg, "ssd")) {
+					ret = scm_protect_keystore((uint32 *) data, sz);
+					if (ret != 0) {
+						dprintf(CRITICAL, "ERROR: scm_protect_keystore Failed\n");
+						return;
+					}
 				}
 			}
 			else
diff --git a/arch/arm/include/arch/defines.h b/arch/arm/include/arch/defines.h
index 825629b..2041f39 100644
--- a/arch/arm/include/arch/defines.h
+++ b/arch/arm/include/arch/defines.h
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 2008 Travis Geiselbrecht
  *
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files
  * (the "Software"), to deal in the Software without restriction,
@@ -38,5 +40,6 @@
  #error unknown cpu
 #endif
 
+#define IS_CACHE_LINE_ALIGNED(addr)  !((uint32_t) (addr) & (CACHE_LINE - 1))
 #endif
 
diff --git a/dev/panel/msm/mipi_sharp_video_qhd.c b/dev/panel/msm/mipi_sharp_video_qhd.c
new file mode 100644
index 0000000..c7699a0
--- /dev/null
+++ b/dev/panel/msm/mipi_sharp_video_qhd.c
@@ -0,0 +1,163 @@
+/* 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 <stdint.h>
+#include <msm_panel.h>
+#include <mipi_dsi.h>
+#include <sys/types.h>
+#include <err.h>
+#include <reg.h>
+#include <mdp4.h>
+
+int mipi_sharp_video_qhd_config(void *pdata)
+{
+	int ret = NO_ERROR;
+
+	/* 2 Lanes -- Enables Data Lane0, 1 */
+	uint8_t lane_en = 0x3;
+	uint64_t low_pwr_stop_mode = 0;
+
+	/* Needed or else will have blank line at top of display */
+	uint8_t eof_bllp_pwr = 0x9;
+
+	uint8_t interleav = 0;
+	struct lcdc_panel_info *lcdc = NULL;
+	struct msm_panel_info *pinfo = (struct msm_panel_info *)pdata;
+
+	if (!pinfo)
+		return ERR_INVALID_ARGS;
+
+	lcdc = &(pinfo->lcdc);
+	if (!lcdc)
+		return ERR_INVALID_ARGS;
+
+	ret = mipi_dsi_video_mode_config((pinfo->xres + lcdc->xres_pad),
+			(pinfo->yres + lcdc->yres_pad),
+			(pinfo->xres),
+			(pinfo->yres),
+			(lcdc->h_front_porch),
+			(lcdc->h_back_porch + lcdc->h_pulse_width),
+			(lcdc->v_front_porch),
+			(lcdc->v_back_porch + lcdc->v_pulse_width),
+			(lcdc->h_pulse_width),
+			(lcdc->v_pulse_width),
+			pinfo->mipi.dst_format,
+			pinfo->mipi.traffic_mode,
+			lane_en,
+			low_pwr_stop_mode,
+			eof_bllp_pwr,
+			interleav);
+	return ret;
+}
+
+int mipi_sharp_video_qhd_on()
+{
+	return NO_ERROR;
+}
+
+int mipi_sharp_video_qhd_off()
+{
+	return NO_ERROR;
+}
+
+static struct mdss_dsi_phy_ctrl dsi_video_mode_phy_db = {
+	/* 540x960, RGB888, 2 Lane 60 fps video mode */
+	/* regulator */
+	{0x07, 0x09, 0x03, 0x00, 0x20, 0x00, 0x01},
+	/* timing */
+	{0x46, 0x1d, 0x20, 0x00, 0x39, 0x3a, 0x21, 0x21,
+		0x32, 0x03, 0x04, 0x00},
+	/* phy ctrl */
+	{0x5f, 0x00, 0x00, 0x10},
+	/* strength */
+	{0xff, 0x06},
+	/* bist control */
+	{0x00, 0x00, 0xb1, 0xff, 0x00, 0x00},
+	/* lanes config */
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x97,
+	 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x97,
+	 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x97,
+	 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x97,
+	 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbb},
+};
+
+void mipi_sharp_video_qhd_init(struct msm_panel_info *pinfo)
+{
+	if (!pinfo)
+		return;
+
+	pinfo->xres = 540;
+	pinfo->yres = 960;
+	pinfo->type = MIPI_VIDEO_PANEL;
+	pinfo->wait_cycle = 0;
+	pinfo->bpp = 24;
+	pinfo->lcdc.h_back_porch = 80;
+	pinfo->lcdc.h_front_porch = 48;
+	pinfo->lcdc.h_pulse_width = 32;
+	pinfo->lcdc.v_back_porch = 15;
+	pinfo->lcdc.v_front_porch = 3;
+	pinfo->lcdc.v_pulse_width = 10;
+	pinfo->lcdc.border_clr = 0;	/* blk */
+	pinfo->lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo->lcdc.hsync_skew = 0;
+	pinfo->clk_rate = 500000000;
+
+	pinfo->mipi.mode = DSI_VIDEO_MODE;
+	pinfo->mipi.pulse_mode_hsa_he = FALSE;
+	pinfo->mipi.hfp_power_stop = FALSE;
+	pinfo->mipi.hbp_power_stop = FALSE;
+	pinfo->mipi.hsa_power_stop = FALSE;
+	pinfo->mipi.eof_bllp_power_stop = FALSE;
+	pinfo->mipi.bllp_power_stop = FALSE;
+	pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_PULSE;
+	pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+	pinfo->mipi.vc = 0;
+	pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+	pinfo->mipi.data_lane0 = TRUE;
+	pinfo->mipi.data_lane1 = TRUE;
+	pinfo->mipi.data_lane2 = FALSE;
+	pinfo->mipi.data_lane3 = FALSE;
+	pinfo->mipi.t_clk_post = 0x04;
+	pinfo->mipi.t_clk_pre = 0x1c;
+	pinfo->mipi.stream = 0; /* dma_p */
+	pinfo->mipi.mdp_trigger = 0;
+	pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+	pinfo->mipi.frame_rate = 60;
+	pinfo->mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
+	pinfo->mipi.tx_eot_append = TRUE;
+	pinfo->mipi.num_of_lanes = 2;
+
+	pinfo->mipi.panel_cmds = sharp_qhd_video_mode_cmds;
+	pinfo->mipi.num_of_panel_cmds =
+				 ARRAY_SIZE(sharp_qhd_video_mode_cmds);
+
+	pinfo->on = mipi_sharp_video_qhd_on;
+	pinfo->off = mipi_sharp_video_qhd_off;
+	pinfo->config = mipi_sharp_video_qhd_config;
+}
diff --git a/dev/panel/msm/mipi_toshiba_video_720p.c b/dev/panel/msm/mipi_toshiba_video_720p.c
index 5357e77..c66e8b2 100644
--- a/dev/panel/msm/mipi_toshiba_video_720p.c
+++ b/dev/panel/msm/mipi_toshiba_video_720p.c
@@ -43,8 +43,9 @@
 	uint8_t lane_en = 0xf;
 	uint64_t low_pwr_stop_mode = 0;
 
-	/* Needed or else will have blank line at top of display */
-	uint8_t eof_bllp_pwr = 0x8;
+	/* Needed or else will have blank line at top of display
+	   Enable LP during EOF to send DCS commands during blanking */
+	uint8_t eof_bllp_pwr = 0x9;
 
 	uint8_t interleav = 0;
 	struct lcdc_panel_info *lcdc = NULL;
diff --git a/dev/panel/msm/rules.mk b/dev/panel/msm/rules.mk
index 4b596f6..f151744 100644
--- a/dev/panel/msm/rules.mk
+++ b/dev/panel/msm/rules.mk
@@ -23,5 +23,6 @@
 
 ifeq ($(PLATFORM),msm8974)
 OBJS += \
-	$(LOCAL_DIR)/mipi_toshiba_video_720p.o
+	$(LOCAL_DIR)/mipi_toshiba_video_720p.o \
+	$(LOCAL_DIR)/mipi_sharp_video_qhd.o
 endif
diff --git a/include/stdlib.h b/include/stdlib.h
index 7fe5b3d..5c5145a 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 2008 Travis Geiselbrecht
  *
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files
  * (the "Software"), to deal in the Software without restriction,
@@ -48,4 +50,12 @@
 #define STACKBUF_DMA_ALIGN(var, size) \
 	uint8_t __##var[(size) + CACHE_LINE]; uint8_t *var = (uint8_t *)(ROUNDUP((addr_t)__##var, CACHE_LINE))
 
+/* Macro to allocate buffer in both local & global space, the STACKBUF_DMA_ALIGN cannot
+ * be used for global space.
+ * If we use STACKBUF_DMA_ALIGN 'C' compiler throws the error "Initializer element
+ * is not constant", since global variable need to be initialized with a constant value.
+ */
+#define BUF_DMA_ALIGN(var, size) \
+	static uint8_t var[ROUNDUP(size, CACHE_LINE)] __attribute__((aligned(CACHE_LINE)));
+
 #endif
diff --git a/platform/mdm9x25/acpuclock.c b/platform/mdm9x25/acpuclock.c
index cf8486d..5812db6 100644
--- a/platform/mdm9x25/acpuclock.c
+++ b/platform/mdm9x25/acpuclock.c
@@ -47,9 +47,6 @@
 	ASSERT(iclk);
 	ASSERT(cclk);
 
-	/* Disable USB boot clock */
-	writel(0, USB_BOOT_CLOCK_CTL);
-
 	/* Disable interface and core clk */
 	clk_disable(iclk);
 	clk_disable(cclk);
diff --git a/platform/mdm9x25/include/platform/iomap.h b/platform/mdm9x25/include/platform/iomap.h
index 5dfa761..ac0d424 100644
--- a/platform/mdm9x25/include/platform/iomap.h
+++ b/platform/mdm9x25/include/platform/iomap.h
@@ -124,6 +124,4 @@
 #define USB_HS_SYSTEM_CMD_RCGR               (CLK_CTL_BASE + 0x490)
 #define USB_HS_SYSTEM_CFG_RCGR               (CLK_CTL_BASE + 0x494)
 
-#define USB_BOOT_CLOCK_CTL                   (CLK_CTL_BASE + 0x1A00)
-
 #endif
diff --git a/platform/msm8974/acpuclock.c b/platform/msm8974/acpuclock.c
index c913d5f..b71d91d 100644
--- a/platform/msm8974/acpuclock.c
+++ b/platform/msm8974/acpuclock.c
@@ -347,8 +347,11 @@
 		}
 
 		while(readl(MDP_GDSCR) & ((GDSC_POWER_ON_BIT) | (GDSC_POWER_ON_STATUS_BIT)));
-	} else
-		ASSERT(1);
+	} else {
+		reg &= ~BIT(0);
+		writel(reg, MDP_GDSCR);
+		while(!(readl(MDP_GDSCR) & ((GDSC_POWER_ON_BIT))));
+	}
 }
 
 /* Configure MDP clock */
@@ -371,6 +374,13 @@
 		ASSERT(0);
 	}
 
+	ret = clk_get_set_enable("mdss_vsync_clk", 0, 1);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set mdss vsync clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
 	ret = clk_get_set_enable("mdss_mdp_clk", 0, 1);
 	if(ret)
 	{
@@ -386,6 +396,18 @@
 	}
 }
 
+void mdp_clock_disable(void)
+{
+	writel(0x0, DSI_BYTE0_CBCR);
+	writel(0x0, DSI_PIXEL0_CBCR);
+	clk_disable(clk_get("mdss_vsync_clk"));
+	clk_disable(clk_get("mdss_mdp_clk"));
+	clk_disable(clk_get("mdss_mdp_lut_clk"));
+	clk_disable(clk_get("mdss_mdp_clk_src"));
+	clk_disable(clk_get("mdp_ahb_clk"));
+
+}
+
 /* Initialize all clocks needed by Display */
 void mmss_clock_init(void)
 {
@@ -433,3 +455,20 @@
 	writel(0x1, DSI_PIXEL0_CMD_RCGR);
 	writel(0x1, DSI_PIXEL0_CBCR);
 }
+
+void mmss_clock_disable(void)
+{
+
+	/* Disable ESC clock */
+	clk_disable(clk_get("mdss_esc0_clk"));
+
+	/* Disable MDSS AXI clock */
+	clk_disable(clk_get("mdss_axi_clk"));
+
+	/* Disable MMSSNOC S0AXI clock */
+	clk_disable(clk_get("mmss_s0_axi_clk"));
+
+	/* Disable MMSSNOC AXI clock */
+	clk_disable(clk_get("mmss_mmssnoc_axi_clk"));
+
+}
diff --git a/platform/msm8974/include/platform/clock.h b/platform/msm8974/include/platform/clock.h
index 0e11d4e..cb96f00 100644
--- a/platform/msm8974/include/platform/clock.h
+++ b/platform/msm8974/include/platform/clock.h
@@ -42,6 +42,9 @@
 #define GDSC_EN_FEW_WAIT_MASK           (0x0F << 16)
 #define GDSC_EN_FEW_WAIT_256_MASK       BIT(19)
 
+#define VSYNC_CMD_RCGR                  REG_MM(0x2080)
+#define VSYNC_CFG_RCGR                  REG_MM(0x2084)
+#define MDSS_VSYNC_CBCR                 REG_MM(0x2328)
 #define MDP_CMD_RCGR                    REG_MM(0x2040)
 #define MDP_CFG_RCGR                    REG_MM(0x2044)
 #define MDP_CBCR                        REG_MM(0x231C)
diff --git a/platform/msm8974/msm8974-clock.c b/platform/msm8974/msm8974-clock.c
index 9f1e590..ae6db46 100644
--- a/platform/msm8974/msm8974-clock.c
+++ b/platform/msm8974/msm8974-clock.c
@@ -426,6 +426,23 @@
 	},
 };
 
+static struct clk_freq_tbl ftbl_mdss_vsync_clk[] = {
+	F_MM(19200000,    cxo,   1,   0,   0),
+	F_END
+};
+
+static struct rcg_clk vsync_clk_src = {
+	.cmd_reg  = (uint32_t *) VSYNC_CMD_RCGR,
+	.cfg_reg  = (uint32_t *) VSYNC_CFG_RCGR,
+	.set_rate = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl = ftbl_mdss_vsync_clk,
+
+	.c        = {
+		.dbg_name = "vsync_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
 static struct rcg_clk mdp_axi_clk_src = {
 	.cmd_reg  = (uint32_t *) MDP_AXI_CMD_RCGR,
 	.cfg_reg  = (uint32_t *) MDP_AXI_CFG_RCGR,
@@ -527,6 +544,17 @@
 	},
 };
 
+static struct branch_clk mdss_vsync_clk = {
+	.cbcr_reg    = MDSS_VSYNC_CBCR,
+	.parent      = &vsync_clk_src.c,
+	.has_sibling = 0,
+
+	.c           = {
+		.dbg_name = "mdss_vsync_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 /* Clock lookup table */
 static struct clk_lookup msm_clocks_8974[] =
 {
@@ -558,6 +586,7 @@
 	CLK_LOOKUP("mdss_axi_clk",         mdss_axi_clk.c),
 	CLK_LOOKUP("mmss_mmssnoc_axi_clk", mmss_mmssnoc_axi_clk.c),
 	CLK_LOOKUP("mmss_s0_axi_clk",      mmss_s0_axi_clk.c),
+	CLK_LOOKUP("mdss_vsync_clk",       mdss_vsync_clk.c),
 	CLK_LOOKUP("mdss_mdp_clk_src",     mdss_mdp_clk_src.c),
 	CLK_LOOKUP("mdss_mdp_clk",         mdss_mdp_clk.c),
 	CLK_LOOKUP("mdss_mdp_lut_clk",     mdss_mdp_lut_clk.c),
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 523f708..773c81b 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -62,7 +62,7 @@
 
 		dprintf(INFO, "Found Appeneded Flattened Device tree\n");
 		dtb = kernel + app_dtb_offset;
-		rc = fdt_open_into(dtb, tags, fdt_totalsize(dtb) + DTB_PAD_SIZE);
+		rc = fdt_open_into(dtb, tags, fdt_totalsize(dtb));
 		if (rc == 0) {
 			/* clear out the old DTB magic so kernel doesn't find it */
 			*((uint32_t *)dtb) = 0;
@@ -195,6 +195,14 @@
 		return ret;
 	}
 
+	/* Add padding to make space for new nodes and properties. */
+	ret = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + DTB_PAD_SIZE);
+	if (ret!= 0)
+	{
+		dprintf(CRITICAL, "Failed to move/resize dtb buffer: %d\n", ret);
+		return ret;
+	}
+
 	/* Get offset of the memory node */
 	ret = fdt_path_offset(fdt, "/memory");
 	if (ret < 0)
diff --git a/platform/msm_shared/display.c b/platform/msm_shared/display.c
index 3a7a166..c6d02c4 100644
--- a/platform/msm_shared/display.c
+++ b/platform/msm_shared/display.c
@@ -110,9 +110,14 @@
 		break;
 	case MIPI_CMD_PANEL:
 		dprintf(INFO, "Config MIPI_CMD_PANEL.\n");
-		ret = mipi_config(panel);
+
+		if (mdp_get_revision() == MDP_REV_50)
+			ret = mdss_dsi_config(panel);
+		else
+			ret = mipi_config(panel);
 		if (ret)
 			goto msm_display_config_out;
+
 		ret = mdp_dsi_cmd_config(pinfo, &(panel->fb));
 		if (ret)
 			goto msm_display_config_out;
@@ -176,9 +181,11 @@
 		ret = mdp_dma_on();
 		if (ret)
 			goto msm_display_on_out;
-		ret = mipi_cmd_trigger();
-		if (ret)
-			goto msm_display_on_out;
+		if (mdp_get_revision() != MDP_REV_50) {
+			ret = mipi_cmd_trigger();
+			if (ret)
+				goto msm_display_on_out;
+		}
 		break;
 	case LCDC_PANEL:
 		dprintf(INFO, "Turn on LCDC PANEL.\n");
diff --git a/platform/msm_shared/include/mdp5.h b/platform/msm_shared/include/mdp5.h
index 357663e..430bdae 100644
--- a/platform/msm_shared/include/mdp5.h
+++ b/platform/msm_shared/include/mdp5.h
@@ -45,6 +45,7 @@
 
 #define MDP_VP_0_LAYER_0_OUT_SIZE               REG_MDP(0x3204)
 #define MDP_VP_0_LAYER_0_OP_MODE                REG_MDP(0x3200)
+#define MDP_VP_0_LAYER_0_BORDER_COLOR_0         REG_MDP(0x3208)
 #define MDP_VP_0_LAYER_0_BLEND_OP               REG_MDP(0x3220)
 #define MDP_VP_0_LAYER_0_BLEND0_FG_ALPHA        REG_MDP(0x3224)
 #define MDP_VP_0_LAYER_1_BLEND_OP               REG_MDP(0x3250)
@@ -73,6 +74,7 @@
 #define MDP_CTL_0_LAYER_0                       REG_MDP(0x600)
 #define MDP_CTL_0_TOP                           REG_MDP(0x614)
 #define MDP_CTL_0_FLUSH                         REG_MDP(0x618)
+#define MDP_CTL_0_START                         REG_MDP(0x61C)
 
 #define MDP_INTF_1_HSYNC_CTL                    REG_MDP(0x12708)
 #define MDP_INTF_1_VSYNC_PERIOD_F0              REG_MDP(0x1270C)
@@ -97,6 +99,7 @@
 #define MDP_CLK_CTRL2                           REG_MDP(0x03BC)
 #define MDP_CLK_CTRL3                           REG_MDP(0x04A8)
 #define MDP_CLK_CTRL4                           REG_MDP(0x04B0)
+#define MDP_CLK_CTRL5                           REG_MDP(0x04B8)
 
 #define MMSS_MDP_SMP_ALLOC_W_0                  REG_MDP(0x0180)
 #define MMSS_MDP_SMP_ALLOC_W_1                  REG_MDP(0x0184)
diff --git a/platform/msm_shared/include/mipi_dsi.h b/platform/msm_shared/include/mipi_dsi.h
index c067714..ba74946 100644
--- a/platform/msm_shared/include/mipi_dsi.h
+++ b/platform/msm_shared/include/mipi_dsi.h
@@ -72,6 +72,7 @@
 #define DSI_CAL_STRENGTH_CTRL                 REG_DSI(0x100)
 #define DSI_CMD_MODE_DMA_SW_TRIGGER           REG_DSI(0x08C)
 #define DSI_CMD_MODE_MDP_SW_TRIGGER           REG_DSI(0x090)
+#define DSI_HS_TIMER_CTRL                     REG_DSI(0x0B8)
 
 #define DSI_LANE_CTRL                         REG_DSI(0x0A8)
 
@@ -869,6 +870,24 @@
 	{sizeof(novatek_panel_set_led_pwm3), novatek_panel_set_led_pwm3}
 };
 
+static struct mipi_dsi_cmd sharp_qhd_video_mode_cmds[] = {
+	{sizeof(novatek_panel_sw_reset), novatek_panel_sw_reset}
+	,
+	{sizeof(novatek_panel_exit_sleep), novatek_panel_exit_sleep}
+	,
+	{sizeof(novatek_panel_display_on), novatek_panel_display_on}
+	,
+	{sizeof(novatek_panel_set_twolane), novatek_panel_set_twolane}
+	,
+	{sizeof(novatek_panel_rgb_888), novatek_panel_rgb_888}
+	,
+	{sizeof(novatek_panel_set_led_pwm1), novatek_panel_set_led_pwm1}
+	,
+	{sizeof(novatek_panel_set_led_pwm2), novatek_panel_set_led_pwm2}
+	,
+	{sizeof(novatek_panel_set_led_pwm3), novatek_panel_set_led_pwm3}
+};
+
 static struct mipi_dsi_phy_ctrl mipi_dsi_novatek_panel_phy_ctrl = {
 	/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
 	{0x03, 0x01, 0x01, 0x00},	/* regulator */
diff --git a/platform/msm_shared/include/mmc.h b/platform/msm_shared/include/mmc.h
index 0c2c6f8..f1c9762 100644
--- a/platform/msm_shared/include/mmc.h
+++ b/platform/msm_shared/include/mmc.h
@@ -29,6 +29,10 @@
 #ifndef __MMC_H__
 #define __MMC_H__
 
+#if MMC_SDHCI_SUPPORT
+#include "mmc_sdhci.h"
+#include "mmc_wrapper.h"
+#else
 #ifndef MMC_SLOT
 #define MMC_SLOT            0
 #endif
@@ -598,10 +602,6 @@
 #define MMC_CLK_DISABLE     0
 
 unsigned int mmc_boot_main(unsigned char slot, unsigned int base);
-unsigned int mmc_boot_read_from_card(struct mmc_host *host,
-				     struct mmc_card *card,
-				     unsigned long long data_addr,
-				     unsigned int data_len, unsigned int *out);
 unsigned int mmc_write(unsigned long long data_addr,
 		       unsigned int data_len, unsigned int *in);
 
@@ -609,19 +609,14 @@
 		      unsigned int data_len);
 unsigned mmc_get_psn(void);
 
-unsigned int mmc_boot_write_to_card(struct mmc_host *host,
-				    struct mmc_card *card,
-				    unsigned long long data_addr,
-				    unsigned int data_len, unsigned int *in);
-
 unsigned int mmc_erase_card(unsigned long long data_addr,
 			    unsigned long long data_len);
 
-struct mmc_host *get_mmc_host(void);
-struct mmc_card *get_mmc_card(void);
 void mmc_mclk_reg_wr_delay();
 void mmc_boot_mci_clk_enable();
 void mmc_boot_mci_clk_disable();
 uint8_t card_supports_ddr_mode();
 uint8_t card_supports_hs200_mode();
+uint64_t mmc_get_device_capacity();
+#endif
 #endif
diff --git a/platform/msm_shared/include/mmc_sdhci.h b/platform/msm_shared/include/mmc_sdhci.h
new file mode 100644
index 0000000..99174bf
--- /dev/null
+++ b/platform/msm_shared/include/mmc_sdhci.h
@@ -0,0 +1,221 @@
+/* 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 __MMC_SDHCI_H__
+#define __MMC_SDHCI_H__
+
+#include <sdhci.h>
+
+/* Emmc Card bus commands */
+#define CMD0_GO_IDLE_STATE                        0
+#define CMD1_SEND_OP_COND                         1
+#define CMD2_ALL_SEND_CID                         2
+#define CMD3_SEND_RELATIVE_ADDR                   3
+#define CMD4_SET_DSR                              4
+#define CMD6_SWITCH_FUNC                          6
+#define CMD7_SELECT_DESELECT_CARD                 7
+#define CMD8_SEND_EXT_CSD                         8
+#define CMD9_SEND_CSD                             9
+#define CMD10_SEND_CID                            10
+#define CMD12_STOP_TRANSMISSION                   12
+#define CMD13_SEND_STATUS                         13
+#define CMD15_GO_INACTIVE_STATUS                  15
+#define CMD16_SET_BLOCKLEN                        16
+#define CMD17_READ_SINGLE_BLOCK                   17
+#define CMD18_READ_MULTIPLE_BLOCK                 18
+#define CMD23_SET_BLOCK_COUNT                     23
+#define CMD24_WRITE_SINGLE_BLOCK                  24
+#define CMD25_WRITE_MULTIPLE_BLOCK                25
+#define CMD28_SET_WRITE_PROTECT                   28
+#define CMD29_CLEAR_WRITE_PROTECT                 29
+#define CMD31_SEND_WRITE_PROT_TYPE                31
+#define CMD32_ERASE_WR_BLK_START                  32
+#define CMD33_ERASE_WR_BLK_END                    33
+#define CMD35_ERASE_GROUP_START                   35
+#define CMD36_ERASE_GROUP_END                     36
+#define CMD38_ERASE                               38
+
+/* Card type */
+#define MMC_TYPE_STD_SD                           0
+#define MMC_TYPE_SDHC                             1
+#define MMC_TYPE_SDIO                             2
+#define MMC_TYPE_MMCHC                            3
+#define MMC_TYPE_STD_MMC                          4
+
+/* OCR Register */
+#define MMC_OCR_17_19                             (1 << 7)
+#define MMC_OCR_27_36                             (0x1FF << 15)
+#define MMC_OCR_SEC_MODE                          (2 << 29)
+#define MMC_OCR_BUSY                              (1 << 31)
+
+/* Card status */
+#define MMC_CARD_STATUS(x)                        ((x >> 9) & 0x0F)
+#define MMC_TRAN_STATE                            4
+#define MMC_PROG_STATE                            7
+#define MMC_SWITCH_FUNC_ERR_FLAG                  (1 << 7)
+#define MMC_STATUS_INACTIVE                       0
+#define MMC_STATUS_ACTIVE                         1
+
+/* EXT_CSD */
+/* Offsets in the ext csd */
+#define MMC_EXT_MMC_BUS_WIDTH                     183
+#define MMC_EXT_MMC_HS_TIMING                     185
+#define MMC_DEVICE_TYPE                           196
+#define MMC_EXT_HC_WP_GRP_SIZE                    221
+#define MMC_SEC_COUNT4                            215
+#define MMC_SEC_COUNT3                            214
+#define MMC_SEC_COUNT2                            213
+#define MMC_SEC_COUNT1                            212
+#define MMC_PART_CONFIG                           179
+#define MMC_ERASE_GRP_DEF                         175
+#define MMC_USR_WP                                171
+
+/* Values for ext csd fields */
+#define MMC_HS_TIMING                             0x1
+#define MMC_HS200_TIMING                          0x2
+#define MMC_ACCESS_WRITE                          0x3
+#define MMC_HS_DDR_MODE                           (BIT(2) | BIT(3))
+#define MMC_HS_HS200_MODE                         (BIT(4) | BIT(5))
+#define MMC_SEC_COUNT4_SHIFT                      24
+#define MMC_SEC_COUNT3_SHIFT                      16
+#define MMC_SEC_COUNT2_SHIFT                      8
+
+/* Command related */
+#define MMC_MAX_COMMAND_RETRY                     1000
+#define MMC_RD_BLOCK_LEN                          512
+#define MMC_WR_BLOCK_LEN                          512
+#define MMC_R1_BLOCK_LEN_ERR                      (1 << 29)
+#define MMC_R1_ADDR_ERR                           (1 << 30)
+
+/* RCA of the card */
+#define MMC_RCA                                   2
+
+/* Misc card macros */
+#define MMC_BLK_SZ                                512
+
+/* Clock rates */
+#define MMC_CLK_400KHZ                            400000
+#define MMC_CLK_144KHZ                            144000
+#define MMC_CLK_20MHZ                             20000000
+#define MMC_CLK_25MHZ                             25000000
+#define MMC_CLK_48MHZ                             48000000
+#define MMC_CLK_50MHZ                             49152000
+#define MMC_CLK_96MHZ                             96000000
+#define MMC_CLK_200MHZ                            200000000
+
+/* Can be used to unpack array of upto 32 bits data */
+#define UNPACK_BITS(array, start, len, size_of)           \
+    ({                                                    \
+     uint32_t indx = (start) / (size_of);                 \
+     uint32_t offset = (start) % (size_of);               \
+     uint32_t mask = (((len)<(size_of))? 1<<(len):0) - 1; \
+     uint32_t unpck = array[indx] >> offset;              \
+     uint32_t indx2 = ((start) + (len) - 1) / (size_of);  \
+     if(indx2 > indx)                                     \
+     unpck |= array[indx2] << ((size_of) - offset);       \
+     unpck & mask;                                        \
+     })
+
+/* CSD Register.
+ * Note: not all the fields have been defined here
+ */
+struct mmc_csd {
+	uint32_t cmmc_structure;
+	uint32_t spec_vers;
+	uint32_t card_cmd_class;
+	uint32_t write_blk_len;
+	uint32_t read_blk_len;
+	uint32_t r2w_factor;
+	uint32_t sector_size;
+	uint32_t c_size_mult;
+	uint32_t c_size;
+	uint32_t nsac_clk_cycle;
+	uint32_t taac_ns;
+	uint32_t tran_speed;
+	uint32_t erase_grp_size;
+	uint32_t erase_grp_mult;
+	uint32_t wp_grp_size;
+	uint32_t wp_grp_enable:1;
+	uint32_t perm_wp:1;
+	uint32_t temp_wp:1;
+	uint32_t erase_blk_len:1;
+	uint32_t read_blk_misalign:1;
+	uint32_t write_blk_misalign:1;
+	uint32_t read_blk_partial:1;
+	uint32_t write_blk_partial:1;
+};
+
+/* CID Register */
+struct mmc_cid {
+	uint32_t mid;    /* 8 bit manufacturer id */
+	uint32_t oid;    /* 16 bits 2 character ASCII - OEM ID */
+	uint8_t  pnm[7]; /* 6 character ASCII -  product name */
+	uint32_t prv;    /* 8 bits - product revision */
+	uint32_t psn;    /* 32 bits - product serial number */
+	uint32_t month;  /* 4 bits manufacturing month */
+	uint32_t year;  /* 4 bits manufacturing year */
+};
+
+/* mmc card register */
+struct mmc_card {
+	uint32_t rca;            /* Relative addres of the card*/
+	uint32_t ocr;            /* Operating range of the card*/
+	uint64_t capacity;       /* card capacity */
+	uint32_t type;           /* Type of the card */
+	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 */
+	struct mmc_cid cid;      /* CID structure */
+	struct mmc_csd csd;      /* CSD structure */
+};
+
+/* mmc device config data */
+struct mmc_config_data {
+	uint8_t slot;          /* Sdcc slot used */
+	uint32_t base;         /* Based address for the sdcc */
+	uint16_t bus_width;    /* Bus width used */
+	uint32_t max_clk_rate; /* Max clock rate supported */
+};
+
+/* mmc device structure */
+struct mmc_device {
+	struct sdhci_host host;          /* Handle to host controller */
+	struct mmc_card card;            /* Handle to mmc card */
+	struct mmc_config_data config;   /* Handle for the mmc config data */
+};
+
+/*
+ * APIS exposed to block level driver
+ */
+/* API: Initialize the mmc card */
+struct mmc_device *mmc_init(struct mmc_config_data *);
+/* API: Read required number of blocks from card into destination */
+uint32_t mmc_sdhci_read(struct mmc_device *dev, void *dest, uint64_t blk_addr, uint32_t num_blocks);
+/* API: Write requried number of blocks from source to card */
+uint32_t mmc_sdhci_write(struct mmc_device *dev, void *src, uint64_t blk_addr, uint32_t num_blocks);
+#endif
diff --git a/platform/msm_shared/include/mmc_wrapper.h b/platform/msm_shared/include/mmc_wrapper.h
new file mode 100644
index 0000000..5b12990
--- /dev/null
+++ b/platform/msm_shared/include/mmc_wrapper.h
@@ -0,0 +1,44 @@
+/* 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 __MMC_WRAPPER_H__
+#define __MMC_WRAPPER_H__
+
+#include <mmc_sdhci.h>
+
+/* Wrapper APIs */
+
+struct mmc_device *get_mmc_device();
+uint32_t mmc_get_psn(void);
+
+uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len);
+uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in);
+uint32_t mmc_erase_card(uint64_t, uint64_t);
+uint64_t mmc_get_device_capacity(void);
+uint32_t mmc_erase_card(uint64_t addr, uint64_t len);
+#endif
diff --git a/platform/msm_shared/include/partition_parser.h b/platform/msm_shared/include/partition_parser.h
index 86e2cf5..0508e00 100644
--- a/platform/msm_shared/include/partition_parser.h
+++ b/platform/msm_shared/include/partition_parser.h
@@ -157,35 +157,10 @@
 	unsigned char name[MAX_GPT_NAME_SIZE];
 };
 
-static void mbr_fill_name(struct partition_entry *partition_ent,
-			  unsigned int type);
-unsigned int mmc_boot_read_gpt(struct mmc_host *mmc_host,
-			       struct mmc_card *mmc_card);
-unsigned int mmc_boot_read_mbr(struct mmc_host *mmc_host,
-			       struct mmc_card *mmc_card);
-unsigned partition_get_index(const char *name);
+int partition_get_index(const char *name);
 unsigned long long partition_get_size(int index);
 unsigned long long partition_get_offset(int index);
-unsigned int partition_verify_mbr_signature(unsigned size,
-					    unsigned char *buffer);
-unsigned int mbr_partition_get_type(unsigned size, unsigned char *partition,
-				    unsigned int *partition_type);
-unsigned int partition_get_type(unsigned size, unsigned char *partition,
-				unsigned int *partition_type);
-unsigned int partition_read_table(void *mmc_host,
-				  struct mmc_card *mmc_card);
-unsigned int partition_parse_gpt_header(unsigned char *buffer,
-					unsigned long long *first_usable_lba,
-					unsigned int *partition_entry_size,
-					unsigned int *header_size,
-					unsigned int *max_partition_count);
-
-unsigned int write_mbr(unsigned size, unsigned char *mbrImage,
-		       struct mmc_host *mmc_host,
-		       struct mmc_card *mmc_card);
-unsigned int write_gpt(unsigned size, unsigned char *gptImage,
-		       struct mmc_host *mmc_host,
-		       struct mmc_card *mmc_card);
+unsigned int partition_read_table();
 unsigned int write_partition(unsigned size, unsigned char *partition);
 
 /* For Debugging */
diff --git a/platform/msm_shared/include/sdhci.h b/platform/msm_shared/include/sdhci.h
new file mode 100644
index 0000000..ff61868
--- /dev/null
+++ b/platform/msm_shared/include/sdhci.h
@@ -0,0 +1,340 @@
+/* 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 __PLATFORM_SDHCI_H_
+#define __PLATFORM_SDHCI_H_
+
+#include <reg.h>
+#include <bits.h>
+
+/*
+ * Capabilities for the host controller
+ * These values are read from the capabilities
+ * register in the controller
+ */
+struct host_caps {
+	uint32_t base_clk_rate;  /* Max clock rate supported */
+	uint32_t max_blk_len;    /* Max block len supported */
+	uint8_t bus_width_8bit;  /* 8 Bit mode supported */
+	uint8_t adma_support;    /* Adma support */
+	uint8_t voltage;         /* Supported voltage */
+	uint8_t sdr_support;     /* Single Data rate */
+	uint8_t ddr_support;     /* Dual Data rate */
+	uint8_t sdr50_support;   /* UHS mode, with 100 MHZ clock */
+};
+
+/*
+ * sdhci host structure, holding information about host
+ * controller parameters
+ */
+struct sdhci_host {
+	uint32_t base;         /* Base address for the host */
+	uint32_t cur_clk_rate; /* Running clock rate */
+	struct host_caps caps; /* Host capabilities */
+};
+
+/*
+ * Data pointer to be read/written
+ */
+struct mmc_data {
+	void *data_ptr;      /* Points to stream of data */
+	uint32_t num_blocks; /* num of blocks, each always of size SDHCI_MMC_BLK_SZ */
+};
+
+/*
+ * mmc command structure as per the spec
+ */
+struct mmc_command {
+	uint16_t cmd_index;     /* Command index */
+	uint32_t argument;      /* Command argument */
+	uint8_t data_present;   /* Command has data */
+	uint8_t cmd_type;       /* command type */
+	uint16_t resp_type;     /* Response type of the command */
+	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 */
+	struct mmc_data data;   /* Data pointer */
+};
+
+/*
+ * Descriptor table for adma
+ */
+struct desc_entry {
+	uint16_t tran_att;   /* Attribute for transfer data */
+	uint16_t len;        /* Length of data */
+	void *addr;          /* Address of the data */
+};
+
+/*
+ * Command types for sdhci
+ */
+enum {
+	SDHCI_CMD_TYPE_NORMAL = 0,
+	SDHCI_CMD_TYPE_SUSPEND,
+	SDHCI_CMD_TYPE_RESUME,
+	SDHCI_CMD_TYPE_ABORT,
+} sdhci_cmd_type;
+
+/*
+ * Response type values for sdhci
+ */
+enum {
+	SDHCI_CMD_RESP_NONE = 0,
+	SDHCI_CMD_RESP_136,
+	SDHCI_CMD_RESP_48,
+	SDHCI_CMD_RESP_48_BUSY,
+} sdhci_resp_type;
+
+
+/*
+ * Helper macros for writing byte, word & long registers
+ */
+#define REG_READ8(host, a)                        readb(host->base + a);
+#define REG_WRITE8(host, v, a)                    writeb(v, (host->base + a))
+
+#define REG_READ32(host, a)                       readl(host->base + a)
+#define REG_WRITE32(host, v, a)                   writel(v, (host->base + a))
+
+#define REG_READ16(host, a)                      readhw(host->base + a)
+#define REG_WRITE16(host, v, a)                  writehw(v, (host->base + a))
+
+/*
+ * SDHCI registers, as per the host controller spec v 3.0
+ */
+#define SDHCI_ARG2_REG                            (0x000)
+#define SDHCI_BLKSZ_REG                           (0x004)
+#define SDHCI_BLK_CNT_REG                         (0x006)
+#define SDHCI_ARGUMENT_REG                        (0x008)
+#define SDHCI_TRANS_MODE_REG                      (0x00C)
+#define SDHCI_CMD_REG                             (0x00E)
+#define SDHCI_RESP_REG                            (0x010)
+#define SDHCI_PRESENT_STATE_REG                   (0x024)
+#define SDHCI_HOST_CTRL1_REG                      (0x028)
+#define SDHCI_PWR_CTRL_REG                        (0x029)
+#define SDHCI_CLK_CTRL_REG                        (0x02C)
+#define SDHCI_TIMEOUT_REG                         (0x02E)
+#define SDHCI_RESET_REG                           (0x02F)
+#define SDHCI_NRML_INT_STS_REG                    (0x030)
+#define SDHCI_ERR_INT_STS_REG                     (0x032)
+#define SDHCI_NRML_INT_STS_EN_REG                 (0x034)
+#define SDHCI_ERR_INT_STS_EN_REG                  (0x036)
+#define SDHCI_NRML_INT_SIG_EN_REG                 (0x038)
+#define SDHCI_ERR_INT_SIG_EN_REG                  (0x03A)
+#define SDHCI_HOST_CTRL2_REG                      (0x03E)
+#define SDHCI_CAPS_REG1                           (0x040)
+#define SDHCI_CAPS_REG2                           (0x044)
+#define SDHCI_ADM_ADDR_REG                        (0x058)
+
+/*
+ * Helper macros for register writes
+ */
+#define SDHCI_SOFT_RESET                          BIT(0)
+#define SOFT_RESET_CMD                            BIT(1)
+#define SOFT_RESET_DATA                           BIT(2)
+#define SDHCI_1_8_VOL_SET                         BIT(3)
+
+/*
+ * Interrupt related
+ */
+#define SDHCI_NRML_INT_STS_EN                     0x000B
+#define SDHCI_ERR_INT_STS_EN                      0xFFFF
+#define SDHCI_NRML_INT_SIG_EN                     0x000B
+#define SDHCI_ERR_INT_SIG_EN                      0xFFFF
+
+#define SDCC_HC_INT_CARD_REMOVE                   BIT(7)
+#define SDCC_HC_INT_CARD_INSERT                   BIT(6)
+
+/*
+ * HC mode enable/disable
+ */
+#define SDHCI_HC_MODE_EN                          BIT(0)
+#define SDHCI_HC_MODE_DIS                         (0 << 1)
+
+/*
+ * Clk control related
+ */
+#define SDHCI_CLK_MAX_DIV                         2046
+#define SDHCI_SDCLK_FREQ_SEL                      8
+#define SDHCI_SDCLK_UP_BIT_SEL                    6
+#define SDHCI_SDCLK_FREQ_MASK                     0xFF
+#define SDHC_SDCLK_UP_BIT_MASK                    0x300
+#define SDHCI_INT_CLK_EN                          BIT(0)
+#define SDHCI_CLK_STABLE_MASK                     BIT(1)
+#define SDHCI_CLK_STABLE                          BIT(1)
+#define SDHCI_CLK_EN                              BIT(2)
+#define SDHCI_CLK_DIS                             (0 << 2)
+#define SDHCI_CLK_RATE_MASK                       0x0000FF00
+#define SDHCI_CLK_RATE_BIT                        8
+
+#define SDHCI_CMD_ACT                             BIT(0)
+#define SDHCI_DAT_ACT                             BIT(1)
+
+/*
+ * Bus voltage related macros
+ */
+#define SDHCI_BUS_VOL_SEL                         1
+#define SDHCI_BUS_PWR_EN                          BIT(0)
+#define SDHCI_VOL_1_8                             5
+#define SDHCI_VOL_3_0                             6
+#define SDHCI_VOL_3_3                             7
+#define SDHCI_3_3_VOL_MASK                        0x01000000
+#define SDHCI_3_0_VOL_MASK                        0x02000000
+#define SDHCI_1_8_VOL_MASK                        0x04000000
+
+/*
+ * Bus width related macros
+ */
+#define SDHCI_8BIT_WIDTH_MASK                     0x00040000
+
+#define SDHCI_BUS_WITDH_1BIT                      (0)
+#define SDHCI_BUS_WITDH_4BIT                      BIT(1)
+#define SDHCI_BUS_WITDH_8BIT                      BIT(5)
+
+/*
+ * Adma related macros
+ */
+#define SDHCI_BLK_LEN_MASK                        0x00030000
+#define SDHCI_BLK_LEN_BIT                         16
+#define SDHCI_BLK_ADMA_MASK                       0x00080000
+#define SDHCI_INT_STS_TRANS_COMPLETE              BIT(1)
+#define SDHCI_STATE_CMD_DAT_MASK                  0x0003
+#define SDHCI_INT_STS_CMD_COMPLETE                BIT(0)
+#define SDHCI_ERR_INT_STAT_MASK                   0x8000
+#define SDHCI_ADMA_DESC_LINE_SZ                   65536
+#define SDHCI_ADMA_MAX_TRANS_SZ                   (65535 * 512)
+#define SDHCI_ADMA_TRANS_VALID                    BIT(0)
+#define SDHCI_ADMA_TRANS_END                      BIT(1)
+#define SDHCI_ADMA_TRANS_DATA                     BIT(5)
+#define SDHCI_MMC_BLK_SZ                          512
+#define SDHCI_MMC_CUR_BLK_CNT_BIT                 16
+#define SDHCI_MMC_BLK_SZ_BIT                      0
+#define SDHCI_TRANS_MULTI                         BIT(5)
+#define SDHCI_TRANS_SINGLE                        (0 << 5)
+#define SDHCI_BLK_CNT_EN                          BIT(1)
+#define SDHCI_DMA_EN                              BIT(0)
+#define SDHCI_AUTO_CMD23_EN                       BIT(3)
+#define SDHCI_ADMA_32BIT                          BIT(4)
+
+/*
+ * Command related macros
+ */
+#define SDHCI_CMD_RESP_TYPE_SEL_BIT               0
+#define SDHCI_CMD_CRC_CHECK_BIT                   3
+#define SDHCI_CMD_IDX_CHECK_BIT                   4
+#define SDHCI_CMD_DATA_PRESENT_BIT                5
+#define SDHCI_CMD_CMD_TYPE_BIT                    6
+#define SDHCI_CMD_CMD_IDX_BIT                     8
+#define SDHCI_CMD_TIMEOUT_MASK                    BIT(0)
+#define SDHCI_CMD_CRC_MASK                        BIT(1)
+#define SDHCI_CMD_END_BIT_MASK                    BIT(2)
+#define SDHCI_CMD_IDX_MASK                        BIT(3)
+#define SDHCI_DAT_TIMEOUT_MASK                    BIT(4)
+#define SDHCI_DAT_CRC_MASK                        BIT(5)
+#define SDHCI_DAT_END_BIT_MASK                    BIT(6)
+#define SDHCI_CUR_LIM_MASK                        BIT(7)
+#define SDHCI_AUTO_CMD12_MASK                     BIT(8)
+#define SDHCI_ADMA_MASK                           BIT(9)
+#define SDHCI_READ_MODE                           BIT(4)
+#define SDHCI_SWITCH_CMD                          6
+#define SDHCI_CMD_TIMEOUT                         0xE
+#define SDHCI_MAX_CMD_RETRY                       10000
+#define SDHCI_MAX_TRANS_RETRY                     100000
+
+#define SDHCI_PREP_CMD(c, f)                      ((((c) & 0xff) << 8) | ((f) & 0xff))
+
+/*
+ * command response related
+ */
+#define SDHCI_RESP_LSHIFT                         8
+#define SDHCI_RESP_RSHIFT                         24
+
+/*
+ * Power control relatd macros
+ */
+#define SDHCI_SOFT_RESET_MASK                     (BIT(0) | BIT(1) | BIT(2))
+#define SDCC_HC_PWR_CTRL_INT                      0xF
+#define SDCC_HC_BUS_ON                            BIT(0)
+#define SDCC_HC_BUS_OFF                           BIT(1)
+#define SDCC_HC_BUS_ON_OFF_SUCC                   BIT(0)
+#define SDCC_HC_IO_SIG_LOW                        BIT(2)
+#define SDCC_HC_IO_SIG_HIGH                       BIT(3)
+#define SDCC_HC_IO_SIG_SUCC                       BIT(2)
+
+/*
+ * Command response
+ */
+#define SDHCI_CMD_RESP_NONE                       0
+#define SDHCI_CMD_RESP_R1                         BIT(0)
+#define SDHCI_CMD_RESP_R1B                        BIT(1)
+#define SDHCI_CMD_RESP_R2                         BIT(2)
+#define SDHCI_CMD_RESP_R3                         BIT(3)
+#define SDHCI_CMD_RESP_R6                         BIT(6)
+#define SDHCI_CMD_RESP_R7                         BIT(7)
+
+/*
+ * Clock Divider values
+ */
+#define SDHCI_CLK_400KHZ                          400000
+#define SDHCI_CLK_25MHZ                           25000000
+#define SDHCI_CLK_50MHZ                           50000000
+#define SDHCI_CLK_100MHZ                          100000000
+#define SDHCI_CLK_200MHZ                          200000000
+
+/* DDR mode related macros */
+#define SDHCI_DDR_MODE_EN                         0x0004
+#define SDHCI_DDR_MODE_MASK                       BIT(2)
+
+/* HS200/SDR50 mode related macros */
+#define SDHCI_SDR50_MODE_MASK                     BIT(0)
+#define SDHCI_SDR50_MODE_EN                       0x0002
+
+/*
+ * APIs and macros exposed for mmc/sd drivers
+ */
+#define SDHCI_MMC_WRITE                           0
+#define SDHCI_MMC_READ                            1
+
+#define DATA_BUS_WIDTH_1BIT                       0
+#define DATA_BUS_WIDTH_4BIT                       1
+#define DATA_BUS_WIDTH_8BIT                       2
+#define DATA_DDR_BUS_WIDTH_4BIT                   5
+#define DATA_DDR_BUS_WIDTH_8BIT                   6
+
+/* API: to initialize the controller */
+void     sdhci_init(struct sdhci_host *);
+/* API: Send the command & transfer data using adma */
+uint32_t sdhci_send_command(struct sdhci_host *, struct mmc_command *);
+/* API: Set the bus width for the contoller */
+uint8_t  sdhci_set_bus_width(struct sdhci_host *, uint16_t);
+/* API: Clock supply for the controller */
+uint32_t sdhci_clk_supply(struct sdhci_host *, uint32_t);
+/* API: Enable DDR mode */
+void sdhci_set_ddr_mode(struct sdhci_host *);
+/* API: To enable SDR mode */
+void sdhci_set_sdr_mode(struct sdhci_host *);
+#endif
diff --git a/platform/msm_shared/mdp5.c b/platform/msm_shared/mdp5.c
index 66afa82..9e5cf67 100644
--- a/platform/msm_shared/mdp5.c
+++ b/platform/msm_shared/mdp5.c
@@ -217,8 +217,80 @@
 int mdp_dsi_cmd_config(struct msm_panel_info *pinfo,
                 struct fbcon_config *fb)
 {
+	int ret = NO_ERROR;
 
-	int ret = 0;
+	struct lcdc_panel_info *lcdc = NULL;
+	uint32_t mdp_rgb_size;
+	int access_secure = 0;
+	uint32_t mdss_mdp_intf_off = 0;
+
+	if (pinfo == NULL)
+		return ERR_INVALID_ARGS;
+
+	lcdc =  &(pinfo->lcdc);
+	if (lcdc == NULL)
+		return ERR_INVALID_ARGS;
+
+	mdss_mdp_intf_off = mdss_mdp_intf_offset();
+	/* write active region size*/
+	mdp_rgb_size = (fb->height << 16) + fb->width;
+
+	access_secure = restore_secure_cfg(SECURE_DEVICE_MDSS);
+
+	mdp_clk_gating_ctrl();
+
+	writel(0x0100, MDP_DISP_INTF_SEL);
+
+	/* Ignore TZ return value till it's fixed */
+	if (!access_secure || 1) {
+		/* Force VBIF Clocks on  */
+		writel(0x1, VBIF_VBIF_DDR_FORCE_CLK_ON);
+		/* Configure DDR burst length */
+		writel(0x00000707, VBIF_VBIF_DDR_OUT_MAX_BURST);
+		writel(0x00000030, VBIF_VBIF_DDR_ARB_CTRL );
+		writel(0x00000001, VBIF_VBIF_DDR_RND_RBN_QOS_ARB);
+		writel(0x00000FFF, VBIF_VBIF_DDR_OUT_AOOO_AXI_EN);
+		writel(0x0FFF0FFF, VBIF_VBIF_DDR_OUT_AX_AOOO);
+		writel(0x22222222, VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF0);
+		writel(0x00002222, VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF1);
+	}
+
+	/* Allocate SMP blocks */
+	writel(0x00101010, MMSS_MDP_SMP_ALLOC_W_0);
+	writel(0x00000010, MMSS_MDP_SMP_ALLOC_W_1);
+	writel(0x00101010, MMSS_MDP_SMP_ALLOC_R_0);
+	writel(0x00000010, MMSS_MDP_SMP_ALLOC_R_1);
+
+	writel(fb->base, MDP_VP_0_RGB_0_SSPP_SRC0_ADDR);
+	writel((fb->stride * fb->bpp/8),MDP_VP_0_RGB_0_SSPP_SRC_YSTRIDE);
+	writel(mdp_rgb_size, MDP_VP_0_RGB_0_SSPP_SRC_IMG_SIZE);
+	writel(mdp_rgb_size, MDP_VP_0_RGB_0_SSPP_SRC_SIZE);
+	writel(mdp_rgb_size, MDP_VP_0_RGB_0_SSPP_SRC_OUT_SIZE);
+	writel(0x00, MDP_VP_0_RGB_0_SSPP_SRC_XY);
+	writel(0x00, MDP_VP_0_RGB_0_SSPP_OUT_XY);
+	/* Tight Packing 3bpp 0-Alpha 8-bit R B G */
+	writel(0x0002243F, MDP_VP_0_RGB_0_SSPP_SRC_FORMAT);
+	writel(0x00020001, MDP_VP_0_RGB_0_SSPP_SRC_UNPACK_PATTERN);
+	writel(0x00, MDP_VP_0_RGB_0_SSPP_SRC_OP_MODE);
+
+	writel(mdp_rgb_size,MDP_VP_0_LAYER_0_OUT_SIZE);
+	writel(0x00, MDP_VP_0_LAYER_0_OP_MODE);
+	writel(0x100, MDP_VP_0_LAYER_0_BLEND_OP);
+	writel(0xFF, MDP_VP_0_LAYER_0_BLEND0_FG_ALPHA);
+	writel(0x100, MDP_VP_0_LAYER_1_BLEND_OP);
+	writel(0xFF, MDP_VP_0_LAYER_1_BLEND0_FG_ALPHA);
+	writel(0x100, MDP_VP_0_LAYER_2_BLEND_OP);
+	writel(0xFF, MDP_VP_0_LAYER_2_BLEND0_FG_ALPHA);
+	writel(0x100, MDP_VP_0_LAYER_3_BLEND_OP);
+	writel(0xFF, MDP_VP_0_LAYER_3_BLEND0_FG_ALPHA);
+
+	/* Baselayer for layer mixer 0 */
+	writel(0x00000200, MDP_CTL_0_LAYER_0);
+
+	writel(0x213F, MDP_INTF_1_PANEL_FORMAT + mdss_mdp_intf_off);
+
+	writel(0x20020, MDP_CTL_0_TOP);
+
 	return ret;
 }
 
@@ -249,11 +321,21 @@
 
 int mdp_dsi_cmd_off()
 {
+	if(!target_cont_splash_screen())
+	{
+		/* Ping-Pong done Tear Check Read/Write  */
+		/* Underrun(Interface 0/1/2/3) VSYNC Interrupt Enable  */
+		writel(0xFF777713, MDP_INTR_CLEAR);
+	}
+	writel(0x00000000, MDP_INTR_EN);
+
 	return NO_ERROR;
 }
 
 int mdp_dma_on(void)
 {
+	writel(0x32048, MDP_CTL_0_FLUSH);
+	writel(0x01, MDP_CTL_0_START);
 	return NO_ERROR;
 }
 
diff --git a/platform/msm_shared/mipi_dsi.c b/platform/msm_shared/mipi_dsi.c
index 64fe03d..313edc4 100644
--- a/platform/msm_shared/mipi_dsi.c
+++ b/platform/msm_shared/mipi_dsi.c
@@ -712,7 +712,7 @@
 	writel(0x00000006, DSI_CLK_CTRL);
 	writel(0x0000000e, DSI_CLK_CTRL);
 	writel(0x0000001e, DSI_CLK_CTRL);
-	writel(0x0000003e, DSI_CLK_CTRL);
+	writel(0x0000023f, DSI_CLK_CTRL);
 
 	writel(0, DSI_CTRL);
 
@@ -746,7 +746,7 @@
 
 	writel(vsync_width << 16 | 0, DSI_VIDEO_MODE_VSYNC_VPOS);
 
-	writel(1, DSI_EOT_PACKET_CTRL);
+	writel(0x0, DSI_EOT_PACKET_CTRL);
 
 	writel(0x00000100, DSI_MISR_VIDEO_CTRL);
 
@@ -760,6 +760,7 @@
 				| dst_format << 4 | 0x0, DSI_VIDEO_MODE_CTRL);
 	}
 
+	writel(0x3fd08, DSI_HS_TIMER_CTRL);
 	writel(0x67, DSI_CAL_STRENGTH_CTRL);
 	writel(0x80006711, DSI_CAL_CTRL);
 	writel(0x00010100, DSI_MISR_VIDEO_CTRL);
@@ -774,6 +775,65 @@
 	return status;
 }
 
+int mdss_dsi_cmd_mode_config(uint16_t disp_width,
+	uint16_t disp_height,
+	uint16_t img_width,
+	uint16_t img_height,
+	uint16_t dst_format,
+	uint16_t traffic_mode)
+{
+	uint8_t DST_FORMAT;
+	uint8_t TRAFIC_MODE;
+	uint8_t DLNx_EN;
+	// video mode data ctrl
+	int status = 0;
+	uint8_t interleav = 0;
+	uint8_t ystride = 0x03;
+	// disable mdp first
+
+	writel(0x00000000, DSI_CLK_CTRL);
+	writel(0x00000000, DSI_CLK_CTRL);
+	writel(0x00000000, DSI_CLK_CTRL);
+	writel(0x00000000, DSI_CLK_CTRL);
+	writel(0x00000002, DSI_CLK_CTRL);
+	writel(0x00000006, DSI_CLK_CTRL);
+	writel(0x0000000e, DSI_CLK_CTRL);
+	writel(0x0000001e, DSI_CLK_CTRL);
+	writel(0x0000023f, DSI_CLK_CTRL);
+
+	writel(0, DSI_CTRL);
+
+	writel(0, DSI_ERR_INT_MASK0);
+
+	writel(0x02020202, DSI_INT_CTRL);
+
+	DST_FORMAT = 8;		// RGB888
+	dprintf(SPEW, "DSI_Cmd_Mode - Dst Format: RGB888\n");
+
+	DLNx_EN = 0xf;		// 4 lane with clk programming
+	dprintf(SPEW, "Data Lane: 4 lane\n");
+
+	TRAFIC_MODE = 0;	// non burst mode with sync pulses
+	dprintf(SPEW, "Traffic mode: non burst mode with sync pulses\n");
+
+	writel(DST_FORMAT, DSI_COMMAND_MODE_MDP_CTRL);
+	writel((img_width * ystride + 1) << 16 | 0x0039,
+	       DSI_COMMAND_MODE_MDP_STREAM0_CTRL);
+	writel((img_width * ystride + 1) << 16 | 0x0039,
+	       DSI_COMMAND_MODE_MDP_STREAM1_CTRL);
+	writel(img_height << 16 | img_width,
+	       DSI_COMMAND_MODE_MDP_STREAM0_TOTAL);
+	writel(img_height << 16 | img_width,
+	       DSI_COMMAND_MODE_MDP_STREAM1_TOTAL);
+	writel(0x13c2c, DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL);
+	writel(interleav << 30 | 0 << 24 | 0 << 20 | DLNx_EN << 4 | 0x105,
+	       DSI_CTRL);
+	writel(0x10000000, DSI_COMMAND_MODE_DMA_CTRL);
+	writel(0x10000000, DSI_MISR_CMD_CTRL);
+
+	return NO_ERROR;
+}
+
 int mipi_dsi_cmd_mode_config(unsigned short disp_width,
 	unsigned short disp_height,
 	unsigned short img_width,
diff --git a/platform/msm_shared/mmc.c b/platform/msm_shared/mmc.c
index 8ed7ec6..3a8f36a 100644
--- a/platform/msm_shared/mmc.c
+++ b/platform/msm_shared/mmc.c
@@ -1510,7 +1510,7 @@
  * Write data_len data to address specified by data_addr. data_len is
  * multiple of blocks for block data transfer.
  */
-unsigned int
+static unsigned int
 mmc_boot_write_to_card(struct mmc_host *host,
 		       struct mmc_card *card,
 		       unsigned long long data_addr,
@@ -1734,7 +1734,7 @@
  * Reads a data of data_len from the address specified. data_len
  * should be multiple of block size for block data transfer.
  */
-unsigned int
+static unsigned int
 mmc_boot_read_from_card(struct mmc_host *host,
 			struct mmc_card *card,
 			unsigned long long data_addr,
@@ -2411,7 +2411,7 @@
 	mmc_display_csd();
 	mmc_display_ext_csd();
 
-	mmc_ret = partition_read_table(&mmc_host, &mmc_card);
+	mmc_ret = partition_read_table();
 	return mmc_ret;
 }
 
@@ -3066,16 +3066,6 @@
 	return MMC_BOOT_E_SUCCESS;
 }
 
-struct mmc_host *get_mmc_host(void)
-{
-	return &mmc_host;
-}
-
-struct mmc_card *get_mmc_card(void)
-{
-	return &mmc_card;
-}
-
 /*
  * Disable MCI clk
  */
@@ -3409,3 +3399,9 @@
 	else
 		return 0;
 }
+
+/* Return the density of the mmc device */
+uint64_t mmc_get_device_capacity()
+{
+	return mmc_card.capacity;
+}
diff --git a/platform/msm_shared/mmc_sdhci.c b/platform/msm_shared/mmc_sdhci.c
new file mode 100644
index 0000000..b565d9e
--- /dev/null
+++ b/platform/msm_shared/mmc_sdhci.c
@@ -0,0 +1,1315 @@
+/* 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 <string.h>
+#include <stdlib.h>
+#include <debug.h>
+#include <reg.h>
+#include <mmc_sdhci.h>
+#include <sdhci.h>
+#include <partition_parser.h>
+#include <platform/iomap.h>
+#include <platform/timer.h>
+
+extern void clock_init_mmc(uint32_t);
+extern void clock_config_mmc(uint32_t, uint32_t);
+
+/* data access time unit in ns */
+static const uint32_t taac_unit[] =
+{
+	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
+};
+
+/* data access time value x 10 */
+static const uint32_t taac_value[] =
+{
+	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
+};
+
+/* data transfer rate in kbit/s */
+static const uint32_t xfer_rate_unit[] =
+{
+	100, 1000, 10000, 100000, 0, 0, 0, 0
+};
+
+/* data transfer rate value x 10*/
+static const uint32_t xfer_rate_value[] =
+{
+	0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80
+};
+
+/*
+ * Function: mmc decode and save csd
+ * Arg     : Card structure & raw csd
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Decodes CSD response received from the card.
+ *           Note that we have defined only few of the CSD elements
+ *           in csd structure. We'll only decode those values.
+ */
+static uint32_t mmc_decode_and_save_csd(struct mmc_card *card)
+{
+	uint32_t mmc_sizeof = 0;
+	uint32_t mmc_unit = 0;
+	uint32_t mmc_value = 0;
+	uint32_t mmc_temp = 0;
+	uint32_t *raw_csd = card->raw_csd;
+
+	struct mmc_csd mmc_csd;
+
+	mmc_sizeof = sizeof(uint32_t) * 8;
+
+	mmc_csd.cmmc_structure = UNPACK_BITS(raw_csd, 126, 2, mmc_sizeof);
+
+	if ((card->type == MMC_TYPE_SDHC)
+	    || (card->type == MMC_TYPE_STD_SD)) {
+		/* Parse CSD according to SD card spec. */
+
+		/* CSD register is little bit differnet for CSD version 2.0 High
+		 * Capacity and CSD version 1.0/2.0 Standard memory cards.
+		 * In Version 2.0 some of the fields have fixed values and it's
+		 * not necessary for host to refer these fields in CSD sent by
+		 * card
+		 */
+
+		if (mmc_csd.cmmc_structure == 1) {
+			/* CSD Version 2.0 */
+			mmc_csd.card_cmd_class = UNPACK_BITS(raw_csd, 84, 12, mmc_sizeof);
+			/* Fixed value is 9 = 2^9 = 512 */
+			mmc_csd.write_blk_len = 512;
+			/* Fixed value is 9 = 512 */
+			mmc_csd.read_blk_len = 512;
+			/* Fixed value: 010b */
+			mmc_csd.r2w_factor = 0x2;
+			/* Not there in version 2.0 */
+			mmc_csd.c_size_mult = 0;
+			mmc_csd.c_size  = UNPACK_BITS(raw_csd, 48, 22, mmc_sizeof);
+			mmc_csd.nsac_clk_cycle = UNPACK_BITS(raw_csd, 104, 8, mmc_sizeof)
+									 * 100;
+
+			mmc_unit = UNPACK_BITS(raw_csd, 112, 3, mmc_sizeof);
+			mmc_value = UNPACK_BITS(raw_csd, 115, 4, mmc_sizeof);
+			mmc_csd.taac_ns = (taac_value[mmc_value] * taac_unit[mmc_unit])
+							   / 10;
+
+			mmc_csd.erase_blk_len = 1;
+			mmc_csd.read_blk_misalign = 0;
+			mmc_csd.write_blk_misalign = 0;
+			mmc_csd.read_blk_partial = 0;
+			mmc_csd.write_blk_partial = 0;
+
+			mmc_unit = UNPACK_BITS(raw_csd, 96, 3, mmc_sizeof);
+			mmc_value = UNPACK_BITS(raw_csd, 99, 4, mmc_sizeof);
+			mmc_csd.tran_speed = (xfer_rate_value[mmc_value] *
+								 xfer_rate_unit[mmc_unit]) / 10;
+
+			mmc_csd.wp_grp_size = 0x0;
+			mmc_csd.wp_grp_enable = 0x0;
+			mmc_csd.perm_wp = UNPACK_BITS(raw_csd, 13, 1, mmc_sizeof);
+			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;
+		} else {
+			/* CSD Version 1.0 */
+			mmc_csd.card_cmd_class = UNPACK_BITS(raw_csd, 84, 12, mmc_sizeof);
+
+			mmc_temp = UNPACK_BITS(raw_csd, 22, 4, mmc_sizeof);
+			mmc_csd.write_blk_len = (mmc_temp > 8 && mmc_temp < 12) ?
+									(1 << mmc_temp) : 512;
+
+			mmc_temp = UNPACK_BITS(raw_csd, 80, 4, mmc_sizeof);
+			mmc_csd.read_blk_len = (mmc_temp > 8 && mmc_temp < 12) ?
+								   (1 << mmc_temp) : 512;
+
+			mmc_unit = UNPACK_BITS(raw_csd, 112, 3, mmc_sizeof);
+			mmc_value = UNPACK_BITS(raw_csd, 115, 4, mmc_sizeof);
+			mmc_csd.taac_ns = (taac_value[mmc_value] * taac_unit[mmc_unit])
+							  / 10;
+
+			mmc_unit = UNPACK_BITS(raw_csd, 96, 3, mmc_sizeof);
+			mmc_value = UNPACK_BITS(raw_csd, 99, 4, mmc_sizeof);
+			mmc_csd.tran_speed = (xfer_rate_value[mmc_value] *
+								 xfer_rate_unit[mmc_unit]) / 10;
+
+			mmc_csd.nsac_clk_cycle = UNPACK_BITS(raw_csd, 104, 8, mmc_sizeof)
+									 * 100;
+
+			mmc_csd.r2w_factor = UNPACK_BITS(raw_csd, 26, 3, mmc_sizeof);
+			mmc_csd.sector_size = UNPACK_BITS(raw_csd, 39, 7, mmc_sizeof) + 1;
+
+			mmc_csd.erase_blk_len = UNPACK_BITS(raw_csd, 46, 1, mmc_sizeof);
+			mmc_csd.read_blk_misalign = UNPACK_BITS(raw_csd, 77, 1, mmc_sizeof);
+			mmc_csd.write_blk_misalign = UNPACK_BITS(raw_csd, 78, 1, mmc_sizeof);
+			mmc_csd.read_blk_partial = UNPACK_BITS(raw_csd, 79, 1, mmc_sizeof);
+			mmc_csd.write_blk_partial = UNPACK_BITS(raw_csd, 21, 1, mmc_sizeof);
+
+			mmc_csd.c_size_mult = UNPACK_BITS(raw_csd, 47, 3, mmc_sizeof);
+			mmc_csd.c_size = UNPACK_BITS(raw_csd, 62, 12, mmc_sizeof);
+			mmc_csd.wp_grp_size = UNPACK_BITS(raw_csd, 32, 7, mmc_sizeof);
+			mmc_csd.wp_grp_enable = UNPACK_BITS(raw_csd, 31, 1, mmc_sizeof);
+			mmc_csd.perm_wp = UNPACK_BITS(raw_csd, 13, 1, mmc_sizeof);
+			mmc_csd.temp_wp = UNPACK_BITS(raw_csd, 12, 1, mmc_sizeof);
+
+			/* 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;
+		}
+	} else {
+		/* Parse CSD according to MMC card spec. */
+		mmc_csd.spec_vers = UNPACK_BITS(raw_csd, 122, 4, mmc_sizeof);
+		mmc_csd.card_cmd_class = UNPACK_BITS(raw_csd, 84, 12, mmc_sizeof);
+		mmc_csd.write_blk_len = 1 << UNPACK_BITS(raw_csd, 22, 4, mmc_sizeof);
+		mmc_csd.read_blk_len =  1 << UNPACK_BITS(raw_csd, 80, 4, mmc_sizeof);
+		mmc_csd.r2w_factor = UNPACK_BITS(raw_csd, 26, 3, mmc_sizeof);
+		mmc_csd.c_size_mult = UNPACK_BITS(raw_csd, 47, 3, mmc_sizeof);
+		mmc_csd.c_size = UNPACK_BITS(raw_csd, 62, 12, mmc_sizeof);
+		mmc_csd.nsac_clk_cycle = UNPACK_BITS(raw_csd, 104, 8, mmc_sizeof) * 100;
+
+		mmc_unit = UNPACK_BITS(raw_csd, 112, 3, mmc_sizeof);
+		mmc_value = UNPACK_BITS(raw_csd, 115, 4, mmc_sizeof);
+		mmc_csd.taac_ns = (taac_value[mmc_value] * taac_unit[mmc_unit]) / 10;
+
+		mmc_csd.read_blk_misalign = UNPACK_BITS(raw_csd, 77, 1, mmc_sizeof);
+		mmc_csd.write_blk_misalign = UNPACK_BITS(raw_csd, 78, 1, mmc_sizeof);
+		mmc_csd.read_blk_partial = UNPACK_BITS(raw_csd, 79, 1, mmc_sizeof);
+		mmc_csd.write_blk_partial = UNPACK_BITS(raw_csd, 21, 1, mmc_sizeof);
+
+		/* Ignore -- no use of this value. */
+		mmc_csd.tran_speed = 0x00;
+
+		mmc_csd.erase_grp_size = UNPACK_BITS(raw_csd, 42, 5, mmc_sizeof);
+		mmc_csd.erase_grp_mult = UNPACK_BITS(raw_csd, 37, 5, mmc_sizeof);
+		mmc_csd.wp_grp_size = UNPACK_BITS(raw_csd, 32, 5, mmc_sizeof);
+		mmc_csd.wp_grp_enable = UNPACK_BITS(raw_csd, 31, 1, mmc_sizeof);
+		mmc_csd.perm_wp = UNPACK_BITS(raw_csd, 13, 1, mmc_sizeof);
+		mmc_csd.temp_wp = UNPACK_BITS(raw_csd, 12, 1, mmc_sizeof);
+
+		/* Calculate the card capcity */
+		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;
+		} else {
+			/* For cards greater than 2GB, Ext CSD register's SEC_COUNT
+			 * is used to calculate the size.
+			 */
+			uint64_t sec_count;
+
+			sec_count = (card->ext_csd[MMC_SEC_COUNT4] << MMC_SEC_COUNT4_SHIFT)
+						| (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;
+		}
+	}
+
+	/* save the information in card structure */
+	memcpy((struct mmc_csd *)&card->csd,(struct mmc_csd *)&mmc_csd,
+			sizeof(struct mmc_csd));
+
+	dprintf(SPEW, "Decoded CSD fields:\n");
+	dprintf(SPEW, "cmmc_structure: %d\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, "Card Capacity: %llu Bytes\n", card->capacity);
+
+	return 0;
+}
+
+/*
+ * Function: mmc decode & save cid
+ * Arg     : card structure & raw cid
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Decode CID sent by the card.
+ */
+static uint32_t mmc_decode_and_save_cid(struct mmc_card *card,
+										uint32_t *raw_cid)
+{
+	struct mmc_cid mmc_cid;
+	uint32_t mmc_sizeof = 0;
+	int i = 0;
+
+	if (!raw_cid) {
+		return 1;
+	}
+
+	mmc_sizeof = sizeof(uint32_t) * 8;
+
+	if ((card->type == MMC_TYPE_SDHC) ||
+		(card->type == MMC_TYPE_STD_SD)) {
+		mmc_cid.mid = UNPACK_BITS(raw_cid, 120, 8, mmc_sizeof);
+		mmc_cid.oid = UNPACK_BITS(raw_cid, 104, 16, mmc_sizeof);
+
+		for (i = 0; i < 5; i++) {
+			mmc_cid.pnm[i] = (uint8_t)UNPACK_BITS(raw_cid,
+								    (104 - 8 * (i + 1)),
+								    8,
+								    mmc_sizeof);
+		}
+		mmc_cid.pnm[5] = 0;
+		mmc_cid.pnm[6] = 0;
+
+		mmc_cid.prv = UNPACK_BITS(raw_cid, 56, 8, mmc_sizeof);
+		mmc_cid.psn = UNPACK_BITS(raw_cid, 24, 31, mmc_sizeof);
+		mmc_cid.month = UNPACK_BITS(raw_cid, 8, 4, mmc_sizeof);
+		mmc_cid.year = UNPACK_BITS(raw_cid, 12, 8, mmc_sizeof);
+		mmc_cid.year += 2000;
+	} else {
+		mmc_cid.mid = UNPACK_BITS(raw_cid, 120, 8, mmc_sizeof);
+		mmc_cid.oid = UNPACK_BITS(raw_cid, 104, 16, mmc_sizeof);
+
+		for (i = 0; i < 6; i++) {
+			mmc_cid.pnm[i] = (uint8_t)UNPACK_BITS(raw_cid, (104 - 8 * (i + 1)),
+												  8, mmc_sizeof);
+		}
+		mmc_cid.pnm[6] = 0;
+
+		mmc_cid.prv = UNPACK_BITS(raw_cid, 48, 8, mmc_sizeof);
+		mmc_cid.psn = UNPACK_BITS(raw_cid, 16, 31, mmc_sizeof);
+		mmc_cid.month = UNPACK_BITS(raw_cid, 8, 4, mmc_sizeof);
+		mmc_cid.year = UNPACK_BITS(raw_cid, 12, 4, mmc_sizeof);
+		mmc_cid.year += 1997;
+	}
+
+	/* save it in card database */
+	memcpy((struct mmc_cid *)&card->cid,
+	       (struct mmc_cid *)&mmc_cid, sizeof(struct mmc_cid));
+
+	dprintf(SPEW, "Decoded CID fields:\n");
+	dprintf(SPEW, "Manufacturer ID: %x\n", mmc_cid.mid);
+	dprintf(SPEW, "OEM ID: 0x%x\n", mmc_cid.oid);
+	dprintf(SPEW, "Product Name: %s\n", mmc_cid.pnm);
+	dprintf(SPEW, "Product revision: %d.%d\n", (mmc_cid.prv >> 4),
+											   (mmc_cid.prv & 0xF));
+	dprintf(SPEW, "Product serial number: %X\n", mmc_cid.psn);
+	dprintf(SPEW, "Manufacturing date: %d %d\n", mmc_cid.month, mmc_cid.year);
+
+	return 0;
+}
+
+/*
+ * Function: mmc reset cards
+ * Arg     : host structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Reset all the cards to idle condition (CMD 0)
+ */
+static uint8_t mmc_reset_card(struct sdhci_host *host)
+{
+	struct mmc_command cmd;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.cmd_index = CMD0_GO_IDLE_STATE;
+	cmd.argument = 0;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_NONE;
+
+	/* send command */
+	return sdhci_send_command(host, &cmd);
+}
+
+/*
+ * Function: mmc operations command
+ * Arg     : host & card structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Send CMD1 to know whether the card supports host VDD profile or not.
+ */
+static uint32_t mmc_send_op_cond(struct sdhci_host *host, struct mmc_card *card)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_resp = 0;
+	uint32_t mmc_ret = 0;
+	uint32_t mmc_retry = 0;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD1 format:
+	 * [31] Busy bit
+	 * [30:29] Access mode
+	 * [28:24] reserved
+	 * [23:15] 2.7-3.6
+	 * [14:8]  2.0-2.6
+	 * [7]     1.7-1.95
+	 * [6:0]   reserved
+	 */
+
+	cmd.cmd_index = CMD1_SEND_OP_COND;
+	cmd.argument = card->ocr;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R3;
+
+	do {
+		mmc_ret = sdhci_send_command(host, &cmd);
+		if (mmc_ret)
+			return mmc_ret;
+
+		/* Command returned success, now it's time to examine response */
+		mmc_resp = cmd.resp[0];
+
+		/* Check the response for busy status */
+		if (!(mmc_resp & MMC_OCR_BUSY)) {
+			mmc_retry++;
+			mdelay(1);
+			continue;
+		} else
+			break;
+	} while (mmc_retry < MMC_MAX_COMMAND_RETRY);
+
+	/* If we reached here after max retries, we failed to get OCR */
+	if (mmc_retry == MMC_MAX_COMMAND_RETRY && !(mmc_resp & MMC_OCR_BUSY)) {
+		dprintf(CRITICAL, "Card has busy status set. Init did not complete\n");
+		return 1;
+	}
+
+	/* Response contains card's ocr. Update card's information */
+	card->ocr = mmc_resp;
+
+	if (mmc_resp & MMC_OCR_SEC_MODE)
+		card->type = MMC_TYPE_MMCHC;
+	else
+		card->type = MMC_TYPE_STD_MMC;
+
+	return 0;
+}
+
+/*
+ * Function: mmc send cid
+ * Arg     : host & card structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Request any card to send its uniquie card identification
+ *           (CID) number (CMD2).
+ */
+static uint32_t mmc_all_send_cid(struct sdhci_host *host, struct mmc_card *card)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_ret = 0;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD2 Format:
+	 * [31:0] stuff bits
+	 */
+	cmd.cmd_index = CMD2_ALL_SEND_CID;
+	cmd.argument = 0;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R2;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(host, &cmd);
+	if (mmc_ret) {
+		return mmc_ret;
+	}
+
+	/* Response contains card's 128 bits CID register */
+	mmc_ret = mmc_decode_and_save_cid(card, cmd.resp);
+	if (mmc_ret) {
+		return mmc_ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Function: mmc send relative address
+ * Arg     : host & card structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Ask card to send it's relative card address (RCA).
+ *           This RCA number is shorter than CID and is used by
+ *           the host to address the card in future (CMD3)
+ */
+static uint32_t mmc_send_relative_address(struct sdhci_host *host,
+										  struct mmc_card *card)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_ret = 0;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD3 Format:
+	 * [31:0] stuff bits
+	 */
+	if (card->type == MMC_TYPE_SDHC ||
+		card->type == MMC_TYPE_STD_SD) {
+		cmd.cmd_index = CMD3_SEND_RELATIVE_ADDR;
+		cmd.argument = 0;
+		cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd.resp_type = SDHCI_CMD_RESP_R6;
+
+		/* send command */
+		mmc_ret = sdhci_send_command(host, &cmd);
+		if (mmc_ret)
+			return mmc_ret;
+
+		/* For sD, card will send RCA. Store it */
+		card->rca = (cmd.resp[0] >> 16);
+	} else {
+		cmd.cmd_index = CMD3_SEND_RELATIVE_ADDR;
+		cmd.argument = (MMC_RCA << 16);
+		card->rca = (cmd.argument >> 16);
+		cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+		cmd.resp_type = SDHCI_CMD_RESP_R6;
+
+		/* send command */
+		mmc_ret = sdhci_send_command(host, &cmd);
+		if (mmc_ret)
+			return mmc_ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Function: mmc send csd
+ * Arg     : host, card structure & o/p arg to store csd
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Requests card to send it's CSD register's contents. (CMD9)
+ */
+static uint32_t mmc_send_csd(struct sdhci_host *host, struct mmc_card *card)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_arg = 0;
+	uint32_t mmc_ret = 0;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD9 Format:
+	 * [31:16] RCA
+	 * [15:0] stuff bits
+	 */
+	mmc_arg |= card->rca << 16;
+
+	cmd.cmd_index = CMD9_SEND_CSD;
+	cmd.argument = mmc_arg;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R2;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(host, &cmd);
+	if (mmc_ret)
+		return mmc_ret;
+
+	/* response contains the card csd */
+	memcpy(card->raw_csd, cmd.resp, sizeof(cmd.resp));
+
+	return 0;
+}
+
+/*
+ * Function: mmc select card
+ * Arg     : host, card structure & RCA
+ * 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)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_arg = 0;
+	uint32_t mmc_ret = 0;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD7 Format:
+	 * [31:16] RCA
+	 * [15:0] stuff bits
+	 */
+	mmc_arg |= 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)
+			cmd.resp_type = SDHCI_CMD_RESP_R1B;
+		else
+			cmd.resp_type = SDHCI_CMD_RESP_R1;
+	} else
+		cmd.resp_type = SDHCI_CMD_RESP_NONE;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(host, &cmd);
+	if (mmc_ret)
+		return mmc_ret;
+
+	return 0;
+}
+
+/*
+ * Function: mmc set block len
+ * Arg     : host, card structure & block length
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Send command to set block length.
+ */
+static uint32_t mmc_set_block_len(struct sdhci_host *host,
+								  struct mmc_card *card,
+								  uint32_t block_len)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_ret = 0;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD16 Format:
+	 * [31:0] block length
+	 */
+
+	cmd.cmd_index = CMD16_SET_BLOCKLEN;
+	cmd.argument = block_len;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(host, &cmd);
+	if (mmc_ret)
+		return mmc_ret;
+
+	/*
+	 * If blocklength is larger than 512 bytes,
+	 * the card sets BLOCK_LEN_ERROR bit.
+	 */
+	if (cmd.resp[0] & MMC_R1_BLOCK_LEN_ERR) {
+		dprintf(CRITICAL, "The block length is not supported by the card\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Function: mmc get card status
+ * Arg     : host, card structure & o/p argument card status
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Get the current status of the card
+ */
+static uint32_t mmc_get_card_status(struct sdhci_host *host,
+									struct mmc_card *card, uint32_t *status)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_ret = 0;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD13 Format:
+	 * [31:16] RCA
+	 * [15:0] stuff bits
+	 */
+	cmd.cmd_index = CMD13_SEND_STATUS;
+	cmd.argument = card->rca << 16;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(host, &cmd);
+	if (mmc_ret)
+		return mmc_ret;
+
+	/* Checking ADDR_OUT_OF_RANGE error in CMD13 response */
+	if ((cmd.resp[0] >> 31) & 0x01)
+		return 1;
+
+	*status = cmd.resp[0];
+	return 0;
+}
+
+/*
+ * Function: mmc get ext csd
+ * Arg     : host, card structure & array to hold ext attributes
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Send ext csd command & get the card attributes
+ */
+static uint32_t mmc_get_ext_csd(struct sdhci_host *host, struct mmc_card *card)
+{
+	struct mmc_command cmd;
+	uint32_t mmc_ret = 0;
+
+	card->ext_csd = memalign(CACHE_LINE, ROUNDUP(512, CACHE_LINE));
+
+	ASSERT(card->ext_csd);
+
+	memset(card->ext_csd, 0, sizeof(card->ext_csd));
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD8 */
+	cmd.cmd_index = CMD8_SEND_EXT_CSD;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+	cmd.data.data_ptr = card->ext_csd;
+	cmd.data.num_blocks = 1;
+	cmd.data_present = 0x1;
+	cmd.trans_mode = SDHCI_MMC_READ;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(host, &cmd);
+	if (mmc_ret)
+		return mmc_ret;
+
+	return mmc_ret;
+}
+
+/*
+ * Function: mmc switch command
+ * Arg     : Host, card structure, access mode, index & value to be set
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Send switch command to the card to set the ext attribute @ index
+ */
+static uint32_t mmc_switch_cmd(struct sdhci_host *host, struct mmc_card *card,
+							   uint32_t access, uint32_t index, uint32_t value)
+{
+
+	struct mmc_command cmd;
+	uint32_t mmc_ret = 0;
+	uint32_t mmc_status;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD6 Format:
+	 * [31:26] set to 0
+	 * [25:24] access
+	 * [23:16] index
+	 * [15:8] value
+	 * [7:3] set to 0
+	 * [2:0] cmd set
+	 */
+	cmd.cmd_index = CMD6_SWITCH_FUNC;
+	cmd.argument |= (access << 24);
+	cmd.argument |= (index << 16);
+	cmd.argument |= (value << 8);
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1B;
+
+	mmc_ret = sdhci_send_command(host, &cmd);
+	if (mmc_ret) {
+		dprintf(CRITICAL, "CMD6 send failed\n");
+		return mmc_ret;
+	}
+
+	/* Check if the card completed the switch command processing */
+	mmc_ret = mmc_get_card_status(host, card, &mmc_status);
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Get card status failed\n");
+		return mmc_ret;
+	}
+
+	if (MMC_CARD_STATUS(mmc_status) != MMC_TRAN_STATE) {
+		dprintf(CRITICAL, "Switch cmd failed. Card not in tran state\n");
+		mmc_ret = 1;
+	}
+
+	if (mmc_status & MMC_SWITCH_FUNC_ERR_FLAG) {
+		dprintf(CRITICAL, "Switch cmd failed. Switch Error.\n");
+		mmc_ret = 1;
+	}
+
+	return mmc_ret;
+}
+
+/*
+ * Function: mmc set bus width
+ * Arg     : Host, card structure & width
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Send switch command to set bus width
+ */
+static uint32_t mmc_set_bus_width(struct sdhci_host *host,
+								  struct mmc_card *card,
+								  uint32_t width)
+{
+	uint32_t mmc_ret = 0;
+
+	mmc_ret = mmc_switch_cmd(host, card, MMC_ACCESS_WRITE,
+							 MMC_EXT_MMC_BUS_WIDTH, width);
+
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Switch cmd failed\n");
+		return mmc_ret;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Function: mmc card supports ddr mode
+ * Arg     : None
+ * Return  : 1 if DDR mode is supported, 0 otherwise
+ * Flow    : Check the ext csd attributes of the card
+ */
+static uint8_t mmc_card_supports_hs200_mode(struct mmc_card *card)
+{
+	if (card->ext_csd[MMC_DEVICE_TYPE] & MMC_HS_HS200_MODE)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * Function: mmc card supports ddr mode
+ * Arg     : None
+ * Return  : 1 if DDR mode is supported, 0 otherwise
+ * Flow    : Check the ext csd attributes of the card
+ */
+static uint8_t mmc_card_supports_ddr_mode(struct mmc_card *card)
+{
+	if (card->ext_csd[MMC_DEVICE_TYPE] & MMC_HS_DDR_MODE)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * Function : Enable HS200 mode
+ * Arg      : Host, card structure and bus width
+ * Return   : 0 on Success, 1 on Failure
+ * Flow     :
+ *           - Set the bus width to 4/8 bit SDR as supported by the target & host
+ *           - Set the HS_TIMING on ext_csd 185 for the card
+ */
+static uint32_t mmc_set_hs200_mode(struct sdhci_host *host,
+								   struct mmc_card *card, uint32_t width)
+{
+	uint32_t mmc_ret = 0;
+
+	/* Set 4/8 bit SDR bus width */
+	mmc_ret = mmc_set_bus_width(host, card, width);
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Failure to set wide bus for Card(RCA:%x)\n",
+						  card->rca);
+		return mmc_ret;
+	}
+
+	/* Setting HS200 in HS_TIMING using EXT_CSD (CMD6) */
+	mmc_ret = mmc_switch_cmd(host, card, MMC_ACCESS_WRITE, MMC_EXT_MMC_HS_TIMING, MMC_HS200_TIMING);
+
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Switch cmd returned failure %d\n", __LINE__);
+		return mmc_ret;
+	}
+
+	/* Enable hs200 mode in controller */
+	sdhci_set_sdr_mode(host);
+
+	return mmc_ret;
+}
+
+/*
+ * Function: mmc set ddr mode
+ * Arg     : Host & card structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Set bus width for ddr mode & set controller in DDR mode
+*/
+static uint8_t mmc_set_ddr_mode(struct sdhci_host *host, struct mmc_card *card)
+{
+	uint8_t mmc_ret = 0;
+
+	/* Set width for 8 bit DDR mode by default */
+	mmc_ret = mmc_set_bus_width(host, card, DATA_DDR_BUS_WIDTH_8BIT);
+
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Failure to set DDR mode for Card(RCA:%x)\n",
+						  card->rca);
+		return mmc_ret;
+	}
+
+	sdhci_set_ddr_mode(host);
+
+	return 0;
+}
+
+/*
+ * Function: mmc set high speed interface
+ * Arg     : Host & card structure
+ * Return  : None
+ * Flow    : Sets the sdcc clock & clock divider in the host controller
+ *           Adjust the interface speed to optimal speed
+ */
+static uint32_t mmc_set_hs_interface(struct sdhci_host *host,
+									 struct mmc_card *card)
+{
+	uint32_t mmc_ret = 0;
+
+	/* Setting HS_TIMING in EXT_CSD (CMD6) */
+	mmc_ret = mmc_switch_cmd(host, card, MMC_ACCESS_WRITE,
+							 MMC_EXT_MMC_HS_TIMING, MMC_HS_TIMING);
+
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Switch cmd returned failure %d\n", __LINE__);
+		return mmc_ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Function: mmc_host_init
+ * Arg     : mmc device structure
+ * Return  : 0 on success, 1 on Failure
+ * Flow    : Initialize the host contoller
+ *           Set the clock rate to 400 KHZ for init
+ */
+static uint8_t mmc_host_init(struct mmc_device *dev)
+{
+	uint8_t mmc_ret = 0;
+
+	struct sdhci_host *host;
+	struct mmc_config_data *cfg;
+
+	host = &dev->host;
+	cfg = &dev->config;
+
+	/*
+	 * Initialize the controller, read the host capabilities
+	 * set power on mode
+	 */
+	sdhci_init(host);
+
+	/* Initialize any clocks needed for SDC controller */
+	clock_init_mmc(cfg->slot);
+
+	/* Setup initial freq to 400KHz */
+	clock_config_mmc(cfg->slot, cfg->max_clk_rate);
+
+	mmc_ret = sdhci_clk_supply(host, SDHCI_CLK_400KHZ);
+
+	return mmc_ret;
+}
+
+/*
+ * Function: mmc identify card
+ * Arg     : host & card structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Performs card identification process:
+ *           1. Get card's unique identification number (CID)
+ *           2. Get(for sd)/set (for mmc) relative card address (RCA)
+ *           3. Select the card to put it in TRAN state
+ */
+static uint32_t mmc_identify_card(struct sdhci_host *host, struct mmc_card *card)
+{
+	uint32_t mmc_return = 0;
+	uint32_t raw_csd[4];
+
+	/* Ask card to send its unique card identification (CID) number (CMD2) */
+	mmc_return = mmc_all_send_cid(host, card);
+	if (mmc_return) {
+		dprintf(CRITICAL,"Failure getting card's CID number!\n");
+		return mmc_return;
+	}
+
+	/* Ask card to send a relative card address (RCA) (CMD3) */
+	mmc_return = mmc_send_relative_address(host, card);
+	if (mmc_return) {
+		dprintf(CRITICAL, "Failure getting card's RCA!\n");
+		return mmc_return;
+	}
+
+	/* Get card's CSD register (CMD9) */
+	mmc_return = mmc_send_csd(host, card);
+	if (mmc_return) {
+		dprintf(CRITICAL,"Failure getting card's CSD information!\n");
+		return mmc_return;
+	}
+
+	/* Select the card (CMD7) */
+	mmc_return = mmc_select_card(host, card, card->rca);
+	if (mmc_return) {
+		dprintf(CRITICAL, "Failure selecting the Card with RCA: %x\n",card->rca);
+		return mmc_return;
+	}
+
+	/* Set the card status as active */
+	card->status = MMC_STATUS_ACTIVE;
+
+	return 0;
+}
+
+/*
+ * Function: mmc_reset_card_and_send_op
+ * Arg     : Host & Card structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Routine to initialize MMC card. It resets a card to idle state,
+ *           verify operating voltage and set the card in ready state.
+ */
+static uint32_t mmc_reset_card_and_send_op(struct sdhci_host *host, struct mmc_card *card)
+{
+	uint32_t mmc_return = 0;
+
+	/* 1. Card Reset - CMD0 */
+	mmc_return = mmc_reset_card(host);
+	if (mmc_return) {
+		dprintf(CRITICAL, "Failure resetting MMC cards!\n");
+		return mmc_return;
+	}
+
+	/* 2. Card Initialization process */
+
+	/*
+	 * 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 */
+	if (mmc_return) {
+		dprintf(CRITICAL, "Failure getting OCR response from MMC Card\n");
+		return mmc_return;
+	}
+
+	return 0;
+}
+
+/*
+ * Function: mmc_init_card
+ * Arg     : mmc device structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow    : Performs initialization and identification of eMMC cards connected
+ *           to the host.
+ */
+
+static uint32_t mmc_card_init(struct mmc_device *dev)
+{
+	uint32_t mmc_return = 0;
+	uint32_t status;
+	uint8_t bus_width = 0;
+
+	struct sdhci_host *host;
+	struct mmc_card *card;
+	struct mmc_config_data *cfg;
+
+	host = &dev->host;
+	card = &dev->card;
+	cfg  = &dev->config;
+
+	/* Initialize MMC card structure */
+	card->status = MMC_STATUS_INACTIVE;
+
+	/* TODO: Get the OCR params from target */
+	card->ocr = MMC_OCR_27_36 | MMC_OCR_SEC_MODE;
+
+	/* Reset the card & get the OCR */
+	mmc_return = mmc_reset_card_and_send_op(host, card);
+	if (mmc_return)
+		return mmc_return;
+
+	/* Identify (CMD2, CMD3 & CMD9) and select the card (CMD7) */
+	mmc_return = mmc_identify_card(host, card);
+	if (mmc_return)
+		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;
+	}
+
+	/* 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)) {
+			/* For MMC cards, also get the extended csd */
+			mmc_return = mmc_get_ext_csd(host, card);
+
+			if (mmc_return) {
+				dprintf(CRITICAL, "Failure getting card's ExtCSD information!\n");
+				return mmc_return;
+			}
+	}
+
+	/* Decode and save the CSD register */
+	mmc_return = mmc_decode_and_save_csd(card);
+	if (mmc_return) {
+		dprintf(CRITICAL, "Failure decoding card's CSD information!\n");
+		return mmc_return;
+	}
+
+
+	/* 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;
+		}
+	}
+
+
+	/* Verify TRAN state after changing speed and bus width */
+	mmc_return = mmc_get_card_status(host, card, &status);
+	if (mmc_return)
+		return mmc_return;
+
+	if (MMC_CARD_STATUS(status) != MMC_TRAN_STATE)
+		mmc_return = 1;
+
+	return mmc_return;
+}
+
+/*
+ * Function: mmc display csd
+ * Arg     : None
+ * Return  : None
+ * Flow    : Displays the csd information
+ */
+static void mmc_display_csd(struct mmc_card *card)
+{
+	dprintf(SPEW, "erase_grpsize: %d\n", card->csd.erase_grp_size);
+	dprintf(SPEW, "erase_grpmult: %d\n", card->csd.erase_grp_mult);
+	dprintf(SPEW, "wp_grpsize: %d\n", card->csd.wp_grp_size);
+	dprintf(SPEW, "wp_grpen: %d\n", card->csd.wp_grp_enable);
+	dprintf(SPEW, "perm_wp: %d\n", card->csd.perm_wp);
+	dprintf(SPEW, "temp_wp: %d\n", card->csd.temp_wp);
+}
+
+/*
+ * Function: mmc_init
+ * Arg     : MMC configuration data
+ * Return  : Pointer to mmc device
+ * Flow    : Entry point to MMC boot process
+ *           Initialize the sd host controller
+ *           Initialize the mmc card
+ *           Set the clock & high speed mode
+ */
+struct mmc_device *mmc_init(struct mmc_config_data *data)
+{
+	uint8_t mmc_ret = 0;
+	struct mmc_device *dev;
+
+	dev = (struct mmc_device *) malloc (sizeof(struct mmc_device));
+
+	if (!dev) {
+		dprintf(CRITICAL, "Error allocating mmc device\n");
+		return NULL;
+	}
+
+	ASSERT(data);
+
+	memcpy((void*)&dev->config, (void*)data, sizeof(struct mmc_config_data));
+
+	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");
+
+	mmc_ret = mmc_host_init(dev);
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Error Initializing MMC host : %u\n", mmc_ret);
+		return NULL;
+	}
+
+	/* Initialize and identify cards connected to host */
+	mmc_ret = mmc_card_init(dev);
+	if (mmc_ret) {
+		dprintf(CRITICAL, "Failed detecting MMC/SDC @ slot%d\n",
+						  dev->config.slot);
+		return NULL;
+	}
+
+	dprintf(INFO, "Done initialization of the card\n");
+
+	mmc_display_csd(&dev->card);
+
+	return dev;
+}
+
+/*
+ * Function: mmc sdhci read
+ * Arg     : mmc device structure, block address, number of blocks & destination
+ * Return  : 0 on Success, non zero on success
+ * Flow    : Fill in the command structure & send the command
+ */
+uint32_t mmc_sdhci_read(struct mmc_device *dev, void *dest,
+						uint64_t blk_addr, uint32_t num_blocks)
+{
+	uint32_t mmc_ret = 0;
+	struct mmc_command cmd;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD17/18 Format:
+	 * [31:0] Data Address
+	 */
+	if (num_blocks == 1)
+		cmd.cmd_index = CMD17_READ_SINGLE_BLOCK;
+	else
+		cmd.cmd_index = CMD18_READ_MULTIPLE_BLOCK;
+
+	cmd.argument = blk_addr;
+	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 = dest;
+	cmd.data.num_blocks = num_blocks;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(&dev->host, &cmd);
+	if (mmc_ret) {
+		return mmc_ret;
+	}
+
+	/* Response contains 32 bit Card status. Here we'll check
+		BLOCK_LEN_ERROR and ADDRESS_ERROR */
+	if (cmd.resp[0] & MMC_R1_BLOCK_LEN_ERR) {
+		dprintf(CRITICAL, "The transferred bytes does not match the block length\n");
+		return 1;
+	}
+
+	/* Misaligned address not matching block length */
+	if (cmd.resp[0] & MMC_R1_ADDR_ERR) {
+		dprintf(CRITICAL, "The misaligned address did not match the block length used\n");
+		return 1;
+	}
+
+	if (MMC_CARD_STATUS(cmd.resp[0]) != MMC_TRAN_STATE) {
+		dprintf(CRITICAL, "MMC read failed, card is not in TRAN state\n");
+		return 1;
+	}
+
+	return mmc_ret;
+}
+
+/*
+ * Function: mmc sdhci write
+ * Arg     : mmc device structure, block address, number of blocks & source
+ * Return  : 0 on Success, non zero on success
+ * Flow    : Fill in the command structure & send the command
+ */
+uint32_t mmc_sdhci_write(struct mmc_device *dev, void *src,
+						 uint64_t blk_addr, uint32_t num_blocks)
+{
+	uint32_t mmc_ret = 0;
+	struct mmc_command cmd;
+
+	memset((struct mmc_command *)&cmd, 0, sizeof(struct mmc_command));
+
+	/* CMD24/25 Format:
+	 * [31:0] Data Address
+	 */
+
+	if (num_blocks == 1)
+		cmd.cmd_index = CMD24_WRITE_SINGLE_BLOCK;
+	else
+		cmd.cmd_index = CMD25_WRITE_MULTIPLE_BLOCK;
+
+	cmd.argument = blk_addr;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1;
+	cmd.trans_mode = SDHCI_MMC_WRITE;
+	cmd.data_present = 0x1;
+	cmd.data.data_ptr = src;
+	cmd.data.num_blocks = num_blocks;
+
+	/* send command */
+	mmc_ret = sdhci_send_command(&dev->host, &cmd);
+	if (mmc_ret)
+		return mmc_ret;
+
+	/* Response contains 32 bit Card status. Here we'll check
+		BLOCK_LEN_ERROR and ADDRESS_ERROR */
+	if (cmd.resp[0] & MMC_R1_BLOCK_LEN_ERR) {
+		dprintf(CRITICAL, "The transferred bytes does not match the block length\n");
+		return 1;
+	}
+
+	/* Misaligned address not matching block length */
+	if (cmd.resp[0] & MMC_R1_ADDR_ERR) {
+		dprintf(CRITICAL, "The misaligned address did not match the block length used\n");
+		return 1;
+	}
+
+	if (MMC_CARD_STATUS(cmd.resp[0]) != MMC_TRAN_STATE) {
+		dprintf(CRITICAL, "MMC read failed, card is not in TRAN state\n");
+		return 1;
+	}
+
+	return mmc_ret;
+}
diff --git a/platform/msm_shared/mmc_wrapper.c b/platform/msm_shared/mmc_wrapper.c
new file mode 100644
index 0000000..c56a61e
--- /dev/null
+++ b/platform/msm_shared/mmc_wrapper.c
@@ -0,0 +1,171 @@
+/* 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 <stdlib.h>
+#include <stdint.h>
+#include <mmc_sdhci.h>
+#include <mmc_wrapper.h>
+#include <sdhci.h>
+#include <target.h>
+
+/*
+ * Function: get mmc card
+ * Arg     : None
+ * Return  : Pointer to mmc card structure
+ * Flow    : Get the card pointer from the device structure
+ */
+static struct mmc_card *get_mmc_card()
+{
+	struct mmc_device *dev;
+	struct mmc_card *card;
+
+	dev = target_mmc_device();
+	card = &dev->card;
+
+	return card;
+}
+
+/*
+ * Function: mmc_write
+ * Arg     : Data address on card, data length, i/p buffer
+ * Return  : 0 on Success, non zero on failure
+ * Flow    : Write the data from in to the card
+ */
+uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
+{
+	int val = 0;
+	uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
+	void *sptr = in;
+	struct mmc_device *dev;
+
+	dev = target_mmc_device();
+
+	ASSERT(!(data_addr % MMC_BLK_SZ));
+
+	if (data_len % MMC_BLK_SZ)
+		data_len = ROUNDUP(data_len, MMC_BLK_SZ);
+
+	/* TODO: This function is aware of max data that can be
+	 * tranferred using sdhci adma mode, need to have a cleaner
+	 * implementation to keep this function independent of sdhci
+	 * limitations
+	 */
+	while (data_len > write_size) {
+		val = mmc_sdhci_write(dev, sptr, (data_addr / MMC_BLK_SZ), (write_size / MMC_BLK_SZ));
+		sptr += write_size;
+		data_addr += write_size;
+		data_len -= write_size;
+	}
+
+	if (data_len)
+		val = mmc_sdhci_write(dev, sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
+
+	return val;
+}
+
+/*
+ * Function: mmc_read
+ * Arg     : Data address on card, o/p buffer & data length
+ * Return  : 0 on Success, non zero on failure
+ * Flow    : Read data from the card to out
+ */
+uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
+{
+	uint32_t ret = 0;
+	uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
+	struct mmc_device *dev;
+	void *sptr = out;
+
+	ASSERT(!(data_addr % MMC_BLK_SZ));
+	ASSERT(!(data_len % MMC_BLK_SZ));
+
+	dev = target_mmc_device();
+
+	/* TODO: This function is aware of max data that can be
+	 * tranferred using sdhci adma mode, need to have a cleaner
+	 * implementation to keep this function independent of sdhci
+	 * limitations
+	 */
+	while (data_len > read_size) {
+		ret = mmc_sdhci_read(dev, sptr, (data_addr / MMC_BLK_SZ), (read_size / MMC_BLK_SZ));
+		sptr += read_size;
+		data_addr += read_size;
+		data_len -= read_size;
+	}
+
+	if (data_len)
+		ret = mmc_sdhci_read(dev, sptr, (data_addr / MMC_BLK_SZ), (data_len / MMC_BLK_SZ));
+
+	return ret;
+}
+
+/*
+ * Function: mmc erase card
+ * Arg     : Block address & length
+ * Return  : Returns 0
+ * Flow    : This is dummy API for backward compatibility
+ *           erase is not supported for sdhci
+ */
+uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
+{
+	/* TODO: Right now with sdhci erase function
+	 * is not implemented, need to be added
+	 */
+	return 0;
+}
+
+/*
+ * Function: mmc get psn
+ * Arg     : None
+ * Return  : Returns the product serial number
+ * Flow    : Get the PSN from card
+ */
+uint32_t mmc_get_psn(void)
+{
+	struct mmc_card *card;
+
+	card = get_mmc_card();
+
+	return card->cid.psn;
+}
+
+/*
+ * Function: mmc get capacity
+ * Arg     : None
+ * Return  : Returns the density of the emmc card
+ * Flow    : Get the density from card
+ */
+uint64_t mmc_get_device_capacity()
+{
+	struct mmc_card *card;
+
+	card = get_mmc_card();
+
+	return card->capacity;
+}
+
diff --git a/platform/msm_shared/partition_parser.c b/platform/msm_shared/partition_parser.c
index c80f7d3..881d2a0 100644
--- a/platform/msm_shared/partition_parser.c
+++ b/platform/msm_shared/partition_parser.c
@@ -31,6 +31,26 @@
 #include "mmc.h"
 #include "partition_parser.h"
 
+static uint32_t mmc_boot_read_gpt();
+static uint32_t mmc_boot_read_mbr();
+static void mbr_fill_name(struct partition_entry *partition_ent,
+						  uint32_t type);
+static uint32_t partition_verify_mbr_signature(uint32_t size,
+											   uint8_t *buffer);
+static uint32_t mbr_partition_get_type(uint32_t size, uint8_t *partition,
+									   uint32_t *partition_type);
+
+static uint32_t partition_get_type(uint32_t size, uint8_t *partition,
+								   uint32_t *partition_type);
+static uint32_t partition_parse_gpt_header(uint8_t *buffer,
+										   uint64_t *first_usable_lba,
+										   uint32_t *partition_entry_size,
+										   uint32_t *header_size,
+										   uint32_t *max_partition_count);
+
+static uint32_t write_mbr(uint32_t, uint8_t *mbrImage);
+static uint32_t write_gpt(uint32_t size, uint8_t *gptImage);
+
 char *ext3_partitions[] =
     { "system", "userdata", "persist", "cache", "tombstones" };
 char *vfat_partitions[] = { "modem", "mdm", "NONE" };
@@ -42,49 +62,43 @@
 unsigned gpt_partitions_exist = 0;
 unsigned partition_count = 0;
 
-//TODO: Remove the dependency of mmc in these functions
-unsigned int
-partition_read_table(void *mmc_host,
-		     struct mmc_card *mmc_card)
+unsigned int partition_read_table()
 {
 	unsigned int ret;
 
 	/* Read MBR of the card */
-	ret = mmc_boot_read_mbr(mmc_host, mmc_card);
-	if (ret != MMC_BOOT_E_SUCCESS) {
+	ret = mmc_boot_read_mbr();
+	if (ret) {
 		dprintf(CRITICAL, "MMC Boot: MBR read failed!\n");
-		return MMC_BOOT_E_FAILURE;
+		return 1;
 	}
 
 	/* Read GPT of the card if exist */
 	if (gpt_partitions_exist) {
-		ret = mmc_boot_read_gpt(mmc_host, mmc_card);
-		if (ret != MMC_BOOT_E_SUCCESS) {
+		ret = mmc_boot_read_gpt();
+		if (ret) {
 			dprintf(CRITICAL, "MMC Boot: GPT read failed!\n");
-			return MMC_BOOT_E_FAILURE;
+			return 1;
 		}
 	}
-	return MMC_BOOT_E_SUCCESS;
+	return 0;
 }
 
 /*
  * Read MBR from MMC card and fill partition table.
  */
-unsigned int
-mmc_boot_read_mbr(struct mmc_host *mmc_host,
-		  struct mmc_card *mmc_card)
+static unsigned int mmc_boot_read_mbr()
 {
-	unsigned char buffer[BLOCK_SIZE];
+	BUF_DMA_ALIGN(buffer, BLOCK_SIZE);
 	unsigned int dtype;
 	unsigned int dfirstsec;
 	unsigned int EBR_first_sec;
 	unsigned int EBR_current_sec;
-	int ret = MMC_BOOT_E_SUCCESS;
+	int ret = 0;
 	int idx, i;
 
 	/* Print out the MBR first */
-	ret = mmc_boot_read_from_card(mmc_host, mmc_card, 0,
-				      BLOCK_SIZE, (unsigned int *)buffer);
+	ret = mmc_read(0, (unsigned int *)buffer, BLOCK_SIZE);
 	if (ret) {
 		dprintf(CRITICAL, "Could not read partition from mmc\n");
 		return ret;
@@ -136,17 +150,15 @@
 	EBR_first_sec = dfirstsec;
 	EBR_current_sec = dfirstsec;
 
-	ret = mmc_boot_read_from_card(mmc_host, mmc_card,
-				      (EBR_first_sec * 512),
-				      BLOCK_SIZE, (unsigned int *)buffer);
-	if (ret) {
+	ret = mmc_read((EBR_first_sec * 512), (unsigned int *)buffer, BLOCK_SIZE);
+	if (ret)
 		return ret;
-	}
+
 	/* Loop to parse the EBR */
 	for (i = 0;; i++) {
 		ret = partition_verify_mbr_signature(BLOCK_SIZE, buffer);
 		if (ret) {
-			ret = MMC_BOOT_E_SUCCESS;
+			ret = 0;
 			break;
 		}
 		partition_entries[partition_count].attribute_flag =
@@ -175,13 +187,11 @@
 		/* More EBR to follow - read in the next EBR sector */
 		dprintf(SPEW, "Reading EBR block from 0x%X\n", EBR_first_sec
 			+ dfirstsec);
-		ret = mmc_boot_read_from_card(mmc_host, mmc_card,
-					      ((EBR_first_sec +
-						dfirstsec) * 512), BLOCK_SIZE,
-					      (unsigned int *)buffer);
-		if (ret) {
+		ret = mmc_read(((EBR_first_sec + dfirstsec) * 512),(unsigned int *)buffer,
+						BLOCK_SIZE);
+		if (ret)
 			return ret;
-		}
+
 		EBR_current_sec = EBR_first_sec + dfirstsec;
 	}
 	return ret;
@@ -190,34 +200,34 @@
 /*
  * Read GPT from MMC and fill partition table
  */
-unsigned int
-mmc_boot_read_gpt(struct mmc_host *mmc_host,
-		  struct mmc_card *mmc_card)
+static unsigned int mmc_boot_read_gpt()
 {
-
-	int ret = MMC_BOOT_E_SUCCESS;
+	BUF_DMA_ALIGN(data, BLOCK_SIZE);
+	int ret = 0;
 	unsigned int header_size;
 	unsigned long long first_usable_lba;
 	unsigned long long backup_header_lba;
 	unsigned long long card_size_sec;
 	unsigned int max_partition_count = 0;
 	unsigned int partition_entry_size;
-	unsigned char data[BLOCK_SIZE];
 	unsigned int i = 0;	/* Counter for each 512 block */
 	unsigned int j = 0;	/* Counter for each 128 entry in the 512 block */
 	unsigned int n = 0;	/* Counter for UTF-16 -> 8 conversion */
 	unsigned char UTF16_name[MAX_GPT_NAME_SIZE];
 	/* LBA of first partition -- 1 Block after Protected MBR + 1 for PT */
 	unsigned long long partition_0;
+	uint64_t device_density;
+
 	partition_count = 0;
 
+	/* Get the density of the mmc device */
+
+	device_density = mmc_get_device_capacity();
+
 	/* Print out the GPT first */
-	ret = mmc_boot_read_from_card(mmc_host, mmc_card,
-				      PROTECTIVE_MBR_SIZE,
-				      BLOCK_SIZE, (unsigned int *)data);
-	if (ret){
+	ret = mmc_read(PROTECTIVE_MBR_SIZE, (unsigned int *)data, BLOCK_SIZE);
+	if (ret)
 		dprintf(CRITICAL, "GPT: Could not read primary gpt from mmc\n");
-	}
 
 	ret = partition_parse_gpt_header(data, &first_usable_lba,
 					 &partition_entry_size, &header_size,
@@ -228,14 +238,12 @@
 		/* Check the backup gpt */
 
 		/* Get size of MMC */
-		card_size_sec = (mmc_card->capacity) / BLOCK_SIZE;
+		card_size_sec = (device_density) / BLOCK_SIZE;
 		ASSERT (card_size_sec > 0);
 
 		backup_header_lba = card_size_sec - 1;
-		ret =
-		    mmc_boot_read_from_card(mmc_host, mmc_card,
-					    (backup_header_lba * BLOCK_SIZE),
-					    BLOCK_SIZE, (unsigned int *)data);
+		ret = mmc_read((backup_header_lba * BLOCK_SIZE), (unsigned int *)data,
+						BLOCK_SIZE);
 
 		if (ret) {
 			dprintf(CRITICAL,
@@ -257,10 +265,8 @@
 	/* Read GPT Entries */
 	for (i = 0; i < (ROUNDUP(max_partition_count, 4)) / 4; i++) {
 		ASSERT(partition_count < NUM_PARTITIONS);
-		ret = mmc_boot_read_from_card(mmc_host, mmc_card,
-					      (partition_0 * BLOCK_SIZE) +
-					      (i * BLOCK_SIZE),
-					      BLOCK_SIZE, (uint32_t *) data);
+		ret = mmc_read((partition_0 * BLOCK_SIZE) + (i * BLOCK_SIZE),
+						(uint32_t *) data, BLOCK_SIZE);
 
 		if (ret) {
 			dprintf(CRITICAL,
@@ -384,9 +390,7 @@
 }
 
 /* Write the MBR/EBR to the MMC. */
-unsigned int
-write_mbr(unsigned size, unsigned char *mbrImage,
-	  struct mmc_host *mmc_host, struct mmc_card *mmc_card)
+static unsigned int write_mbr(unsigned size, unsigned char *mbrImage)
 {
 	unsigned int ret;
 
@@ -403,7 +407,7 @@
 		goto end;
 	}
 	/* Re-read the MBR partition into mbr table */
-	ret = mmc_boot_read_mbr(mmc_host, mmc_card);
+	ret = mmc_boot_read_mbr();
 	if (ret) {
 		dprintf(CRITICAL, "Failed to re-read mbr partition.\n");
 		goto end;
@@ -472,7 +476,7 @@
 			  unsigned int partition_array_start,
 			  unsigned int array_size)
 {
-	unsigned int ret = MMC_BOOT_E_INVAL;
+	unsigned int ret = 1;
 	unsigned long long partition_entry_lba;
 	unsigned long long partition_entry_array_start_location;
 
@@ -493,10 +497,8 @@
 }
 
 static void
-patch_gpt(unsigned char *gptImage,
-	  struct mmc_card *mmc_card,
-	  unsigned int array_size,
-	  unsigned int max_part_count, unsigned int part_entry_size)
+patch_gpt(unsigned char *gptImage, uint64_t density, unsigned int array_size,
+		  unsigned int max_part_count, unsigned int part_entry_size)
 {
 	unsigned int partition_entry_array_start;
 	unsigned char *primary_gpt_header;
@@ -508,7 +510,7 @@
 	unsigned int crc_value;
 
 	/* Get size of MMC */
-	card_size_sec = (mmc_card->capacity) / 512;
+	card_size_sec = (density) / 512;
 	/* Working around cap at 4GB */
 	if (card_size_sec == 0) {
 		card_size_sec = 4 * 1024 * 1024 * 2 - 1;
@@ -569,11 +571,9 @@
 /*
  * Write the GPT to the MMC.
  */
-unsigned int
-write_gpt(unsigned size, unsigned char *gptImage,
-	  struct mmc_host *mmc_host, struct mmc_card *mmc_card)
+static unsigned int write_gpt(unsigned size, unsigned char *gptImage)
 {
-	unsigned int ret = MMC_BOOT_E_INVAL;
+	unsigned int ret = 1;
 	unsigned int header_size;
 	unsigned long long first_usable_lba;
 	unsigned long long backup_header_lba;
@@ -586,6 +586,7 @@
 	unsigned int partition_entry_array_size;
 	unsigned long long primary_header_location;	/* address on the emmc card */
 	unsigned long long secondary_header_location;	/* address on the emmc card */
+	uint64_t device_density;
 
 	/* Verify that passed block has a valid GPT primary header */
 	primary_gpt_header = (gptImage + PROTECTIVE_MBR_SIZE);
@@ -598,6 +599,10 @@
 		goto end;
 	}
 
+	/* Get the density of the mmc device */
+
+	device_density = mmc_get_device_capacity();
+
 	/* Verify that passed block has a valid backup GPT HEADER */
 	partition_entry_array_size = partition_entry_size * max_partition_count;
 	if (partition_entry_array_size < MIN_PARTITION_ARRAY_SIZE) {
@@ -616,11 +621,11 @@
 	}
 
 	/* Patching the primary and the backup header of the GPT table */
-	patch_gpt(gptImage, mmc_card, partition_entry_array_size,
+	patch_gpt(gptImage, device_density, partition_entry_array_size,
 		  max_partition_count, partition_entry_size);
 
 	/* Erasing the eMMC card before writing */
-	ret = mmc_erase_card(0x00000000, mmc_card->capacity);
+	ret = mmc_erase_card(0x00000000, device_density);
 	if (ret) {
 		dprintf(CRITICAL, "Failed to erase the eMMC card\n");
 		goto end;
@@ -677,7 +682,7 @@
 
 	/* Re-read the GPT partition table */
 	dprintf(INFO, "Re-reading the GPT Partition Table\n");
-	ret = mmc_boot_read_gpt(mmc_host, mmc_card);
+	ret = mmc_boot_read_gpt();
 	if (ret) {
 		dprintf(CRITICAL,
 			"GPT: Failure to re- read the GPT Partition table\n");
@@ -693,10 +698,8 @@
 
 unsigned int write_partition(unsigned size, unsigned char *partition)
 {
-	unsigned int ret = MMC_BOOT_E_INVAL;
+	unsigned int ret = 1;
 	unsigned int partition_type;
-	struct mmc_host *mmc_host;
-	struct mmc_card *mmc_card;
 
 	if (partition == 0) {
 		dprintf(CRITICAL, "NULL partition\n");
@@ -704,28 +707,24 @@
 	}
 
 	ret = partition_get_type(size, partition, &partition_type);
-	if (ret != MMC_BOOT_E_SUCCESS) {
+	if (ret)
 		goto end;
-	}
-
-	mmc_host = get_mmc_host();
-	mmc_card = get_mmc_card();
 
 	switch (partition_type) {
 	case PARTITION_TYPE_MBR:
 		dprintf(INFO, "Writing MBR partition\n");
-		ret = write_mbr(size, partition, mmc_host, mmc_card);
+		ret = write_mbr(size, partition);
 		break;
 
 	case PARTITION_TYPE_GPT:
 		dprintf(INFO, "Writing GPT partition\n");
-		ret = write_gpt(size, partition, mmc_host, mmc_card);
+		ret = write_gpt(size, partition);
 		dprintf(CRITICAL, "Re-Flash all the partitions\n");
 		break;
 
 	default:
 		dprintf(CRITICAL, "Invalid partition\n");
-		ret = MMC_BOOT_E_INVAL;
+		ret = 1;
 		goto end;
 	}
 
@@ -808,7 +807,7 @@
 /*
  * Find index of parition in array of partition entries
  */
-unsigned partition_get_index(const char *name)
+int partition_get_index(const char *name)
 {
 	unsigned int input_string_length = strlen(name);
 	unsigned n;
@@ -862,23 +861,23 @@
 	}
 }
 
-unsigned int
+static unsigned int
 partition_verify_mbr_signature(unsigned size, unsigned char *buffer)
 {
 	/* Avoid checking past end of buffer */
 	if ((TABLE_SIGNATURE + 1) > size) {
-		return MMC_BOOT_E_FAILURE;
+		return 1;
 	}
 	/* Check to see if signature exists */
 	if ((buffer[TABLE_SIGNATURE] != MMC_MBR_SIGNATURE_BYTE_0) ||
 	    (buffer[TABLE_SIGNATURE + 1] != MMC_MBR_SIGNATURE_BYTE_1)) {
 		dprintf(CRITICAL, "MBR signature does not match.\n");
-		return MMC_BOOT_E_FAILURE;
+		return 1;
 	}
-	return MMC_BOOT_E_SUCCESS;
+	return 0;
 }
 
-unsigned int
+static unsigned int
 mbr_partition_get_type(unsigned size, unsigned char *partition,
 		       unsigned int *partition_type)
 {
@@ -890,14 +889,14 @@
 
 	*partition_type = partition[type_offset];
  end:
-	return MMC_BOOT_E_SUCCESS;
+	return 0;
 }
 
-unsigned int
+static unsigned int
 partition_get_type(unsigned size, unsigned char *partition,
 		   unsigned int *partition_type)
 {
-	unsigned int ret = MMC_BOOT_E_SUCCESS;
+	unsigned int ret = 0;
 
 	/*
 	 * If the block contains the MBR signature, then it's likely either
@@ -907,14 +906,14 @@
 
 	/* First check the MBR signature */
 	ret = partition_verify_mbr_signature(size, partition);
-	if (ret == MMC_BOOT_E_SUCCESS) {
+	if (!ret) {
 		unsigned int mbr_partition_type = PARTITION_TYPE_MBR;
 
 		/* MBR signature verified.  This could be MBR, MBR + EBR, or GPT */
 		ret =
 		    mbr_partition_get_type(size, partition,
 					   &mbr_partition_type);
-		if (ret != MMC_BOOT_E_SUCCESS) {
+		if (ret) {
 			dprintf(CRITICAL, "Cannot get TYPE of partition");
 		} else if (MBR_PROTECTED_TYPE == mbr_partition_type) {
 			*partition_type = PARTITION_TYPE_GPT;
@@ -936,7 +935,7 @@
  * Parse the gpt header and get the required header fields
  * Return 0 on valid signature
  */
-unsigned int
+static unsigned int
 partition_parse_gpt_header(unsigned char *buffer,
 			   unsigned long long *first_usable_lba,
 			   unsigned int *partition_entry_size,
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 1045240..46f7cb3 100644
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -13,9 +13,18 @@
 	$(LOCAL_DIR)/hsusb.o \
 	$(LOCAL_DIR)/jtag_hook.o \
 	$(LOCAL_DIR)/jtag.o \
-	$(LOCAL_DIR)/mmc.o \
 	$(LOCAL_DIR)/partition_parser.o
 
+ifeq ($(ENABLE_SDHCI_SUPPORT),1)
+OBJS += \
+	$(LOCAL_DIR)/sdhci.o \
+	$(LOCAL_DIR)/mmc_sdhci.o \
+	$(LOCAL_DIR)/mmc_wrapper.o
+else
+OBJS += \
+	$(LOCAL_DIR)/mmc.o
+endif
+
 ifeq ($(PLATFORM),msm8x60)
 	OBJS += $(LOCAL_DIR)/mipi_dsi.o \
 			$(LOCAL_DIR)/i2c_qup.o \
diff --git a/platform/msm_shared/scm.c b/platform/msm_shared/scm.c
index 7bb1093..adeecc8 100644
--- a/platform/msm_shared/scm.c
+++ b/platform/msm_shared/scm.c
@@ -312,10 +312,6 @@
 			*img_ptr     = (uint32_t*)parse_rsp.md_end_ptr;
 			ret          = 1;
 		}
-		else
-		{
-			dprintf(INFO,"Image is not encrypted");
-		}
 	}
 	else
 	{
diff --git a/platform/msm_shared/sdhci.c b/platform/msm_shared/sdhci.c
new file mode 100644
index 0000000..dac6fdc
--- /dev/null
+++ b/platform/msm_shared/sdhci.c
@@ -0,0 +1,835 @@
+/* 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 <kernel/event.h>
+#include <target.h>
+#include <string.h>
+#include <stdlib.h>
+#include <bits.h>
+#include <debug.h>
+#include <sdhci.h>
+
+
+/*
+ * 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
+ * Flow:   : Enable command error status
+ */
+static void sdhci_error_status_enable(struct sdhci_host *host)
+{
+	/* Enable all interrupt status */
+	REG_WRITE16(host, SDHCI_NRML_INT_STS_EN, SDHCI_NRML_INT_STS_EN_REG);
+	REG_WRITE16(host, SDHCI_ERR_INT_STS_EN, SDHCI_ERR_INT_STS_EN_REG);
+	/* Enable all interrupt signal */
+	REG_WRITE16(host, SDHCI_NRML_INT_SIG_EN, SDHCI_NRML_INT_SIG_EN_REG);
+	REG_WRITE16(host, SDHCI_ERR_INT_SIG_EN, SDHCI_ERR_INT_SIG_EN_REG);
+}
+
+/*
+ * Function: sdhci clock supply
+ * Arg     : Host structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow:   : 1. Calculate the clock divider
+ *           2. Set the clock divider
+ *           3. Check if clock stable
+ *           4. Enable Clock
+ */
+uint32_t sdhci_clk_supply(struct sdhci_host *host, uint32_t clk)
+{
+	uint32_t div = 0;
+	uint32_t freq = 0;
+	uint16_t clk_val = 0;
+
+	if (clk > host->caps.base_clk_rate) {
+		dprintf(CRITICAL, "Error: Requested clk freq is more than supported\n");
+		return 1;
+	}
+
+	if (clk == host->caps.base_clk_rate)
+		goto clk_ctrl;
+
+	/* As per the sd spec div should be a multiplier of 2 */
+	for (div = 2; div < SDHCI_CLK_MAX_DIV; div += 2) {
+		freq = host->caps.base_clk_rate / div;
+		if (freq <= clk)
+			break;
+	}
+
+	div >>= 1;
+
+clk_ctrl:
+	/* As per the sdhci spec 3.0, bits 6-7 of the clock
+	 * control registers will be mapped to bit 8-9, to
+	 * support a 10 bit divider value.
+	 * This is needed when the divider value overflows
+	 * the 8 bit range.
+	 */
+	clk_val = ((div & SDHCI_SDCLK_FREQ_MASK) << SDHCI_SDCLK_FREQ_SEL);
+	clk_val |= ((div & SDHC_SDCLK_UP_BIT_MASK) >> SDHCI_SDCLK_FREQ_SEL)
+				<< SDHCI_SDCLK_UP_BIT_SEL;
+
+	clk_val |= SDHCI_INT_CLK_EN;
+	REG_WRITE16(host, clk_val, SDHCI_CLK_CTRL_REG);
+
+	/* Check for clock stable */
+	while (!(REG_READ16(host, SDHCI_CLK_CTRL_REG) & SDHCI_CLK_STABLE));
+
+	/* Now clock is stable, enable it */
+	clk_val = REG_READ16(host, SDHCI_CLK_CTRL_REG);
+	clk_val |= SDHCI_CLK_EN;
+	REG_WRITE16(host, clk_val, SDHCI_CLK_CTRL_REG);
+
+	host->cur_clk_rate = freq;
+
+	return 0;
+}
+
+/*
+ * Function: sdhci stop sdcc clock
+ * Arg     : Host structure
+ * Return  : 0 on Success, 1 on Failure
+ * Flow:   : 1. Stop the clock
+ */
+static uint32_t sdhci_stop_sdcc_clk(struct sdhci_host *host)
+{
+	uint32_t reg;
+
+	reg = REG_READ32(host, SDHCI_PRESENT_STATE_REG);
+
+	if (reg & (SDHCI_CMD_ACT | SDHCI_DAT_ACT)) {
+		dprintf(CRITICAL, "Error: SDCC command & data line are active\n");
+		return 1;
+	}
+
+	REG_WRITE16(host, SDHCI_CLK_DIS, SDHCI_CLK_CTRL_REG);
+
+	return 0;
+}
+
+/*
+ * Function: sdhci change frequency
+ * Arg     : Host structure & clock value
+ * Return  : 0 on Success, 1 on Failure
+ * Flow:   : 1. Stop the clock
+ *           2. Star the clock with new frequency
+ */
+static uint32_t sdhci_change_freq_clk(struct sdhci_host *host, uint32_t clk)
+{
+	if (sdhci_stop_sdcc_clk(host)) {
+		dprintf(CRITICAL, "Error: Card is busy, cannot change frequency\n");
+		return 1;
+	}
+
+	if (sdhci_clk_supply(host, clk)) {
+		dprintf(CRITICAL, "Error: cannot change frequency\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Function: sdhci set bus power
+ * Arg     : Host structure
+ * Return  : None
+ * Flow:   : 1. Set the voltage
+ *           2. Set the sd power control register
+ */
+static void sdhci_set_bus_power_on(struct sdhci_host *host)
+{
+	uint8_t voltage;
+
+	voltage = host->caps.voltage;
+
+	voltage <<= SDHCI_BUS_VOL_SEL;
+	REG_WRITE8(host, voltage, SDHCI_BUS_PWR_EN);
+
+	voltage |= SDHCI_BUS_PWR_EN;
+
+	REG_WRITE8(host, voltage, SDHCI_PWR_CTRL_REG);
+
+}
+
+/*
+ * Function: sdhci set SDR mode
+ * Arg     : Host structure
+ * Return  : None
+ * Flow:   : 1. Disable the clock
+ *           2. Enable sdr mode
+ *           3. Enable the clock
+ * Details : SDR50/SDR104 mode is nothing but HS200
+ *			 mode SDCC spec refers to it as SDR mode
+ *			 & emmc spec refers as HS200 mode.
+ */
+void sdhci_set_sdr_mode(struct sdhci_host *host)
+{
+	uint16_t clk;
+	uint16_t ctrl = 0;
+
+	/* Disable the clock */
+	clk = REG_READ16(host, SDHCI_CLK_CTRL_REG);
+	clk &= ~SDHCI_CLK_EN;
+	REG_WRITE16(host, clk, SDHCI_CLK_CTRL_REG);
+
+	/* Enable SDR50 mode:
+	 * Right now we support only SDR50 mode which runs at
+	 * 100 MHZ sdcc clock, we dont need tuning with SDR50
+	 * mode
+	 */
+	ctrl = REG_READ16(host, SDHCI_HOST_CTRL2_REG);
+
+	/* Enable SDR50/SDR104 mode based on the controller
+	 * capabilities.
+	 */
+	if (host->caps.sdr50_support)
+		ctrl |= SDHCI_SDR50_MODE_EN;
+
+	REG_WRITE16(host, ctrl, SDHCI_HOST_CTRL2_REG);
+
+	/* Run the clock back */
+	sdhci_clk_supply(host, SDHCI_CLK_100MHZ);
+}
+
+/*
+ * Function: sdhci set ddr mode
+ * Arg     : Host structure
+ * Return  : None
+ * Flow:   : 1. Disable the clock
+ *           2. Enable DDR mode
+ *           3. Enable the clock
+ */
+void sdhci_set_ddr_mode(struct sdhci_host *host)
+{
+	uint16_t clk;
+	uint16_t ctrl = 0;
+
+	/* Disable the clock */
+	clk = REG_READ16(host, SDHCI_CLK_CTRL_REG);
+	clk &= ~SDHCI_CLK_EN;
+	REG_WRITE16(host, clk, SDHCI_CLK_CTRL_REG);
+
+	ctrl = REG_READ16(host, SDHCI_HOST_CTRL2_REG);
+	ctrl |= SDHCI_DDR_MODE_EN;
+
+	/* Enalbe DDR mode */
+	REG_WRITE16(host, ctrl, SDHCI_HOST_CTRL2_REG);
+
+	/* Run the clock back */
+	sdhci_clk_supply(host, host->cur_clk_rate);
+}
+
+/*
+ * Function: sdhci set adma mode
+ * Arg     : Host structure
+ * Return  : None
+ * Flow:   : Set adma mode
+ */
+static void sdhci_set_adma_mode(struct sdhci_host *host)
+{
+	/* Select 32 Bit ADMA2 type */
+	REG_WRITE8(host, SDHCI_ADMA_32BIT, SDHCI_HOST_CTRL1_REG);
+}
+
+/*
+ * Function: sdhci set bus width
+ * Arg     : Host & width
+ * Return  : 0 on Sucess, 1 on Failure
+ * Flow:   : Set the bus width for controller
+ */
+uint8_t sdhci_set_bus_width(struct sdhci_host *host, uint16_t width)
+{
+	uint16_t reg = 0;
+
+	reg = REG_READ8(host, SDHCI_HOST_CTRL1_REG);
+
+	switch(width) {
+		case DATA_BUS_WIDTH_8BIT:
+			width = SDHCI_BUS_WITDH_8BIT;
+			break;
+		case DATA_BUS_WIDTH_4BIT:
+			width = SDHCI_BUS_WITDH_4BIT;
+			break;
+		case DATA_BUS_WIDTH_1BIT:
+			width = SDHCI_BUS_WITDH_1BIT;
+			break;
+		default:
+			dprintf(CRITICAL, "Bus width is invalid: %u\n", width);
+			return 1;
+	}
+
+	REG_WRITE8(host, (reg | width), SDHCI_HOST_CTRL1_REG);
+
+	return 0;
+}
+
+/*
+ * Function: sdhci command err status
+ * Arg     : Host structure
+ * Return  : 0 on Sucess, 1 on Failure
+ * Flow:   : Look for error status
+ */
+static uint8_t sdhci_cmd_err_status(struct sdhci_host *host)
+{
+	uint32_t err;
+
+	err = REG_READ16(host, SDHCI_ERR_INT_STS_REG);
+
+	if (err & SDHCI_CMD_TIMEOUT_MASK) {
+		dprintf(CRITICAL, "Error: Command timeout error\n");
+		return 1;
+	} else if (err & SDHCI_CMD_CRC_MASK) {
+		dprintf(CRITICAL, "Error: Command CRC error\n");
+		return 1;
+	} else if (err & SDHCI_CMD_END_BIT_MASK) {
+		dprintf(CRITICAL, "Error: CMD end bit error\n");
+		return 1;
+	} else if (err & SDHCI_CMD_IDX_MASK) {
+		dprintf(CRITICAL, "Error: Command Index error\n");
+		return 1;
+	} else if (err & SDHCI_DAT_TIMEOUT_MASK) {
+		dprintf(CRITICAL, "Error: DATA time out error\n");
+		return 1;
+	} else if (err & SDHCI_DAT_CRC_MASK) {
+		dprintf(CRITICAL, "Error: DATA CRC error\n");
+		return 1;
+	} else if (err & SDHCI_DAT_END_BIT_MASK) {
+		dprintf(CRITICAL, "Error: DATA end bit error\n");
+		return 1;
+	} else if (err & SDHCI_CUR_LIM_MASK) {
+		dprintf(CRITICAL, "Error: Current limit error\n");
+		return 1;
+	} else if (err & SDHCI_AUTO_CMD12_MASK) {
+		dprintf(CRITICAL, "Error: Auto CMD12 error\n");
+		return 1;
+	} else if (err & SDHCI_ADMA_MASK) {
+		dprintf(CRITICAL, "Error: ADMA error\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Function: sdhci command complete
+ * Arg     : Host & command structure
+ * Return  : 0 on Sucess, 1 on Failure
+ * Flow:   : 1. Check for command complete
+ *           2. Check for transfer complete
+ *           3. Get the command response
+ *           4. Check for errors
+ */
+static uint8_t sdhci_cmd_complete(struct sdhci_host *host, struct mmc_command *cmd)
+{
+	uint8_t i;
+	uint16_t retry = 0;
+	uint32_t int_status;
+
+	do {
+		int_status = REG_READ16(host, SDHCI_NRML_INT_STS_REG);
+		int_status &= SDHCI_INT_STS_CMD_COMPLETE;
+
+		if (int_status == SDHCI_INT_STS_CMD_COMPLETE)
+			break;
+
+		retry++;
+		udelay(500);
+		if (retry == SDHCI_MAX_CMD_RETRY) {
+			dprintf(CRITICAL, "Error: Command never completed\n");
+			goto err;
+		}
+	} while(1);
+
+	/* Command is complete, clear the interrupt bit */
+	REG_WRITE16(host, SDHCI_INT_STS_CMD_COMPLETE, SDHCI_NRML_INT_STS_REG);
+
+	/* Copy the command response,
+	 * The valid bits for R2 response are 0-119, & but the actual response
+	 * is stored in bits 8-128. We need to move 8 bits of MSB of each
+	 * response to register 8 bits of LSB of next response register.
+	 * As:
+	 * MSB 8 bits of RESP0 --> LSB 8 bits of RESP1
+	 * MSB 8 bits of RESP1 --> LSB 8 bits of RESP2
+	 * MSB 8 bits of RESP2 --> LSB 8 bits of RESP3
+	 */
+	if (cmd->resp_type == SDHCI_CMD_RESP_R2) {
+		for (i = 0; i < 4; i++) {
+			cmd->resp[i] = REG_READ32(host, SDHCI_RESP_REG + (i * 4));
+			cmd->resp[i] <<= SDHCI_RESP_LSHIFT;
+
+			if (i != 0)
+				cmd->resp[i] |= (REG_READ32(host, SDHCI_RESP_REG + ((i-1) * 4)) >> SDHCI_RESP_RSHIFT);
+		}
+	} else
+			cmd->resp[0] = REG_READ32(host, SDHCI_RESP_REG);
+
+	retry = 0;
+
+	/*
+	 * Clear the transfer complete interrupt
+	 */
+	if (cmd->data_present || cmd->cmd_index == SDHCI_SWITCH_CMD) {
+		do {
+			int_status = REG_READ16(host, SDHCI_NRML_INT_STS_REG);
+			int_status &= SDHCI_INT_STS_TRANS_COMPLETE;
+
+			if (int_status & SDHCI_INT_STS_TRANS_COMPLETE)
+				break;
+
+			retry++;
+			udelay(1000);
+			if (retry == SDHCI_MAX_TRANS_RETRY) {
+				dprintf(CRITICAL, "Error: Transfer never completed\n");
+				goto err;
+			}
+		} while(1);
+
+		/* Transfer is complete, clear the interrupt bit */
+		REG_WRITE16(host, SDHCI_INT_STS_TRANS_COMPLETE, SDHCI_NRML_INT_STS_REG);
+	}
+
+err:
+	/* Look for errors */
+	int_status = REG_READ16(host, SDHCI_NRML_INT_STS_REG);
+	if (int_status & SDHCI_ERR_INT_STAT_MASK) {
+		if (sdhci_cmd_err_status(host)) {
+			dprintf(CRITICAL, "Error: Command completed with errors\n");
+			return 1;
+		}
+	}
+
+	/* Reset data & command line */
+	if (cmd->data_present)
+		REG_WRITE8(host, (SOFT_RESET_CMD | SOFT_RESET_DATA), SDHCI_RESET_REG);
+
+	return 0;
+}
+
+/*
+ * Function: sdhci prep desc table
+ * Arg     : Pointer data & length
+ * Return  : Pointer to desc table
+ * Flow:   : Prepare the adma table as per the sd spec v 3.0
+ */
+static struct desc_entry *sdhci_prep_desc_table(void *data, uint32_t len)
+{
+	struct desc_entry *sg_list;
+	uint32_t sg_len = 0;
+	uint32_t remain = 0;
+	uint32_t i;
+	uint32_t table_len = 0;
+
+	if (len <= SDHCI_ADMA_DESC_LINE_SZ) {
+		/* Allocate only one descriptor */
+		sg_list = (struct desc_entry *) memalign(4, sizeof(struct desc_entry));
+
+		if (!sg_list) {
+			dprintf(CRITICAL, "Error allocating memory\n");
+			ASSERT(0);
+		}
+
+		sg_list[0].addr = data;
+		sg_list[0].len = len;
+		sg_list[0].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA
+							  | SDHCI_ADMA_TRANS_END;
+
+		arch_clean_invalidate_cache_range((addr_t)sg_list, sizeof(struct desc_entry));
+	} else {
+		/* Calculate the number of entries in desc table */
+		sg_len = len / SDHCI_ADMA_DESC_LINE_SZ;
+		remain = len - (sg_len * SDHCI_ADMA_DESC_LINE_SZ);
+		/* Allocate sg_len + 1 entries */
+		if (remain)
+			sg_len++;
+
+		table_len = (sg_len * sizeof(struct desc_entry));
+
+		sg_list = (struct desc_entry *) memalign(4, table_len);
+
+		if (!sg_list) {
+			dprintf(CRITICAL, "Error allocating memory\n");
+			ASSERT(0);
+		}
+
+		memset((void *) sg_list, 0, table_len);
+
+		/*
+		 * Prepare sglist in the format:
+		 *  ___________________________________________________
+		 * |Transfer Len | Transfer ATTR | Data Address        |
+		 * | (16 bit)    | (16 bit)      | (32 bit)            |
+		 * |_____________|_______________|_____________________|
+		 */
+		for (i = 0; i < (sg_len - 1); i++) {
+				sg_list[i].addr = data;
+				sg_list[i].len = SDHCI_ADMA_DESC_LINE_SZ;
+				sg_list[i].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA;
+				data += SDHCI_ADMA_DESC_LINE_SZ;
+				len -= SDHCI_ADMA_DESC_LINE_SZ;
+			}
+
+			/* Fill the last entry of the table with Valid & End
+			 * attributes
+			 */
+			sg_list[sg_len - 1].addr = data;
+			sg_list[sg_len - 1].len = len;
+			sg_list[sg_len - 1].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA
+										   | SDHCI_ADMA_TRANS_END;
+		}
+
+	arch_clean_invalidate_cache_range((addr_t)sg_list, table_len);
+
+	return sg_list;
+}
+
+/*
+ * Function: sdhci adma transfer
+ * Arg     : Host structure & command stucture
+ * Return  : Pointer to desc table
+ * Flow    : 1. Prepare data transfer properties
+ *           2. Write adma register
+ *           3. Write transfer mode register
+ */
+static struct desc_entry *sdhci_adma_transfer(struct sdhci_host *host,
+											  struct mmc_command *cmd)
+{
+	uint32_t num_blks = 0;
+	uint32_t sz;
+	uint16_t trans_mode = 0;
+	void *data;
+	struct desc_entry *adma_addr;
+
+
+	num_blks = cmd->data.num_blocks;
+	data = cmd->data.data_ptr;
+
+	sz = num_blks * SDHCI_MMC_BLK_SZ;
+
+	/* Prepare adma descriptor table */
+	adma_addr = sdhci_prep_desc_table(data, sz);
+
+	/* Write the block size */
+	REG_WRITE16(host, SDHCI_MMC_BLK_SZ, SDHCI_BLKSZ_REG);
+
+	/* Enalbe auto cmd 23 for multi block transfer */
+	if (num_blks > 1) {
+		trans_mode |= SDHCI_TRANS_MULTI | SDHCI_AUTO_CMD23_EN | SDHCI_BLK_CNT_EN;
+		REG_WRITE32(host, num_blks, SDHCI_ARG2_REG);
+	}
+
+	/*
+	 * Set block count in block count register
+	 */
+
+	REG_WRITE16(host, num_blks, SDHCI_BLK_CNT_REG);
+
+	if (cmd->trans_mode == SDHCI_MMC_READ)
+		trans_mode |= SDHCI_READ_MODE;
+
+	trans_mode |= SDHCI_DMA_EN;
+
+	/* Write adma address to adma register */
+	REG_WRITE32(host, (uint32_t) adma_addr, SDHCI_ADM_ADDR_REG);
+
+	/* Set transfer mode */
+	REG_WRITE16(host, trans_mode, SDHCI_TRANS_MODE_REG);
+
+	return adma_addr;
+}
+
+/*
+ * Function: sdhci send command
+ * Arg     : Host structure & command stucture
+ * Return  : 0 on Success, 1 on Failure
+ * Flow:   : 1. Prepare the command register
+ *           2. If data is present, prepare adma table
+ *           3. Run the command
+ *           4. Check for command results & take action
+ */
+uint32_t sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
+{
+	uint8_t retry = 0;
+	uint32_t resp_type = 0;
+	uint16_t present_state;
+	uint32_t flags;
+	struct desc_entry *sg_list = NULL;
+
+	if (cmd->data_present)
+		ASSERT(cmd->data.data_ptr);
+
+	/*
+	 * Assert if the data buffer is not aligned to cache
+	 * line size for read operations.
+	 * For write operations this function assumes that
+	 * the cache is already flushed by the caller. As
+	 * the data buffer we receive for write operation
+	 * may not be aligned to cache boundary due to
+	 * certain image formats like sparse image.
+	 */
+	if (cmd->trans_mode == SDHCI_READ_MODE)
+		ASSERT(IS_CACHE_LINE_ALIGNED(cmd->data.data_ptr));
+
+	do {
+		present_state = REG_READ32(host, SDHCI_PRESENT_STATE_REG);
+		/* check if CMD & DAT lines are free */
+		present_state &= SDHCI_STATE_CMD_DAT_MASK;
+
+		if (!present_state)
+			break;
+		udelay(1000);
+		retry++;
+		if (retry == 10) {
+			dprintf(CRITICAL, "Error: CMD or DAT lines were never freed\n");
+			return 1;
+		}
+	} while(1);
+
+	switch(cmd->resp_type) {
+		case SDHCI_CMD_RESP_R1:
+		case SDHCI_CMD_RESP_R3:
+		case SDHCI_CMD_RESP_R6:
+		case SDHCI_CMD_RESP_R7:
+			/* Response of length 48 have 32 bits
+			 * of response data stored in RESP0[0:31]
+			 */
+			resp_type = SDHCI_CMD_RESP_48;
+			break;
+
+		case SDHCI_CMD_RESP_R2:
+			/* Response of length 136 have 120 bits
+			 * of response data stored in RESP0[0:119]
+			 */
+			resp_type = SDHCI_CMD_RESP_136;
+			break;
+
+		case SDHCI_CMD_RESP_R1B:
+			/* Response of length 48 have 32 bits
+			 * of response data stored in RESP0[0:31]
+			 * & set CARD_BUSY status if card is busy
+			 */
+			resp_type = SDHCI_CMD_RESP_48_BUSY;
+			break;
+
+		case SDHCI_CMD_RESP_NONE:
+			resp_type = SDHCI_CMD_RESP_NONE;
+			break;
+
+		default:
+			dprintf(CRITICAL, "Invalid response type for the command\n");
+			return 1;
+	};
+
+	flags =  (resp_type << SDHCI_CMD_RESP_TYPE_SEL_BIT);
+	flags |= (cmd->data_present << SDHCI_CMD_DATA_PRESENT_BIT);
+	flags |= (cmd->cmd_type << SDHCI_CMD_CMD_TYPE_BIT);
+
+	/* Set the timeout value */
+	REG_WRITE8(host, SDHCI_CMD_TIMEOUT, SDHCI_TIMEOUT_REG);
+
+	/* Check if data needs to be processed */
+	if (cmd->data_present)
+		sg_list = sdhci_adma_transfer(host, cmd);
+
+	/* Write the argument 1 */
+	REG_WRITE32(host, cmd->argument, SDHCI_ARGUMENT_REG);
+
+	/* Write the command register */
+	REG_WRITE16(host, SDHCI_PREP_CMD(cmd->cmd_index, flags), SDHCI_CMD_REG);
+
+	/* Command complete sequence */
+	if (sdhci_cmd_complete(host, cmd))
+		return 1;
+
+	/* Invalidate the cache only for read operations */
+	if (cmd->trans_mode == SDHCI_MMC_READ)
+		arch_invalidate_cache_range((addr_t)cmd->data.data_ptr, (cmd->data.num_blocks * SDHCI_MMC_BLK_SZ));
+
+	/* Free the scatter/gather list */
+	if (sg_list)
+		free(sg_list);
+
+	return 0;
+}
+
+/*
+ * Function: sdhci reset
+ * Arg     : Host structure
+ * Return  : None
+ * Flow:   : Reset the host controller
+ */
+static void sdhci_reset(struct sdhci_host *host)
+{
+	uint32_t reg;
+
+	REG_WRITE8(host, SDHCI_SOFT_RESET, SDHCI_RESET_REG);
+
+	/* Wait for the reset to complete */
+	do {
+		reg = REG_READ8(host, SDHCI_RESET_REG);
+		reg &= SDHCI_SOFT_RESET_MASK;
+
+		if (!reg)
+			break;
+	} while(1);
+}
+
+/*
+ * 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
+ * Flow:   : 1. Reset the controller
+ *           2. Read the capabilities register & populate the host
+ *           controller capabilities for use by other functions
+ *           3. Enable the power control
+ *           4. Set initial bus width
+ *           5. Set Adma mode
+ *           6. Enable the error status
+ */
+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
+	 */
+	sdhci_reset(host);
+
+	/* Read the capabilities register & store the info */
+	caps[0] = REG_READ32(host, SDHCI_CAPS_REG1);
+	caps[1] = REG_READ32(host, SDHCI_CAPS_REG2);
+
+	host->caps.base_clk_rate = (caps[0] & SDHCI_CLK_RATE_MASK) >> SDHCI_CLK_RATE_BIT;
+	host->caps.base_clk_rate *= 1000000;
+
+	/* Get the max block length for mmc */
+	host->caps.max_blk_len = (caps[0] & SDHCI_BLK_LEN_MASK) >> SDHCI_BLK_LEN_BIT;
+
+	/* 8 bit Bus width */
+	if (caps[0] & SDHCI_8BIT_WIDTH_MASK)
+		host->caps.bus_width_8bit = 1;
+
+	/* Adma support */
+	if (caps[0] & SDHCI_BLK_ADMA_MASK)
+		host->caps.adma_support = 1;
+
+	/* Supported voltage */
+	if (caps[0] & SDHCI_3_3_VOL_MASK)
+		host->caps.voltage = SDHCI_VOL_3_3;
+	else if (caps[0] & SDHCI_3_0_VOL_MASK)
+		host->caps.voltage = SDHCI_VOL_3_0;
+	else if (caps[0] & SDHCI_1_8_VOL_MASK)
+		host->caps.voltage = SDHCI_VOL_1_8;
+
+	/* DDR mode support */
+	host->caps.ddr_support = (caps[1] & SDHCI_DDR_MODE_MASK) ? 1 : 0;
+
+	/* 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);
+
+	/* Set bus width */
+	sdhci_set_bus_width(host, SDHCI_BUS_WITDH_1BIT);
+
+	/* Set Adma mode */
+	sdhci_set_adma_mode(host);
+
+	/*
+	 * Enable error status
+	 */
+	sdhci_error_status_enable(host);
+}
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index 88528e1..e0cbc5b 100755
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -285,7 +285,9 @@
 	MSM8110   = 161,
 	MSM8210   = 162,
 	MSM8810   = 163,
+	MSM8212   = 164,
 	MSM8612   = 165,
+	MSM8812   = 166,
 	MSM8125   = 167,
 	MDM9310   = 171,
 	APQ8064AA = 172, /* aka V2 SLOW_PRIME */
diff --git a/project/msm8974.mk b/project/msm8974.mk
index 2cbec50..6ffa254 100644
--- a/project/msm8974.mk
+++ b/project/msm8974.mk
@@ -15,6 +15,7 @@
 DEFINES += DEVICE_TREE=1
 #DEFINES += MMC_BOOT_BAM=1
 DEFINES += CRYPTO_BAM=1
+DEFINES += ABOOT_IGNORE_BOOT_HEADER_ADDRS=1
 
 #Disable thumb mode
 ENABLE_THUMB := false
@@ -23,11 +24,6 @@
 DEFINES += ABOOT_FORCE_RAMDISK_ADDR=0x02000000
 DEFINES += ABOOT_FORCE_TAGS_ADDR=0x01e00000
 
-# Right now we are assuming these are the only default values
-DEFINES += ABOOT_DEFAULT_KERNEL_ADDR=0x10008000
-DEFINES += ABOOT_DEFAULT_RAMDISK_ADDR=0x1100000
-DEFINES += ABOOT_DEFAULT_TAGS_ADDR=0x10000100
-
 ifeq ($(EMMC_BOOT),1)
 DEFINES += _EMMC_BOOT=1
 endif
diff --git a/target/msm8610/init.c b/target/msm8610/init.c
index 61f29b3..63c9e62 100644
--- a/target/msm8610/init.c
+++ b/target/msm8610/init.c
@@ -41,6 +41,7 @@
 #include <dev/keys.h>
 #include <pm8x41.h>
 #include <hsusb.h>
+#include <kernel/thread.h>
 
 #define PMIC_ARB_CHANNEL_NUM    0
 #define PMIC_ARB_OWNER_ID       0
@@ -64,6 +65,8 @@
 
 	gpio_tlmm_config(TLMM_VOL_UP_BTN_GPIO, 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA, GPIO_ENABLE);
 
+	/* Wait for the configuration to complete.*/
+	thread_sleep(1);
 	/* Get status of GPIO */
 	status = gpio_status(TLMM_VOL_UP_BTN_GPIO);
 
@@ -161,6 +164,8 @@
 	case MSM8210:
 	case MSM8810:
 	case MSM8612:
+	case MSM8212:
+	case MSM8812:
 		board->baseband = BASEBAND_MSM;
 		break;
 	default:
diff --git a/target/msm8974/init.c b/target/msm8974/init.c
index e1ab1c2..1cec156 100644
--- a/target/msm8974/init.c
+++ b/target/msm8974/init.c
@@ -46,6 +46,7 @@
 #include <partition_parser.h>
 #include <scm.h>
 #include <platform/clock.h>
+#include <stdlib.h>
 
 extern  bool target_use_signed_kernel(void);
 static void set_sdc_power_ctrl();
@@ -208,7 +209,6 @@
 
 /* Do any target specific intialization needed before entering fastboot mode */
 #ifdef SSD_ENABLE
-static uint32_t  buffer[SSD_PARTITION_SIZE] __attribute__ ((aligned(32)));
 static void ssd_load_keystore_from_emmc()
 {
 	uint64_t           ptn    = 0;
@@ -216,6 +216,14 @@
 	uint32_t           size   = SSD_PARTITION_SIZE;
 	int                ret    = -1;
 
+	uint32_t *buffer = (uint32_t *)memalign(CACHE_LINE,
+								   ROUNDUP(SSD_PARTITION_SIZE, CACHE_LINE));
+
+	if (!buffer) {
+		dprintf(CRITICAL, "Error Allocating memory for SSD buffer\n");
+		ASSERT(0);
+	}
+
 	index = partition_get_index("ssd");
 
 	ptn   = partition_get_offset(index);
@@ -232,6 +240,8 @@
 	ret = scm_protect_keystore((uint32_t *)&buffer[0],size);
 	if(ret != 0)
 		dprintf(CRITICAL,"ERROR: scm_protect_keystore Failed");
+
+	free(buffer);
 }
 #endif
 
@@ -269,6 +279,9 @@
 	switch(platform_subtype) {
 	case HW_PLATFORM_SUBTYPE_UNKNOWN:
 		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);
diff --git a/target/msm8974/target_display.c b/target/msm8974/target_display.c
index f310b22..5968b88 100644
--- a/target/msm8974/target_display.c
+++ b/target/msm8974/target_display.c
@@ -71,13 +71,16 @@
 		mmss_clock_init();
 	} else if(!target_cont_splash_screen()) {
 		// * Add here for continuous splash  *
+		mmss_clock_disable();
+		mdp_clock_disable();
+		mdp_gdsc_ctrl(enable);
 	}
 
 	return 0;
 }
 
 /* Pull DISP_RST_N high to get panel out of reset */
-static void msm8974_mdss_mipi_panel_reset(void)
+static void msm8974_mdss_mipi_panel_reset(uint8_t enable)
 {
 	struct pm8x41_gpio gpio19_param = {
 		.direction = PM_GPIO_DIR_OUT,
@@ -86,18 +89,24 @@
 	};
 
 	pm8x41_gpio_config(19, &gpio19_param);
-	gpio_tlmm_config(58, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE);
+	if (enable) {
+		gpio_tlmm_config(58, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE);
 
-	pm8x41_gpio_set(19, PM_GPIO_FUNC_HIGH);
-	mdelay(2);
-	pm8x41_gpio_set(19, PM_GPIO_FUNC_LOW);
-	mdelay(5);
-	pm8x41_gpio_set(19, PM_GPIO_FUNC_HIGH);
-	mdelay(2);
-	gpio_set(58, 2);
+		pm8x41_gpio_set(19, PM_GPIO_FUNC_HIGH);
+		mdelay(2);
+		pm8x41_gpio_set(19, PM_GPIO_FUNC_LOW);
+		mdelay(5);
+		pm8x41_gpio_set(19, PM_GPIO_FUNC_HIGH);
+		mdelay(2);
+		gpio_set(58, 2);
+	} else {
+		gpio19_param.out_strength = PM_GPIO_OUT_DRIVE_LOW;
+		pm8x41_gpio_config(19, &gpio19_param);
+		pm8x41_gpio_set(19, PM_GPIO_FUNC_LOW);
+		gpio_set(58, 2);
+	}
 }
 
-
 static int msm8974_mipi_panel_power(uint8_t enable)
 {
 	if (enable) {
@@ -122,8 +131,14 @@
 
 		dprintf(SPEW, " Panel Reset \n");
 		/* Panel Reset */
-		msm8974_mdss_mipi_panel_reset();
+		msm8974_mdss_mipi_panel_reset(enable);
 		dprintf(SPEW, " Panel Reset Done\n");
+	} else {
+		msm8974_mdss_mipi_panel_reset(enable);
+		pm8x41_wled_enable(enable);
+		pm8x41_ldo_control("LDO2", enable);
+		pm8x41_ldo_control("LDO22", enable);
+
 	}
 
 	return 0;