Merge "msm: change the pr_err to CDBG to reduce the log output" into msm-3.0
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 01150aa..255d06e 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -294,6 +294,7 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_SX150X=y
+# CONFIG_MPP_PMIC8901 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
 CONFIG_BATTERY_MSM8X60=y
@@ -305,7 +306,6 @@
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_HWMON=y
-CONFIG_THERMAL_PM8901=y
 CONFIG_THERMAL_TSENS=y
 CONFIG_THERMAL_PM8XXX=y
 CONFIG_PMIC8058=y
@@ -314,6 +314,7 @@
 CONFIG_TIMPANI_CODEC=y
 # CONFIG_MFD_PM8XXX_PWM is not set
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -333,6 +334,7 @@
 CONFIG_FB_MSM_TRIPLE_BUFFER=y
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
 CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 7b2fede..0a88039 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -284,6 +284,7 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_SX150X=y
+# CONFIG_MPP_PMIC8901 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
 CONFIG_BATTERY_MSM8X60=y
@@ -294,7 +295,6 @@
 CONFIG_BATTERY_BQ27541=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_THERMAL=y
-CONFIG_THERMAL_PM8901=y
 CONFIG_THERMAL_TSENS=y
 CONFIG_THERMAL_PM8XXX=y
 CONFIG_PMIC8058=y
@@ -303,6 +303,7 @@
 CONFIG_TIMPANI_CODEC=y
 # CONFIG_MFD_PM8XXX_PWM is not set
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -320,6 +321,7 @@
 CONFIG_FB_MSM_TRIPLE_BUFFER=y
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
 CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 9f3d72b..bb94d2a 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -235,7 +235,7 @@
 CONFIG_KS8851=m
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-CONFIG_WCNSS_CORE=m
+CONFIG_WCNSS_CORE=y
 CONFIG_USB_USBNET=y
 CONFIG_SLIP=y
 CONFIG_SLIP_COMPRESSED=y
@@ -282,6 +282,7 @@
 CONFIG_THERMAL_PM8XXX=y
 CONFIG_MFD_PM8921_CORE=y
 CONFIG_MFD_PM8821_CORE=y
+CONFIG_MFD_PM8038_CORE=y
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
 CONFIG_WCD9310_CODEC=y
 CONFIG_REGULATOR_GPIO=y
@@ -308,6 +309,7 @@
 CONFIG_FB_MSM_TRIPLE_BUFFER=y
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
 CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
 CONFIG_FB_MSM_HDMI_MSM_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index be8c31c..a332ad1 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -68,7 +68,7 @@
 #define STBY_KHZ		1
 
 #define HFPLL_NOMINAL_VDD	1050000
-#define HFPLL_LOW_VDD		945000
+#define HFPLL_LOW_VDD		 850000
 #define HFPLL_LOW_VDD_PLL_L_MAX	0x28
 
 #define SECCLKAGD		BIT(4)
@@ -303,19 +303,35 @@
 	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
 };
 
-static struct acpu_level acpu_freq_tbl_8960_kraitv1[] = {
-	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
-	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   950000 },
-	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   962500 },
-	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   962500 },
-	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   987500 },
-	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),  1000000 },
-	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),  1025000 },
-	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
-	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1087500 },
-	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1125000 },
-	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1137500 },
+static struct acpu_level acpu_freq_tbl_8960_kraitv1_slow[] = {
+	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
+	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   925000 },
+	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   925000 },
+	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   937500 },
+	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   962500 },
+	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),   987500 },
+	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),  1000000 },
+	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
+	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
+	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
+	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_8960_kraitv1_nom_fast[] = {
+	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   862500 },
+	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   862500 },
+	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   862500 },
+	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   887500 },
+	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   900000 },
+	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   925000 },
+	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),   925000 },
+	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),   937500 },
+	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11),  962500 },
+	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1012500 },
+	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
+	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
 	{ 0, { 0 } }
 };
 
@@ -341,19 +357,46 @@
 	[16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 4 },
 };
 
-static struct acpu_level acpu_freq_tbl_8960_kraitv2[] = {
-	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
-	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   950000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   962500 },
-	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   962500 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   987500 },
-	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),  1000000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1025000 },
-	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1087500 },
-	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1125000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1137500 },
+static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
+	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   925000 },
+	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   937500 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   962500 },
+	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),   987500 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),  1000000 },
+	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
+	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
+	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1300000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1300000 },
+	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1300000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1300000 },
+	{ 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1300000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1300000 },
+	{ 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1300000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1300000 },
+	{ 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1300000 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1300000 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1300000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom_fast[] = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   862500 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   862500 },
+	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   862500 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(6),   887500 },
+	{ 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(6),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(6),   925000 },
+	{ 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(6),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(6),   937500 },
+	{ 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(11),  962500 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(11), 1012500 },
+	{ 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
 	{ 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(16), 1300000 },
 	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1300000 },
 	{ 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1300000 },
@@ -1080,6 +1123,7 @@
 	/* Select frequency tables. */
 	if (cpu_is_msm8960() || cpu_is_msm8930()) {
 		uint32_t pte_efuse, pvs;
+		struct acpu_level *v1, *v2;
 
 		pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
 		pvs = (pte_efuse >> 10) & 0x7;
@@ -1090,26 +1134,33 @@
 		case 0x0:
 		case 0x7:
 			pr_info("ACPU PVS: Slow\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_slow;
+			v2 = acpu_freq_tbl_8960_kraitv2_slow;
 			break;
 		case 0x1:
 			pr_info("ACPU PVS: Nominal\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_nom_fast;
+			v2 = acpu_freq_tbl_8960_kraitv2_nom_fast;
 			break;
 		case 0x3:
 			pr_info("ACPU PVS: Fast\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_nom_fast;
+			v2 = acpu_freq_tbl_8960_kraitv2_nom_fast;
 			break;
 		default:
 			pr_warn("ACPU PVS: Unknown. Defaulting to slow.\n");
+			v1 = acpu_freq_tbl_8960_kraitv1_slow;
+			v2 = acpu_freq_tbl_8960_kraitv2_slow;
 			break;
 		}
 
-		/* TODO: Select tables based on PVS data. */
 		scalable = scalable_8960;
 		if (cpu_is_krait_v1()) {
-			acpu_freq_tbl = acpu_freq_tbl_8960_kraitv1;
+			acpu_freq_tbl = v1;
 			l2_freq_tbl = l2_freq_tbl_8960_kraitv1;
 			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv1);
 		} else {
-			acpu_freq_tbl = acpu_freq_tbl_8960_kraitv2;
+			acpu_freq_tbl = v2;
 			l2_freq_tbl = l2_freq_tbl_8960_kraitv2;
 			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv2);
 		}
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index ca21fac..f1103cb 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -22,7 +22,15 @@
 #include <mach/gpiomux.h>
 #include <mach/socinfo.h>
 #include "devices.h"
+
+/* TODO: Remove this once PM8038 physically becomes
+ * available.
+ */
+#ifndef MSM8930_PHASE_2
+#include "board-8960.h"
+#else
 #include "board-8930.h"
+#endif
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
 #define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
@@ -137,6 +145,12 @@
 
 static bool dsi_power_on;
 
+/*
+ * TODO: When physical 8930/PM8038 hardware becomes
+ * available, replace mipi_dsi_cdp_panel_power with
+ * appropriate function.
+ */
+#ifndef MSM8930_PHASE_2
 static int mipi_dsi_cdp_panel_power(int on)
 {
 	static struct regulator *reg_l8, *reg_l23, *reg_l2;
@@ -258,6 +272,7 @@
 	}
 	return 0;
 }
+#endif
 
 static int mipi_dsi_panel_power(int on)
 {
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index cfb2347..283493d 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -12,10 +12,8 @@
  */
 
 #include <linux/interrupt.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/pm8038.h>
 #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
-#include <linux/leds.h>
-#include <linux/leds-pm8xxx.h>
 #include <linux/msm_ssbi.h>
 #include <asm/mach-types.h>
 #include <mach/msm_bus_board.h>
@@ -36,7 +34,7 @@
 #define PM8XXX_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
 			_func, _inv, _disable) \
 { \
-	.gpio	= PM8921_GPIO_PM_TO_SYS(_gpio), \
+	.gpio	= PM8038_GPIO_PM_TO_SYS(_gpio), \
 	.config	= { \
 		.direction	= _dir, \
 		.output_buffer	= _buf, \
@@ -52,7 +50,7 @@
 
 #define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
 { \
-	.mpp	= PM8921_MPP_PM_TO_SYS(_mpp), \
+	.mpp	= PM8038_MPP_PM_TO_SYS(_mpp), \
 	.config	= { \
 		.type		= PM8XXX_MPP_TYPE_##_type, \
 		.level		= _level, \
@@ -61,24 +59,24 @@
 }
 
 #define PM8XXX_GPIO_DISABLE(_gpio) \
-	PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
+	PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM8038_GPIO_VIN_L11, \
 			 0, 0, 0, 1)
 
 #define PM8XXX_GPIO_OUTPUT(_gpio, _val) \
 	PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
-			PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+			PM_GPIO_PULL_NO, PM8038_GPIO_VIN_L11, \
 			PM_GPIO_STRENGTH_HIGH, \
 			PM_GPIO_FUNC_NORMAL, 0, 0)
 
 #define PM8XXX_GPIO_INPUT(_gpio, _pull) \
 	PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
-			_pull, PM_GPIO_VIN_S4, \
+			_pull, PM8038_GPIO_VIN_L11, \
 			PM_GPIO_STRENGTH_NO, \
 			PM_GPIO_FUNC_NORMAL, 0, 0)
 
 #define PM8XXX_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
 	PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
-			PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+			PM_GPIO_PULL_NO, PM8038_GPIO_VIN_L11, \
 			PM_GPIO_STRENGTH_HIGH, \
 			_func, 0, 0)
 
@@ -88,45 +86,32 @@
 			PM_GPIO_STRENGTH_HIGH, \
 			PM_GPIO_FUNC_NORMAL, 0, 0)
 
-/* Initial PM8921 GPIO configurations */
-static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
-	PM8XXX_GPIO_DISABLE(6),				 /* Disable unused */
-	PM8XXX_GPIO_DISABLE(7),				 /* Disable NFC */
-	PM8XXX_GPIO_INPUT(16,	    PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
-    /* External regulator shared by display and touchscreen on LiQUID */
-	PM8XXX_GPIO_OUTPUT(17,	    0),			 /* DISP 3.3 V Boost */
-	PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH),	 /* Backlight Enable */
-	PM8XXX_GPIO_DISABLE(22),			 /* Disable NFC */
-	PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2),	 /* Bl: Off, PWM mode */
-	PM8XXX_GPIO_INPUT(26,	    PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
-	PM8XXX_GPIO_OUTPUT(43,	    PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
-	PM8XXX_GPIO_OUTPUT(42, 0),                      /* USB 5V reg enable */
-};
+/* Initial pm8038 GPIO configurations */
+static struct pm8xxx_gpio_init pm8038_gpios[] __initdata = {};
 
-/* Initial PM8921 MPP configurations */
-static struct pm8xxx_mpp_init pm8921_mpps[] __initdata = {
+/* Initial pm8038 MPP configurations */
+static struct pm8xxx_mpp_init pm8038_mpps[] __initdata = {
 	/* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
-	PM8XXX_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
-	PM8XXX_MPP_INIT(PM8XXX_AMUX_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
-								DOUT_CTRL_LOW),
+	PM8XXX_MPP_INIT(3, D_INPUT, PM8038_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
 };
 
-void __init msm8930_pm8921_gpio_mpp_init(void)
+void __init msm8930_pm8038_gpio_mpp_init(void)
 {
 	int i, rc;
 
-	for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
-		rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
-					&pm8921_gpios[i].config);
+	for (i = 0; i < ARRAY_SIZE(pm8038_gpios); i++) {
+		rc = pm8xxx_gpio_config(pm8038_gpios[i].gpio,
+					&pm8038_gpios[i].config);
 		if (rc) {
 			pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
 			break;
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(pm8921_mpps); i++) {
-		rc = pm8xxx_mpp_config(pm8921_mpps[i].mpp,
-					&pm8921_mpps[i].config);
+	/* Initial MPP configuration. */
+	for (i = 0; i < ARRAY_SIZE(pm8038_mpps); i++) {
+		rc = pm8xxx_mpp_config(pm8038_mpps[i].mpp,
+					&pm8038_mpps[i].config);
 		if (rc) {
 			pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
 			break;
@@ -134,71 +119,22 @@
 	}
 }
 
-static struct pm8xxx_adc_amux pm8xxx_adc_channels_data[] = {
-	{"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
-	{"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
-	{"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
-	{"pa_therm1", ADC_MPP_1_AMUX8, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
-	{"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
-	{"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
-		ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
-};
-
-static struct pm8xxx_adc_properties pm8xxx_adc_data = {
-	.adc_vdd_reference	= 1800, /* milli-voltage for this adc */
-	.bitresolution		= 15,
-	.bipolar                = 0,
-};
-
-static struct pm8xxx_adc_platform_data pm8xxx_adc_pdata = {
-	.adc_channel            = pm8xxx_adc_channels_data,
-	.adc_num_board_channel  = ARRAY_SIZE(pm8xxx_adc_channels_data),
-	.adc_prop               = &pm8xxx_adc_data,
-	.adc_mpp_base		= PM8921_MPP_PM_TO_SYS(1),
-};
-
-
 static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata __devinitdata = {
-	.irq_base		= PM8921_IRQ_BASE,
+	.irq_base		= PM8038_IRQ_BASE,
 	.devirq			= MSM_GPIO_TO_INT(104),
 	.irq_trigger_flag	= IRQF_TRIGGER_LOW,
 };
 
 static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata __devinitdata = {
-	.gpio_base	= PM8921_GPIO_PM_TO_SYS(1),
+	.gpio_base	= PM8038_GPIO_PM_TO_SYS(1),
 };
 
 static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata __devinitdata = {
-	.mpp_base	= PM8921_MPP_PM_TO_SYS(1),
+	.mpp_base	= PM8038_MPP_PM_TO_SYS(1),
 };
 
 static struct pm8xxx_rtc_platform_data pm8xxx_rtc_pdata __devinitdata = {
-	.rtc_write_enable       = false,
+	.rtc_write_enable	= false,
 	.rtc_alarm_powerup	= false,
 };
 
@@ -208,292 +144,30 @@
 	.wakeup			= 1,
 };
 
-/* Rotate lock key is not available so use F1 */
-#define KEY_ROTATE_LOCK KEY_F1
-
-static const unsigned int keymap_liquid[] = {
-	KEY(0, 0, KEY_VOLUMEUP),
-	KEY(0, 1, KEY_VOLUMEDOWN),
-	KEY(1, 3, KEY_ROTATE_LOCK),
-	KEY(1, 4, KEY_HOME),
-};
-
-static const unsigned int keymap[] = {
-	KEY(0, 0, KEY_VOLUMEUP),
-	KEY(0, 1, KEY_VOLUMEDOWN),
-	KEY(0, 2, KEY_CAMERA_SNAPSHOT),
-	KEY(0, 3, KEY_CAMERA_FOCUS),
-};
-
-static struct matrix_keymap_data keymap_data = {
-	.keymap_size    = ARRAY_SIZE(keymap),
-	.keymap         = keymap,
-};
-
-static struct pm8xxx_keypad_platform_data keypad_data = {
-	.input_name             = "keypad_8960",
-	.input_phys_device      = "keypad_8960/input0",
-	.num_rows               = 1,
-	.num_cols               = 5,
-	.rows_gpio_start	= PM8921_GPIO_PM_TO_SYS(9),
-	.cols_gpio_start	= PM8921_GPIO_PM_TO_SYS(1),
-	.debounce_ms            = 15,
-	.scan_delay_ms          = 32,
-	.row_hold_ns            = 91500,
-	.wakeup                 = 1,
-	.keymap_data            = &keymap_data,
-};
-
-static const unsigned int keymap_sim[] = {
-	KEY(0, 0, KEY_7),
-	KEY(0, 1, KEY_DOWN),
-	KEY(0, 2, KEY_UP),
-	KEY(0, 3, KEY_RIGHT),
-	KEY(0, 4, KEY_ENTER),
-	KEY(0, 5, KEY_L),
-	KEY(0, 6, KEY_BACK),
-	KEY(0, 7, KEY_M),
-
-	KEY(1, 0, KEY_LEFT),
-	KEY(1, 1, KEY_SEND),
-	KEY(1, 2, KEY_1),
-	KEY(1, 3, KEY_4),
-	KEY(1, 4, KEY_CLEAR),
-	KEY(1, 5, KEY_MSDOS),
-	KEY(1, 6, KEY_SPACE),
-	KEY(1, 7, KEY_COMMA),
-
-	KEY(2, 0, KEY_6),
-	KEY(2, 1, KEY_5),
-	KEY(2, 2, KEY_8),
-	KEY(2, 3, KEY_3),
-	KEY(2, 4, KEY_NUMERIC_STAR),
-	KEY(2, 5, KEY_UP),
-	KEY(2, 6, KEY_DOWN),
-	KEY(2, 7, KEY_LEFTSHIFT),
-
-	KEY(3, 0, KEY_9),
-	KEY(3, 1, KEY_NUMERIC_POUND),
-	KEY(3, 2, KEY_0),
-	KEY(3, 3, KEY_2),
-	KEY(3, 4, KEY_SLEEP),
-	KEY(3, 5, KEY_F1),
-	KEY(3, 6, KEY_F2),
-	KEY(3, 7, KEY_F3),
-
-	KEY(4, 0, KEY_BACK),
-	KEY(4, 1, KEY_HOME),
-	KEY(4, 2, KEY_MENU),
-	KEY(4, 3, KEY_VOLUMEUP),
-	KEY(4, 4, KEY_VOLUMEDOWN),
-	KEY(4, 5, KEY_F4),
-	KEY(4, 6, KEY_F5),
-	KEY(4, 7, KEY_F6),
-
-	KEY(5, 0, KEY_R),
-	KEY(5, 1, KEY_T),
-	KEY(5, 2, KEY_Y),
-	KEY(5, 3, KEY_LEFTALT),
-	KEY(5, 4, KEY_KPENTER),
-	KEY(5, 5, KEY_Q),
-	KEY(5, 6, KEY_W),
-	KEY(5, 7, KEY_E),
-
-	KEY(6, 0, KEY_F),
-	KEY(6, 1, KEY_G),
-	KEY(6, 2, KEY_H),
-	KEY(6, 3, KEY_CAPSLOCK),
-	KEY(6, 4, KEY_PAGEUP),
-	KEY(6, 5, KEY_A),
-	KEY(6, 6, KEY_S),
-	KEY(6, 7, KEY_D),
-
-	KEY(7, 0, KEY_V),
-	KEY(7, 1, KEY_B),
-	KEY(7, 2, KEY_N),
-	KEY(7, 3, KEY_MENU),
-	KEY(7, 4, KEY_PAGEDOWN),
-	KEY(7, 5, KEY_Z),
-	KEY(7, 6, KEY_X),
-	KEY(7, 7, KEY_C),
-
-	KEY(8, 0, KEY_P),
-	KEY(8, 1, KEY_J),
-	KEY(8, 2, KEY_K),
-	KEY(8, 3, KEY_INSERT),
-	KEY(8, 4, KEY_LINEFEED),
-	KEY(8, 5, KEY_U),
-	KEY(8, 6, KEY_I),
-	KEY(8, 7, KEY_O),
-
-	KEY(9, 0, KEY_4),
-	KEY(9, 1, KEY_5),
-	KEY(9, 2, KEY_6),
-	KEY(9, 3, KEY_7),
-	KEY(9, 4, KEY_8),
-	KEY(9, 5, KEY_1),
-	KEY(9, 6, KEY_2),
-	KEY(9, 7, KEY_3),
-
-	KEY(10, 0, KEY_F7),
-	KEY(10, 1, KEY_F8),
-	KEY(10, 2, KEY_F9),
-	KEY(10, 3, KEY_F10),
-	KEY(10, 4, KEY_FN),
-	KEY(10, 5, KEY_9),
-	KEY(10, 6, KEY_0),
-	KEY(10, 7, KEY_DOT),
-
-	KEY(11, 0, KEY_LEFTCTRL),
-	KEY(11, 1, KEY_F11),
-	KEY(11, 2, KEY_ENTER),
-	KEY(11, 3, KEY_SEARCH),
-	KEY(11, 4, KEY_DELETE),
-	KEY(11, 5, KEY_RIGHT),
-	KEY(11, 6, KEY_LEFT),
-	KEY(11, 7, KEY_RIGHTSHIFT),
-	KEY(0, 0, KEY_VOLUMEUP),
-	KEY(0, 1, KEY_VOLUMEDOWN),
-	KEY(0, 2, KEY_CAMERA_SNAPSHOT),
-	KEY(0, 3, KEY_CAMERA_FOCUS),
-};
-
-static int pm8921_therm_mitigation[] = {
-	1100,
-	700,
-	600,
-	325,
-};
-
-static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
-	.safety_time		= 180,
-	.update_time		= 60000,
-	.max_voltage		= 4200,
-	.min_voltage		= 3200,
-	.resume_voltage_delta	= 100,
-	.term_current		= 100,
-	.cool_temp		= 10,
-	.warm_temp		= 40,
-	.temp_check_period	= 1,
-	.max_bat_chg_current	= 1100,
-	.cool_bat_chg_current	= 350,
-	.warm_bat_chg_current	= 350,
-	.cool_bat_voltage	= 4100,
-	.warm_bat_voltage	= 4100,
-	.thermal_mitigation	= pm8921_therm_mitigation,
-	.thermal_levels		= ARRAY_SIZE(pm8921_therm_mitigation),
-};
-
 static struct pm8xxx_misc_platform_data pm8xxx_misc_pdata = {
 	.priority		= 0,
 };
 
-static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
-	.r_sense		= 10,
-	.i_test			= 2500,
-	.v_failure		= 3000,
-	.calib_delay_ms		= 600000,
-};
-
-#define	PM8921_LC_LED_MAX_CURRENT	4	/* I = 4mA */
-#define PM8XXX_LED_PWM_PERIOD		1000
-#define PM8XXX_LED_PWM_DUTY_MS		20
-/**
- * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
- * driven using PWM feature.
- */
-#define PM8XXX_PWM_CHANNEL_NONE		-1
-
-static struct led_info pm8921_led_info[] = {
-	[0] = {
-		.name			= "led:battery_charging",
-		.default_trigger	= "battery-charging",
-	},
-	[1] = {
-		.name			= "led:battery_full",
-		.default_trigger	= "battery-full",
-	},
-};
-
-static struct led_platform_data pm8921_led_core_pdata = {
-	.num_leds = ARRAY_SIZE(pm8921_led_info),
-	.leds = pm8921_led_info,
-};
-
-static int pm8921_led0_pwm_duty_pcts[56] = {
-		1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
-		40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
-		80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
-		92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
-		58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
-		14, 10, 6, 4, 1
-};
-
-static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
-	.duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
-	.num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
-	.duty_ms = PM8XXX_LED_PWM_DUTY_MS,
-	.start_idx = 0,
-};
-
-static struct pm8xxx_led_config pm8921_led_configs[] = {
-	[0] = {
-		.id = PM8XXX_ID_LED_0,
-		.mode = PM8XXX_LED_MODE_PWM2,
-		.max_current = PM8921_LC_LED_MAX_CURRENT,
-		.pwm_channel = 5,
-		.pwm_period_us = PM8XXX_LED_PWM_PERIOD,
-		.pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
-	},
-	[1] = {
-		.id = PM8XXX_ID_LED_1,
-		.mode = PM8XXX_LED_MODE_PWM1,
-		.max_current = PM8921_LC_LED_MAX_CURRENT,
-		.pwm_channel = 4,
-		.pwm_period_us = PM8XXX_LED_PWM_PERIOD,
-	},
-};
-
-static struct pm8xxx_led_platform_data pm8xxx_leds_pdata = {
-		.led_core = &pm8921_led_core_pdata,
-		.configs = pm8921_led_configs,
-		.num_configs = ARRAY_SIZE(pm8921_led_configs),
-};
-
-static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
-	.r_sense		= 10,
-};
-
-static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
+static struct pm8038_platform_data pm8038_platform_data __devinitdata = {
 	.irq_pdata		= &pm8xxx_irq_pdata,
 	.gpio_pdata		= &pm8xxx_gpio_pdata,
 	.mpp_pdata		= &pm8xxx_mpp_pdata,
 	.rtc_pdata              = &pm8xxx_rtc_pdata,
 	.pwrkey_pdata		= &pm8xxx_pwrkey_pdata,
-	.keypad_pdata		= &keypad_data,
 	.misc_pdata		= &pm8xxx_misc_pdata,
-	.regulator_pdatas	= msm_pm8921_regulator_pdata,
-	.charger_pdata		= &pm8921_chg_pdata,
-	.bms_pdata		= &pm8921_bms_pdata,
-	.adc_pdata		= &pm8xxx_adc_pdata,
-	.leds_pdata		= &pm8xxx_leds_pdata,
-	.ccadc_pdata		= &pm8xxx_ccadc_pdata,
 };
 
-static struct msm_ssbi_platform_data msm8960_ssbi_pm8921_pdata __devinitdata = {
+static struct msm_ssbi_platform_data msm8930_ssbi_pm8038_pdata __devinitdata = {
 	.controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
 	.slave	= {
-		.name			= "pm8921-core",
-		.platform_data		= &pm8921_platform_data,
+		.name			= "pm8038-core",
+		.platform_data		= &pm8038_platform_data,
 	},
 };
 
 void __init msm8930_init_pmic(void)
 {
-	pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
-	msm8960_device_ssbi_pm8921.dev.platform_data =
-				&msm8960_ssbi_pm8921_pdata;
-	pm8921_platform_data.num_regulators = msm_pm8921_regulator_pdata_len;
-
-	/* Simulator supports a QWERTY keypad */
+	pmic_reset_irq = PM8038_IRQ_BASE + PM8038_RESOUT_IRQ;
+	msm8960_device_ssbi_pmic.dev.platform_data =
+				&msm8930_ssbi_pm8038_pdata;
 }
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index 032d3d0..e38f877 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -22,7 +22,15 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 #include "devices.h"
+
+/* TODO: Remove this once PM8038 physically becomes
+ * available.
+ */
+#ifndef MSM8930_PHASE_2
+#include "board-8960.h"
+#else
 #include "board-8930.h"
+#endif
 
 /* MSM8960 has 5 SDCC controllers */
 enum sdcc_controllers {
@@ -239,13 +247,19 @@
 	.sup_clk_cnt	= ARRAY_SIZE(sdc3_sup_clk_rates),
 	.pclk_src_dfab	= 1,
 #ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
+/*TODO: Insert right replacement for PM8038 */
+#ifndef MSM8930_PHASE_2
 	.wpswitch_gpio	= PM8921_GPIO_PM_TO_SYS(16),
 #endif
+#endif
 	.vreg_data	= &mmc_slot_vreg_data[SDCC3],
 	.pin_data	= &mmc_slot_pin_data[SDCC3],
 #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
+/*TODO: Insert right replacement for PM8038 */
+#ifndef MSM8930_PHASE_2
 	.status_gpio	= PM8921_GPIO_PM_TO_SYS(26),
 	.status_irq	= PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 26),
+#endif
 	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 #endif
 	.xpc_cap	= 1,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index cc020b5..d6c6ec8 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -81,7 +81,6 @@
 #include "devices.h"
 #include "devices-msm8x60.h"
 #include "spm.h"
-#include "board-8930.h"
 #include "pm.h"
 #include "cpuidle.h"
 #include "rpm_resources.h"
@@ -91,6 +90,7 @@
 #include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
+#include "board-8930.h"
 
 static struct platform_device msm_fm_platform_init = {
 	.name = "iris_fm",
@@ -428,7 +428,11 @@
 	.irq = MSM_GPIO_TO_INT(62),
 	.irq_base = TABLA_INTERRUPT_BASE,
 	.num_irqs = NR_TABLA_IRQS,
+
+/*TODO: Replace this with right PM8038 gpio */
+#ifndef MSM8930_PHASE_2
 	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+#endif
 	.micbias = {
 		.ldoh_v = TABLA_LDOH_2P85_V,
 		.cfilt1_mv = 1800,
@@ -457,7 +461,11 @@
 	.irq = MSM_GPIO_TO_INT(62),
 	.irq_base = TABLA_INTERRUPT_BASE,
 	.num_irqs = NR_TABLA_IRQS,
+
+/*TODO: Replace this with right PM8038 gpio */
+#ifndef MSM8930_PHASE_2
 	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+#endif
 	.micbias = {
 		.ldoh_v = TABLA_LDOH_2P85_V,
 		.cfilt1_mv = 1800,
@@ -785,21 +793,25 @@
 			pr_err("Unable to get mvs_otg_switch\n");
 			return;
 		}
-
+		/* TODO: Replace this with appropriate PM8038 alternative */
+#ifndef MSM8930_PHASE_2
 		rc = gpio_request(PM8921_GPIO_PM_TO_SYS(USB_5V_EN),
 						"usb_5v_en");
+#endif
 		if (rc < 0) {
 			pr_err("failed to request usb_5v_en gpio\n");
 			goto put_mvs_otg;
 		}
 
+		/* TODO: Replace this with appropriate PM8038 alternative */
+#ifndef MSM8930_PHASE_2
 		rc = gpio_direction_output(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 1);
 		if (rc) {
 			pr_err("%s: unable to set_direction for gpio [%d]\n",
 				__func__, PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
 			goto free_usb_5v_en;
 		}
-
+#endif
 		if (regulator_enable(mvs_otg_switch)) {
 			pr_err("unable to enable mvs_otg_switch\n");
 			goto err_ldo_gpio_set_dir;
@@ -809,10 +821,14 @@
 		return;
 	}
 	regulator_disable(mvs_otg_switch);
+
+/* TODO: Replace this with appropriate PM8038 alternative */
+#ifndef MSM8930_PHASE_2
 err_ldo_gpio_set_dir:
 	gpio_set_value(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 0);
 free_usb_5v_en:
 	gpio_free(PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
+#endif
 put_mvs_otg:
 	regulator_put(mvs_otg_switch);
 	vbus_is_on = false;
@@ -823,7 +839,7 @@
 	.otg_control		= OTG_PMIC_CONTROL,
 	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
 	.pclk_src_name		= "dfab_usb_hs_clk",
-	.pmic_id_irq		= PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
+	.pmic_id_irq		= PM8038_USB_ID_IN_IRQ(PM8038_IRQ_BASE),
 	.vbus_power		= msm_hsusb_vbus_power,
 	.power_budget		= 750,
 };
@@ -1025,8 +1041,13 @@
 	},
 };
 
+#/* TODO: Remove this once PM8038 physically becomes
+ * available.
+ */
+#ifndef MSM8930_PHASE_2
 #define PM_HAP_EN_GPIO		PM8921_GPIO_PM_TO_SYS(33)
 #define PM_HAP_LEN_GPIO		PM8921_GPIO_PM_TO_SYS(20)
+#endif
 
 static struct msm_xo_voter *xo_handle_d1;
 
@@ -1407,26 +1428,40 @@
 };
 
 static struct platform_device msm_device_saw_core0 = {
-	.name          = "saw-regulator",
-	.id            = 0,
+	.name	= "saw-regulator",
+	.id	= 0,
 	.dev	= {
+	/*
+	 * TODO: When physical 8930/PM8038 hardware becomes
+	 * available, replace msm_saw_regulator_pdata_s5
+	 * with 8930 saw regulator object.
+	 */
+#ifndef MSM8930_PHASE_2
 		.platform_data = &msm_saw_regulator_pdata_s5,
+#endif
 	},
 };
 
 static struct platform_device msm_device_saw_core1 = {
-	.name          = "saw-regulator",
-	.id            = 1,
+	.name	= "saw-regulator",
+	.id	= 1,
 	.dev	= {
+	/*
+	 * TODO: When physical 8930/PM8038 hardware becomes
+	 * available, replace msm_saw_regulator_pdata_s5
+	 * with 8930 saw regulator object.
+	 */
+#if     !defined(MSM8930_PHASE_2)
 		.platform_data = &msm_saw_regulator_pdata_s6,
+#endif
 	},
 };
 
 static struct tsens_platform_data msm_tsens_pdata  = {
-		.slope			= 910,
-		.tsens_factor		= 1000,
-		.hw_type		= MSM_8960,
-		.tsens_num_sensor	= 5,
+	.slope			= 910,
+	.tsens_factor		= 1000,
+	.hw_type		= MSM_8960,
+	.tsens_num_sensor	= 5,
 };
 
 static struct platform_device msm_tsens_device = {
@@ -1443,27 +1478,52 @@
 };
 #endif
 
-static struct platform_device msm8960_device_ext_5v_vreg __devinitdata = {
+static struct platform_device msm8930_device_ext_5v_vreg __devinitdata = {
 	.name	= GPIO_REGULATOR_DEV_NAME,
+/* TODO: Replace this with right MPP for 8038 */
+#ifndef MSM8930_PHASE_2
 	.id	= PM8921_MPP_PM_TO_SYS(7),
+#endif
 	.dev	= {
+	/*
+	 * TODO: When physical 8930/PM8038 hardware becomes
+	 * available, replace msm_gpio_regulator_pdata
+	 * with 8930 gpio regulator object.
+	 */
+#if     !defined(MSM8930_PHASE_2)
 		.platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+#endif
 	},
 };
 
-static struct platform_device msm8960_device_ext_l2_vreg __devinitdata = {
+static struct platform_device msm8930_device_ext_l2_vreg __devinitdata = {
 	.name	= GPIO_REGULATOR_DEV_NAME,
 	.id	= 91,
 	.dev	= {
+	 /*
+	 * TODO: When physical 8930/PM8038 hardware becomes
+	 * available, replace msm_gpio_regulator_pdata
+	 * with 8930 gpio regulator object.
+	 */
+#if     !defined(MSM8930_PHASE_2)
 		.platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_L2],
+#endif
 	},
 };
 
-static struct platform_device msm8960_device_rpm_regulator __devinitdata = {
+static struct platform_device msm8930_device_rpm_regulator __devinitdata = {
 	.name	= "rpm-regulator",
 	.id	= -1,
 	.dev	= {
+	/*
+	 * TODO: When physical 8930/PM8038 hardware becomes
+	 * available, replace msm_rpm_regulator_pdata
+	 * with 8930 rpm regulator object.
+	 */
+#if     !defined(MSM8930_PHASE_2)
+
 		.platform_data = &msm_rpm_regulator_pdata,
+#endif
 	},
 };
 
@@ -1493,9 +1553,9 @@
 	&msm_device_uart_dm6,
 	&msm_device_saw_core0,
 	&msm_device_saw_core1,
-	&msm8960_device_ext_5v_vreg,
-	&msm8960_device_ext_l2_vreg,
-	&msm8960_device_ssbi_pm8921,
+	&msm8930_device_ext_5v_vreg,
+	&msm8930_device_ext_l2_vreg,
+	&msm8960_device_ssbi_pmic,
 	&msm8960_device_qup_spi_gsbi1,
 	&msm8960_device_qup_i2c_gsbi3,
 	&msm8960_device_qup_i2c_gsbi4,
@@ -1895,7 +1955,7 @@
 	regulator_suppress_info_printing();
 	if (msm_xo_init())
 		pr_err("Failed to initialize XO votes\n");
-	platform_device_register(&msm8960_device_rpm_regulator);
+	platform_device_register(&msm8930_device_rpm_regulator);
 	msm_clock_init(&msm8960_clock_init_data);
 	msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
 	msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
@@ -1904,7 +1964,16 @@
 				&msm8960_qup_spi_gsbi1_pdata;
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
+	/*
+	 * TODO: When physical 8930/PM8038 hardware becomes
+	 * available, remove this block or add the config
+	 * option.
+	 */
+#ifndef MSM8930_PHASE_2
+	msm8960_init_pmic();
+#else
 	msm8930_init_pmic();
+#endif
 	msm8930_i2c_init();
 	msm8930_gfx_init();
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
@@ -1913,7 +1982,16 @@
 	platform_add_devices(msm_footswitch_devices,
 		msm_num_footswitch_devices);
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
-	msm8930_pm8921_gpio_mpp_init();
+	/*
+	 * TODO: When physical 8930/PM8038 hardware becomes
+	 * available, remove this block or add the config
+	 * option.
+	 */
+#ifndef MSM8930_PHASE_2
+	msm8960_pm8921_gpio_mpp_init();
+#else
+	msm8930_pm8038_gpio_mpp_init();
+#endif
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
 	msm8930_init_hsic();
 	msm8930_init_cam();
diff --git a/arch/arm/mach-msm/board-8930.h b/arch/arm/mach-msm/board-8930.h
index c413061..ec0b867 100644
--- a/arch/arm/mach-msm/board-8930.h
+++ b/arch/arm/mach-msm/board-8930.h
@@ -14,39 +14,59 @@
 #define __ARCH_ARM_MACH_MSM_BOARD_MSM8930_H
 
 #include <linux/regulator/gpio-regulator.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/pm8038.h>
 #include <linux/i2c/sx150x.h>
 #include <mach/irqs.h>
 #include <mach/rpm-regulator.h>
 
-/* Macros assume PMIC GPIOs and MPPs start at 1 */
+/*
+ * TODO: When physical 8930/PM8038 hardware becomes
+ * available, remove this block.
+ */
+#ifndef MSM8930_PHASE_2
+#include <linux/mfd/pm8xxx/pm8921.h>
 #define PM8921_GPIO_BASE		NR_GPIO_IRQS
 #define PM8921_GPIO_PM_TO_SYS(pm_gpio)	(pm_gpio - 1 + PM8921_GPIO_BASE)
 #define PM8921_MPP_BASE			(PM8921_GPIO_BASE + PM8921_NR_GPIOS)
 #define PM8921_MPP_PM_TO_SYS(pm_gpio)	(pm_gpio - 1 + PM8921_MPP_BASE)
-#define PM8921_IRQ_BASE			(NR_MSM_IRQS + NR_GPIO_IRQS)
+#endif
+
+/* Macros assume PMIC GPIOs and MPPs start at 1 */
+#define PM8038_GPIO_BASE		NR_GPIO_IRQS
+#define PM8038_GPIO_PM_TO_SYS(pm_gpio)	(pm_gpio - 1 + PM8038_GPIO_BASE)
+#define PM8038_MPP_BASE			(PM8038_GPIO_BASE + PM8038_NR_GPIOS)
+#define PM8038_MPP_PM_TO_SYS(pm_gpio)	(pm_gpio - 1 + PM8038_MPP_BASE)
+#define PM8038_IRQ_BASE			(NR_MSM_IRQS + NR_GPIO_IRQS)
+
+/*
+ * TODO: When physical 8930/PM8038 hardware becomes
+ * available, replace this block with 8930/pm8038 regulator
+ * declarations.
+ */
+#ifndef MSM8930_PHASE_2
+extern struct regulator_init_data msm_saw_regulator_pdata_s5;
+extern struct regulator_init_data msm_saw_regulator_pdata_s6;
 
 extern struct pm8921_regulator_platform_data
 	msm_pm8921_regulator_pdata[] __devinitdata;
 
 extern int msm_pm8921_regulator_pdata_len __devinitdata;
 
+extern struct gpio_regulator_platform_data
+	msm_gpio_regulator_pdata[] __devinitdata;
+
+extern struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata;
+#endif
+
 #define GPIO_VREG_ID_EXT_5V		0
 #define GPIO_VREG_ID_EXT_L2		1
 #define GPIO_VREG_ID_EXT_3P3V		2
 
-extern struct gpio_regulator_platform_data
-	msm_gpio_regulator_pdata[] __devinitdata;
-
-extern struct regulator_init_data msm_saw_regulator_pdata_s5;
-extern struct regulator_init_data msm_saw_regulator_pdata_s6;
-
-extern struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata;
 
 #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
 enum {
-	GPIO_EXPANDER_IRQ_BASE = (PM8921_IRQ_BASE + PM8921_NR_IRQS),
-	GPIO_EXPANDER_GPIO_BASE = (PM8921_MPP_BASE + PM8921_NR_MPPS),
+	GPIO_EXPANDER_IRQ_BASE = (PM8038_IRQ_BASE + PM8038_NR_IRQS),
+	GPIO_EXPANDER_GPIO_BASE = (PM8038_MPP_BASE + PM8038_NR_MPPS),
 	/* CAM Expander */
 	GPIO_CAM_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
 	GPIO_CAM_GP_STROBE_READY = GPIO_CAM_EXPANDER_BASE,
@@ -71,10 +91,21 @@
 void msm8930_init_cam(void);
 void msm8930_init_fb(void);
 void msm8930_init_pmic(void);
+
+/*
+ * TODO: When physical 8930/PM8038 hardware becomes
+ * available, remove this block or add the config
+ * option.
+ */
+#ifndef MSM8930_PHASE_2
+void msm8960_init_pmic(void);
+void msm8960_pm8921_gpio_mpp_init(void);
+#endif
+
 void msm8930_init_mmc(void);
 int msm8930_init_gpiomux(void);
 void msm8930_allocate_fb_region(void);
-void msm8930_pm8921_gpio_mpp_init(void);
+void msm8930_pm8038_gpio_mpp_init(void);
 
 #define PLATFORM_IS_CHARM25() \
 	(machine_is_msm8930_cdp() && \
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 9be65bb..ce260e1 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -243,6 +243,20 @@
 	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
+
+static struct gpiomux_setting hdmi_active_3_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+	.dir = GPIOMUX_IN,
+};
+
+static struct gpiomux_setting hdmi_active_4_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+	.dir = GPIOMUX_OUT_HIGH,
+};
 #endif
 
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
@@ -600,6 +614,20 @@
 			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
 		},
 	},
+		{
+		.gpio = 15,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_3_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
+	{
+		.gpio = 66,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &hdmi_active_4_cfg,
+			[GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+		},
+	},
 };
 #endif
 
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 44f7be6..5e1ea0d 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -529,7 +529,7 @@
 void __init msm8960_init_pmic(void)
 {
 	pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
-	msm8960_device_ssbi_pm8921.dev.platform_data =
+	msm8960_device_ssbi_pmic.dev.platform_data =
 				&msm8960_ssbi_pm8921_pdata;
 	pm8921_platform_data.num_regulators = msm_pm8921_regulator_pdata_len;
 
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 7bc3ca5..f3e4f20 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -449,9 +449,9 @@
 /* SAW regulator constraints */
 struct regulator_init_data msm_saw_regulator_pdata_s5 =
 	/*	      ID  vreg_name	       min_uV   max_uV */
-	SAW_VREG_INIT(S5, "8921_s5",	       950000, 1300000);
+	SAW_VREG_INIT(S5, "8921_s5",	       850000, 1300000);
 struct regulator_init_data msm_saw_regulator_pdata_s6 =
-	SAW_VREG_INIT(S6, "8921_s6",	       950000, 1300000);
+	SAW_VREG_INIT(S6, "8921_s6",	       850000, 1300000);
 
 /* PM8921 regulator constraints */
 struct pm8921_regulator_platform_data
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 2492a2e..fa607bf 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -814,7 +814,7 @@
 	}
 	regulator_disable(mvs_otg_switch);
 err_ldo_gpio_set_dir:
-	gpio_set_value(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 0);
+	gpio_set_value_cansleep(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 0);
 free_usb_5v_en:
 	gpio_free(PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
 put_mvs_otg:
@@ -964,7 +964,7 @@
 		.reg_base_addr = MSM_SAW0_BASE,
 		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -981,7 +981,7 @@
 		.reg_base_addr = MSM_SAW1_BASE,
 		.reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
-		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+		.reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0xB0,
 #if defined(CONFIG_MSM_AVS_HW)
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
 		.reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
@@ -1590,7 +1590,7 @@
 	&msm_device_saw_core1,
 	&msm8960_device_ext_5v_vreg,
 	&msm8960_device_ext_l2_vreg,
-	&msm8960_device_ssbi_pm8921,
+	&msm8960_device_ssbi_pmic,
 	&msm8960_device_qup_spi_gsbi1,
 	&msm8960_device_qup_i2c_gsbi3,
 	&msm8960_device_qup_i2c_gsbi4,
@@ -2154,6 +2154,8 @@
 			msm_otg_pdata.phy_init_seq =
 				liquid_v1_phy_init_seq;
 	}
+	msm_otg_pdata.swfi_latency =
+		msm_rpmrs_levels[0].latency_us;
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
 	if (machine_is_msm8960_liquid()) {
 		if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 5de5ea3..f369c6c 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -61,6 +61,15 @@
 #define BAHAMA_SLAVE_ID_QMEMBIST_ADDR   0x7B
 #define BAHAMA_SLAVE_ID_FM_REG 0x02
 #define FM_GPIO	83
+#define BT_PCM_BCLK_MODE  0x88
+#define BT_PCM_DIN_MODE   0x89
+#define BT_PCM_DOUT_MODE  0x8A
+#define BT_PCM_SYNC_MODE  0x8B
+#define FM_I2S_SD_MODE    0x8E
+#define FM_I2S_WS_MODE    0x8F
+#define FM_I2S_SCK_MODE   0x90
+#define I2C_PIN_CTL       0x15
+#define I2C_NORMAL        0x40
 
 enum {
 	GPIO_EXPANDER_IRQ_BASE	= NR_MSM_IRQS + NR_GPIO_IRQS,
@@ -125,6 +134,57 @@
 
 	/* FM Platform power and shutdown routines */
 #define FPGA_MSM_CNTRL_REG2 0x90008010
+static int switch_pcm_i2s_reg_mode(int mode)
+{
+	unsigned char reg = 0;
+	int rc = -1;
+	unsigned char set = I2C_PIN_CTL; /*SET PIN CTL mode*/
+	unsigned char unset = I2C_NORMAL; /* UNSET PIN CTL MODE*/
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+
+	if (mode == 0) {
+		/* as we need to switch path to FM we need to move
+		 BT AUX PCM lines to PIN CONTROL mode then move
+		 FM to normal mode.*/
+		for (reg = BT_PCM_BCLK_MODE; reg <= BT_PCM_SYNC_MODE; reg++) {
+			rc = marimba_write(&config, reg, &set, 1);
+			if (rc < 0) {
+				pr_err("pcm pinctl failed = %d", rc);
+				goto err_all;
+			}
+		}
+		for (reg = FM_I2S_SD_MODE; reg <= FM_I2S_SCK_MODE; reg++) {
+			rc = marimba_write(&config, reg, &unset, 1);
+			if (rc < 0) {
+				pr_err("i2s normal failed = %d", rc);
+				goto err_all;
+			}
+		}
+	} else {
+		/* as we need to switch path to AUXPCM we need to move
+		 FM I2S lines to PIN CONTROL mode then move
+		 BT AUX_PCM to normal mode.*/
+		for (reg = FM_I2S_SD_MODE; reg <= FM_I2S_SCK_MODE; reg++) {
+			rc = marimba_write(&config, reg, &set, 1);
+			if (rc < 0) {
+				pr_err("i2s pinctl failed = %d", rc);
+				goto err_all;
+			}
+		}
+		for (reg = BT_PCM_BCLK_MODE; reg <= BT_PCM_SYNC_MODE; reg++) {
+			rc = marimba_write(&config, reg, &unset, 1);
+			if (rc < 0) {
+				pr_err("pcm normal failed = %d", rc);
+				goto err_all;
+			}
+		}
+	}
+
+	return 0;
+
+err_all:
+	return rc;
+}
 
 static void config_pcm_i2s_mode(int mode)
 {
@@ -220,6 +280,12 @@
 		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
 			config_pcm_i2s_mode(0);
 		pr_err("%s mode = FM_I2S_ON", __func__);
+
+		rc = switch_pcm_i2s_reg_mode(0);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(fm_i2s_config_power_on);
 			pin++) {
 				rc = gpio_tlmm_config(
@@ -231,6 +297,11 @@
 			}
 	} else if (mode == FM_I2S_OFF) {
 		pr_err("%s mode = FM_I2S_OFF", __func__);
+		rc = switch_pcm_i2s_reg_mode(1);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(fm_i2s_config_power_off);
 			pin++) {
 				rc = gpio_tlmm_config(
@@ -251,6 +322,11 @@
 		if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
 			config_pcm_i2s_mode(1);
 		pr_err("%s mode =BT_PCM_ON", __func__);
+		rc = switch_pcm_i2s_reg_mode(1);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_on);
 			pin++) {
 				rc = gpio_tlmm_config(bt_config_pcm_on[pin],
@@ -260,6 +336,11 @@
 			}
 	} else if (mode == BT_PCM_OFF) {
 		pr_err("%s mode =BT_PCM_OFF", __func__);
+		rc = switch_pcm_i2s_reg_mode(0);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_off);
 			pin++) {
 				rc = gpio_tlmm_config(bt_config_pcm_off[pin],
@@ -1069,8 +1150,8 @@
 };
 
 #ifdef CONFIG_ARCH_MSM7X27A
-#define MSM_PMEM_MDP_SIZE       0x1900000
-#define MSM7x25A_MSM_PMEM_MDP_SIZE	0x1000000
+#define MSM_PMEM_MDP_SIZE       0x2300000
+#define MSM7x25A_MSM_PMEM_MDP_SIZE       0x1500000
 
 #define MSM_PMEM_ADSP_SIZE      0x1000000
 #define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 3038ff0..765f49e 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -22,6 +22,7 @@
 #include <linux/leds.h>
 #include <linux/pmic8058-othc.h>
 #include <linux/mfd/pmic8901.h>
+#include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/pmic8901-regulator.h>
 #include <linux/bootmem.h>
 #include <linux/msm_adc.h>
@@ -54,7 +55,6 @@
 #include <asm/setup.h>
 
 #include <mach/dma.h>
-#include <mach/mpp.h>
 #include <mach/board.h>
 #include <mach/irqs.h>
 #include <mach/msm_spi.h>
@@ -83,6 +83,7 @@
 #include <mach/rpm.h>
 #include <mach/rpm-regulator.h>
 #include <mach/restart.h>
+#include <mach/board-msm8660.h>
 
 #include "devices.h"
 #include "devices-msm8x60.h"
@@ -104,23 +105,6 @@
 #include <mach/ion.h>
 
 #define MSM_SHARED_RAM_PHYS 0x40000000
-
-/* Macros assume PMIC GPIOs start at 0 */
-#define PM8058_GPIO_BASE			NR_MSM_GPIOS
-#define PM8058_GPIO_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_GPIO_BASE)
-#define PM8058_GPIO_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_GPIO_BASE)
-#define PM8058_MPP_BASE			(PM8058_GPIO_BASE + PM8058_GPIOS)
-#define PM8058_MPP_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_MPP_BASE)
-#define PM8058_MPP_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_MPP_BASE)
-#define PM8058_IRQ_BASE				(NR_MSM_IRQS + NR_GPIO_IRQS)
-
-#define PM8901_GPIO_BASE			(PM8058_GPIO_BASE + \
-						PM8058_GPIOS + PM8058_MPPS)
-#define PM8901_GPIO_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8901_GPIO_BASE)
-#define PM8901_GPIO_SYS_TO_PM(sys_gpio)		(sys_gpio - PM901_GPIO_BASE)
-#define PM8901_IRQ_BASE				(PM8058_IRQ_BASE + \
-						NR_PMIC8058_IRQS)
-
 #define MDM2AP_SYNC 129
 
 #define GPIO_ETHERNET_RESET_N_DRAGON	30
@@ -150,7 +134,7 @@
 
 enum {
 	GPIO_EXPANDER_IRQ_BASE  = PM8901_IRQ_BASE + NR_PMIC8901_IRQS,
-	GPIO_EXPANDER_GPIO_BASE = PM8901_GPIO_BASE + PM8901_MPPS,
+	GPIO_EXPANDER_GPIO_BASE = PM8901_MPP_BASE + PM8901_MPPS,
 	/* CORE expander */
 	GPIO_CORE_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
 	GPIO_CLASS_D1_EN        = GPIO_CORE_EXPANDER_BASE,
@@ -273,7 +257,7 @@
 	struct pm8xxx_mpp_config_data	config;
 };
 
-#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+#define PM8058_MPP_INIT(_mpp, _type, _level, _control) \
 { \
 	.mpp	= PM8058_MPP_PM_TO_SYS(_mpp), \
 	.config	= { \
@@ -283,6 +267,16 @@
 	} \
 }
 
+#define PM8901_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+	.mpp	= PM8901_MPP_PM_TO_SYS(_mpp), \
+	.config	= { \
+		.type		= PM8XXX_MPP_TYPE_##_type, \
+		.level		= _level, \
+		.control	= PM8XXX_MPP_##_control, \
+	} \
+}
+
 /*
  * The UI_INTx_N lines are pmic gpio lines which connect i2c
  * gpio expanders to the pm8058.
@@ -1045,14 +1039,21 @@
 {
 	unsigned ret;
 
+	struct pm8xxx_mpp_config_data hsusb_phy_mpp = {
+		.type	= PM8XXX_MPP_TYPE_D_OUTPUT,
+		.level	= PM8901_MPP_DIG_LEVEL_L5,
+	};
+
 	if (init) {
-		ret = pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 1);
+		hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+		ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1),
+							&hsusb_phy_mpp);
 		if (ret < 0)
 			pr_err("%s:MPP2 configuration failed\n", __func__);
 	} else {
-		ret = pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 0);
+		hsusb_phy_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+		ret = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1),
+							&hsusb_phy_mpp);
 		if (ret < 0)
 			pr_err("%s:MPP2 un config failed\n", __func__);
 	}
@@ -4837,23 +4838,20 @@
 {
 	int rc, i;
 	struct pm8xxx_mpp_init_info xoadc_mpps[] = {
-		PM8XXX_MPP_INIT(XOADC_MPP_3, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
+		PM8058_MPP_INIT(XOADC_MPP_3, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_5, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH9,
+		PM8058_MPP_INIT(XOADC_MPP_5, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH9,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
+		PM8058_MPP_INIT(XOADC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
+		PM8058_MPP_INIT(XOADC_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
 							AOUT_CTRL_DISABLE),
-		PM8XXX_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
+		PM8058_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
 							AOUT_CTRL_DISABLE),
+		PM8901_MPP_INIT(XOADC_MPP_4, D_OUTPUT, PM8901_MPP_DIG_LEVEL_S4,
+							DOUT_CTRL_LOW),
 	};
 
-	rc = pm8901_mpp_config_digital_out(XOADC_MPP_4,
-			PM8901_MPP_DIG_LEVEL_S4, PM_MPP_DOUT_CTL_LOW);
-	if (rc)
-		pr_err("%s: Config mpp4 on pmic 8901 failed\n", __func__);
-
 	for (i = 0; i < ARRAY_SIZE(xoadc_mpps); i++) {
 		rc = pm8xxx_mpp_config(xoadc_mpps[i].mpp,
 					&xoadc_mpps[i].config);
@@ -4982,6 +4980,75 @@
 
 #endif /* CONFIG_MSM_SDIO_AL */
 
+#define GPIO_VREG_ID_EXT_5V		0
+
+static struct regulator_consumer_supply vreg_consumers_EXT_5V[] = {
+	REGULATOR_SUPPLY("ext_5v",	NULL),
+	REGULATOR_SUPPLY("8901_mpp0",	NULL),
+};
+
+#define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \
+	[GPIO_VREG_ID_##_id] = { \
+		.init_data = { \
+			.constraints = { \
+				.valid_ops_mask	= REGULATOR_CHANGE_STATUS, \
+			}, \
+			.num_consumer_supplies	= \
+					ARRAY_SIZE(vreg_consumers_##_id), \
+			.consumer_supplies	= vreg_consumers_##_id, \
+		}, \
+		.regulator_name	= _reg_name, \
+		.active_low	= _active_low, \
+		.gpio_label	= _gpio_label, \
+		.gpio		= _gpio, \
+	}
+
+/* GPIO regulator constraints */
+static struct gpio_regulator_platform_data msm_gpio_regulator_pdata[] = {
+	GPIO_VREG_INIT(EXT_5V, "ext_5v", "ext_5v_en",
+					PM8901_MPP_PM_TO_SYS(0), 0),
+};
+
+/* GPIO regulator */
+static struct platform_device msm8x60_8901_mpp_vreg __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= PM8901_MPP_PM_TO_SYS(0),
+	.dev	= {
+		.platform_data =
+			&msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+	},
+};
+
+static void __init pm8901_vreg_mpp0_init(void)
+{
+	int rc;
+
+	struct pm8xxx_mpp_init_info pm8901_vreg_mpp0 = {
+		.mpp	= PM8901_MPP_PM_TO_SYS(0),
+		.config =  {
+			.type	= PM8XXX_MPP_TYPE_D_OUTPUT,
+			.level	= PM8901_MPP_DIG_LEVEL_VPH,
+		},
+	};
+
+	/*
+	 * Set PMIC 8901 MPP0 active_high to 0 for surf and charm_surf. This
+	 * implies that the regulator connected to MPP0 is enabled when
+	 * MPP0 is low.
+	 */
+	if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion()) {
+		msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 1;
+		pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+	} else {
+		msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V].active_low = 0;
+		pm8901_vreg_mpp0.config.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+	}
+
+	rc = pm8xxx_mpp_config(pm8901_vreg_mpp0.mpp, &pm8901_vreg_mpp0.config);
+	if (rc)
+		pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+}
+
 static struct platform_device *charm_devices[] __initdata = {
 	&msm_charm_modem,
 #ifdef CONFIG_MSM_SDIO_AL
@@ -5309,9 +5376,9 @@
 #define EXT_CHG_VALID_MPP_2 11
 
 static struct pm8xxx_mpp_init_info isl_mpp[] = {
-	PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
+	PM8058_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
 		PM8058_MPP_DIG_LEVEL_S3, DIN_TO_INT),
-	PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
+	PM8058_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
 		PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM),
 };
 
@@ -6526,32 +6593,10 @@
 #ifdef CONFIG_PMIC8901
 
 #define PM8901_GPIO_INT           91
-
-static struct pm8901_gpio_platform_data pm8901_mpp_data = {
-	.gpio_base	= PM8901_GPIO_PM_TO_SYS(0),
-	.irq_base	= PM8901_MPP_IRQ(PM8901_IRQ_BASE, 0),
-};
-
-static struct resource pm8901_temp_alarm[] = {
-	{
-		.start = PM8901_TEMP_ALARM_IRQ(PM8901_IRQ_BASE),
-		.end = PM8901_TEMP_ALARM_IRQ(PM8901_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.start = PM8901_TEMP_HI_ALARM_IRQ(PM8901_IRQ_BASE),
-		.end = PM8901_TEMP_HI_ALARM_IRQ(PM8901_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
 /*
  * Consumer specific regulator names:
  *			 regulator name		consumer dev_name
  */
-static struct regulator_consumer_supply vreg_consumers_8901_MPP0[] = {
-	REGULATOR_SUPPLY("8901_mpp0",		NULL),
-};
 static struct regulator_consumer_supply vreg_consumers_8901_USB_OTG[] = {
 	REGULATOR_SUPPLY("8901_usb_otg",	NULL),
 };
@@ -6560,8 +6605,8 @@
 };
 
 #define PM8901_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
-			 _always_on, _active_high) \
-	[PM8901_VREG_ID_##_id] = { \
+			 _always_on) \
+	{ \
 		.init_data = { \
 			.constraints = { \
 				.valid_modes_mask = _modes, \
@@ -6576,53 +6621,33 @@
 			.num_consumer_supplies = \
 				ARRAY_SIZE(vreg_consumers_8901_##_id), \
 		}, \
-		.active_high = _active_high, \
+		.id = PM8901_VREG_ID_##_id, \
 	}
 
-#define PM8901_VREG_INIT_MPP(_id, _active_high) \
-	PM8901_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL, \
-			REGULATOR_CHANGE_STATUS, 0, 0, _active_high)
-
 #define PM8901_VREG_INIT_VS(_id) \
 	PM8901_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL, \
-			REGULATOR_CHANGE_STATUS, 0, 0, 0)
+			REGULATOR_CHANGE_STATUS, 0, 0)
 
-static struct pm8901_vreg_pdata pm8901_vreg_init_pdata[PM8901_VREG_MAX] = {
-	PM8901_VREG_INIT_MPP(MPP0, 1),
-
+static struct pm8901_vreg_pdata pm8901_vreg_init[] = {
 	PM8901_VREG_INIT_VS(USB_OTG),
 	PM8901_VREG_INIT_VS(HDMI_MVS),
 };
 
-#define PM8901_VREG(_id) { \
-	.name = "pm8901-regulator", \
-	.id = _id, \
-	.platform_data = &pm8901_vreg_init_pdata[_id], \
-	.pdata_size = sizeof(pm8901_vreg_init_pdata[_id]), \
-}
+static struct pm8xxx_irq_platform_data pm8901_irq_pdata = {
+	.irq_base		= PM8901_IRQ_BASE,
+	.devirq			= MSM_GPIO_TO_INT(PM8901_GPIO_INT),
+	.irq_trigger_flag	= IRQF_TRIGGER_LOW,
+};
 
-static struct mfd_cell pm8901_subdevs[] = {
-	{	.name = "pm8901-mpp",
-		.id		= -1,
-		.platform_data	= &pm8901_mpp_data,
-		.pdata_size      = sizeof(pm8901_mpp_data),
-	},
-	{	.name = "pm8901-tm",
-		.id		= -1,
-		.num_resources  = ARRAY_SIZE(pm8901_temp_alarm),
-		.resources      = pm8901_temp_alarm,
-	},
-	PM8901_VREG(PM8901_VREG_ID_MPP0),
-	PM8901_VREG(PM8901_VREG_ID_USB_OTG),
-	PM8901_VREG(PM8901_VREG_ID_HDMI_MVS),
+static struct pm8xxx_mpp_platform_data pm8901_mpp_pdata = {
+	.mpp_base		= PM8901_MPP_PM_TO_SYS(0),
 };
 
 static struct pm8901_platform_data pm8901_platform_data = {
-	.irq_base = PM8901_IRQ_BASE,
-	.irq = MSM_GPIO_TO_INT(PM8901_GPIO_INT),
-	.num_subdevs = ARRAY_SIZE(pm8901_subdevs),
-	.sub_devices = pm8901_subdevs,
-	.irq_trigger_flags = IRQF_TRIGGER_LOW,
+	.irq_pdata		= &pm8901_irq_pdata,
+	.mpp_pdata		= &pm8901_mpp_pdata,
+	.regulator_pdatas	= pm8901_vreg_init,
+	.num_regulators		= ARRAY_SIZE(pm8901_vreg_init),
 };
 
 static struct msm_ssbi_platform_data msm8x60_ssbi_pm8901_pdata __devinitdata = {
@@ -7106,15 +7131,6 @@
 		sx150x_data[SX150X_CORE_FLUID].irq_summary =
 			PM8058_GPIO_IRQ(PM8058_IRQ_BASE, UI_INT1_N);
 #endif
-	/*
-	 * Set PMIC 8901 MPP0 active_high to 0 for surf and charm_surf. This
-	 * implies that the regulator connected to MPP0 is enabled when
-	 * MPP0 is low.
-	 */
-	if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion())
-		pm8901_vreg_init_pdata[PM8901_VREG_ID_MPP0].active_high = 0;
-	else
-		pm8901_vreg_init_pdata[PM8901_VREG_ID_MPP0].active_high = 1;
 #endif
 }
 
@@ -9905,7 +9921,13 @@
 static void __init msm8x60_init(struct msm_board_data *board_data)
 {
 	uint32_t soc_platform_version;
-
+#ifdef CONFIG_USB_EHCI_MSM_72K
+	struct pm8xxx_mpp_config_data hsusb_phy_mpp = {
+		.type		= PM8XXX_MPP_TYPE_D_OUTPUT,
+		.level		= PM8901_MPP_DIG_LEVEL_L5,
+		.control	= PM8XXX_MPP_DOUT_CTRL_HIGH,
+	};
+#endif
 	pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
 
 	/*
@@ -10057,16 +10079,18 @@
 		}
 #endif
 
+	pm8901_vreg_mpp0_init();
+
+	platform_device_register(&msm8x60_8901_mpp_vreg);
+
 #ifdef CONFIG_USB_EHCI_MSM_72K
 	/*
 	 * Drive MPP2 pin HIGH for PHY to generate ID interrupts on 8660
 	 * fluid
 	 */
-	if (machine_is_msm8x60_fluid()) {
-		pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 1);
-	}
-		msm_add_host(0, &msm_usb_host_pdata);
+	if (machine_is_msm8x60_fluid())
+		pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(1), &hsusb_phy_mpp);
+	msm_add_host(0, &msm_usb_host_pdata);
 #endif
 
 #ifdef CONFIG_SND_SOC_MSM8660_APQ
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index ad803f8..8c251ba 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -564,6 +564,7 @@
 	.memtype = MEMTYPE_EBI1,
 	.enable_ion = 0,
 #endif
+	.disable_dmx = 0,
 };
 
 struct platform_device msm_device_vidc = {
@@ -1286,7 +1287,7 @@
 };
 #endif
 
-static struct resource resources_ssbi_pm8921[] = {
+static struct resource resources_ssbi_pmic[] = {
 	{
 		.start  = MSM_PMIC1_SSBI_CMD_PHYS,
 		.end    = MSM_PMIC1_SSBI_CMD_PHYS + MSM_PMIC_SSBI_SIZE - 1,
@@ -1294,11 +1295,11 @@
 	},
 };
 
-struct platform_device msm8960_device_ssbi_pm8921 = {
+struct platform_device msm8960_device_ssbi_pmic = {
 	.name           = "msm_ssbi",
 	.id             = 0,
-	.resource       = resources_ssbi_pm8921,
-	.num_resources  = ARRAY_SIZE(resources_ssbi_pm8921),
+	.resource       = resources_ssbi_pmic,
+	.num_resources  = ARRAY_SIZE(resources_ssbi_pmic),
 };
 
 static struct resource resources_qup_spi_gsbi1[] = {
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 41136d2..2c21f57 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -790,7 +790,8 @@
 
 struct msm_vidc_platform_data vidc_platform_data = {
 	.memtype = MEMTYPE_EBI0,
-	.enable_ion = 0
+	.enable_ion = 0,
+	.disable_dmx = 0
 };
 
 struct platform_device msm_device_vidc_720p = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index b9ff604..72fdcf7 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -2129,6 +2129,7 @@
 	.memtype = MEMTYPE_SMI_KERNEL,
 	.enable_ion = 0,
 #endif
+	.disable_dmx = 0
 };
 
 struct platform_device msm_device_vidc = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 1ba63c9..2fac2ef 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -51,7 +51,7 @@
 
 extern struct platform_device msm8960_device_uart_gsbi2;
 extern struct platform_device msm8960_device_uart_gsbi5;
-extern struct platform_device msm8960_device_ssbi_pm8921;
+extern struct platform_device msm8960_device_ssbi_pmic;
 extern struct platform_device msm8960_device_qup_i2c_gsbi3;
 extern struct platform_device msm8960_device_qup_i2c_gsbi4;
 extern struct platform_device msm8960_device_qup_i2c_gsbi10;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index a8e2449..5006419 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -151,21 +151,21 @@
 	/* Make sure required clocks are on at the correct rates. */
 	rc = setup_clocks(fs);
 	if (rc)
-		goto out;
+		return rc;
 
 	/* Un-halt all bus ports in the power domain. */
 	if (fs->bus_port1) {
 		rc = msm_bus_axi_portunhalt(fs->bus_port1);
 		if (rc) {
 			pr_err("%s: Port 1 unhalt failed.\n", __func__);
-			goto out;
+			goto err;
 		}
 	}
 	if (fs->bus_port2) {
 		rc = msm_bus_axi_portunhalt(fs->bus_port2);
 		if (rc) {
 			pr_err("%s: Port 2 unhalt failed.\n", __func__);
-			goto out;
+			goto err_port2_halt;
 		}
 	}
 
@@ -209,7 +209,12 @@
 	restore_clocks(fs);
 
 	fs->is_enabled = true;
-out:
+	return 0;
+
+err_port2_halt:
+	msm_bus_axi_porthalt(fs->bus_port1);
+err:
+	restore_clocks(fs);
 	return rc;
 }
 
@@ -226,14 +231,14 @@
 	/* Make sure required clocks are on at the correct rates. */
 	rc = setup_clocks(fs);
 	if (rc)
-		goto out;
+		return rc;
 
 	/* Halt all bus ports in the power domain. */
 	if (fs->bus_port1) {
 		rc = msm_bus_axi_porthalt(fs->bus_port1);
 		if (rc) {
 			pr_err("%s: Port 1 halt failed.\n", __func__);
-			goto out;
+			goto err;
 		}
 	}
 	if (fs->bus_port2) {
@@ -275,12 +280,12 @@
 	writel_relaxed(regval, fs->gfs_ctl_reg);
 
 	fs->is_enabled = false;
-
-	return rc;
+	return 0;
 
 err_port2_halt:
 	msm_bus_axi_portunhalt(fs->bus_port1);
-out:
+err:
+	restore_clocks(fs);
 	return rc;
 }
 
@@ -301,14 +306,14 @@
 	/* Make sure required clocks are on at the correct rates. */
 	rc = setup_clocks(fs);
 	if (rc)
-		goto out;
+		return rc;
 
 	/* Un-halt all bus ports in the power domain. */
 	if (fs->bus_port1) {
 		rc = msm_bus_axi_portunhalt(fs->bus_port1);
 		if (rc) {
 			pr_err("%s: Port 1 unhalt failed.\n", __func__);
-			goto out;
+			goto err;
 		}
 	}
 
@@ -351,7 +356,10 @@
 	restore_clocks(fs);
 
 	fs->is_enabled = true;
-out:
+	return 0;
+
+err:
+	restore_clocks(fs);
 	return rc;
 }
 
@@ -368,14 +376,14 @@
 	/* Make sure required clocks are on at the correct rates. */
 	rc = setup_clocks(fs);
 	if (rc)
-		goto out;
+		return rc;
 
 	/* Halt all bus ports in the power domain. */
 	if (fs->bus_port1) {
 		rc = msm_bus_axi_porthalt(fs->bus_port1);
 		if (rc) {
 			pr_err("%s: Port 1 halt failed.\n", __func__);
-			goto out;
+			goto err;
 		}
 	}
 
@@ -411,8 +419,10 @@
 	restore_clocks(fs);
 
 	fs->is_enabled = false;
+	return 0;
 
-out:
+err:
+	restore_clocks(fs);
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/include/mach/board-msm8660.h b/arch/arm/mach-msm/include/mach/board-msm8660.h
new file mode 100644
index 0000000..b07cc62
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/board-msm8660.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_BOARD_MSM8660_H
+#define __ARCH_ARM_MACH_MSM_BOARD_MSM8660_H
+
+#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pmic8901.h>
+#include <mach/irqs.h>
+
+/* Macros assume PMIC GPIOs start at 0 */
+#define PM8058_GPIO_BASE			NR_MSM_GPIOS
+#define PM8058_GPIO_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_GPIO_BASE)
+#define PM8058_GPIO_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_GPIO_BASE)
+#define PM8058_MPP_BASE			(PM8058_GPIO_BASE + PM8058_GPIOS)
+#define PM8058_MPP_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8058_MPP_BASE)
+#define PM8058_MPP_SYS_TO_PM(sys_gpio)		(sys_gpio - PM8058_MPP_BASE)
+#define PM8058_IRQ_BASE				(NR_MSM_IRQS + NR_GPIO_IRQS)
+
+#define PM8901_MPP_BASE				(PM8058_GPIO_BASE + \
+						PM8058_GPIOS + PM8058_MPPS)
+#define PM8901_MPP_PM_TO_SYS(pm_gpio)		(pm_gpio + PM8901_MPP_BASE)
+#define PM8901_MPP_SYS_TO_PM(sys_gpio)		(sys_gpio - PM901_MPP_BASE)
+#define PM8901_IRQ_BASE				(PM8058_IRQ_BASE + \
+						NR_PMIC8058_IRQS)
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 2116ee7..06a389e 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -405,6 +405,7 @@
 struct msm_vidc_platform_data {
 	int memtype;
 	u32 enable_ion;
+	int disable_dmx;
 #ifdef CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *vidc_bus_client_pdata;
 #endif
diff --git a/arch/arm/mach-msm/memory_topology.c b/arch/arm/mach-msm/memory_topology.c
index 7a75bc1..5854a23 100644
--- a/arch/arm/mach-msm/memory_topology.c
+++ b/arch/arm/mach-msm/memory_topology.c
@@ -113,7 +113,7 @@
 
 static int switch_memory_state(int id, int new_state)
 {
-	int mask;
+	int mask = 0;
 	int power_down_masks[MAX_NR_REGIONS] = { 0xFFFFFF00, 0xFFFF00FF,
 						0xFF00FFFF, 0x00FFFFFF };
 	int self_refresh_masks[MAX_NR_REGIONS] = { 0xFFFFFFF0, 0xFFFFFF0F,
diff --git a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
index 135dd03..11687ac 100644
--- a/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
+++ b/arch/arm/mach-msm/qdsp6v2/board-msm8x60-audio.c
@@ -17,19 +17,16 @@
 #include <linux/delay.h>
 #include <linux/debugfs.h>
 #include <linux/mfd/pmic8058.h>
-#include <linux/pmic8058-othc.h>
 #include <linux/mfd/pmic8901.h>
 #include <linux/mfd/msm-adie-codec.h>
-#include <linux/regulator/pmic8058-regulator.h>
-#include <linux/regulator/pmic8901-regulator.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
 
 #include <mach/qdsp6v2/audio_dev_ctl.h>
-#include <mach/mpp.h>
 #include <sound/apr_audio.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
+#include <mach/board-msm8660.h>
 
 #include "snddev_icodec.h"
 #include "snddev_ecodec.h"
@@ -266,10 +263,15 @@
 {
 	int rc;
 
-	if (enable) {
-		rc = pm8901_mpp_config_digital_out(PM8901_MPP_3,
-			PM8901_MPP_DIG_LEVEL_MSMIO, 1);
+	struct pm8xxx_mpp_config_data class_d0_mpp = {
+		.type		= PM8XXX_MPP_TYPE_D_OUTPUT,
+		.level		= PM8901_MPP_DIG_LEVEL_MSMIO,
+	};
 
+	if (enable) {
+		class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_HIGH;
+		rc = pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+							&class_d0_mpp);
 		if (rc) {
 			pr_err("%s: CLASS_D0_EN failed\n", __func__);
 			return rc;
@@ -280,18 +282,20 @@
 		if (rc) {
 			pr_err("%s: spkr pamp gpio pm8901 mpp3 request"
 			"failed\n", __func__);
-			pm8901_mpp_config_digital_out(PM8901_MPP_3,
-			PM8901_MPP_DIG_LEVEL_MSMIO, 0);
+			class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+			pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+						&class_d0_mpp);
 			return rc;
 		}
 
 		gpio_direction_output(SNDDEV_GPIO_CLASS_D0_EN, 1);
-		gpio_set_value(SNDDEV_GPIO_CLASS_D0_EN, 1);
+		gpio_set_value_cansleep(SNDDEV_GPIO_CLASS_D0_EN, 1);
 
 	} else {
-		pm8901_mpp_config_digital_out(PM8901_MPP_3,
-		PM8901_MPP_DIG_LEVEL_MSMIO, 0);
-		gpio_set_value(SNDDEV_GPIO_CLASS_D0_EN, 0);
+		class_d0_mpp.control = PM8XXX_MPP_DOUT_CTRL_LOW;
+		pm8xxx_mpp_config(PM8901_MPP_PM_TO_SYS(PM8901_MPP_3),
+						&class_d0_mpp);
+		gpio_set_value_cansleep(SNDDEV_GPIO_CLASS_D0_EN, 0);
 		gpio_free(SNDDEV_GPIO_CLASS_D0_EN);
 	}
 	return 0;
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 18b7334..af92d22 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -17,6 +17,8 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/wcnss_wlan.h>
 #include <mach/irqs.h>
 #include <mach/scm.h>
 #include <mach/subsystem_restart.h>
@@ -79,14 +81,32 @@
 /* Subsystem handlers */
 static int riva_shutdown(const struct subsys_data *subsys)
 {
+	struct platform_device *pdev = wcnss_get_platform_device();
+	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+	int    ret = -1;
+
 	pil_force_shutdown("wcnss");
-	return 0;
+
+	/* proxy vote on behalf of Riva */
+	if (pdev && pwlanconfig)
+		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
+					WCNSS_WLAN_SWITCH_OFF);
+	return ret;
 }
 
 static int riva_powerup(const struct subsys_data *subsys)
 {
-	pil_force_boot("wcnss");
-	return 0;
+	struct platform_device *pdev = wcnss_get_platform_device();
+	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+	int    ret = -1;
+
+	if (pdev && pwlanconfig)
+		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
+					WCNSS_WLAN_SWITCH_ON);
+	if (!ret)
+		pil_force_boot("wcnss");
+
+	return ret;
 }
 
 /* RAM segments for Riva SS;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 58c9b9a..c8555cd 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -503,9 +503,11 @@
 	} else {
 		if (len > 0) {
 			if (entry.client_id == MODEM_PROC && driver->ch) {
-				if ((cpu_is_msm8960() || cpu_is_msm8930()) &&
+				if ((cpu_is_msm8960() || cpu_is_msm8930() ||
+					cpu_is_msm9615()) &&
 					 (int)(*(char *)buf) == MODE_CMD)
-					if ((int)(*(char *)(buf+1)) == RESET_ID)
+					if ((int)(*(char *)(buf+1)) ==
+						RESET_ID)
 						return;
 				smd_write(driver->ch, buf, len);
 			} else if (entry.client_id == QDSP_PROC &&
@@ -542,7 +544,8 @@
 	temp += 2;
 	data_type = APPS_DATA;
 	/* Dont send any command other than mode reset */
-	if ((cpu_is_msm8960() || cpu_is_msm8930()) && cmd_code == MODE_CMD) {
+	if ((cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615()) &&
+		cmd_code == MODE_CMD) {
 		if (subsys_id != RESET_ID)
 			data_type = MODEM_DATA;
 	}
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index e659df5..1428315 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1168,6 +1168,7 @@
 		vma->vm_private_data = NULL;
 		return;
 	}
+	ion_handle_get(handle);
 	mutex_lock(&buffer->lock);
 	buffer->umap_cnt++;
 	mutex_unlock(&buffer->lock);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index eb0c828..8a65df4 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1374,19 +1374,6 @@
 		cal_req);
 }
 
-static int hci_fm_set_cal_req_dc(struct radio_hci_dev *hdev,
-		unsigned long param)
-{
-	u16 opcode = 0;
-	struct hci_fm_set_cal_req_dc *cal_req =
-		(struct hci_fm_set_cal_req_dc *)param;
-
-	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
-		HCI_OCF_FM_SET_CALIBRATION);
-	return radio_hci_send_cmd(hdev, opcode, sizeof(*cal_req),
-		cal_req);
-}
-
 static int hci_fm_do_cal_req(struct radio_hci_dev *hdev,
 		unsigned long param)
 {
@@ -1785,12 +1772,12 @@
 	if (rsp.mode == PROCS_CALIB_MODE) {
 		memcpy(&rsp.data[0], &skb->data[CALIB_DATA_OFSET],
 				PROCS_CALIB_SIZE);
-	} else if (rsp.mode == DC_CALIB_MODE) {
-		memcpy(&rsp.data[PROCS_CALIB_SIZE],
-			&skb->data[CALIB_DATA_OFSET], DC_CALIB_SIZE);
-		iris_q_evt_data(radio, rsp.data, (PROCS_CALIB_SIZE +
-				DC_CALIB_SIZE), IRIS_BUF_CAL_DATA);
+	iris_q_evt_data(radio, rsp.data, PROCS_CALIB_SIZE,
+					IRIS_BUF_CAL_DATA);
+	} else {
+		return;
 	}
+
 	radio_hci_req_complete(hdev, rsp.status);
 }
 static inline void hci_cmd_complete_event(struct radio_hci_dev *hdev,
@@ -1911,17 +1898,10 @@
 		struct sk_buff *skb)
 {
 	int i;
-	int len;
-
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	struct hci_fm_station_rsp *rsp;
 
-	len = sizeof(struct hci_fm_station_rsp);
-	rsp = (struct hci_fm_station_rsp *)skb_pull(skb, len);
-	if (rsp == NULL)
-		return;
-	memcpy(&radio->fm_st_rsp.station_rsp, rsp, len);
-
+	memcpy(&radio->fm_st_rsp.station_rsp, &skb->data[0],
+				sizeof(struct hci_ev_tune_status));
 	iris_q_event(radio, IRIS_EVT_TUNE_SUCC);
 
 	for (i = 0; i < IRIS_BUF_MAX; i++) {
@@ -2400,13 +2380,6 @@
 		FMDERR("Do Process calibration failed %x", retval);
 		return retval;
 	}
-	cal_mode = DC_CALIB_MODE;
-	retval = radio_hci_request(radio->fm_hdev, hci_fm_do_cal_req,
-		(unsigned long)cal_mode, RADIO_HCI_TIMEOUT);
-	if (retval < 0) {
-		FMDERR("Do DC calibration failed %x", retval);
-		return retval;
-	}
 	retval = hci_cmd(HCI_FM_DISABLE_RECV_CMD,
 			radio->fm_hdev);
 	if (retval < 0)
@@ -2568,7 +2541,6 @@
 	struct hci_fm_tx_rt tx_rt;
 	struct hci_fm_def_data_wr_req default_data;
 	struct hci_fm_set_cal_req_proc proc_cal_req;
-	struct hci_fm_set_cal_req_dc dc_cal_req;
 
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 	char *data = NULL;
@@ -2624,7 +2596,7 @@
 	case V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION:
 		data = (ctrl->controls[0]).string;
 		bytes_to_copy = (ctrl->controls[0]).size;
-		if (bytes_to_copy < (PROCS_CALIB_SIZE + DC_CALIB_SIZE)) {
+		if (bytes_to_copy < PROCS_CALIB_SIZE) {
 			FMDERR("data is less than required size");
 			return -EFAULT;
 		}
@@ -2639,18 +2611,7 @@
 				 RADIO_HCI_TIMEOUT);
 		if (retval < 0) {
 			FMDERR("Set Process calibration failed %d", retval);
-			return retval;
 		}
-		memset(dc_cal_req.data, 0, DC_CALIB_SIZE);
-		if (copy_from_user(&dc_cal_req.data[0], &data[PROCS_CALIB_SIZE],
-				sizeof(dc_cal_req.data)))
-				return -EFAULT;
-		dc_cal_req.mode = DC_CALIB_MODE;
-		retval = radio_hci_request(radio->fm_hdev,
-				hci_fm_set_cal_req_dc,
-				(unsigned long)&dc_cal_req, RADIO_HCI_TIMEOUT);
-		if (retval < 0)
-			FMDERR("Set DC calibration failed %d", retval);
 		break;
 	default:
 		FMDBG("Shouldn't reach here\n");
diff --git a/drivers/mfd/pmic8901.c b/drivers/mfd/pmic8901.c
index 3d87f0b..9e8786e 100644
--- a/drivers/mfd/pmic8901.c
+++ b/drivers/mfd/pmic8901.c
@@ -11,51 +11,25 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/ratelimit.h>
-#include <linux/gpio.h>
+#include <linux/delay.h>
 #include <linux/mfd/core.h>
 #include <linux/msm_ssbi.h>
 #include <linux/mfd/pmic8901.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
+#include <linux/mfd/pm8xxx/core.h>
 
 /* PMIC8901 Revision */
-#define SSBI_REG_REV			0x002  /* PMIC4 revision */
+#define PM8901_REG_REV			0x002
+#define PM8901_VERSION_MASK		0xF0
+#define PM8901_REVISION_MASK		0x0F
+#define PM8901_VERSION_VALUE		0xF0
 
-/* PMIC8901 IRQ */
-#define	SSBI_REG_ADDR_IRQ_BASE		0xD5
+#define REG_IRQ_BASE			0xD5
+#define REG_MPP_BASE			0x27
 
-#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
-#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
-#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
-#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
-#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
-
-#define	PM8901_IRQF_LVL_SEL		0x01	/* level select */
-#define	PM8901_IRQF_MASK_FE		0x02	/* mask falling edge */
-#define	PM8901_IRQF_MASK_RE		0x04	/* mask rising edge */
-#define	PM8901_IRQF_CLR			0x08	/* clear interrupt */
-#define	PM8901_IRQF_BITS_MASK		0x70
-#define	PM8901_IRQF_BITS_SHIFT		4
-#define	PM8901_IRQF_WRITE		0x80
-
-#define	PM8901_IRQF_MASK_ALL		(PM8901_IRQF_MASK_FE | \
-					PM8901_IRQF_MASK_RE)
-#define PM8901_IRQF_W_C_M		(PM8901_IRQF_WRITE |	\
-					PM8901_IRQF_CLR |	\
-					PM8901_IRQF_MASK_ALL)
-
-#define	MAX_PM_IRQ			72
-#define	MAX_PM_BLOCKS			(MAX_PM_IRQ / 8 + 1)
-#define	MAX_PM_MASTERS			(MAX_PM_BLOCKS / 8 + 1)
-
-#define MPP_IRQ_BLOCK			1
+#define REG_TEMP_ALRM_CTRL		0x23
+#define REG_TEMP_ALRM_PWM		0x24
 
 /* FTS regulator PMR registers */
 #define SSBI_REG_ADDR_S1_PMR		(0xA7)
@@ -70,47 +44,24 @@
 #define DELAY_AFTER_REG_DISABLE_MS	4
 #define DELAY_BEFORE_SHUTDOWN_MS	8
 
+#define SINGLE_IRQ_RESOURCE(_name, _irq) \
+{ \
+	.name	= _name, \
+	.start	= _irq, \
+	.end	= _irq, \
+	.flags	= IORESOURCE_IRQ, \
+}
+
 struct pm8901_chip {
 	struct pm8901_platform_data	pdata;
 	struct device			*dev;
-
-	u8	irqs_allowed[MAX_PM_BLOCKS];
-	u8	blocks_allowed[MAX_PM_MASTERS];
-	u8	masters_allowed;
-	int	pm_max_irq;
-	int	pm_max_blocks;
-	int	pm_max_masters;
-
-	u8	config[MAX_PM_IRQ];
-	u8	wake_enable[MAX_PM_IRQ];
-	u16	count_wakeable;
-
-	u8	revision;
-
-	spinlock_t	pm_lock;
+	struct pm_irq_chip		*irq_chip;
+	struct mfd_cell			*mfd_regulators;
+	u8				revision;
 };
 
-#if defined(CONFIG_DEBUG_FS)
-struct pm8901_dbg_device {
-	struct mutex		dbg_mutex;
-	struct pm8901_chip	*pm_chip;
-	struct dentry		*dent;
-	int			addr;
-};
-
-static struct pm8901_dbg_device *pmic_dbg_device;
-#endif
-
 static struct pm8901_chip *pmic_chip;
 
-/* Helper Functions */
-DEFINE_RATELIMIT_STATE(pm8901_msg_ratelimit, 60 * HZ, 10);
-
-static inline int pm8901_can_print(void)
-{
-	return __ratelimit(&pm8901_msg_ratelimit);
-}
-
 static inline int
 ssbi_read(struct device *dev, u16 addr, u8 *buf, size_t len)
 {
@@ -123,80 +74,6 @@
 	return msm_ssbi_write(dev->parent, addr, buf, len);
 }
 
-/* External APIs */
-int pm8901_rev(struct pm8901_chip *chip)
-{
-	if (chip == NULL) {
-		if (pmic_chip != NULL)
-			return pmic_chip->revision;
-		else
-			return -EINVAL;
-	}
-
-	return chip->revision;
-}
-EXPORT_SYMBOL(pm8901_rev);
-
-int pm8901_read(struct pm8901_chip *chip, u16 addr, u8 *values,
-		unsigned int len)
-{
-	if (chip == NULL)
-		return -EINVAL;
-
-	return ssbi_read(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8901_read);
-
-int pm8901_write(struct pm8901_chip *chip, u16 addr, u8 *values,
-		 unsigned int len)
-{
-	if (chip == NULL)
-		return -EINVAL;
-
-	return ssbi_write(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8901_write);
-
-int pm8901_irq_get_rt_status(struct pm8901_chip *chip, int irq)
-{
-	int     rc;
-	u8      block, bits, bit;
-	unsigned long   irqsave;
-
-	if (chip == NULL || irq < chip->pdata.irq_base ||
-			irq >= chip->pdata.irq_base + MAX_PM_IRQ)
-		return -EINVAL;
-
-	irq -= chip->pdata.irq_base;
-
-	block = irq / 8;
-	bit = irq % 8;
-
-	spin_lock_irqsave(&chip->pm_lock, irqsave);
-
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
-				__func__, rc);
-		goto bail_out;
-	}
-
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
-				__func__, rc);
-		goto bail_out;
-	}
-
-	rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
-	spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-
-	return rc;
-}
-EXPORT_SYMBOL(pm8901_irq_get_rt_status);
-
 int pm8901_reset_pwr_off(int reset)
 {
 	int rc = 0, i;
@@ -240,673 +117,283 @@
 }
 EXPORT_SYMBOL(pm8901_reset_pwr_off);
 
-/* Internal functions */
-static inline int
-pm8901_config_irq(struct pm8901_chip *chip, u8 *bp, u8 *cp)
+static int pm8901_readb(const struct device *dev, u16 addr, u8 *val)
 {
-	int	rc;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
-	if (rc) {
-		pr_err("%s: ssbi_write: rc=%d (Select block)\n",
-			__func__, rc);
-		goto bail_out;
-	}
-
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp, 1);
-	if (rc)
-		pr_err("%s: ssbi_write: rc=%d (Configure IRQ)\n",
-			__func__, rc);
-
-bail_out:
-	return rc;
+	return msm_ssbi_read(pmic->dev->parent, addr, val, 1);
 }
 
-static void pm8901_irq_mask(struct irq_data *d)
+static int pm8901_writeb(const struct device *dev, u16 addr, u8 val)
 {
-	int	master, irq_bit;
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-	master = block / 8;
-	irq_bit = irq % 8;
-
-	chip->irqs_allowed[block] &= ~(1 << irq_bit);
-	if (!chip->irqs_allowed[block]) {
-		chip->blocks_allowed[master] &= ~(1 << (block % 8));
-
-		if (!chip->blocks_allowed[master])
-			chip->masters_allowed &= ~(1 << master);
-	}
-
-	config = PM8901_IRQF_WRITE | chip->config[irq] |
-		PM8901_IRQF_MASK_FE | PM8901_IRQF_MASK_RE;
-	pm8901_config_irq(chip, &block, &config);
+	return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
 }
 
-static void pm8901_irq_unmask(struct irq_data *d)
+static int pm8901_read_buf(const struct device *dev, u16 addr, u8 *buf,
+								int cnt)
 {
-	int	master, irq_bit;
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config, old_irqs_allowed, old_blocks_allowed;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-	master = block / 8;
-	irq_bit = irq % 8;
-
-	old_irqs_allowed = chip->irqs_allowed[block];
-	chip->irqs_allowed[block] |= 1 << irq_bit;
-	if (!old_irqs_allowed) {
-		master = block / 8;
-
-		old_blocks_allowed = chip->blocks_allowed[master];
-		chip->blocks_allowed[master] |= 1 << (block % 8);
-
-		if (!old_blocks_allowed)
-			chip->masters_allowed |= 1 << master;
-	}
-
-	config = PM8901_IRQF_WRITE | chip->config[irq];
-	pm8901_config_irq(chip, &block, &config);
+	return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
 }
 
-static void pm8901_irq_ack(struct irq_data *d)
+static int pm8901_write_buf(const struct device *dev, u16 addr, u8 *buf,
+								int cnt)
 {
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-
-	config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
-	pm8901_config_irq(chip, &block, &config);
+	return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
 }
 
-static int pm8901_irq_set_type(struct irq_data *d, unsigned int flow_type)
+static int pm8901_read_irq_stat(const struct device *dev, int irq)
 {
-	int	master, irq_bit;
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	u8	block, config;
-	unsigned int irq = d->irq;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	if (irq > chip->pm_max_irq) {
-		chip->pm_max_irq = irq;
-		chip->pm_max_blocks =
-			chip->pm_max_irq / 8 + 1;
-		chip->pm_max_masters =
-			chip->pm_max_blocks / 8 + 1;
-	}
-	block = irq / 8;
-	master = block / 8;
-	irq_bit = irq % 8;
-
-	chip->config[irq] = (irq_bit << PM8901_IRQF_BITS_SHIFT) |
-			PM8901_IRQF_MASK_RE | PM8901_IRQF_MASK_FE;
-	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		if (flow_type & IRQF_TRIGGER_RISING)
-			chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
-		if (flow_type & IRQF_TRIGGER_FALLING)
-			chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
-	} else {
-		chip->config[irq] |= PM8901_IRQF_LVL_SEL;
-
-		if (flow_type & IRQF_TRIGGER_HIGH)
-			chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
-		else
-			chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
-	}
-
-	config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
-	return pm8901_config_irq(chip, &block, &config);
-}
-
-static int pm8901_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-	struct	pm8901_chip *chip = irq_data_get_irq_handler_data(d);
-	unsigned int irq = d->irq;
-
-	irq -= chip->pdata.irq_base;
-	if (on) {
-		if (!chip->wake_enable[irq]) {
-			chip->wake_enable[irq] = 1;
-			chip->count_wakeable++;
-		}
-	} else {
-		if (chip->wake_enable[irq]) {
-			chip->wake_enable[irq] = 0;
-			chip->count_wakeable--;
-		}
-	}
+	return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
 
 	return 0;
 }
 
-static inline int
-pm8901_read_root(struct pm8901_chip *chip, u8 *rp)
+static enum pm8xxx_version pm8901_get_version(const struct device *dev)
 {
-	int	rc;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
+	enum pm8xxx_version version = -ENODEV;
 
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read Root)\n",
-			__func__, rc);
-		*rp = 0;
-	}
+	if ((pmic->revision & PM8901_VERSION_MASK) == PM8901_VERSION_VALUE)
+		version = PM8XXX_VERSION_8901;
 
-	return rc;
+	return version;
 }
 
-static inline int
-pm8901_read_master(struct pm8901_chip *chip, u8 m, u8 *bp)
+static int pm8901_get_revision(const struct device *dev)
 {
-	int	rc;
+	const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
+	const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
 
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read Master)\n",
-			__func__, rc);
-		*bp = 0;
-	}
-
-	return rc;
+	return pmic->revision & PM8901_REVISION_MASK;
 }
 
-static inline int
-pm8901_read_block(struct pm8901_chip *chip, u8 *bp, u8 *ip)
-{
-	int	rc;
-
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
-		       __func__, rc);
-		*bp = 0;
-		goto bail_out;
-	}
-
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip, 1);
-	if (rc)
-		pr_err("%s: FAIL ssbi_read(): rc=%d (Read Status)\n",
-		       __func__, rc);
-
-bail_out:
-	return rc;
-}
-
-static irqreturn_t pm8901_isr_thread(int irq_requested, void *data)
-{
-	struct pm8901_chip *chip = data;
-	int	i, j, k;
-	u8	root, block, config, bits;
-	u8	blocks[MAX_PM_MASTERS];
-	int	masters = 0, irq, handled = 0, spurious = 0;
-	u16     irqs_to_handle[MAX_PM_IRQ];
-	unsigned long	irqsave;
-
-	spin_lock_irqsave(&chip->pm_lock, irqsave);
-
-	/* Read root for masters */
-	if (pm8901_read_root(chip, &root))
-		goto bail_out;
-
-	masters = root >> 1;
-
-	if (!(masters & chip->masters_allowed) ||
-	    (masters & ~chip->masters_allowed)) {
-		spurious = 1000000;
-	}
-
-	/* Read allowed masters for blocks. */
-	for (i = 0; i < chip->pm_max_masters; i++) {
-		if (masters & (1 << i)) {
-			if (pm8901_read_master(chip, i, &blocks[i]))
-				goto bail_out;
-
-			if (!blocks[i]) {
-				if (pm8901_can_print())
-					pr_err("%s: Spurious master: %d "
-					       "(blocks=0)", __func__, i);
-				spurious += 10000;
-			}
-		} else
-			blocks[i] = 0;
-	}
-
-	/* Select block, read status and call isr */
-	for (i = 0; i < chip->pm_max_masters; i++) {
-		if (!blocks[i])
-			continue;
-
-		for (j = 0; j < 8; j++) {
-			if (!(blocks[i] & (1 << j)))
-				continue;
-
-			block = i * 8 + j;	/* block # */
-			if (pm8901_read_block(chip, &block, &bits))
-				goto bail_out;
-
-			if (!bits) {
-				if (pm8901_can_print())
-					pr_err("%s: Spurious block: "
-					       "[master, block]=[%d, %d] "
-					       "(bits=0)\n", __func__, i, j);
-				spurious += 100;
-				continue;
-			}
-
-			/* Check IRQ bits */
-			for (k = 0; k < 8; k++) {
-				if (!(bits & (1 << k)))
-					continue;
-
-				/* Check spurious interrupts */
-				if (((1 << i) & chip->masters_allowed) &&
-				    (blocks[i] & chip->blocks_allowed[i]) &&
-				    (bits & chip->irqs_allowed[block])) {
-
-					/* Found one */
-					irq = block * 8 + k;
-					irqs_to_handle[handled] = irq +
-						chip->pdata.irq_base;
-					handled++;
-				} else {
-					/* Clear and mask wrong one */
-					config = PM8901_IRQF_W_C_M |
-						(k < PM8901_IRQF_BITS_SHIFT);
-
-					pm8901_config_irq(chip,
-							  &block, &config);
-
-					if (pm8901_can_print())
-						pr_err("%s: Spurious IRQ: "
-						       "[master, block, bit]="
-						       "[%d, %d (%d), %d]\n",
-							__func__,
-						       i, j, block, k);
-					spurious++;
-				}
-			}
-		}
-
-	}
-
-bail_out:
-
-	spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-
-	for (i = 0; i < handled; i++)
-		generic_handle_irq(irqs_to_handle[i]);
-
-	if (spurious) {
-		if (!pm8901_can_print())
-			return IRQ_HANDLED;
-
-		pr_err("%s: spurious = %d (handled = %d)\n",
-		       __func__, spurious, handled);
-		pr_err("   root = 0x%x (masters_allowed<<1 = 0x%x)\n",
-		       root, chip->masters_allowed << 1);
-		for (i = 0; i < chip->pm_max_masters; i++) {
-			if (masters & (1 << i))
-				pr_err("   blocks[%d]=0x%x, "
-				       "allowed[%d]=0x%x\n",
-				       i, blocks[i],
-				       i, chip->blocks_allowed[i]);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int check_addr(int addr, const char *func_name)
-{
-	if (addr < 0 || addr > 0x3FF) {
-		pr_err("%s: PMIC 8901 register address is invalid: %d\n",
-			func_name, addr);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int data_set(void *data, u64 val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	u8 reg = val;
-	int rc;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-
-	rc = check_addr(dbgdev->addr, __func__);
-	if (rc)
-		goto done;
-
-	rc = pm8901_write(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
-
-	if (rc)
-		pr_err("%s: FAIL pm8901_write(0x%03X)=0x%02X: rc=%d\n",
-			__func__, dbgdev->addr, reg, rc);
-done:
-	mutex_unlock(&dbgdev->dbg_mutex);
-	return rc;
-}
-
-static int data_get(void *data, u64 *val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	int rc;
-	u8 reg;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-
-	rc = check_addr(dbgdev->addr, __func__);
-	if (rc)
-		goto done;
-
-	rc = pm8901_read(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
-
-	if (rc) {
-		pr_err("%s: FAIL pm8901_read(0x%03X)=0x%02X: rc=%d\n",
-			__func__, dbgdev->addr, reg, rc);
-		goto done;
-	}
-
-	*val = reg;
-done:
-	mutex_unlock(&dbgdev->dbg_mutex);
-	return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_data_fops, data_get, data_set, "0x%02llX\n");
-
-static int addr_set(void *data, u64 val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	int rc;
-
-	rc = check_addr(val, __func__);
-	if (rc)
-		return rc;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-	dbgdev->addr = val;
-	mutex_unlock(&dbgdev->dbg_mutex);
-
-	return 0;
-}
-
-static int addr_get(void *data, u64 *val)
-{
-	struct pm8901_dbg_device *dbgdev = data;
-	int rc;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-
-	rc = check_addr(dbgdev->addr, __func__);
-	if (rc) {
-		mutex_unlock(&dbgdev->dbg_mutex);
-		return rc;
-	}
-	*val = dbgdev->addr;
-
-	mutex_unlock(&dbgdev->dbg_mutex);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_addr_fops, addr_get, addr_set, "0x%03llX\n");
-
-static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
-{
-	struct pm8901_dbg_device *dbgdev;
-	struct dentry *dent;
-	struct dentry *temp;
-	int rc;
-
-	if (chip == NULL) {
-		pr_err("%s: no parent data passed in.\n", __func__);
-		return -EINVAL;
-	}
-
-	dbgdev = kzalloc(sizeof *dbgdev, GFP_KERNEL);
-	if (dbgdev == NULL) {
-		pr_err("%s: kzalloc() failed.\n", __func__);
-		return -ENOMEM;
-	}
-
-	dbgdev->pm_chip = chip;
-	dbgdev->addr = -1;
-
-	dent = debugfs_create_dir("pm8901-dbg", NULL);
-	if (dent == NULL || IS_ERR(dent)) {
-		pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
-					__func__, (unsigned)dent);
-		rc = PTR_ERR(dent);
-		goto dir_error;
-	}
-
-	temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dent,
-					dbgdev, &dbg_addr_fops);
-	if (temp == NULL || IS_ERR(temp)) {
-		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
-					__func__, (unsigned)temp);
-		rc = PTR_ERR(temp);
-		goto debug_error;
-	}
-
-	temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dent,
-					dbgdev, &dbg_data_fops);
-	if (temp == NULL || IS_ERR(temp)) {
-		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
-					__func__, (unsigned)temp);
-		rc = PTR_ERR(temp);
-		goto debug_error;
-	}
-
-	mutex_init(&dbgdev->dbg_mutex);
-
-	dbgdev->dent = dent;
-
-	pmic_dbg_device = dbgdev;
-
-	return 0;
-
-debug_error:
-	debugfs_remove_recursive(dent);
-dir_error:
-	kfree(dbgdev);
-
-	return rc;
-}
-
-static int __devexit pmic8901_dbg_remove(void)
-{
-	if (pmic_dbg_device) {
-		debugfs_remove_recursive(pmic_dbg_device->dent);
-		mutex_destroy(&pmic_dbg_device->dbg_mutex);
-		kfree(pmic_dbg_device);
-	}
-	return 0;
-}
-
-#else
-
-static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
-{
-	return 0;
-}
-
-static int __devexit pmic8901_dbg_remove(void)
-{
-	return 0;
-}
-
-#endif
-
-static struct irq_chip pm8901_irq_chip = {
-	.name      = "pm8901",
-	.irq_ack       = pm8901_irq_ack,
-	.irq_mask      = pm8901_irq_mask,
-	.irq_unmask    = pm8901_irq_unmask,
-	.irq_set_type  = pm8901_irq_set_type,
-	.irq_set_wake  = pm8901_irq_set_wake,
+static struct pm8xxx_drvdata pm8901_drvdata = {
+	.pmic_readb		= pm8901_readb,
+	.pmic_writeb		= pm8901_writeb,
+	.pmic_read_buf		= pm8901_read_buf,
+	.pmic_write_buf		= pm8901_write_buf,
+	.pmic_read_irq_stat	= pm8901_read_irq_stat,
+	.pmic_get_version	= pm8901_get_version,
+	.pmic_get_revision	= pm8901_get_revision,
 };
 
+static struct mfd_cell debugfs_cell = {
+	.name		= "pm8xxx-debug",
+	.id		= 1,
+	.platform_data	= "pm8901-dbg",
+	.pdata_size	= sizeof("pm8901-dbg"),
+};
+
+static const struct resource thermal_alarm_cell_resources[] = {
+	SINGLE_IRQ_RESOURCE("pm8901_tempstat_irq", PM8901_TEMPSTAT_IRQ),
+	SINGLE_IRQ_RESOURCE("pm8901_overtemp_irq", PM8901_OVERTEMP_IRQ),
+};
+
+static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
+	.adc_type			= PM8XXX_TM_ADC_NONE,
+	.reg_addr_temp_alarm_ctrl	= REG_TEMP_ALRM_CTRL,
+	.reg_addr_temp_alarm_pwm	= REG_TEMP_ALRM_PWM,
+	.tm_name			= "pm8901_tz",
+	.irq_name_temp_stat		= "pm8901_tempstat_irq",
+	.irq_name_over_temp		= "pm8901_overtemp_irq",
+};
+
+static struct mfd_cell thermal_alarm_cell = {
+	.name		= PM8XXX_TM_DEV_NAME,
+	.id		= 1,
+	.resources	= thermal_alarm_cell_resources,
+	.num_resources	= ARRAY_SIZE(thermal_alarm_cell_resources),
+	.platform_data	= &thermal_alarm_cdata,
+	.pdata_size	= sizeof(struct pm8xxx_tm_core_data),
+};
+
+static const struct resource mpp_cell_resources[] = {
+	{
+		.start	= PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0),
+		.end	= PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0)
+			  + PM8901_MPPS - 1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell mpp_cell = {
+	.name		= PM8XXX_MPP_DEV_NAME,
+	.id		= 1,
+	.resources	= mpp_cell_resources,
+	.num_resources	= ARRAY_SIZE(mpp_cell_resources),
+};
+
+static int __devinit
+pm8901_add_subdevices(const struct pm8901_platform_data *pdata,
+				struct pm8901_chip *pmic)
+{
+	int rc = 0, irq_base = 0, i;
+	struct pm_irq_chip *irq_chip;
+	static struct mfd_cell *mfd_regulators;
+
+	if (pdata->irq_pdata) {
+		pdata->irq_pdata->irq_cdata.nirqs = PM8901_NR_IRQS;
+		pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
+		irq_base = pdata->irq_pdata->irq_base;
+		irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
+
+		if (IS_ERR(irq_chip)) {
+			pr_err("Failed to init interrupts ret=%ld\n",
+					PTR_ERR(irq_chip));
+			return PTR_ERR(irq_chip);
+		}
+		pmic->irq_chip = irq_chip;
+	}
+
+	if (pdata->mpp_pdata) {
+		pdata->mpp_pdata->core_data.nmpps = PM8901_MPPS;
+		pdata->mpp_pdata->core_data.base_addr = REG_MPP_BASE;
+		mpp_cell.platform_data = pdata->mpp_pdata;
+		mpp_cell.pdata_size = sizeof(struct pm8xxx_mpp_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &mpp_cell, 1, NULL,
+					irq_base);
+		if (rc) {
+			pr_err("Failed to add mpp subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
+		mfd_regulators = kzalloc(sizeof(struct mfd_cell)
+					 * (pdata->num_regulators), GFP_KERNEL);
+		if (!mfd_regulators) {
+			pr_err("Cannot allocate %d bytes for pm8901 regulator "
+				"mfd cells\n", sizeof(struct mfd_cell)
+						* (pdata->num_regulators));
+			rc = -ENOMEM;
+			goto bail;
+		}
+		for (i = 0; i < pdata->num_regulators; i++) {
+			mfd_regulators[i].name = "pm8901-regulator";
+			mfd_regulators[i].id = pdata->regulator_pdatas[i].id;
+			mfd_regulators[i].platform_data =
+				&(pdata->regulator_pdatas[i]);
+			mfd_regulators[i].pdata_size =
+					sizeof(struct pm8901_vreg_pdata);
+		}
+		rc = mfd_add_devices(pmic->dev, 0, mfd_regulators,
+				pdata->num_regulators, NULL, irq_base);
+		if (rc) {
+			pr_err("Failed to add regulator subdevices ret=%d\n",
+				rc);
+			kfree(mfd_regulators);
+			goto bail;
+		}
+		pmic->mfd_regulators = mfd_regulators;
+	}
+
+	rc = mfd_add_devices(pmic->dev, 0, &thermal_alarm_cell, 1, NULL,
+							irq_base);
+	if (rc) {
+		pr_err("Failed to add thermal alarm subdevice ret=%d\n",
+			rc);
+		goto bail;
+	}
+
+	rc = mfd_add_devices(pmic->dev, 0, &debugfs_cell, 1, NULL, irq_base);
+	if (rc) {
+		pr_err("Failed to add debugfs subdevice ret=%d\n", rc);
+		goto bail;
+	}
+
+	return rc;
+
+bail:
+	if (pmic->irq_chip) {
+		pm8xxx_irq_exit(pmic->irq_chip);
+		pmic->irq_chip = NULL;
+	}
+	return rc;
+}
+
 static int pm8901_probe(struct platform_device *pdev)
 {
-	int i, rc;
+	int rc;
 	struct pm8901_platform_data *pdata = pdev->dev.platform_data;
-	struct pm8901_chip *chip;
+	struct pm8901_chip *pmic;
 
-	if (pdata == NULL || pdata->irq <= 0) {
+	if (pdata == NULL) {
 		pr_err("%s: No platform_data or IRQ.\n", __func__);
 		return -ENODEV;
 	}
 
-	chip = kzalloc(sizeof *chip, GFP_KERNEL);
-	if (chip == NULL) {
+	pmic = kzalloc(sizeof *pmic, GFP_KERNEL);
+	if (pmic == NULL) {
 		pr_err("%s: kzalloc() failed.\n", __func__);
 		return -ENOMEM;
 	}
 
-	chip->dev = &pdev->dev;
+	pmic->dev = &pdev->dev;
+
+	pm8901_drvdata.pm_chip_data = pmic;
+	platform_set_drvdata(pdev, &pm8901_drvdata);
+	pmic_chip = pmic;
 
 	/* Read PMIC chip revision */
-	rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
+	rc = pm8901_readb(pmic->dev, PM8901_REG_REV, &pmic->revision);
 	if (rc)
-		pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
+		pr_err("%s: Failed reading version register rc=%d.\n",
 			__func__, rc);
-	pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);
 
-	(void) memcpy((void *)&chip->pdata, (const void *)pdata,
-		      sizeof(chip->pdata));
+	pr_info("%s: PMIC REVISION = %X\n", __func__, pmic->revision);
 
-	irq_set_handler_data(pdata->irq, (void *)chip);
-	irq_set_irq_wake(pdata->irq, 1);
+	(void) memcpy((void *)&pmic->pdata, (const void *)pdata,
+		      sizeof(pmic->pdata));
 
-	chip->pm_max_irq = 0;
-	chip->pm_max_blocks = 0;
-	chip->pm_max_masters = 0;
-
-	platform_set_drvdata(pdev, chip);
-
-	pmic_chip = chip;
-	spin_lock_init(&chip->pm_lock);
-
-	/* Register for all reserved IRQs */
-	for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
-		irq_set_chip(i, &pm8901_irq_chip);
-		irq_set_handler(i, handle_edge_irq);
-		set_irq_flags(i, IRQF_VALID);
-		irq_set_handler_data(i, (void *)chip);
-	}
-
-	rc = mfd_add_devices(chip->dev, 0, pdata->sub_devices,
-			     pdata->num_subdevs, NULL, 0);
+	rc = pm8901_add_subdevices(pdata, pmic);
 	if (rc) {
-		pr_err("%s: could not add devices %d\n", __func__, rc);
-		return rc;
+		pr_err("Cannot add subdevices rc=%d\n", rc);
+		goto err;
 	}
 
-	rc = request_threaded_irq(pdata->irq, NULL, pm8901_isr_thread,
-			IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
-			"pm8901-irq", chip);
-	if (rc)
-		pr_err("%s: could not request irq %d: %d\n", __func__,
-				pdata->irq, rc);
+	return 0;
 
-	rc = pmic8901_dbg_probe(chip);
-	if (rc < 0)
-		pr_err("%s: could not set up debugfs: %d\n", __func__, rc);
-
+err:
+	platform_set_drvdata(pdev, NULL);
+	kfree(pmic);
 	return rc;
 }
 
 static int __devexit pm8901_remove(struct platform_device *pdev)
 {
-	struct	pm8901_chip *chip;
+	struct pm8xxx_drvdata *drvdata;
+	struct pm8901_chip *pmic = NULL;
 
-	chip = platform_get_drvdata(pdev);
-	if (chip) {
-		if (chip->pm_max_irq) {
-			irq_set_irq_wake(chip->pdata.irq, 0);
-			free_irq(chip->pdata.irq, chip);
-		}
-
-		mfd_remove_devices(chip->dev);
-
-		chip->dev = NULL;
-
-		kfree(chip);
+	drvdata = platform_get_drvdata(pdev);
+	if (drvdata)
+		pmic = drvdata->pm_chip_data;
+	if (pmic) {
+		if (pmic->dev)
+			mfd_remove_devices(pmic->dev);
+		if (pmic->irq_chip)
+			pm8xxx_irq_exit(pmic->irq_chip);
+		kfree(pmic->mfd_regulators);
+		kfree(pmic);
 	}
-
-	pmic8901_dbg_remove();
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int pm8901_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	struct	pm8901_chip *chip;
-	int	i;
-	unsigned long	irqsave;
-
-	chip = platform_get_drvdata(pdev);
-
-	for (i = 0; i < MAX_PM_IRQ; i++) {
-		spin_lock_irqsave(&chip->pm_lock, irqsave);
-		if (chip->config[i] && !chip->wake_enable[i]) {
-			if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
-			      == PM8901_IRQF_MASK_ALL))
-				pm8901_irq_mask(irq_get_irq_data(i +
-							chip->pdata.irq_base));
-		}
-		spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-	}
-
-	if (!chip->count_wakeable)
-		disable_irq(chip->pdata.irq);
-
-	return 0;
-}
-
-static int pm8901_resume(struct platform_device *pdev)
-{
-	struct	pm8901_chip *chip;
-	int	i;
-	unsigned long	irqsave;
-
-	chip = platform_get_drvdata(pdev);
-
-	for (i = 0; i < MAX_PM_IRQ; i++) {
-		spin_lock_irqsave(&chip->pm_lock, irqsave);
-		if (chip->config[i] && !chip->wake_enable[i]) {
-			if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
-			      == PM8901_IRQF_MASK_ALL))
-				pm8901_irq_unmask(irq_get_irq_data(i +
-							chip->pdata.irq_base));
-		}
-		spin_unlock_irqrestore(&chip->pm_lock, irqsave);
-	}
-
-	if (!chip->count_wakeable)
-		enable_irq(chip->pdata.irq);
-
-	return 0;
-}
-#else
-#define	pm8901_suspend		NULL
-#define	pm8901_resume		NULL
-#endif
-
 static struct platform_driver pm8901_driver = {
 	.probe		= pm8901_probe,
 	.remove		= __devexit_p(pm8901_remove),
@@ -914,15 +401,13 @@
 		.name	= "pm8901-core",
 		.owner	= THIS_MODULE,
 	},
-	.suspend	= pm8901_suspend,
-	.resume		= pm8901_resume,
 };
 
 static int __init pm8901_init(void)
 {
 	return  platform_driver_register(&pm8901_driver);
 }
-arch_initcall(pm8901_init);
+postcore_initcall(pm8901_init);
 
 static void __exit pm8901_exit(void)
 {
diff --git a/drivers/mfd/timpani-codec.c b/drivers/mfd/timpani-codec.c
index b9ae84e..d2c2eb4 100644
--- a/drivers/mfd/timpani-codec.c
+++ b/drivers/mfd/timpani-codec.c
@@ -2755,6 +2755,7 @@
 	case TIMPANI_A_CDC_ANC2_CTL1:
 	case TIMPANI_A_CDC_ANC2_CTL2:
 	case TIMPANI_A_CDC_ANC2_FF_FB_SHIFT:
+	case TIMPANI_A_AUXPGA_LR_GAIN:
 		return false;
 	default:
 		return true;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 1116ca8..2c7c0a5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -412,7 +412,9 @@
 		int err;
 
 		host->en_dis_recurs = 1;
+		mmc_host_clk_hold(host);
 		err = host->ops->enable(host);
+		mmc_host_clk_release(host);
 		host->en_dis_recurs = 0;
 
 		if (err) {
@@ -432,7 +434,9 @@
 		int err;
 
 		host->en_dis_recurs = 1;
+		mmc_host_clk_hold(host);
 		err = host->ops->disable(host, lazy);
+		mmc_host_clk_release(host);
 		host->en_dis_recurs = 0;
 
 		if (err < 0) {
@@ -1003,8 +1007,11 @@
 
 	host->ios.signal_voltage = signal_voltage;
 
-	if (host->ops->start_signal_voltage_switch)
+	if (host->ops->start_signal_voltage_switch) {
+		mmc_host_clk_hold(host);
 		err = host->ops->start_signal_voltage_switch(host, &host->ios);
+		mmc_host_clk_release(host);
+	}
 
 	return err;
 }
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index fb8a5cd..08a7852 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -14,27 +14,6 @@
 
 int mmc_register_host_class(void);
 void mmc_unregister_host_class(void);
-
-#ifdef CONFIG_MMC_CLKGATE
-void mmc_host_clk_hold(struct mmc_host *host);
-void mmc_host_clk_release(struct mmc_host *host);
-unsigned int mmc_host_clk_rate(struct mmc_host *host);
-
-#else
-static inline void mmc_host_clk_hold(struct mmc_host *host)
-{
-}
-
-static inline void mmc_host_clk_release(struct mmc_host *host)
-{
-}
-
-static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
-{
-	return host->ios.clock;
-}
-#endif
-
 void mmc_host_deeper_disable(struct work_struct *work);
 
 #endif
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 8175d9b..71518f6 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -649,8 +649,11 @@
 		goto out;
 
 	/* SPI mode doesn't define CMD19 */
-	if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
+	if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) {
+		mmc_host_clk_hold(card->host);
 		err = card->host->ops->execute_tuning(card->host);
+		mmc_host_clk_release(card->host);
+	}
 
 out:
 	kfree(status);
@@ -860,8 +863,11 @@
 	if (!reinit) {
 		int ro = -1;
 
-		if (host->ops->get_ro)
+		if (host->ops->get_ro) {
+			mmc_host_clk_hold(host);
 			ro = host->ops->get_ro(host);
+			mmc_host_clk_release(host);
+		}
 
 		if (ro < 0) {
 			printk(KERN_WARNING "%s: host does not "
@@ -979,8 +985,11 @@
 		 * Since initialization is now complete, enable preset
 		 * value registers for UHS-I cards.
 		 */
-		if (host->ops->enable_preset_value)
+		if (host->ops->enable_preset_value) {
+			mmc_host_clk_hold(host);
 			host->ops->enable_preset_value(host, true);
+			mmc_host_clk_release(host);
+		}
 	} else {
 		/*
 		 * Attempt to change to high-speed (if supported)
@@ -1195,8 +1204,11 @@
 		return err;
 
 	/* Disable preset value enable if already set since last time */
-	if (host->ops->enable_preset_value)
+	if (host->ops->enable_preset_value) {
+		mmc_host_clk_hold(host);
 		host->ops->enable_preset_value(host, false);
+		mmc_host_clk_release(host);
+	}
 
 	err = mmc_send_app_op_cond(host, 0, &ocr);
 	if (err)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 2024824..3237742 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -397,8 +397,11 @@
 	/*
 	 * Call the optional HC's init_card function to handle quirks.
 	 */
-	if (host->ops->init_card)
+	if (host->ops->init_card) {
+		mmc_host_clk_hold(host);
 		host->ops->init_card(host, card);
+		mmc_host_clk_release(host);
+	}
 
 	/*
 	 * For native busses:  set card RCA and quit open drain mode.
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 03ead02..8b250c12 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -145,15 +145,21 @@
 		}
 
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (host->caps & MMC_CAP_SDIO_IRQ)
+		if (host->caps & MMC_CAP_SDIO_IRQ) {
+			mmc_host_clk_hold(host);
 			host->ops->enable_sdio_irq(host, 1);
+			mmc_host_clk_release(host);
+		}
 		if (!kthread_should_stop())
 			schedule_timeout(period);
 		set_current_state(TASK_RUNNING);
 	} while (!kthread_should_stop());
 
-	if (host->caps & MMC_CAP_SDIO_IRQ)
+	if (host->caps & MMC_CAP_SDIO_IRQ) {
+		mmc_host_clk_hold(host);
 		host->ops->enable_sdio_irq(host, 0);
+		mmc_host_clk_release(host);
+	}
 
 	pr_debug("%s: IRQ thread exiting with code %d\n",
 		 mmc_hostname(host), ret);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b46bee6..eeca25a 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2501,8 +2501,38 @@
 	return rc;
 }
 #else
-#define msmsdcc_enable NULL
-#define msmsdcc_disable NULL
+static int msmsdcc_enable(struct mmc_host *mmc)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (!host->clks_on) {
+		msmsdcc_setup_clocks(host, true);
+		host->clks_on = 1;
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int msmsdcc_disable(struct mmc_host *mmc, int lazy)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	if (mmc->card && mmc_card_sdio(mmc->card))
+		return -ENOTSUPP;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (host->clks_on) {
+		msmsdcc_setup_clocks(host, false);
+		host->clks_on = 0;
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
 #endif
 
 static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
@@ -4102,6 +4132,9 @@
 		pm_runtime_enable(&(pdev)->dev);
 	}
 #endif
+#ifndef CONFIG_PM_RUNTIME
+	mmc_set_disable_delay(mmc, MSM_MMC_DISABLE_TIMEOUT);
+#endif
 	setup_timer(&host->req_tout_timer, msmsdcc_req_tout_timer_hdlr,
 			(unsigned long)host);
 
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index ca3eed8..a8332e51 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -216,6 +216,7 @@
  * bad cards/controller to respond.
  */
 #define MSM_MMC_REQ_TIMEOUT	10000 /* msecs */
+#define MSM_MMC_DISABLE_TIMEOUT        200 /* msecs */
 
 /*
  * Controller HW limitations
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.c b/drivers/net/wireless/wcnss/wcnss_riva.c
index 9f69f12..b0eac55 100644
--- a/drivers/net/wireless/wcnss/wcnss_riva.c
+++ b/drivers/net/wireless/wcnss/wcnss_riva.c
@@ -18,10 +18,10 @@
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/gpio.h>
+#include <linux/wcnss_wlan.h>
 #include <mach/msm_xo.h>
 #include <mach/msm_iomap.h>
 
-#include "wcnss_riva.h"
 
 static void __iomem *msm_riva_base;
 static struct msm_xo_voter *wlan_clock;
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.h b/drivers/net/wireless/wcnss/wcnss_riva.h
deleted file mode 100644
index e037f58..0000000
--- a/drivers/net/wireless/wcnss/wcnss_riva.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _WCNSS_RIVA_H_
-#define _WCNSS_RIVA_H_
-
-#include <linux/device.h>
-
-enum wcnss_opcode {
-	WCNSS_WLAN_SWITCH_OFF = 0,
-	WCNSS_WLAN_SWITCH_ON,
-};
-
-struct wcnss_wlan_config {
-	int		use_48mhz_xo;
-};
-
-int wcnss_wlan_power(struct device *dev,
-		struct wcnss_wlan_config *cfg,
-		enum wcnss_opcode opcode);
-
-#endif /* _WCNSS_RIVA_H_ */
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 7453068..7217434 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -22,7 +22,6 @@
 #include <linux/jiffies.h>
 #include <linux/gpio.h>
 #include <mach/peripheral-loader.h>
-#include "wcnss_riva.h"
 
 #define DEVICE "wcnss_wlan"
 #define VERSION "1.01"
@@ -128,6 +127,22 @@
 }
 EXPORT_SYMBOL(wcnss_wlan_get_device);
 
+struct platform_device *wcnss_get_platform_device(void)
+{
+	if (penv && penv->pdev)
+		return penv->pdev;
+	return NULL;
+}
+EXPORT_SYMBOL(wcnss_get_platform_device);
+
+struct wcnss_wlan_config *wcnss_get_wlan_config(void)
+{
+	if (penv && penv->pdev)
+		return &penv->wlan_config;
+	return NULL;
+}
+EXPORT_SYMBOL(wcnss_get_wlan_config);
+
 struct resource *wcnss_wlan_get_memory_map(struct device *dev)
 {
 	if (penv && dev && (dev == &penv->pdev->dev) && penv->smd_channel_ready)
diff --git a/drivers/regulator/pmic8901-regulator.c b/drivers/regulator/pmic8901-regulator.c
index 5b4b907..6fd0a05 100644
--- a/drivers/regulator/pmic8901-regulator.c
+++ b/drivers/regulator/pmic8901-regulator.c
@@ -16,14 +16,13 @@
 #include <linux/init.h>
 #include <linux/mfd/pmic8901.h>
 #include <linux/regulator/driver.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/regulator/pmic8901-regulator.h>
-#include <mach/mpp.h>
 
 /* Regulator types */
 #define REGULATOR_TYPE_LDO		0
 #define REGULATOR_TYPE_SMPS		1
 #define REGULATOR_TYPE_VS		2
-#define REGULATOR_TYPE_MPP		3
 
 /* Bank select/write macros */
 #define REGULATOR_BANK_SEL(n)           ((n) << 4)
@@ -140,9 +139,9 @@
 #define VS_PULL_DOWN_ENABLE		0x20
 
 struct pm8901_vreg {
+	struct device			*dev;
 	struct pm8901_vreg_pdata	*pdata;
 	struct regulator_dev		*rdev;
-	struct pm8901_chip		*chip;
 	int				hpm_min_load;
 	unsigned			pc_vote;
 	unsigned			optimum;
@@ -159,7 +158,6 @@
 	u8				pfm_ctrl_reg;
 	u8				pwr_cnfg_reg;
 	u8				is_nmos;
-	u8				mpp_id;
 	u8				state;
 };
 
@@ -167,8 +165,8 @@
  * These are used to compensate for the PMIC 8901 v1 FTS regulators which
  * output ~10% higher than the programmed set point.
  */
-#define IS_PMIC_8901_V1(rev)		((rev) == PM_8901_REV_1p0 || \
-					 (rev) == PM_8901_REV_1p1)
+#define IS_PMIC_8901_V1(rev)		((rev) == PM8XXX_REVISION_8901_1p0 || \
+					 (rev) == PM8XXX_REVISION_8901_1p1)
 
 #define PMIC_8901_V1_SCALE(uV)		((((uV) - 62100) * 23) / 25)
 
@@ -207,12 +205,6 @@
 		.type = REGULATOR_TYPE_VS, \
 	}
 
-#define MPP(_id, _mpp_id) \
-	[_id] = { \
-		.mpp_id = _mpp_id, \
-		.type = REGULATOR_TYPE_MPP, \
-	}
-
 static struct pm8901_vreg pm8901_vreg[] = {
 	/*  id                 ctrl   pmr    tst    n/p */
 	LDO(PM8901_VREG_ID_L0, 0x02F, 0x0AB, 0x030, 1),
@@ -230,9 +222,6 @@
 	SMPS(PM8901_VREG_ID_S3, 0x088, 0x0A9, 0x089, 0x0F6),
 	SMPS(PM8901_VREG_ID_S4, 0x097, 0x0AA, 0x098, 0x0FB),
 
-	/* id			  MPP ID */
-	MPP(PM8901_VREG_ID_MPP0,    0),
-
 	/* id                       ctrl   pmr */
 	VS(PM8901_VREG_ID_LVS0,     0x046, 0x0B2),
 	VS(PM8901_VREG_ID_LVS1,     0x048, 0x0B3),
@@ -246,7 +235,7 @@
 static void print_write_error(struct pm8901_vreg *vreg, int rc,
 				const char *func);
 
-static int pm8901_vreg_write(struct pm8901_chip *chip,
+static int pm8901_vreg_write(struct pm8901_vreg *vreg,
 		u16 addr, u8 val, u8 mask, u8 *reg_save)
 {
 	int rc = 0;
@@ -254,7 +243,7 @@
 
 	reg = (*reg_save & ~mask) | (val & mask);
 	if (reg != *reg_save)
-		rc = pm8901_write(chip, addr, &reg, 1);
+		rc = pm8xxx_writeb(vreg->dev->parent, addr, reg);
 	if (!rc)
 		*reg_save = reg;
 	return rc;
@@ -283,7 +272,6 @@
 static int pm8901_vreg_enable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	u8 val = VREG_PMR_STATE_HPM;
 	int rc;
 
@@ -298,7 +286,7 @@
 
 	pm8901_vreg_select_pin_ctrl(vreg, &val);
 
-	rc = pm8901_vreg_write(chip, vreg->pmr_addr,
+	rc = pm8901_vreg_write(vreg, vreg->pmr_addr,
 			val,
 			VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
 			&vreg->pmr_reg);
@@ -311,10 +299,9 @@
 static int pm8901_vreg_disable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
-	rc = pm8901_vreg_write(chip, vreg->pmr_addr,
+	rc = pm8901_vreg_write(vreg, vreg->pmr_addr,
 			VREG_PMR_STATE_OFF | VREG_PMR_PIN_CTRL_ALL_MASKED,
 			VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
 			&vreg->pmr_reg);
@@ -359,11 +346,10 @@
 static int pm8901_ldo_disable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
 	/* Disassert local enable bit in CTRL register. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, 0, LDO_LOCAL_ENABLE_MASK,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, 0, LDO_LOCAL_ENABLE_MASK,
 			&vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -374,8 +360,7 @@
 	return rc;
 }
 
-static int pm8901_pldo_set_voltage(struct pm8901_chip *chip,
-		struct pm8901_vreg *vreg, int uV)
+static int pm8901_pldo_set_voltage(struct pm8901_vreg *vreg, int uV)
 {
 	int vmin, rc = 0;
 	unsigned vprog, fine_step;
@@ -414,7 +399,7 @@
 		|| ((range_sel ^ vreg->test_reg[2]) & LDO_TEST_RANGE_SEL_MASK)
 		|| ((fine_step_reg ^ vreg->test_reg[2])
 			& LDO_TEST_FINE_STEP_MASK))) {
-		rc = pm8901_vreg_write(chip, vreg->test_addr,
+		rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			REGULATOR_BANK_SEL(2) | REGULATOR_BANK_WRITE,
 			REGULATOR_BANK_MASK | LDO_TEST_VPROG_UPDATE_MASK,
 			&vreg->test_reg[2]);
@@ -423,13 +408,13 @@
 	}
 
 	/* Write new voltage. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, vprog,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, vprog,
 				LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
 	if (rc)
 		goto bail;
 
 	/* Write range extension. */
-	rc = pm8901_vreg_write(chip, vreg->test_addr,
+	rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			range_ext | REGULATOR_BANK_SEL(4)
 			 | REGULATOR_BANK_WRITE,
 			LDO_TEST_RANGE_EXT_MASK | REGULATOR_BANK_MASK,
@@ -438,7 +423,7 @@
 		goto bail;
 
 	/* Write fine step, range select and program voltage update. */
-	rc = pm8901_vreg_write(chip, vreg->test_addr,
+	rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			fine_step_reg | range_sel | REGULATOR_BANK_SEL(2)
 			 | REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
 			LDO_TEST_FINE_STEP_MASK | LDO_TEST_RANGE_SEL_MASK
@@ -451,8 +436,7 @@
 	return rc;
 }
 
-static int pm8901_nldo_set_voltage(struct pm8901_chip *chip,
-		struct pm8901_vreg *vreg, int uV)
+static int pm8901_nldo_set_voltage(struct pm8901_vreg *vreg, int uV)
 {
 	unsigned vprog, fine_step_reg;
 	int rc;
@@ -465,13 +449,13 @@
 	vprog >>= 1;
 
 	/* Write new voltage. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, vprog,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, vprog,
 				LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
 
 	/* Write fine step. */
-	rc = pm8901_vreg_write(chip, vreg->test_addr,
+	rc = pm8901_vreg_write(vreg, vreg->test_addr,
 			fine_step_reg | REGULATOR_BANK_SEL(2)
 			 | REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
 			LDO_TEST_FINE_STEP_MASK | REGULATOR_BANK_MASK
@@ -487,12 +471,11 @@
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 
 	if (vreg->is_nmos)
-		return pm8901_nldo_set_voltage(chip, vreg, min_uV);
+		return pm8901_nldo_set_voltage(vreg, min_uV);
 	else
-		return pm8901_pldo_set_voltage(chip, vreg, min_uV);
+		return pm8901_pldo_set_voltage(vreg, min_uV);
 }
 
 static int pm8901_pldo_get_voltage(struct pm8901_vreg *vreg)
@@ -560,7 +543,6 @@
 static int pm8901_vreg_set_mode(struct regulator_dev *dev, unsigned int mode)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	unsigned optimum = vreg->optimum;
 	unsigned pc_vote = vreg->pc_vote;
 	unsigned mode_initialized = vreg->mode_initialized;
@@ -614,7 +596,7 @@
 
 	/* Only apply mode setting to hardware if currently enabled. */
 	if (pm8901_vreg_is_enabled(dev))
-		rc = pm8901_vreg_write(chip, vreg->pmr_addr, val,
+		rc = pm8901_vreg_write(vreg, vreg->pmr_addr, val,
 			       VREG_PMR_STATE_MASK | VREG_PMR_PIN_CTRL_ALL_MASK,
 			       &vreg->pmr_reg);
 
@@ -678,11 +660,10 @@
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 	u8 val, band;
 
-	if (IS_PMIC_8901_V1(pm8901_rev(chip)))
+	if (IS_PMIC_8901_V1(pm8xxx_get_revision(vreg->dev->parent)))
 		min_uV = PMIC_8901_V1_SCALE(min_uV);
 
 	if (min_uV < SMPS_BAND_1_UV_MIN || min_uV > SMPS_BAND_3_UV_MAX)
@@ -707,13 +688,13 @@
 		band = SMPS_VCTRL_BAND_3;
 	}
 
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, band | val,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, band | val,
 			SMPS_VCTRL_BAND_MASK | SMPS_VCTRL_VPROG_MASK,
 			&vreg->ctrl_reg);
 	if (rc)
 		goto bail;
 
-	rc = pm8901_vreg_write(chip, vreg->pfm_ctrl_addr, band | val,
+	rc = pm8901_vreg_write(vreg, vreg->pfm_ctrl_addr, band | val,
 			SMPS_VCTRL_BAND_MASK | SMPS_VCTRL_VPROG_MASK,
 			&vreg->pfm_ctrl_reg);
 bail:
@@ -726,7 +707,6 @@
 static int pm8901_smps_get_voltage(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	u8 vprog, band;
 	int ret = 0;
 
@@ -745,7 +725,7 @@
 	else
 		ret = vprog * SMPS_BAND_3_UV_STEP + SMPS_BAND_3_UV_MIN;
 
-	if (IS_PMIC_8901_V1(pm8901_rev(chip)))
+	if (IS_PMIC_8901_V1(pm8xxx_get_revision(vreg->dev->parent)))
 		ret = PMIC_8901_V1_SCALE_INV(ret);
 
 	return ret;
@@ -754,14 +734,13 @@
 static int pm8901_vs_enable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
 	/* Assert enable bit in PMR register. */
 	rc = pm8901_vreg_enable(dev);
 
 	/* Make sure that switch is controlled via PMR register */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, VS_CTRL_USE_PMR,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, VS_CTRL_USE_PMR,
 			VS_CTRL_ENABLE_MASK, &vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -772,14 +751,13 @@
 static int pm8901_vs_disable(struct regulator_dev *dev)
 {
 	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8901_chip *chip = vreg->chip;
 	int rc;
 
 	/* Disassert enable bit in PMR register. */
 	rc = pm8901_vreg_disable(dev);
 
 	/* Make sure that switch is controlled via PMR register */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr, VS_CTRL_USE_PMR,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr, VS_CTRL_USE_PMR,
 			VS_CTRL_ENABLE_MASK, &vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -787,52 +765,6 @@
 	return rc;
 }
 
-static int pm8901_mpp_enable(struct regulator_dev *dev)
-{
-	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	int out_val;
-	int rc;
-
-	out_val = (vreg->pdata->active_high
-		   ? PM_MPP_DOUT_CTL_HIGH : PM_MPP_DOUT_CTL_LOW);
-
-	rc = pm8901_mpp_config(vreg->mpp_id, PM_MPP_TYPE_D_OUTPUT,
-			PM8901_MPP_DIG_LEVEL_VPH, out_val);
-
-	if (rc)
-		pr_err("%s: pm8901_mpp_config failed, rc=%d\n", __func__, rc);
-	else
-		vreg->state = 1;
-
-	return rc;
-}
-
-static int pm8901_mpp_disable(struct regulator_dev *dev)
-{
-	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	int out_val;
-	int rc;
-
-	out_val = (vreg->pdata->active_high
-		   ? PM_MPP_DOUT_CTL_LOW : PM_MPP_DOUT_CTL_HIGH);
-
-	rc = pm8901_mpp_config(vreg->mpp_id, PM_MPP_TYPE_D_OUTPUT,
-			PM8901_MPP_DIG_LEVEL_VPH, out_val);
-
-	if (rc)
-		pr_err("%s: pm8901_mpp_config failed, rc=%d\n", __func__, rc);
-	else
-		vreg->state = 0;
-
-	return rc;
-}
-
-static int pm8901_mpp_is_enabled(struct regulator_dev *dev)
-{
-	struct pm8901_vreg *vreg = rdev_get_drvdata(dev);
-	return vreg->state;
-}
-
 static struct regulator_ops pm8901_ldo_ops = {
 	.enable = pm8901_vreg_enable,
 	.disable = pm8901_ldo_disable,
@@ -863,12 +795,6 @@
 	.get_mode = pm8901_vreg_get_mode,
 };
 
-static struct regulator_ops pm8901_mpp_ops = {
-	.enable = pm8901_mpp_enable,
-	.disable = pm8901_mpp_disable,
-	.is_enabled = pm8901_mpp_is_enabled,
-};
-
 #define VREG_DESCRIP(_id, _name, _ops) \
 	[_id] = { \
 		.name = _name, \
@@ -893,8 +819,6 @@
 	VREG_DESCRIP(PM8901_VREG_ID_S3, "8901_s3", &pm8901_smps_ops),
 	VREG_DESCRIP(PM8901_VREG_ID_S4, "8901_s4", &pm8901_smps_ops),
 
-	VREG_DESCRIP(PM8901_VREG_ID_MPP0,     "8901_mpp0",     &pm8901_mpp_ops),
-
 	VREG_DESCRIP(PM8901_VREG_ID_LVS0,     "8901_lvs0",     &pm8901_vs_ops),
 	VREG_DESCRIP(PM8901_VREG_ID_LVS1,     "8901_lvs1",     &pm8901_vs_ops),
 	VREG_DESCRIP(PM8901_VREG_ID_LVS2,     "8901_lvs2",     &pm8901_vs_ops),
@@ -904,7 +828,7 @@
 	VREG_DESCRIP(PM8901_VREG_ID_HDMI_MVS, "8901_hdmi_mvs", &pm8901_vs_ops),
 };
 
-static int pm8901_init_ldo(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_ldo(struct pm8901_vreg *vreg)
 {
 	int rc = 0, i;
 	u8 bank;
@@ -912,11 +836,12 @@
 	/* Store current regulator register values. */
 	for (i = 0; i < LDO_TEST_BANKS; i++) {
 		bank = REGULATOR_BANK_SEL(i);
-		rc = pm8901_write(chip, vreg->test_addr, &bank, 1);
+		rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank);
 		if (rc)
 			goto bail;
 
-		rc = pm8901_read(chip, vreg->test_addr, &vreg->test_reg[i], 1);
+		rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+							&vreg->test_reg[i]);
 		if (rc)
 			goto bail;
 
@@ -924,30 +849,30 @@
 	}
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr,
 		     (vreg->pdata->pull_down_enable ? LDO_PULL_DOWN_ENABLE : 0),
 		     LDO_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
 bail:
 	return rc;
 }
 
-static int pm8901_init_smps(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_smps(struct pm8901_vreg *vreg)
 {
 	int rc;
 
 	/* Store current regulator register values. */
-	rc = pm8901_read(chip, vreg->pfm_ctrl_addr,
-			 &vreg->pfm_ctrl_reg, 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->pfm_ctrl_addr,
+					 &vreg->pfm_ctrl_reg);
 	if (rc)
 		goto bail;
 
-	rc = pm8901_read(chip, vreg->pwr_cnfg_addr,
-			 &vreg->pwr_cnfg_reg, 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->pwr_cnfg_addr,
+				 &vreg->pwr_cnfg_reg);
 	if (rc)
 		goto bail;
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8901_vreg_write(chip, vreg->pwr_cnfg_addr,
+	rc = pm8901_vreg_write(vreg, vreg->pwr_cnfg_addr,
 		    (vreg->pdata->pull_down_enable ? SMPS_PULL_DOWN_ENABLE : 0),
 		    SMPS_PULL_DOWN_ENABLE_MASK, &vreg->pwr_cnfg_reg);
 
@@ -955,33 +880,30 @@
 	return rc;
 }
 
-static int pm8901_init_vs(struct pm8901_chip *chip, struct pm8901_vreg *vreg)
+static int pm8901_init_vs(struct pm8901_vreg *vreg)
 {
 	int rc = 0;
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8901_vreg_write(chip, vreg->ctrl_addr,
+	rc = pm8901_vreg_write(vreg, vreg->ctrl_addr,
 		      (vreg->pdata->pull_down_enable ? VS_PULL_DOWN_ENABLE : 0),
 		      VS_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
 
 	return rc;
 }
 
-static int pm8901_init_regulator(struct pm8901_chip *chip,
-		struct pm8901_vreg *vreg)
+static int pm8901_init_regulator(struct pm8901_vreg *vreg)
 {
 	int rc;
 
 	/* Store current regulator register values. */
-	if (vreg->type != REGULATOR_TYPE_MPP) {
-		rc = pm8901_read(chip, vreg->ctrl_addr, &vreg->ctrl_reg, 1);
-		if (rc)
-			goto bail;
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg);
+	if (rc)
+		goto bail;
 
-		rc = pm8901_read(chip, vreg->pmr_addr, &vreg->pmr_reg, 1);
-		if (rc)
-			goto bail;
-	}
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->pmr_addr, &vreg->pmr_reg);
+	if (rc)
+		goto bail;
 
 	/* Set initial mode based on hardware state. */
 	if ((vreg->pmr_reg & VREG_PMR_STATE_MASK) == VREG_PMR_STATE_LPM)
@@ -992,11 +914,11 @@
 	vreg->mode_initialized = 0;
 
 	if (vreg->type == REGULATOR_TYPE_LDO)
-		rc = pm8901_init_ldo(chip, vreg);
+		rc = pm8901_init_ldo(vreg);
 	else if (vreg->type == REGULATOR_TYPE_SMPS)
-		rc = pm8901_init_smps(chip, vreg);
+		rc = pm8901_init_smps(vreg);
 	else if (vreg->type == REGULATOR_TYPE_VS)
-		rc = pm8901_init_vs(chip, vreg);
+		rc = pm8901_init_vs(vreg);
 bail:
 	if (rc)
 		pr_err("%s: pm8901_read/write failed; initial register states "
@@ -1008,7 +930,6 @@
 static int __devinit pm8901_vreg_probe(struct platform_device *pdev)
 {
 	struct regulator_desc *rdesc;
-	struct pm8901_chip *chip;
 	struct pm8901_vreg *vreg;
 	const char *reg_name = NULL;
 	int rc = 0;
@@ -1017,14 +938,13 @@
 		return -EINVAL;
 
 	if (pdev->id >= 0 && pdev->id < PM8901_VREG_MAX) {
-		chip = dev_get_drvdata(pdev->dev.parent);
 		rdesc = &pm8901_vreg_descrip[pdev->id];
 		vreg = &pm8901_vreg[pdev->id];
 		vreg->pdata = pdev->dev.platform_data;
-		vreg->chip = chip;
 		reg_name = pm8901_vreg_descrip[pdev->id].name;
+		vreg->dev = &pdev->dev;
 
-		rc = pm8901_init_regulator(chip, vreg);
+		rc = pm8901_init_regulator(vreg);
 		if (rc)
 			goto bail;
 
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index d8003bf..a541d8b 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1876,7 +1876,7 @@
 			*ctrlw = maxctrlw1;
 		}
 	} else {
-		struct slim_ich *slc1;
+		struct slim_ich *slc1 = NULL;
 		struct slim_ich *slc3 = ctrl->sched.chc3[coeff3];
 		u32 expshft = SLIM_MAX_CLK_GEAR - clkgear;
 		int curexp, finalexp, exp1;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index ec922f1..2466246 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -37,6 +37,7 @@
 #include <linux/usb/msm_hsusb_hw.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
+#include <linux/pm_qos_params.h>
 
 #include <mach/clk.h>
 #include <mach/msm_xo.h>
@@ -63,6 +64,25 @@
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
 
+/* Prevent idle power collapse(pc) while operating in peripheral mode */
+static void otg_pm_qos_update_latency(struct msm_otg *dev, int vote)
+{
+	struct msm_otg_platform_data *pdata = dev->pdata;
+	u32 swfi_latency = 0;
+
+	if (!pdata || !pdata->swfi_latency)
+		return;
+
+	swfi_latency = pdata->swfi_latency + 1;
+
+	if (vote)
+		pm_qos_update_request(&dev->pm_qos_req_dma,
+				swfi_latency);
+	else
+		pm_qos_update_request(&dev->pm_qos_req_dma,
+				PM_QOS_DEFAULT_VALUE);
+}
+
 static struct regulator *hsusb_3p3;
 static struct regulator *hsusb_1p8;
 static struct regulator *hsusb_vddcx;
@@ -991,10 +1011,16 @@
 		 */
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
+		/*
+		 * vote for minimum dma_latency to prevent idle
+		 * power collapse(pc) while running in peripheral mode.
+		 */
+		otg_pm_qos_update_latency(motg, 1);
 		usb_gadget_vbus_connect(otg->gadget);
 	} else {
 		dev_dbg(otg->dev, "gadget off\n");
 		usb_gadget_vbus_disconnect(otg->gadget);
+		otg_pm_qos_update_latency(motg, 0);
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_UNDEFINED);
 	}
@@ -1824,7 +1850,7 @@
 	struct msm_otg *motg = the_msm_otg;
 
 	/* We depend on PMIC for only VBUS ON interrupt */
-	if (!atomic_read(&motg->in_lpm) || !online)
+	if (!atomic_read(&motg->in_lpm) || !online || motg->async_int)
 		return;
 
 	/*
@@ -2240,6 +2266,10 @@
 	}
 	clk_set_rate(motg->clk, 60000000);
 
+	/* pm qos request to prevent apps idle power collapse */
+	if (motg->pdata->swfi_latency)
+		pm_qos_add_request(&motg->pm_qos_req_dma,
+			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 	/*
 	 * If USB Core is running its protocol engine based on CORE CLK,
 	 * CORE CLK  must be running at >55Mhz for correct HSUSB
@@ -2460,6 +2490,8 @@
 	if (!IS_ERR(motg->phy_reset_clk))
 		clk_put(motg->phy_reset_clk);
 free_motg:
+	if (motg->pdata->swfi_latency)
+		pm_qos_remove_request(&motg->pm_qos_req_dma);
 	kfree(motg);
 	return ret;
 }
@@ -2535,8 +2567,10 @@
 	if (!IS_ERR(motg->system_clk))
 		clk_put(motg->system_clk);
 
-	kfree(motg);
+	if (motg->pdata->swfi_latency)
+		pm_qos_remove_request(&motg->pm_qos_req_dma);
 
+	kfree(motg);
 	return 0;
 }
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index a8aa44a..29f178d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -901,6 +901,9 @@
 			property_value);
 		vcd_status = VCD_S_SUCCESS;
 	break;
+	case VCD_I_META_BUFFER_MODE:
+		vcd_status = VCD_S_SUCCESS;
+		break;
 	default:
 		DDL_MSG_ERROR("INVALID ID %d\n", (int)property_hdr->prop_id);
 		vcd_status = VCD_ERR_ILLEGAL_OP;
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 184da27..65f9b54 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -36,14 +36,9 @@
 
 
 
-#if DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
-#else
-#define DBG(x...)
-#endif
-
-#define INFO(x...) printk(KERN_INFO x)
-#define ERR(x...) printk(KERN_ERR x)
+#define DBG(x...) pr_debug(x)
+#define INFO(x...) pr_info(x)
+#define ERR(x...) pr_err(x)
 
 #define VID_DEC_NAME		"msm_vidc_dec"
 
@@ -359,49 +354,49 @@
 
 	switch (event) {
 	case VCD_EVT_IND_OUTPUT_RECONFIG:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_CONFIG_CHANGED"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_CONFIG_CHANGED"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_CONFIG_CHANGED;
 		break;
 	case VCD_EVT_IND_RESOURCES_LOST:
-		INFO("msm_vidc_dec: Sending VDEC_EVT_RESOURCES_LOST"
+		DBG("msm_vidc_dec: Sending VDEC_EVT_RESOURCES_LOST"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_EVT_RESOURCES_LOST;
 		break;
 	case VCD_EVT_RESP_FLUSH_INPUT_DONE:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_INPUT_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_INPUT_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode =
 		    VDEC_MSG_RESP_FLUSH_INPUT_DONE;
 		break;
 	case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_OUTPUT_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_OUTPUT_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode =
 		    VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
 		break;
 	case VCD_EVT_IND_HWERRFATAL:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_HW_ERROR"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_HW_ERROR"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_HW_ERROR;
 		break;
 	case VCD_EVT_RESP_START:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_START_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_START_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_START_DONE;
 		break;
 	case VCD_EVT_RESP_STOP:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_STOP_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_STOP_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_STOP_DONE;
 		break;
 	case VCD_EVT_RESP_PAUSE:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_RESP_PAUSE_DONE"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_PAUSE_DONE"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_PAUSE_DONE;
 		break;
 	case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
-		INFO("msm_vidc_dec: Sending VDEC_MSG_EVT_INFO_CONFIG_CHANGED"
+		DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_INFO_CONFIG_CHANGED"
 			 " to client");
 		vdec_msg->vdec_msg_info.msgcode =
 			 VDEC_MSG_EVT_INFO_CONFIG_CHANGED;
@@ -1027,11 +1022,11 @@
 	}
 
 	if (pause) {
-		INFO("msm_vidc_dec: PAUSE command from client = %p\n",
+		DBG("msm_vidc_dec: PAUSE command from client = %p\n",
 			 client_ctx);
 		vcd_status = vcd_pause(client_ctx->vcd_handle);
 	} else{
-		INFO("msm_vidc_dec: RESUME command from client = %p\n",
+		DBG("msm_vidc_dec: RESUME command from client = %p\n",
 			 client_ctx);
 		vcd_status = vcd_resume(client_ctx->vcd_handle);
 	}
@@ -1048,7 +1043,7 @@
 	struct vid_dec_msg *vdec_msg = NULL;
 	u32 vcd_status;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	if (!client_ctx) {
 		ERR("\n Invalid client_ctx");
 		return false;
@@ -1056,7 +1051,7 @@
 
 	if (start) {
 		if (client_ctx->seq_header_set) {
-			INFO("%s(): Seq Hdr set: Send START_DONE to client",
+			DBG("%s(): Seq Hdr set: Send START_DONE to client",
 				 __func__);
 			vdec_msg = kzalloc(sizeof(*vdec_msg), GFP_KERNEL);
 			if (!vdec_msg) {
@@ -1078,7 +1073,7 @@
 			    client_ctx);
 
 		} else {
-			INFO("%s(): Calling decode_start()", __func__);
+			DBG("%s(): Calling decode_start()", __func__);
 			vcd_status =
 			    vcd_decode_start(client_ctx->vcd_handle, NULL);
 
@@ -1089,7 +1084,7 @@
 			}
 		}
 	} else {
-		INFO("%s(): Calling vcd_stop()", __func__);
+		DBG("%s(): Calling vcd_stop()", __func__);
 		mutex_lock(&vid_dec_device_p->lock);
 		vcd_status = VCD_ERR_FAIL;
 		if (!client_ctx->stop_called) {
@@ -1207,7 +1202,7 @@
 {
 	u32 vcd_status = VCD_ERR_FAIL;
 
-	INFO("msm_vidc_dec: %s() called with dir = %u", __func__,
+	DBG("msm_vidc_dec: %s() called with dir = %u", __func__,
 		 flush_dir);
 	if (!client_ctx) {
 		ERR("\n Invalid client_ctx");
@@ -1802,7 +1797,7 @@
 	struct vid_dec_msg *vdec_msg;
 	u32 vcd_status;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	if (!client_ctx || (!client_ctx->vcd_handle)) {
 		ERR("\n Invalid client_ctx");
 		return false;
@@ -1849,7 +1844,7 @@
 	u32 vcd_status = VCD_ERR_FAIL;
 	u8 client_count = 0;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	mutex_lock(&vid_dec_device_p->lock);
 
 	client_count = vcd_get_num_of_clients();
@@ -1912,13 +1907,13 @@
 {
 	struct video_client_ctx *client_ctx = file->private_data;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	vid_dec_close_client(client_ctx);
 	vidc_release_firmware();
 #ifndef USE_RES_TRACKER
 	vidc_disable_clk();
 #endif
-	INFO("msm_vidc_dec: Return from %s()", __func__);
+	DBG("msm_vidc_dec: Return from %s()", __func__);
 	return 0;
 }
 
@@ -1953,7 +1948,7 @@
 	u32 i;
 
 	/* init_timer(&hw_timer); */
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	vid_dec_device_p->num_clients = 0;
 
 	for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
@@ -1995,7 +1990,7 @@
 	int rc = 0;
 	struct device *class_devp;
 
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	vid_dec_device_p = kzalloc(sizeof(struct vid_dec_dev), GFP_KERNEL);
 	if (!vid_dec_device_p) {
 		ERR("%s Unable to allocate memory for vid_dec_dev\n",
@@ -2056,13 +2051,13 @@
 
 static void __exit vid_dec_exit(void)
 {
-	INFO("msm_vidc_dec: Inside %s()", __func__);
+	DBG("msm_vidc_dec: Inside %s()", __func__);
 	cdev_del(&(vid_dec_device_p->cdev));
 	device_destroy(vid_dec_class, vid_dec_dev_num);
 	class_destroy(vid_dec_class);
 	unregister_chrdev_region(vid_dec_dev_num, 1);
 	kfree(vid_dec_device_p);
-	INFO("msm_vidc_dec: Return from %s()", __func__);
+	DBG("msm_vidc_dec: Return from %s()", __func__);
 }
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 1435b86..5ee315f 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1540,6 +1540,29 @@
 			return -EFAULT;
 		break;
 	}
+	case VEN_IOCTL_SET_METABUFFER_MODE:
+	{
+		u32 metabuffer_mode, vcd_status;
+		struct vcd_property_hdr vcd_property_hdr;
+		struct vcd_property_live live_mode;
+
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		if (copy_from_user(&metabuffer_mode, venc_msg.in,
+			sizeof(metabuffer_mode)))
+			return -EFAULT;
+		vcd_property_hdr.prop_id = VCD_I_META_BUFFER_MODE;
+		vcd_property_hdr.sz =
+			sizeof(struct vcd_property_live);
+		live_mode.live = metabuffer_mode;
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+					&vcd_property_hdr, &live_mode);
+		if (vcd_status) {
+			pr_err(" Setting metabuffer mode failed");
+			return -EIO;
+		}
+		break;
+	}
 	case VEN_IOCTL_SET_AC_PREDICTION:
 	case VEN_IOCTL_GET_AC_PREDICTION:
 	case VEN_IOCTL_SET_RVLC:
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 973ed48..e00e85f 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -90,13 +90,13 @@
 		return VCD_ERR_ILLEGAL_OP;
 	}
 
-	if (!cctxt->in_buf_pool.entries ||
+	if ((!cctxt->meta_mode && !cctxt->in_buf_pool.entries) ||
 	    !cctxt->out_buf_pool.entries ||
-	    cctxt->in_buf_pool.validated != cctxt->in_buf_pool.count ||
+	    (!cctxt->meta_mode &&
+		 cctxt->in_buf_pool.validated != cctxt->in_buf_pool.count) ||
 	    cctxt->out_buf_pool.validated !=
 	    cctxt->out_buf_pool.count) {
 		VCD_MSG_ERROR("Buffer pool is not completely setup yet");
-
 		return VCD_ERR_BAD_STATE;
 	}
 
@@ -495,6 +495,13 @@
 	rc = ddl_set_property(cctxt->ddl_handle, prop_hdr, prop_val);
 	VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
 	switch (prop_hdr->prop_id) {
+	case VCD_I_META_BUFFER_MODE:
+		{
+			struct vcd_property_live *live =
+			    (struct vcd_property_live *)prop_val;
+			cctxt->meta_mode = live->live;
+			break;
+		}
 	case VCD_I_LIVE:
 		{
 			struct vcd_property_live *live =
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index b424059..64dec2d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -208,6 +208,7 @@
 	struct ion_client *vcd_ion_client;
 	u32 vcd_enable_ion;
 	struct vcd_clnt_ctxt *next;
+	u32 meta_mode;
 };
 
 #define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_property.h b/drivers/video/msm/vidc/common/vcd/vcd_property.h
index f51d226..3f7b131 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_property.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_property.h
@@ -47,6 +47,7 @@
 #define VCD_I_GET_H264_MV_SIZE (VCD_START_BASE + 0x1F)
 #define VCD_I_DEC_PICTYPE (VCD_START_BASE + 0x20)
 #define VCD_I_CONT_ON_RECONFIG (VCD_START_BASE + 0x21)
+#define VCD_I_META_BUFFER_MODE (VCD_START_BASE + 0x22)
 
 #define VCD_START_REQ      (VCD_START_BASE + 0x1000)
 #define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 75e0acf..217030f 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -653,7 +653,7 @@
 	VCD_FAILED_RETURN(rc, "Invalid buffer type provided");
 
 	first_frm_recvd &= cctxt->status.mask;
-	if (first_frm_recvd) {
+	if (first_frm_recvd && !cctxt->meta_mode) {
 		VCD_MSG_ERROR(
 			"VCD free buffer called when data path is active");
 		return VCD_ERR_BAD_STATE;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 150107b..c22f9b0 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -95,6 +95,7 @@
  * @flags:	flags (see IRQF_* above)
  * @name:	name of the device
  * @dev_id:	cookie to identify the device
+ * @percpu_dev_id:	cookie to identify the device
  * @next:	pointer to the next irqaction for shared interrupts
  * @irq:	interrupt number
  * @dir:	pointer to the proc/irq/NN/name entry
@@ -104,17 +105,18 @@
  * @thread_mask:	bitmask for keeping track of @thread activity
  */
 struct irqaction {
-	irq_handler_t handler;
-	unsigned long flags;
-	void *dev_id;
-	struct irqaction *next;
-	int irq;
-	irq_handler_t thread_fn;
-	struct task_struct *thread;
-	unsigned long thread_flags;
-	unsigned long thread_mask;
-	const char *name;
-	struct proc_dir_entry *dir;
+	irq_handler_t		handler;
+	unsigned long		flags;
+	void			*dev_id;
+	void __percpu		*percpu_dev_id;
+	struct irqaction	*next;
+	int			irq;
+	irq_handler_t		thread_fn;
+	struct task_struct	*thread;
+	unsigned long		thread_flags;
+	unsigned long		thread_mask;
+	const char		*name;
+	struct proc_dir_entry	*dir;
 } ____cacheline_internodealigned_in_smp;
 
 extern irqreturn_t no_action(int cpl, void *dev_id);
@@ -136,6 +138,10 @@
 request_any_context_irq(unsigned int irq, irq_handler_t handler,
 			unsigned long flags, const char *name, void *dev_id);
 
+extern int __must_check
+request_percpu_irq(unsigned int irq, irq_handler_t handler,
+		   const char *devname, void __percpu *percpu_dev_id);
+
 extern void exit_irq_thread(void);
 #else
 
@@ -164,10 +170,18 @@
 	return request_irq(irq, handler, flags, name, dev_id);
 }
 
+static inline int __must_check
+request_percpu_irq(unsigned int irq, irq_handler_t handler,
+		   const char *devname, void __percpu *percpu_dev_id)
+{
+	return request_irq(irq, handler, 0, devname, percpu_dev_id);
+}
+
 static inline void exit_irq_thread(void) { }
 #endif
 
 extern void free_irq(unsigned int, void *);
+extern void free_percpu_irq(unsigned int, void __percpu *);
 
 struct device;
 
@@ -207,7 +221,9 @@
 
 extern void disable_irq_nosync(unsigned int irq);
 extern void disable_irq(unsigned int irq);
+extern void disable_percpu_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
+extern void enable_percpu_irq(unsigned int irq, unsigned int type);
 
 /* The following three functions are for the core kernel use only. */
 #ifdef CONFIG_GENERIC_HARDIRQS
diff --git a/include/linux/irq.h b/include/linux/irq.h
index d03bc09..93c601f 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -23,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/topology.h>
 #include <linux/wait.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -65,6 +66,7 @@
  * IRQ_NO_BALANCING		- Interrupt cannot be balanced (affinity set)
  * IRQ_MOVE_PCNTXT		- Interrupt can be migrated from process context
  * IRQ_NESTED_TRHEAD		- Interrupt nests into another thread
+ * IRQ_PER_CPU_DEVID		- Dev_id is a per-cpu variable
  */
 enum {
 	IRQ_TYPE_NONE		= 0x00000000,
@@ -87,12 +89,13 @@
 	IRQ_MOVE_PCNTXT		= (1 << 14),
 	IRQ_NESTED_THREAD	= (1 << 15),
 	IRQ_NOTHREAD		= (1 << 16),
+	IRQ_PER_CPU_DEVID	= (1 << 17),
 };
 
 #define IRQF_MODIFY_MASK	\
 	(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
 	 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
-	 IRQ_PER_CPU | IRQ_NESTED_THREAD)
+	 IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID)
 
 #define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
 
@@ -371,6 +374,8 @@
 struct irqaction;
 extern int setup_irq(unsigned int irq, struct irqaction *new);
 extern void remove_irq(unsigned int irq, struct irqaction *act);
+extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
+extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
 
 extern void irq_cpu_online(void);
 extern void irq_cpu_offline(void);
@@ -398,6 +403,7 @@
 extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
+extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
@@ -428,6 +434,8 @@
 	irq_set_chip_and_handler_name(irq, chip, handle, NULL);
 }
 
+extern int irq_set_percpu_devid(unsigned int irq);
+
 extern void
 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 		  const char *name);
@@ -489,6 +497,13 @@
 		irq_clear_status_flags(irq, IRQ_NESTED_THREAD);
 }
 
+static inline void irq_set_percpu_devid_flags(unsigned int irq)
+{
+	irq_set_status_flags(irq,
+			     IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD |
+			     IRQ_NOPROBE | IRQ_PER_CPU_DEVID);
+}
+
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
 extern int create_irq(void);
@@ -556,7 +571,15 @@
 	return d->msi_desc;
 }
 
-int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node);
+int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
+		struct module *owner);
+
+static inline int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt,
+		int node)
+{
+	return __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE);
+}
+
 void irq_free_descs(unsigned int irq, unsigned int cnt);
 int irq_reserve_irqs(unsigned int from, unsigned int cnt);
 
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index 2d921b3..6b69c2c 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -53,6 +53,7 @@
 	unsigned long		last_unhandled;	/* Aging timer for unhandled count */
 	unsigned int		irqs_unhandled;
 	raw_spinlock_t		lock;
+	struct cpumask		*percpu_enabled;
 #ifdef CONFIG_SMP
 	const struct cpumask	*affinity_hint;
 	struct irq_affinity_notify *affinity_notify;
@@ -66,6 +67,7 @@
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry	*dir;
 #endif
+	struct module		*owner;
 	const char		*name;
 } ____cacheline_internodealigned_in_smp;
 
diff --git a/include/linux/mfd/pmic8901.h b/include/linux/mfd/pmic8901.h
index 5d23edc..932f8da 100644
--- a/include/linux/mfd/pmic8901.h
+++ b/include/linux/mfd/pmic8901.h
@@ -19,51 +19,33 @@
 
 #include <linux/irq.h>
 #include <linux/mfd/core.h>
-
-/* PM8901 interrupt numbers */
-
-#define PM8901_MPPS		4
+#include <linux/mfd/pm8xxx/irq.h>
+#include <linux/mfd/pm8xxx/mpp.h>
+#include <linux/mfd/pm8xxx/tm.h>
+#include <linux/regulator/pmic8901-regulator.h>
 
 #define PM8901_IRQ_BLOCK_BIT(block, bit) ((block) * 8 + (bit))
 
-/* MPPs [0,N) */
-#define PM8901_MPP_IRQ(base, mpp)	((base) + \
-					PM8901_IRQ_BLOCK_BIT(6, (mpp)))
+#define PM8901_NR_IRQS			72
 
-#define PM8901_TEMP_ALARM_IRQ(base)	((base) + PM8901_IRQ_BLOCK_BIT(6, 4))
-#define PM8901_TEMP_HI_ALARM_IRQ(base)	((base) + PM8901_IRQ_BLOCK_BIT(6, 5))
+/* PM8901 MPP */
+#define PM8901_MPP_BLOCK_START		6
+#define PM8901_MPPS			4
+
+/* PM8901 IRQs */
+#define PM8901_MPP_IRQ(mpp)		PM8901_IRQ_BLOCK_BIT(6, (mpp))
+#define PM8901_TEMPSTAT_IRQ		PM8901_IRQ_BLOCK_BIT(6, 4)
+#define PM8901_OVERTEMP_IRQ		PM8901_IRQ_BLOCK_BIT(6, 5)
 
 struct pm8901_chip;
 
 struct pm8901_platform_data {
-	/* This table is only needed for misc interrupts. */
-	int		irq_base;
-	int		irq;
-
-	int		num_subdevs;
-	struct mfd_cell *sub_devices;
-	int		irq_trigger_flags;
+	struct pm8xxx_irq_platform_data *irq_pdata;
+	struct pm8xxx_mpp_platform_data *mpp_pdata;
+	struct pm8901_vreg_pdata	*regulator_pdatas;
+	int				num_regulators;
 };
 
-struct pm8901_gpio_platform_data {
-	int	gpio_base;
-	int	irq_base;
-};
-
-/* chip revision */
-#define PM_8901_REV_1p0			0xF1
-#define PM_8901_REV_1p1			0xF2
-#define PM_8901_REV_2p0			0xF3
-
-int pm8901_read(struct pm8901_chip *pm_chip, u16 addr, u8 *values,
-		unsigned int len);
-int pm8901_write(struct pm8901_chip *pm_chip, u16 addr, u8 *values,
-		 unsigned int len);
-
-int pm8901_rev(struct pm8901_chip *pm_chip);
-
-int pm8901_irq_get_rt_status(struct pm8901_chip *pm_chip, int irq);
-
 #ifdef CONFIG_PMIC8901
 int pm8901_reset_pwr_off(int reset);
 #else
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 461192e..d1f478b 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -430,5 +430,25 @@
 {
 	return host->caps & MMC_CAP_CMD23;
 }
+
+#ifdef CONFIG_MMC_CLKGATE
+void mmc_host_clk_hold(struct mmc_host *host);
+void mmc_host_clk_release(struct mmc_host *host);
+unsigned int mmc_host_clk_rate(struct mmc_host *host);
+
+#else
+static inline void mmc_host_clk_hold(struct mmc_host *host)
+{
+}
+
+static inline void mmc_host_clk_release(struct mmc_host *host)
+{
+}
+
+static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
+{
+	return host->ios.clock;
+}
+#endif
 #endif
 
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index 12c7afd..45199cb 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -435,6 +435,9 @@
 #define VEN_IOCTL_GET_NUMBER_INSTANCES \
 	_IOR(VEN_IOCTLBASE_ENC, 46, struct venc_ioctl_msg)
 
+#define VEN_IOCTL_SET_METABUFFER_MODE \
+	_IOW(VEN_IOCTLBASE_ENC, 47, struct venc_ioctl_msg)
+
 struct venc_switch{
 	unsigned char	status;
 };
diff --git a/include/linux/regulator/pmic8901-regulator.h b/include/linux/regulator/pmic8901-regulator.h
index 953c4ad..ec842bc 100644
--- a/include/linux/regulator/pmic8901-regulator.h
+++ b/include/linux/regulator/pmic8901-regulator.h
@@ -32,23 +32,20 @@
 #define PM8901_VREG_ID_S3	10
 #define PM8901_VREG_ID_S4	11
 
-/* External regulator controlled by MPP pin ids */
-#define PM8901_VREG_ID_MPP0	12
-
 /* Low voltage switch regulator ids */
-#define PM8901_VREG_ID_LVS0	13
-#define PM8901_VREG_ID_LVS1	14
-#define PM8901_VREG_ID_LVS2	15
-#define PM8901_VREG_ID_LVS3	16
+#define PM8901_VREG_ID_LVS0	12
+#define PM8901_VREG_ID_LVS1	13
+#define PM8901_VREG_ID_LVS2	14
+#define PM8901_VREG_ID_LVS3	15
 
 /* Medium voltage switch regulator ids */
-#define PM8901_VREG_ID_MVS0	17
+#define PM8901_VREG_ID_MVS0	16
 
 /* USB OTG voltage switch regulator ids */
-#define PM8901_VREG_ID_USB_OTG	18
+#define PM8901_VREG_ID_USB_OTG	17
 
 /* HDMI medium voltage switch regulator ids */
-#define PM8901_VREG_ID_HDMI_MVS	19
+#define PM8901_VREG_ID_HDMI_MVS	18
 
 #define PM8901_VREG_MAX		(PM8901_VREG_ID_HDMI_MVS + 1)
 
@@ -70,10 +67,10 @@
 
 struct pm8901_vreg_pdata {
 	struct regulator_init_data	init_data;
+	int				id;
 	unsigned			pull_down_enable;
 	unsigned			pin_ctrl;
 	enum pm8901_vreg_pin_fn		pin_fn;
-	unsigned			active_high; /* For use with MPP. */
 };
 
 #endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index a2251fe..68fc67c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -21,6 +21,7 @@
 #include <linux/types.h>
 #include <linux/usb/otg.h>
 #include <linux/wakelock.h>
+#include <linux/pm_qos_params.h>
 
 /**
  * Supported USB modes
@@ -145,6 +146,7 @@
  *              dfab_usb_hs_clk in case of 8660 and 8960.
  * @pmic_id_irq: IRQ number assigned for PMIC USB ID line.
  * @mhl_enable: indicates MHL connector or not.
+ * @swfi_latency: miminum latency to allow swfi.
  */
 struct msm_otg_platform_data {
 	int *phy_init_seq;
@@ -158,6 +160,7 @@
 	const char *pclk_src_name;
 	int pmic_id_irq;
 	bool mhl_enable;
+	u32 swfi_latency;
 };
 
 /**
@@ -188,6 +191,8 @@
  *             connected. Useful only when ACA_A charger is
  *             connected.
  * @mA_port: The amount of current drawn by the attached B-device.
+ * @pm_qos_req_dma: miminum DMA latency to vote against idle power
+	collapse when cable is connected.
  * @id_timer: The timer used for polling ID line to detect ACA states.
  * @xo_handle: TCXO buffer handle
  */
@@ -244,6 +249,7 @@
 #define PHY_PWR_COLLAPSED		BIT(0)
 #define PHY_RETENTIONED			BIT(1)
 #define PHY_OTG_COMP_DISABLED		BIT(2)
+	struct pm_qos_request_list pm_qos_req_dma;
 };
 
 struct msm_hsic_host_platform_data {
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 3b37f85..02c0b95 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -16,6 +16,15 @@
 
 #include <linux/device.h>
 
+enum wcnss_opcode {
+	WCNSS_WLAN_SWITCH_OFF = 0,
+	WCNSS_WLAN_SWITCH_ON,
+};
+
+struct wcnss_wlan_config {
+	int		use_48mhz_xo;
+};
+
 #define WCNSS_WLAN_IRQ_INVALID -1
 
 struct device *wcnss_wlan_get_device(void);
@@ -26,6 +35,11 @@
 				const struct dev_pm_ops *pm_ops);
 void wcnss_wlan_unregister_pm_ops(struct device *dev,
 				const struct dev_pm_ops *pm_ops);
+struct platform_device *wcnss_get_platform_device(void);
+struct wcnss_wlan_config *wcnss_get_wlan_config(void);
+int wcnss_wlan_power(struct device *dev,
+				struct wcnss_wlan_config *cfg,
+				enum wcnss_opcode opcode);
 
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 2adc6b5..fe1f47a 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -26,7 +26,7 @@
 int irq_set_chip(unsigned int irq, struct irq_chip *chip)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return -EINVAL;
@@ -54,7 +54,7 @@
 int irq_set_irq_type(unsigned int irq, unsigned int type)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 	int ret = 0;
 
 	if (!desc)
@@ -78,7 +78,7 @@
 int irq_set_handler_data(unsigned int irq, void *data)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return -EINVAL;
@@ -98,7 +98,7 @@
 int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return -EINVAL;
@@ -119,7 +119,7 @@
 int irq_set_chip_data(unsigned int irq, void *data)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return -EINVAL;
@@ -204,6 +204,24 @@
 	}
 }
 
+void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu)
+{
+	if (desc->irq_data.chip->irq_enable)
+		desc->irq_data.chip->irq_enable(&desc->irq_data);
+	else
+		desc->irq_data.chip->irq_unmask(&desc->irq_data);
+	cpumask_set_cpu(cpu, desc->percpu_enabled);
+}
+
+void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu)
+{
+	if (desc->irq_data.chip->irq_disable)
+		desc->irq_data.chip->irq_disable(&desc->irq_data);
+	else
+		desc->irq_data.chip->irq_mask(&desc->irq_data);
+	cpumask_clear_cpu(cpu, desc->percpu_enabled);
+}
+
 static inline void mask_ack_irq(struct irq_desc *desc)
 {
 	if (desc->irq_data.chip->irq_mask_ack)
@@ -553,12 +571,44 @@
 		chip->irq_eoi(&desc->irq_data);
 }
 
+/**
+ * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids
+ * @irq:	the interrupt number
+ * @desc:	the interrupt description structure for this irq
+ *
+ * Per CPU interrupts on SMP machines without locking requirements. Same as
+ * handle_percpu_irq() above but with the following extras:
+ *
+ * action->percpu_dev_id is a pointer to percpu variables which
+ * contain the real device id for the cpu on which this handler is
+ * called
+ */
+void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irqaction *action = desc->action;
+	void *dev_id = __this_cpu_ptr(action->percpu_dev_id);
+	irqreturn_t res;
+
+	kstat_incr_irqs_this_cpu(irq, desc);
+
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
+
+	trace_irq_handler_entry(irq, action);
+	res = action->handler(irq, dev_id);
+	trace_irq_handler_exit(irq, action, res);
+
+	if (chip->irq_eoi)
+		chip->irq_eoi(&desc->irq_data);
+}
+
 void
 __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 		  const char *name)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
 
 	if (!desc)
 		return;
@@ -602,7 +652,7 @@
 void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 
 	if (!desc)
 		return;
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 6546431..a73dd6c 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -71,6 +71,8 @@
 extern void irq_shutdown(struct irq_desc *desc);
 extern void irq_enable(struct irq_desc *desc);
 extern void irq_disable(struct irq_desc *desc);
+extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
+extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
 extern void mask_irq(struct irq_desc *desc);
 extern void unmask_irq(struct irq_desc *desc);
 
@@ -114,14 +116,21 @@
 		desc->irq_data.chip->irq_bus_sync_unlock(&desc->irq_data);
 }
 
+#define _IRQ_DESC_CHECK		(1 << 0)
+#define _IRQ_DESC_PERCPU	(1 << 1)
+
+#define IRQ_GET_DESC_CHECK_GLOBAL	(_IRQ_DESC_CHECK)
+#define IRQ_GET_DESC_CHECK_PERCPU	(_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU)
+
 struct irq_desc *
-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus);
+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,
+		    unsigned int check);
 void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus);
 
 static inline struct irq_desc *
-irq_get_desc_buslock(unsigned int irq, unsigned long *flags)
+irq_get_desc_buslock(unsigned int irq, unsigned long *flags, unsigned int check)
 {
-	return __irq_get_desc_lock(irq, flags, true);
+	return __irq_get_desc_lock(irq, flags, true, check);
 }
 
 static inline void
@@ -131,9 +140,9 @@
 }
 
 static inline struct irq_desc *
-irq_get_desc_lock(unsigned int irq, unsigned long *flags)
+irq_get_desc_lock(unsigned int irq, unsigned long *flags, unsigned int check)
 {
-	return __irq_get_desc_lock(irq, flags, false);
+	return __irq_get_desc_lock(irq, flags, false, check);
 }
 
 static inline void
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 4c60a50..028e377 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -70,7 +70,8 @@
 static inline int desc_node(struct irq_desc *desc) { return 0; }
 #endif
 
-static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
+static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
+		struct module *owner)
 {
 	int cpu;
 
@@ -86,6 +87,7 @@
 	desc->irq_count = 0;
 	desc->irqs_unhandled = 0;
 	desc->name = NULL;
+	desc->owner = owner;
 	for_each_possible_cpu(cpu)
 		*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
 	desc_smp_init(desc, node);
@@ -128,7 +130,7 @@
 static inline void free_masks(struct irq_desc *desc) { }
 #endif
 
-static struct irq_desc *alloc_desc(int irq, int node)
+static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
 {
 	struct irq_desc *desc;
 	gfp_t gfp = GFP_KERNEL;
@@ -147,7 +149,7 @@
 	raw_spin_lock_init(&desc->lock);
 	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
 
-	desc_set_defaults(irq, desc, node);
+	desc_set_defaults(irq, desc, node, owner);
 
 	return desc;
 
@@ -173,13 +175,14 @@
 	kfree(desc);
 }
 
-static int alloc_descs(unsigned int start, unsigned int cnt, int node)
+static int alloc_descs(unsigned int start, unsigned int cnt, int node,
+		       struct module *owner)
 {
 	struct irq_desc *desc;
 	int i;
 
 	for (i = 0; i < cnt; i++) {
-		desc = alloc_desc(start + i, node);
+		desc = alloc_desc(start + i, node, owner);
 		if (!desc)
 			goto err;
 		mutex_lock(&sparse_irq_lock);
@@ -227,7 +230,7 @@
 		nr_irqs = initcnt;
 
 	for (i = 0; i < initcnt; i++) {
-		desc = alloc_desc(i, node);
+		desc = alloc_desc(i, node, NULL);
 		set_bit(i, allocated_irqs);
 		irq_insert_desc(i, desc);
 	}
@@ -261,7 +264,7 @@
 		alloc_masks(&desc[i], GFP_KERNEL, node);
 		raw_spin_lock_init(&desc[i].lock);
 		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
-		desc_set_defaults(i, &desc[i], node);
+		desc_set_defaults(i, &desc[i], node, NULL);
 	}
 	return arch_early_irq_init();
 }
@@ -276,8 +279,16 @@
 	dynamic_irq_cleanup(irq);
 }
 
-static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
+static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
+			      struct module *owner)
 {
+	u32 i;
+
+	for (i = 0; i < cnt; i++) {
+		struct irq_desc *desc = irq_to_desc(start + i);
+
+		desc->owner = owner;
+	}
 	return start;
 }
 
@@ -337,7 +348,8 @@
  * Returns the first irq number or error code
  */
 int __ref
-irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
+__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
+		  struct module *owner)
 {
 	int start, ret;
 
@@ -366,13 +378,13 @@
 
 	bitmap_set(allocated_irqs, start, cnt);
 	mutex_unlock(&sparse_irq_lock);
-	return alloc_descs(start, cnt, node);
+	return alloc_descs(start, cnt, node, owner);
 
 err:
 	mutex_unlock(&sparse_irq_lock);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(irq_alloc_descs);
+EXPORT_SYMBOL_GPL(__irq_alloc_descs);
 
 /**
  * irq_reserve_irqs - mark irqs allocated
@@ -411,11 +423,22 @@
 }
 
 struct irq_desc *
-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus)
+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,
+		    unsigned int check)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
 	if (desc) {
+		if (check & _IRQ_DESC_CHECK) {
+			if ((check & _IRQ_DESC_PERCPU) &&
+			    !irq_settings_is_per_cpu_devid(desc))
+				return NULL;
+
+			if (!(check & _IRQ_DESC_PERCPU) &&
+			    irq_settings_is_per_cpu_devid(desc))
+				return NULL;
+		}
+
 		if (bus)
 			chip_bus_lock(desc);
 		raw_spin_lock_irqsave(&desc->lock, *flags);
@@ -430,6 +453,25 @@
 		chip_bus_sync_unlock(desc);
 }
 
+int irq_set_percpu_devid(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (!desc)
+		return -EINVAL;
+
+	if (desc->percpu_enabled)
+		return -EINVAL;
+
+	desc->percpu_enabled = kzalloc(sizeof(*desc->percpu_enabled), GFP_KERNEL);
+
+	if (!desc->percpu_enabled)
+		return -ENOMEM;
+
+	irq_set_percpu_devid_flags(irq);
+	return 0;
+}
+
 /**
  * dynamic_irq_cleanup - cleanup a dynamically allocated irq
  * @irq:	irq number to initialize
@@ -440,7 +482,7 @@
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc_set_defaults(irq, desc, desc_node(desc));
+	desc_set_defaults(irq, desc, desc_node(desc), NULL);
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index b495711..1db1dc6 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -195,7 +195,7 @@
 int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return -EINVAL;
@@ -356,7 +356,7 @@
 static int __disable_irq_nosync(unsigned int irq)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return -EINVAL;
@@ -448,7 +448,7 @@
 void enable_irq(unsigned int irq)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 
 	if (!desc)
 		return;
@@ -488,7 +488,7 @@
 int irq_set_irq_wake(unsigned int irq, unsigned int on)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
 	int ret = 0;
 
 	if (!desc)
@@ -555,7 +555,7 @@
 int can_request_irq(unsigned int irq, unsigned long irqflags)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
 	int canrequest = 0;
 
 	if (!desc)
@@ -909,6 +909,8 @@
 
 	if (desc->irq_data.chip == &no_irq_chip)
 		return -ENOSYS;
+	if (!try_module_get(desc->owner))
+		return -ENODEV;
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
 	 * so we have to be careful not to interfere with a
@@ -932,8 +934,10 @@
 	 */
 	nested = irq_settings_is_nested_thread(desc);
 	if (nested) {
-		if (!new->thread_fn)
-			return -EINVAL;
+		if (!new->thread_fn) {
+			ret = -EINVAL;
+			goto out_mput;
+		}
 		/*
 		 * Replace the primary handler which was provided from
 		 * the driver for non nested interrupt handling by the
@@ -955,8 +959,10 @@
 
 		t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
 				   new->name);
-		if (IS_ERR(t))
-			return PTR_ERR(t);
+		if (IS_ERR(t)) {
+			ret = PTR_ERR(t);
+			goto out_mput;
+		}
 		/*
 		 * We keep the reference to the task struct even if
 		 * the thread dies to avoid that the interrupt code
@@ -1121,6 +1127,8 @@
 			kthread_stop(t);
 		put_task_struct(t);
 	}
+out_mput:
+	module_put(desc->owner);
 	return ret;
 }
 
@@ -1136,6 +1144,8 @@
 	int retval;
 	struct irq_desc *desc = irq_to_desc(irq);
 
+	if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+		return -EINVAL;
 	chip_bus_lock(desc);
 	retval = __setup_irq(irq, desc, act);
 	chip_bus_sync_unlock(desc);
@@ -1144,7 +1154,7 @@
 }
 EXPORT_SYMBOL_GPL(setup_irq);
 
- /*
+/*
  * Internal function to unregister an irqaction - used to free
  * regular and special interrupts that are part of the architecture.
  */
@@ -1236,6 +1246,7 @@
 		put_task_struct(action->thread);
 	}
 
+	module_put(desc->owner);
 	return action;
 }
 
@@ -1248,7 +1259,10 @@
  */
 void remove_irq(unsigned int irq, struct irqaction *act)
 {
-	__free_irq(irq, act->dev_id);
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc)))
+	    __free_irq(irq, act->dev_id);
 }
 EXPORT_SYMBOL_GPL(remove_irq);
 
@@ -1270,7 +1284,7 @@
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (!desc)
+	if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
 		return;
 
 #ifdef CONFIG_SMP
@@ -1348,7 +1362,8 @@
 	if (!desc)
 		return -EINVAL;
 
-	if (!irq_settings_can_request(desc))
+	if (!irq_settings_can_request(desc) ||
+	    WARN_ON(irq_settings_is_per_cpu_devid(desc)))
 		return -EINVAL;
 
 	if (!handler) {
@@ -1446,3 +1461,194 @@
 	}
 }
 EXPORT_SYMBOL_GPL(irq_set_pending);
+
+void enable_percpu_irq(unsigned int irq, unsigned int type)
+{
+	unsigned int cpu = smp_processor_id();
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);
+
+	if (!desc)
+		return;
+
+	type &= IRQ_TYPE_SENSE_MASK;
+	if (type != IRQ_TYPE_NONE) {
+		int ret;
+
+		ret = __irq_set_trigger(desc, irq, type);
+
+		if (ret) {
+			WARN(1, "failed to set type for IRQ%d\n", irq);
+			goto out;
+		}
+	}
+
+	irq_percpu_enable(desc, cpu);
+out:
+	irq_put_desc_unlock(desc, flags);
+}
+
+void disable_percpu_irq(unsigned int irq)
+{
+	unsigned int cpu = smp_processor_id();
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);
+
+	if (!desc)
+		return;
+
+	irq_percpu_disable(desc, cpu);
+	irq_put_desc_unlock(desc, flags);
+}
+
+/*
+ * Internal function to unregister a percpu irqaction.
+ */
+static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irqaction *action;
+	unsigned long flags;
+
+	WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
+
+	if (!desc)
+		return NULL;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+
+	action = desc->action;
+	if (!action || action->percpu_dev_id != dev_id) {
+		WARN(1, "Trying to free already-free IRQ %d\n", irq);
+		goto bad;
+	}
+
+	if (!cpumask_empty(desc->percpu_enabled)) {
+		WARN(1, "percpu IRQ %d still enabled on CPU%d!\n",
+		     irq, cpumask_first(desc->percpu_enabled));
+		goto bad;
+	}
+
+	/* Found it - now remove it from the list of entries: */
+	desc->action = NULL;
+
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+
+	unregister_handler_proc(irq, action);
+
+	module_put(desc->owner);
+	return action;
+
+bad:
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	return NULL;
+}
+
+/**
+ *	remove_percpu_irq - free a per-cpu interrupt
+ *	@irq: Interrupt line to free
+ *	@act: irqaction for the interrupt
+ *
+ * Used to remove interrupts statically setup by the early boot process.
+ */
+void remove_percpu_irq(unsigned int irq, struct irqaction *act)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc && irq_settings_is_per_cpu_devid(desc))
+	    __free_percpu_irq(irq, act->percpu_dev_id);
+}
+
+/**
+ *	free_percpu_irq - free an interrupt allocated with request_percpu_irq
+ *	@irq: Interrupt line to free
+ *	@dev_id: Device identity to free
+ *
+ *	Remove a percpu interrupt handler. The handler is removed, but
+ *	the interrupt line is not disabled. This must be done on each
+ *	CPU before calling this function. The function does not return
+ *	until any executing interrupts for this IRQ have completed.
+ *
+ *	This function must not be called from interrupt context.
+ */
+void free_percpu_irq(unsigned int irq, void __percpu *dev_id)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (!desc || !irq_settings_is_per_cpu_devid(desc))
+		return;
+
+	chip_bus_lock(desc);
+	kfree(__free_percpu_irq(irq, dev_id));
+	chip_bus_sync_unlock(desc);
+}
+
+/**
+ *	setup_percpu_irq - setup a per-cpu interrupt
+ *	@irq: Interrupt line to setup
+ *	@act: irqaction for the interrupt
+ *
+ * Used to statically setup per-cpu interrupts in the early boot process.
+ */
+int setup_percpu_irq(unsigned int irq, struct irqaction *act)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	int retval;
+
+	if (!desc || !irq_settings_is_per_cpu_devid(desc))
+		return -EINVAL;
+	chip_bus_lock(desc);
+	retval = __setup_irq(irq, desc, act);
+	chip_bus_sync_unlock(desc);
+
+	return retval;
+}
+
+/**
+ *	request_percpu_irq - allocate a percpu interrupt line
+ *	@irq: Interrupt line to allocate
+ *	@handler: Function to be called when the IRQ occurs.
+ *	@devname: An ascii name for the claiming device
+ *	@dev_id: A percpu cookie passed back to the handler function
+ *
+ *	This call allocates interrupt resources, but doesn't
+ *	automatically enable the interrupt. It has to be done on each
+ *	CPU using enable_percpu_irq().
+ *
+ *	Dev_id must be globally unique. It is a per-cpu variable, and
+ *	the handler gets called with the interrupted CPU's instance of
+ *	that variable.
+ */
+int request_percpu_irq(unsigned int irq, irq_handler_t handler,
+		       const char *devname, void __percpu *dev_id)
+{
+	struct irqaction *action;
+	struct irq_desc *desc;
+	int retval;
+
+	if (!dev_id)
+		return -EINVAL;
+
+	desc = irq_to_desc(irq);
+	if (!desc || !irq_settings_can_request(desc) ||
+	    !irq_settings_is_per_cpu_devid(desc))
+		return -EINVAL;
+
+	action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = IRQF_PERCPU;
+	action->name = devname;
+	action->percpu_dev_id = dev_id;
+
+	chip_bus_lock(desc);
+	retval = __setup_irq(irq, desc, action);
+	chip_bus_sync_unlock(desc);
+
+	if (retval)
+		kfree(action);
+
+	return retval;
+}
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h
index f166783..1162f10 100644
--- a/kernel/irq/settings.h
+++ b/kernel/irq/settings.h
@@ -13,6 +13,7 @@
 	_IRQ_MOVE_PCNTXT	= IRQ_MOVE_PCNTXT,
 	_IRQ_NO_BALANCING	= IRQ_NO_BALANCING,
 	_IRQ_NESTED_THREAD	= IRQ_NESTED_THREAD,
+	_IRQ_PER_CPU_DEVID	= IRQ_PER_CPU_DEVID,
 	_IRQF_MODIFY_MASK	= IRQF_MODIFY_MASK,
 };
 
@@ -24,6 +25,7 @@
 #define IRQ_NOTHREAD		GOT_YOU_MORON
 #define IRQ_NOAUTOEN		GOT_YOU_MORON
 #define IRQ_NESTED_THREAD	GOT_YOU_MORON
+#define IRQ_PER_CPU_DEVID	GOT_YOU_MORON
 #undef IRQF_MODIFY_MASK
 #define IRQF_MODIFY_MASK	GOT_YOU_MORON
 
@@ -39,6 +41,11 @@
 	return desc->status_use_accessors & _IRQ_PER_CPU;
 }
 
+static inline bool irq_settings_is_per_cpu_devid(struct irq_desc *desc)
+{
+	return desc->status_use_accessors & _IRQ_PER_CPU_DEVID;
+}
+
 static inline void irq_settings_set_per_cpu(struct irq_desc *desc)
 {
 	desc->status_use_accessors |= _IRQ_PER_CPU;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 3573169..b254cd8 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -518,9 +518,11 @@
 	int eq_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->reg;
 
+	ucontrol->value.integer.value[0] = eq_data[eq_idx].enable;
+
 	pr_debug("%s: EQ #%d enable %d\n", __func__,
 		eq_idx, eq_data[eq_idx].enable);
-	return eq_data[eq_idx].enable;
+	return 0;
 }
 
 static int msm_routing_put_eq_enable_mixer(struct snd_kcontrol *kcontrol,
@@ -545,6 +547,8 @@
 	int eq_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->reg;
 
+	ucontrol->value.integer.value[0] = eq_data[eq_idx].num_bands;
+
 	pr_debug("%s: EQ #%d bands %d\n", __func__,
 		eq_idx, eq_data[eq_idx].num_bands);
 	return eq_data[eq_idx].num_bands;
@@ -558,7 +562,6 @@
 					kcontrol->private_value)->reg;
 	int value = ucontrol->value.integer.value[0];
 
-
 	pr_debug("%s: EQ #%d bands %d\n", __func__,
 		eq_idx, value);
 	eq_data[eq_idx].num_bands = value;
@@ -573,6 +576,17 @@
 	int band_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->shift;
 
+	ucontrol->value.integer.value[0] =
+			eq_data[eq_idx].eq_bands[band_idx].band_idx;
+	ucontrol->value.integer.value[1] =
+			eq_data[eq_idx].eq_bands[band_idx].filter_type;
+	ucontrol->value.integer.value[2] =
+			eq_data[eq_idx].eq_bands[band_idx].center_freq_hz;
+	ucontrol->value.integer.value[3] =
+			eq_data[eq_idx].eq_bands[band_idx].filter_gain;
+	ucontrol->value.integer.value[4] =
+			eq_data[eq_idx].eq_bands[band_idx].q_factor;
+
 	pr_debug("%s: band_idx = %d\n", __func__,
 			eq_data[eq_idx].eq_bands[band_idx].band_idx);
 	pr_debug("%s: filter_type = %d\n", __func__,