Merge "mmc: core: Use usleep_range for delays less than 20ms" into msm-3.0
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
new file mode 100644
index 0000000..c1399ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -0,0 +1,51 @@
+MSM SoC HSUSB controllers
+
+OTG:
+
+Required properties :
+- compatible : should be "qcom,hsusb-otg"
+- regs : offset and length of the register set in the memory map
+- interrupts: IRQ line
+- qcom,hsusb-otg-phy-type: PHY type can be one of
+            1 - Chipidea 45nm PHY
+	    2 - Synopsis 28nm PHY
+- qcom,hsusb-otg-mode: Operational mode. Can be one of
+            1 - Peripheral only mode
+	    2 - Host only mode
+	    3 - OTG mode
+	    Based on the mode, OTG driver registers platform devices for
+	    gadget and host.
+- qcom,hsusb-otg-control: OTG control (VBUS and ID notifications)
+  can be one of
+            1 - PHY control
+	    2 - PMIC control
+	    3 - User control (via debugfs)
+
+Optional properties :
+- qcom,hsusb-otg-default-mode: The default USB mode after boot-up.
+  Applicable only when OTG is controlled by user. Can be one of
+            0 - None. Low power mode
+            1 - Peripheral
+	    2 - Host
+- qcom,hsusb-otg-phy-init-seq: PHY configuration sequence. val, reg pairs
+  terminate with -1
+- qcom,hsusb-otg-power-budget: VBUS power budget in mA
+  0 will be treated as 500mA
+- qcom,hsusb-otg-pclk-src-name: The source of pclk
+- qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
+
+Example HSUSB OTG controller device node :
+	usb@F9690000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0xF9690000 0x400>;
+		interrupts = <134>;
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-default-mode = <2>;
+		qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xFFFFFFFF>;
+		qcom,hsusb-otg-power-budget = <500>;
+		qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
+		qcom,hsusb-otg-pmic-id-irq = <47>
+	};
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index 52c0b66..74fc5a9 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -20,4 +20,14 @@
 		reg = <0xF9684000 0x1000>;
 		interrupts = <109>;
 	};
+
+	usb@F9690000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0xF9690000 0x400>;
+		interrupts = <134>;
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+	};
 };
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 60d8a32..92d401c 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -26,7 +26,6 @@
 CONFIG_MSM7X00A_USE_DG_TIMER=y
 CONFIG_MSM7X00A_SLEEP_WAIT_FOR_INTERRUPT=y
 CONFIG_MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT=y
-CONFIG_MSM_JTAG_V7=y
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG3=y
 # CONFIG_MSM_SMD_DEBUG is not set
@@ -35,6 +34,7 @@
 # CONFIG_MSM_HW3D is not set
 # CONFIG_QSD_AUDIO is not set
 # CONFIG_SURF_FFA_GPIO_KEYPAD is not set
+CONFIG_MSM_JTAG_V7=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_VMSPLIT_2G=y
@@ -134,12 +134,13 @@
 CONFIG_POWER_SUPPLY=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_PMIC8058=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_PM8058_XO=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-# CONFIG_LEDS_MSM_PMIC is not set
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index 6913409..ebff2d2 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -132,12 +132,13 @@
 CONFIG_POWER_SUPPLY=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_PMIC8058=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_PM8058_XO=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
-# CONFIG_LEDS_MSM_PMIC is not set
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 9fb4615..6c50ae9 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -95,7 +95,9 @@
 # CONFIG_HWMON is not set
 # CONFIG_MFD_SUPPORT is not set
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 # CONFIG_LEDS_MSM_PMIC is not set
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 4322baf..90d4c4a 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -31,7 +31,6 @@
 # CONFIG_MACH_MSM7X27_FFA is not set
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_MSM7X00A_USE_DG_TIMER=y
-# CONFIG_MSM_JTAG_V7 is not set
 # CONFIG_MSM_FIQ_SUPPORT is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
@@ -45,6 +44,7 @@
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM7X27A_AUDIO=y
 CONFIG_MSM_DMA_TEST=y
+# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_BT_MSM_PINTEST=y
 CONFIG_MSM_RPC_VIBRATOR=y
 CONFIG_PM8XXX_RPC_VIBRATOR=y
@@ -157,8 +157,9 @@
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_BT_MSM_SLEEP=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
 CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -184,8 +185,6 @@
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_10000 is not set
 CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
@@ -194,7 +193,6 @@
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C=y
-CONFIG_SYNA_MULTI_TOUCH=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=y
@@ -275,6 +273,7 @@
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_BLOCK_MINORS=32
 # CONFIG_MMC_BLOCK_BOUNCE is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index be8ade5..53d6367 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -30,7 +30,6 @@
 # CONFIG_MACH_MSM7X27_FFA is not set
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_MSM7X00A_USE_DG_TIMER=y
-# CONFIG_MSM_JTAG_V7 is not set
 # CONFIG_MSM_FIQ_SUPPORT is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
@@ -44,6 +43,7 @@
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM7X27A_AUDIO=y
 CONFIG_MSM_DMA_TEST=y
+# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_BT_MSM_PINTEST=y
 CONFIG_MSM_RPC_VIBRATOR=y
 CONFIG_PM8XXX_RPC_VIBRATOR=y
@@ -155,8 +155,9 @@
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_BT_MSM_SLEEP=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
 CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -182,8 +183,6 @@
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_10000 is not set
 CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
@@ -192,7 +191,6 @@
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C=y
-CONFIG_SYNA_MULTI_TOUCH=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=y
@@ -270,6 +268,7 @@
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_BLOCK_MINORS=32
 # CONFIG_MMC_BLOCK_BOUNCE is not set
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 202d117..2cd7b97 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -26,7 +26,6 @@
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM7X30=y
 # CONFIG_MSM_STACKED_MEMORY is not set
-# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG3=y
 CONFIG_MSM_SDIO_DMUX=y
@@ -41,6 +40,7 @@
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
 CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
 CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
+# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -71,7 +71,6 @@
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -173,9 +172,10 @@
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
 # CONFIG_WIRELESS_EXT_SYSFS is not set
 CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -187,7 +187,7 @@
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_MISC_DEVICES=y
 CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_UPL=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
@@ -208,8 +208,6 @@
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
 CONFIG_SLIP=y
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_MODE_SLIP6=y
@@ -218,6 +216,8 @@
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 # CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_MSM=y
@@ -251,6 +251,9 @@
 CONFIG_MARIMBA_CORE=y
 CONFIG_MARIMBA_CODEC=y
 CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_DEBUG is not set
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -326,7 +329,6 @@
 CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
 CONFIG_MMC_MSM_SDC3_SUPPORT=y
 CONFIG_MMC_MSM_SDC4_SUPPORT=y
-# CONFIG_LEDS_MSM_PMIC is not set
 CONFIG_LEDS_PMIC8058=y
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index bc944d0..362babe 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -70,7 +70,6 @@
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -172,9 +171,10 @@
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
 # CONFIG_WIRELESS_EXT_SYSFS is not set
 CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -186,7 +186,7 @@
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_MISC_DEVICES=y
 CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_UPL=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
@@ -207,8 +207,6 @@
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
 CONFIG_SLIP=y
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_MODE_SLIP6=y
@@ -217,6 +215,8 @@
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 # CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_MSM=y
@@ -250,6 +250,9 @@
 CONFIG_MARIMBA_CORE=y
 CONFIG_MARIMBA_CODEC=y
 CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_DEBUG is not set
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
 CONFIG_MSM_KGSL=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index d377460..d84f64a 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -43,7 +43,6 @@
 CONFIG_MSM7X00A_USE_DG_TIMER=y
 CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE=y
 CONFIG_MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT=y
-# CONFIG_MSM_JTAG_V7 is not set
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
@@ -67,6 +66,7 @@
 CONFIG_MSM_RPM_STATS_LOG=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
+# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_MSM_ETM=y
 CONFIG_MSM_SLEEP_STATS=y
 CONFIG_MSM_GSBI9_UART=y
@@ -104,7 +104,6 @@
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -212,9 +211,10 @@
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
 # CONFIG_WIRELESS_EXT_SYSFS is not set
 CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_MISC_DEVICES=y
@@ -222,10 +222,9 @@
 CONFIG_TSIF=m
 CONFIG_TSIF_CHRDEV=m
 CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_VIBRATOR=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_VIBRATOR=y
+CONFIG_PMIC8XXX_UPL=y
 CONFIG_PMIC8058_XOADC=y
-CONFIG_PMIC8058_MISC=y
 CONFIG_TZCOM=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
@@ -249,8 +248,6 @@
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
 CONFIG_PPP=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_DEFLATE=y
@@ -264,6 +261,8 @@
 CONFIG_INPUT_KEYRESET=y
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_MATRIX=y
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -271,7 +270,7 @@
 CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
-CONFIG_PMIC8058_PWRKEY=y
+CONFIG_INPUT_PMIC8XXX_PWRKEY=y
 CONFIG_PMIC8058_OTHC=y
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_HSL=y
@@ -302,11 +301,13 @@
 CONFIG_THERMAL=y
 CONFIG_THERMAL_HWMON=y
 CONFIG_THERMAL_PM8901=y
-CONFIG_THERMAL_PM8058=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_THERMAL_PM8XXX=y
 CONFIG_PMIC8058=y
 CONFIG_MARIMBA_CORE=y
 CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+CONFIG_MFD_PM8XXX_BATT_ALARM=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -369,6 +370,7 @@
 CONFIG_MMC_EMBEDDED_SDIO=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SDIO_SUPPORT=y
 CONFIG_MMC_MSM_CARD_HW_DETECTION=y
@@ -379,7 +381,6 @@
 CONFIG_MMC_MSM_SDC4_SUPPORT=y
 CONFIG_MMC_MSM_SDC5_SUPPORT=y
 CONFIG_LEDS_GPIO=y
-# CONFIG_LEDS_MSM_PMIC is not set
 CONFIG_LEDS_PMIC8058=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
@@ -389,7 +390,7 @@
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
-CONFIG_RTC_PM8058=y
+CONFIG_RTC_DRV_PM8XXX=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 2569f82..8f049a5 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -95,7 +95,6 @@
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
 CONFIG_IPV6=y
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -203,9 +202,10 @@
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
 # CONFIG_WIRELESS_EXT_SYSFS is not set
 CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_MISC_DEVICES=y
@@ -214,10 +214,9 @@
 CONFIG_TSIF=m
 CONFIG_TSIF_CHRDEV=m
 CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_VIBRATOR=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_VIBRATOR=y
+CONFIG_PMIC8XXX_UPL=y
 CONFIG_PMIC8058_XOADC=y
-CONFIG_PMIC8058_MISC=y
 CONFIG_TZCOM=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
@@ -242,8 +241,6 @@
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
 CONFIG_PPP=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_DEFLATE=y
@@ -256,6 +253,8 @@
 CONFIG_INPUT_KEYRESET=y
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_MATRIX=y
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -263,7 +262,7 @@
 CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
-CONFIG_PMIC8058_PWRKEY=y
+CONFIG_INPUT_PMIC8XXX_PWRKEY=y
 CONFIG_PMIC8058_OTHC=y
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_HSL=y
@@ -293,11 +292,13 @@
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_PM8901=y
-CONFIG_THERMAL_PM8058=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_THERMAL_PM8XXX=y
 CONFIG_PMIC8058=y
 CONFIG_MARIMBA_CORE=y
 CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+CONFIG_MFD_PM8XXX_BATT_ALARM=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -356,6 +357,7 @@
 CONFIG_MMC_EMBEDDED_SDIO=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SDIO_SUPPORT=y
 CONFIG_MMC_MSM_CARD_HW_DETECTION=y
@@ -366,7 +368,6 @@
 CONFIG_MMC_MSM_SDC4_SUPPORT=y
 CONFIG_MMC_MSM_SDC5_SUPPORT=y
 CONFIG_LEDS_GPIO=y
-# CONFIG_LEDS_MSM_PMIC is not set
 CONFIG_LEDS_PMIC8058=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
@@ -376,7 +377,7 @@
 CONFIG_SWITCH_GPIO=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_DRV_MSM is not set
-CONFIG_RTC_PM8058=y
+CONFIG_RTC_DRV_PM8XXX=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 235db63..c41f64c 100755
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -63,6 +63,7 @@
 CONFIG_MSM_LPASS_8960=y
 CONFIG_MSM_WCNSS_SSR_8960=y
 CONFIG_MSM_RPM_LOG=y
+CONFIG_MSM_RPM_STATS_LOG=y
 CONFIG_MSM_BUS_SCALING=y
 CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
 CONFIG_MSM_WATCHDOG=y
@@ -201,6 +202,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_MISC_DEVICES=y
+CONFIG_HAPTIC_ISA1200=y
 CONFIG_PMIC8XXX_VIBRATOR=y
 CONFIG_TZCOM=y
 CONFIG_SCSI=y
@@ -263,6 +265,7 @@
 CONFIG_GPIO_SX150X=y
 CONFIG_POWER_SUPPLY=y
 # CONFIG_BATTERY_MSM is not set
+CONFIG_ISL9519_CHARGER=y
 CONFIG_PM8921_CHARGER=y
 CONFIG_PM8921_BMS=y
 CONFIG_SENSORS_PM8921_ADC=y
@@ -270,6 +273,7 @@
 CONFIG_THERMAL_TSENS8960=y
 CONFIG_THERMAL_PM8XXX=y
 CONFIG_MFD_PM8921_CORE=y
+CONFIG_MFD_PM8821_CORE=y
 CONFIG_MFD_PM8XXX_BATT_ALARM=y
 CONFIG_WCD9310_CODEC=y
 CONFIG_REGULATOR_GPIO=y
@@ -333,6 +337,7 @@
 CONFIG_USB_SERIAL=y
 CONFIG_USB_SERIAL_QUALCOMM=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_QCOM_DIAG_BRIDGE=y
 CONFIG_USB_QCOM_DUN_BRIDGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
@@ -345,6 +350,7 @@
 CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_CARD_HW_DETECTION=y
 CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 714e630..83efc02 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -36,16 +36,21 @@
 CONFIG_MACH_MSM9615_MTP=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
-# CONFIG_MSM_JTAG_V7 is not set
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_BAM_DMUX=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+# CONFIG_MSM_SYSMON_COMM is not set
+CONFIG_MSM_MODEM_8960=y
+CONFIG_MSM_LPASS_8960=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG=y
 CONFIG_MSM_DLOAD_MODE=y
+# CONFIG_MSM_JTAG_V7 is not set
 CONFIG_SWP_EMULATE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -62,16 +67,35 @@
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_CFG80211=y
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_PM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_MISC_DEVICES=y
 # CONFIG_ANDROID_PMEM is not set
+CONFIG_NETDEVICES=y
+CONFIG_HOSTAP=m
+# CONFIG_MSM_RMNET is not set
+CONFIG_MSM_RMNET_BAM=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
@@ -94,21 +118,17 @@
 CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_MSM is not set
 CONFIG_I2C_QUP=y
+CONFIG_MSM_BUS_SCALING=y
+CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
-CONFIG_HWMON=y
 CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
 CONFIG_MFD_PM8018_CORE=y
-CONFIG_MFD_PM8XXX_PWM=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_PM8XXX=y
-# CONFIG_LEDS_MSM_PMIC is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_GPIO=y
 # CONFIG_HID_SUPPORT is not set
@@ -116,56 +136,23 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_CI13XXX_MSM=y
 CONFIG_USB_G_ANDROID=y
-CONFIG_SWITCH=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-# CONFIG_ANDROID_PARANOID_NETWORK is not set
-# CONFIG_WIRELESS is not set
+CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
+CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
 CONFIG_MMC=y
-# CONFIG_MMC_DEBUG is not set
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
-# CONFIG_MMC_CLKGATE is not set
 CONFIG_MMC_EMBEDDED_SDIO=y
 CONFIG_MMC_PARANOID_SD_INIT=y
-
-#
-# MMC/SD/SDIO Card Drivers
-#
-CONFIG_MMC_BLOCK=y
 CONFIG_MMC_BLOCK_MINORS=32
 # CONFIG_MMC_BLOCK_BOUNCE is not set
-# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
-# CONFIG_SDIO_UART is not set
-# CONFIG_MMC_TEST is not set
-
-#
-# MMC/SD/SDIO Host Controller Drivers
-#
-# CONFIG_MMC_SDHCI is not set
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SDIO_SUPPORT=y
 CONFIG_MMC_MSM_CARD_HW_DETECTION=y
-CONFIG_MMC_MSM_SDC1_SUPPORT=y
-# CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT is not set
-CONFIG_MMC_MSM_SDC2_SUPPORT=y
-# CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT is not set
-# CONFIG_MMC_MSM_SDC3_SUPPORT is not set
-# CONFIG_MMC_MSM_SDC4_SUPPORT is not set
-# CONFIG_MMC_MSM_SDC5_SUPPORT is not set
 CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PM8XXX=y
+CONFIG_SWITCH=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_INTF_ALARM is not set
 # CONFIG_RTC_DRV_MSM is not set
@@ -178,6 +165,7 @@
 CONFIG_YAFFS_FS=y
 CONFIG_YAFFS_DISABLE_TAGS_ECC=y
 CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
@@ -205,29 +193,8 @@
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_HW=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-
-CONFIG_WIRELESS=y
-CONFIG_WEXT_CORE=y
-CONFIG_WEXT_PROC=y
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=y
-CONFIG_WIRELESS_EXT_SYSFS=y
-CONFIG_LIB80211=m
-CONFIG_NETDEVICES=y
-CONFIG_WLAN=y
-# CONFIG_MSM_RMNET is not set
-CONFIG_MSM_BAM_DMUX=y
-CONFIG_MSM_RMNET_BAM=y
-CONFIG_HOSTAP=m
-CONFIG_WIRELESS_EXT=y
-CONFIG_WEXT_SPY=y
-CONFIG_WEXT_PRIV=y
-CONFIG_LIB80211_CRYPT_WEP=m
-CONFIG_LIB80211_CRYPT_CCMP=m
-CONFIG_LIB80211_CRYPT_TKIP=m
diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h
index c1062c3..c93a22a 100644
--- a/arch/arm/include/asm/hwcap.h
+++ b/arch/arm/include/asm/hwcap.h
@@ -4,22 +4,26 @@
 /*
  * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
  */
-#define HWCAP_SWP	1
-#define HWCAP_HALF	2
-#define HWCAP_THUMB	4
-#define HWCAP_26BIT	8	/* Play it safe */
-#define HWCAP_FAST_MULT	16
-#define HWCAP_FPA	32
-#define HWCAP_VFP	64
-#define HWCAP_EDSP	128
-#define HWCAP_JAVA	256
-#define HWCAP_IWMMXT	512
-#define HWCAP_CRUNCH	1024
-#define HWCAP_THUMBEE	2048
-#define HWCAP_NEON	4096
-#define HWCAP_VFPv3	8192
-#define HWCAP_VFPv3D16	16384
-#define HWCAP_TLS	32768
+#define HWCAP_SWP	(1 << 0)
+#define HWCAP_HALF	(1 << 1)
+#define HWCAP_THUMB	(1 << 2)
+#define HWCAP_26BIT	(1 << 3)	/* Play it safe */
+#define HWCAP_FAST_MULT	(1 << 4)
+#define HWCAP_FPA	(1 << 5)
+#define HWCAP_VFP	(1 << 6)
+#define HWCAP_EDSP	(1 << 7)
+#define HWCAP_JAVA	(1 << 8)
+#define HWCAP_IWMMXT	(1 << 9)
+#define HWCAP_CRUNCH	(1 << 10)
+#define HWCAP_THUMBEE	(1 << 11)
+#define HWCAP_NEON	(1 << 12)
+#define HWCAP_VFPv3	(1 << 13)
+#define HWCAP_VFPv3D16	(1 << 14)
+#define HWCAP_TLS	(1 << 15)
+#define HWCAP_VFPv4	(1 << 16)
+#define HWCAP_IDIVA	(1 << 17)
+#define HWCAP_IDIVT	(1 << 18)
+#define HWCAP_IDIV	(HWCAP_IDIVA | HWCAP_IDIVT)
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 /*
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 6e55bf3..c86fad9 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -140,7 +140,6 @@
 	bool nonremovable;
 	bool pclk_src_dfab;
 	int (*cfg_mpm_sdiowakeup)(struct device *, unsigned);
-	bool sdcc_v4_sup;
 	unsigned int wpswitch_gpio;
 	unsigned char wpswitch_polarity;
 	struct msm_mmc_slot_reg_data *vreg_data;
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index 0e1fd19..87d1bed 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -24,6 +24,8 @@
 	ARM_PERF_PMU_ID_V6MP,
 	ARM_PERF_PMU_ID_CA8,
 	ARM_PERF_PMU_ID_CA9,
+	ARM_PERF_PMU_ID_CA5,
+	ARM_PERF_PMU_ID_CA15,
 	ARM_PERF_PMU_ID_SCORPION,
 	ARM_PERF_PMU_ID_SCORPIONMP,
 	ARM_PERF_PMU_ID_KRAIT,
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index f379b04..2f8bf62 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -348,8 +348,8 @@
  *  r13 = *virtual* address to jump to upon completion
  */
 __enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
-	orr	r0, r0, #CR_A
+#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
+      orr     r0, r0, #CR_A
 #else
 	bic	r0, r0, #CR_A
 #endif
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index c9982829..c8f963c 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -680,6 +680,12 @@
 		case 0xC090:	/* Cortex-A9 */
 			armpmu = armv7_a9_pmu_init();
 			break;
+		case 0xC050:	/* Cortex-A5 */
+			armpmu = armv7_a5_pmu_init();
+			break;
+		case 0xC0F0:	/* Cortex-A15 */
+			armpmu = armv7_a15_pmu_init();
+			break;
 		}
 	/* Intel CPUs [xscale]. */
 	} else if (0x69 == implementor) {
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index fb53650..579cd3b 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -215,15 +215,15 @@
 	[C(BPU)] = {
 		[C(OP_READ)] = {
 			[C(RESULT_ACCESS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 		},
 		[C(OP_WRITE)] = {
 			[C(RESULT_ACCESS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 62509b4..1e77489 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -122,15 +122,15 @@
 	[C(BPU)] = {
 		[C(OP_READ)] = {
 			[C(RESULT_ACCESS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 		},
 		[C(OP_WRITE)] = {
 			[C(RESULT_ACCESS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 			[C(RESULT_MISS)]
-					= ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+					= ARMV7_PERFCTR_PC_BRANCH_PRED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
@@ -365,7 +365,7 @@
 
 static struct arm_pmu krait_pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
-#ifdef CONFIG_MSM_SMP
+#ifdef CONFIG_SMP
 	.secondary_enable       = scorpion_secondary_enable,
 	.secondary_disable      = scorpion_secondary_disable,
 #endif
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 4960686..9633178 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -17,17 +17,23 @@
  */
 
 #ifdef CONFIG_CPU_V7
-/* Common ARMv7 event types */
+/*
+ * Common ARMv7 event types
+ *
+ * Note: An implementation may not be able to count all of these events
+ * but the encodings are considered to be `reserved' in the case that
+ * they are not available.
+ */
 enum armv7_perf_types {
 	ARMV7_PERFCTR_PMNC_SW_INCR		= 0x00,
 	ARMV7_PERFCTR_IFETCH_MISS		= 0x01,
 	ARMV7_PERFCTR_ITLB_MISS			= 0x02,
-	ARMV7_PERFCTR_DCACHE_REFILL		= 0x03,
-	ARMV7_PERFCTR_DCACHE_ACCESS		= 0x04,
+	ARMV7_PERFCTR_DCACHE_REFILL		= 0x03,	/* L1 */
+	ARMV7_PERFCTR_DCACHE_ACCESS		= 0x04,	/* L1 */
 	ARMV7_PERFCTR_DTLB_REFILL		= 0x05,
 	ARMV7_PERFCTR_DREAD			= 0x06,
 	ARMV7_PERFCTR_DWRITE			= 0x07,
-
+	ARMV7_PERFCTR_INSTR_EXECUTED		= 0x08,
 	ARMV7_PERFCTR_EXC_TAKEN			= 0x09,
 	ARMV7_PERFCTR_EXC_EXECUTED		= 0x0A,
 	ARMV7_PERFCTR_CID_WRITE			= 0x0B,
@@ -39,21 +45,30 @@
 	 */
 	ARMV7_PERFCTR_PC_WRITE			= 0x0C,
 	ARMV7_PERFCTR_PC_IMM_BRANCH		= 0x0D,
+	ARMV7_PERFCTR_PC_PROC_RETURN		= 0x0E,
 	ARMV7_PERFCTR_UNALIGNED_ACCESS		= 0x0F,
+
+	/* These events are defined by the PMUv2 supplement (ARM DDI 0457A). */
 	ARMV7_PERFCTR_PC_BRANCH_MIS_PRED	= 0x10,
 	ARMV7_PERFCTR_CLOCK_CYCLES		= 0x11,
-
-	ARMV7_PERFCTR_PC_BRANCH_MIS_USED	= 0x12,
+	ARMV7_PERFCTR_PC_BRANCH_PRED		= 0x12,
+	ARMV7_PERFCTR_MEM_ACCESS		= 0x13,
+	ARMV7_PERFCTR_L1_ICACHE_ACCESS		= 0x14,
+	ARMV7_PERFCTR_L1_DCACHE_WB		= 0x15,
+	ARMV7_PERFCTR_L2_DCACHE_ACCESS		= 0x16,
+	ARMV7_PERFCTR_L2_DCACHE_REFILL		= 0x17,
+	ARMV7_PERFCTR_L2_DCACHE_WB		= 0x18,
+	ARMV7_PERFCTR_BUS_ACCESS		= 0x19,
+	ARMV7_PERFCTR_MEMORY_ERROR		= 0x1A,
+	ARMV7_PERFCTR_INSTR_SPEC		= 0x1B,
+	ARMV7_PERFCTR_TTBR_WRITE		= 0x1C,
+	ARMV7_PERFCTR_BUS_CYCLES		= 0x1D,
 
 	ARMV7_PERFCTR_CPU_CYCLES		= 0xFF
 };
 
 /* ARMv7 Cortex-A8 specific event types */
 enum armv7_a8_perf_types {
-	ARMV7_PERFCTR_INSTR_EXECUTED		= 0x08,
-
-	ARMV7_PERFCTR_PC_PROC_RETURN		= 0x0E,
-
 	ARMV7_PERFCTR_WRITE_BUFFER_FULL		= 0x40,
 	ARMV7_PERFCTR_L2_STORE_MERGED		= 0x41,
 	ARMV7_PERFCTR_L2_STORE_BUFF		= 0x42,
@@ -138,6 +153,39 @@
 	ARMV7_PERFCTR_PLE_RQST_PROG		= 0xA5
 };
 
+/* ARMv7 Cortex-A5 specific event types */
+enum armv7_a5_perf_types {
+	ARMV7_PERFCTR_IRQ_TAKEN			= 0x86,
+	ARMV7_PERFCTR_FIQ_TAKEN			= 0x87,
+
+	ARMV7_PERFCTR_EXT_MEM_RQST		= 0xc0,
+	ARMV7_PERFCTR_NC_EXT_MEM_RQST		= 0xc1,
+	ARMV7_PERFCTR_PREFETCH_LINEFILL		= 0xc2,
+	ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP	= 0xc3,
+	ARMV7_PERFCTR_ENTER_READ_ALLOC		= 0xc4,
+	ARMV7_PERFCTR_READ_ALLOC		= 0xc5,
+
+	ARMV7_PERFCTR_STALL_SB_FULL		= 0xc9,
+};
+
+/* ARMv7 Cortex-A15 specific event types */
+enum armv7_a15_perf_types {
+	ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS	= 0x40,
+	ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS	= 0x41,
+	ARMV7_PERFCTR_L1_DCACHE_READ_REFILL	= 0x42,
+	ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL	= 0x43,
+
+	ARMV7_PERFCTR_L1_DTLB_READ_REFILL	= 0x4C,
+	ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL	= 0x4D,
+
+	ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS	= 0x50,
+	ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS	= 0x51,
+	ARMV7_PERFCTR_L2_DCACHE_READ_REFILL	= 0x52,
+	ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL	= 0x53,
+
+	ARMV7_PERFCTR_SPEC_PC_WRITE		= 0x76,
+};
+
 /*
  * Cortex-A8 HW events mapping
  *
@@ -207,11 +255,6 @@
 		},
 	},
 	[C(DTLB)] = {
-		/*
-		 * Only ITLB misses and DTLB refills are supported.
-		 * If users want the DTLB refills misses a raw counter
-		 * must be used.
-		 */
 		[C(OP_READ)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
@@ -323,11 +366,6 @@
 		},
 	},
 	[C(DTLB)] = {
-		/*
-		 * Only ITLB misses and DTLB refills are supported.
-		 * If users want the DTLB refills misses a raw counter
-		 * must be used.
-		 */
 		[C(OP_READ)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
@@ -374,6 +412,242 @@
 };
 
 /*
+ * Cortex-A5 HW events mapping
+ */
+static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		/*
+		 * The prefetch counters don't differentiate between the I
+		 * side and the D side.
+		 */
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
+ * Cortex-A15 HW events mapping
+ */
+static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_SPEC_PC_WRITE,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_BUS_CYCLES,
+};
+
+static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DCACHE_READ_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		/*
+		 * Not all performance counters differentiate between read
+		 * and write accesses/misses so we're not always strictly
+		 * correct, but it's the best we can do. Writes and reads get
+		 * combined in these cases.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L2_DCACHE_READ_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DTLB_READ_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
  * Perf Events counters
  */
 enum armv7_counters {
@@ -905,6 +1179,26 @@
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
+
+static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+{
+	armv7pmu.id		= ARM_PERF_PMU_ID_CA5;
+	armv7pmu.name		= "ARMv7 Cortex-A5";
+	armv7pmu.cache_map	= &armv7_a5_perf_cache_map;
+	armv7pmu.event_map	= &armv7_a5_perf_map;
+	armv7pmu.num_events	= armv7_read_num_pmnc_events();
+	return &armv7pmu;
+}
+
+static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+{
+	armv7pmu.id		= ARM_PERF_PMU_ID_CA15;
+	armv7pmu.name		= "ARMv7 Cortex-A15";
+	armv7pmu.cache_map	= &armv7_a15_perf_cache_map;
+	armv7pmu.event_map	= &armv7_a15_perf_map;
+	armv7pmu.num_events	= armv7_read_num_pmnc_events();
+	return &armv7pmu;
+}
 #else
 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
@@ -915,4 +1209,14 @@
 {
 	return NULL;
 }
+
+static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+{
+	return NULL;
+}
+
+static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+{
+	return NULL;
+}
 #endif	/* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 34fca2e..26959d5 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -142,6 +142,9 @@
 	/* Push out any further dirty data, and ensure cache is empty */
 	flush_cache_all();
 
+	/*Push out the dirty data from external caches */
+	outer_disable();
+
 	/*
 	 * Now call the architecture specific reboot code.
 	 */
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index eaf8690..3f8ff74 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -984,6 +984,10 @@
 	"neon",
 	"vfpv3",
 	"vfpv3d16",
+	"tls",
+	"vfpv4",
+	"idiva",
+	"idivt",
 	NULL
 };
 
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 66d1044..2d681fa 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -133,6 +133,7 @@
 	select MSM_AUDIO_QDSP6 if SND_SOC
 	select CPU_HAS_L2_PMU
 	select MSM_SPM_V2
+	select HAS_QDSS
 	select MSM_L2_SPM
 	select MSM_NATIVE_RESTART
 	select DONT_MAP_HOLE_AFTER_MEMBANK0
@@ -176,6 +177,8 @@
 	select MIGRATION
 	select ARCH_MEMORY_PROBE
 	select ARCH_MEMORY_REMOVE
+	select DONT_RESERVE_FROM_MOVABLE_ZONE
+	select MSM_ULTRASOUND
 
 config ARCH_APQ8064
 	bool "APQ8064"
@@ -709,28 +712,52 @@
 		bool "6.2.20 + New ADSP"
 endchoice
 
-config MSM_DEBUG_UART
-	int
-	default 1 if MSM_DEBUG_UART1
-	default 2 if MSM_DEBUG_UART2
-	default 3 if MSM_DEBUG_UART3
+config DEBUG_MSM8930_UART
+	bool "Kernel low-level debugging messages via MSM 8930 UART"
+	depends on ARCH_MSM8930 && DEBUG_LL
+	help
+	  Say Y here if you want the debug print routines to direct
+	  their output to the serial port on MSM 8930 devices.
 
 choice
 	prompt "Debug UART"
+	depends on DEBUG_LL
 
-	default MSM_DEBUG_UART_NONE
+	config DEBUG_MSM_UART1
+		bool "Kernel low-level debugging messages via MSM UART1"
+		depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the first serial port on MSM devices.
 
-	config MSM_DEBUG_UART_NONE
-		bool "None"
+	config DEBUG_MSM_UART2
+		bool "Kernel low-level debugging messages via MSM UART2"
+		depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the second serial port on MSM devices.
 
-	config MSM_DEBUG_UART1
-		bool "UART1"
+	config DEBUG_MSM_UART3
+		bool "Kernel low-level debugging messages via MSM UART3"
+		depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the third serial port on MSM devices.
 
-	config MSM_DEBUG_UART2
-		bool "UART2"
+	config DEBUG_MSM8660_UART
+		bool "Kernel low-level debugging messages via MSM 8660 UART"
+		depends on ARCH_MSM8X60
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on MSM 8660 devices.
 
-	config MSM_DEBUG_UART3
-		bool "UART3"
+	config DEBUG_MSM8960_UART
+		bool "Kernel low-level debugging messages via MSM 8960 UART"
+		depends on ARCH_MSM8960
+		select DEBUG_MSM8930_UART
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on MSM 8960 devices.
 endchoice
 
 choice
@@ -867,13 +894,6 @@
 	help
 	 Select this if the L2 cache controller has a Performance Monitoring Unit.
 
-config MSM_JTAG_V7
-	depends on CPU_V7
-	default y if DEBUG_KERNEL
-        bool "JTAG debug support"
-	help
-          Add additional support for JTAG kernel debugging.
-
 config HTC_HEADSET
 	tristate "HTC 2 Wire detection driver"
 	default n
@@ -1522,7 +1542,7 @@
 
 config MSM_SUBSYSTEM_RESTART
 	bool "MSM Subsystem Restart Driver"
-	depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+	depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM9615)
 	default n
 	help
 	  This option enables the MSM subsystem restart driver, which provides
@@ -1539,19 +1559,19 @@
 
 config MSM_MODEM_8960
 	bool "MSM 8960 Modem driver"
-	depends on (ARCH_MSM8960)
+	depends on (ARCH_MSM8960 || ARCH_MSM9615)
 	help
-	 This option enables the modem driver for the MSM8960, which monitors
+	 This option enables the modem driver for the MSM8960 and MSM9615, which monitors
 	 modem hardware watchdog interrupt lines and plugs into the subsystem
-	 restart and PIL drivers.
+	 restart and PIL drivers. For MSM9615, it only supports a full chip reset.
 
 config MSM_LPASS_8960
 	tristate "MSM 8960 Lpass driver"
-	depends on (ARCH_MSM8960)
+	depends on (ARCH_MSM8960 || ARCH_MSM9615)
 	help
-	 This option enables the lpass driver for the MSM8960, which monitors
+	 This option enables the lpass driver for the MSM8960 and MSM9615. This monitors
 	 lpass hardware watchdog interrupt lines and plugs into the subsystem
-	 restart and PIL drivers.
+	 restart and PIL drivers. For MSM9615, it only supports a full chip reset.
 
 config MSM_WCNSS_SSR_8960
 	tristate "MSM 8960 WCNSS restart module"
@@ -1587,6 +1607,7 @@
 config MSM_RPM_LOG
 	tristate "MSM Resource Power Manager Log Driver"
 	depends on DEBUG_FS
+	depends on MSM_RPM
 	default n
 	help
 	  This option enables a driver which can read from a circular buffer
@@ -1597,7 +1618,7 @@
 config MSM_RPM_STATS_LOG
 	tristate "MSM Resource Power Manager Stat Driver"
 	depends on DEBUG_FS
-	depends on ARCH_MSM8X60
+	depends on MSM_RPM
 	default n
 	  help
 	  This option enables a driver which reads RPM messages from a shared
@@ -1679,25 +1700,43 @@
 		make the kernel reboot on a kernel panic - that must be
 		enabled via another mechanism.
 
+config HAS_QDSS
+	bool "QDSS Present"
+	help
+	 Select this if the chip has Qualcomm Debug Subsystem implemented.
+
+config MSM_DEBUG_ACROSS_PC
+	bool "Debug support across power collapse"
+	help
+	  Enables debug state to be saved and restored across power collapse.
+
+config MSM_JTAG_V7
+	depends on CPU_V7 && !HAS_QDSS
+	default y if DEBUG_KERNEL
+	bool "JTAG debug support"
+	select MSM_DEBUG_ACROSS_PC
+	help
+          Add additional support for JTAG kernel debugging.
+
 config MSM_TRACE_ACROSS_PC
 	bool "Trace support across power collapse"
-	depends on ARCH_MSM8X60 || ARCH_MSM8960
 	help
 	  Enables trace state to be saved and restored across power collapse.
 
 config MSM_ETM
 	tristate "Enable MSM ETM and ETB"
-	depends on ARCH_MSM8X60
+	depends on ARCH_MSM8X60 && !HAS_QDSS
 	select MSM_TRACE_ACROSS_PC
 	help
 	  Enables embedded trace collection on Qualcomm v7 CPUs.
 
 config MSM_QDSS
-	bool "Coresight tracing support"
-	depends on ARCH_MSM8960
+	bool "Qualcomm Debug Subsystem"
+	depends on HAS_QDSS
+	select MSM_DEBUG_ACROSS_PC
 	select MSM_TRACE_ACROSS_PC
 	help
-	  Enables support for Qualcomm debug subsystem.
+	  Enables support for Qualcomm Debug Subsystem.
 
 config MSM_SLEEP_STATS
 	bool "Enable exporting of MSM sleep stats to userspace"
@@ -1767,6 +1806,12 @@
           Enable HW audio support in QDSP6.
           QDSP6 can support HW encoder & decoder and audio processing
 
+config MSM_ULTRASOUND
+	bool "MSM ultrasound support"
+	depends on MSM_AUDIO_QDSP6
+	help
+	  Enable support for qdsp6/ultrasound.
+
 config MSM_RPC_VIBRATOR
 	bool "RPC based MSM Vibrator Support"
 	depends on MSM_ONCRPCROUTER
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 74f312a..604989d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -45,7 +45,13 @@
 
 msm-etm-objs := cp14.o etm.o
 obj-$(CONFIG_MSM_ETM) += msm-etm.o
-obj-$(CONFIG_MSM_QDSS) += qdss-etb.o qdss-tpiu.o qdss-funnel.o qdss-ptm.o
+
+ifdef CONFIG_MSM_QDSS
+	obj-y += qdss-debug.o
+	obj-y += qdss-etb.o qdss-tpiu.o
+	obj-y += qdss-funnel.o
+	obj-y += qdss-ptm.o
+endif
 
 quiet_cmd_mkrpcsym = MKCAP   $@
       cmd_mkrpcsym = $(PERL) $(srctree)/$(src)/mkrpcsym.pl $< $@
@@ -247,7 +253,6 @@
 obj-$(CONFIG_HTC_HEADSET) += htc_headset.o
 obj-$(CONFIG_MSM_RMT_STORAGE_CLIENT) += rmt_storage_client.o
 obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o
-obj-$(CONFIG_PMIC8058) += pmic8058-gpio.o pmic8058-mpp.o
 obj-$(CONFIG_MSM_RPM) += rpm.o rpm_resources.o
 obj-$(CONFIG_MSM_MPM) += mpm.o
 obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o
diff --git a/arch/arm/mach-msm/acpuclock-7x30.c b/arch/arm/mach-msm/acpuclock-7x30.c
index 24c910e..7ee4e5b 100644
--- a/arch/arm/mach-msm/acpuclock-7x30.c
+++ b/arch/arm/mach-msm/acpuclock-7x30.c
@@ -231,8 +231,7 @@
 	 * increasing the ACPU frequency, since voting for high AXI rates
 	 * implicitly takes care of increasing the MSMC1 voltage, as needed. */
 	if (tgt_s->axi_clk_hz > strt_s->axi_clk_hz) {
-		rc = clk_set_min_rate(drv_state.ebi1_clk,
-					tgt_s->axi_clk_hz);
+		rc = clk_set_rate(drv_state.ebi1_clk, tgt_s->axi_clk_hz);
 		if (rc < 0) {
 			pr_err("Setting AXI min rate failed (%d)\n", rc);
 			goto out;
@@ -277,8 +276,7 @@
 
 	/* Decrease the AXI bus frequency if we can. */
 	if (tgt_s->axi_clk_hz < strt_s->axi_clk_hz) {
-		res = clk_set_min_rate(drv_state.ebi1_clk,
-					tgt_s->axi_clk_hz);
+		res = clk_set_rate(drv_state.ebi1_clk, tgt_s->axi_clk_hz);
 		if (res < 0)
 			pr_warning("Setting AXI min rate failed (%d)\n", res);
 	}
@@ -385,7 +383,7 @@
 	if (s->src >= 0)
 		clk_enable(acpuclk_sources[s->src]);
 
-	res = clk_set_min_rate(drv_state.ebi1_clk, s->axi_clk_hz);
+	res = clk_set_rate(drv_state.ebi1_clk, s->axi_clk_hz);
 	if (res < 0)
 		pr_warning("Setting AXI min rate failed!\n");
 
diff --git a/arch/arm/mach-msm/acpuclock-9615.c b/arch/arm/mach-msm/acpuclock-9615.c
index ebc7f1b..e6206dd 100644
--- a/arch/arm/mach-msm/acpuclock-9615.c
+++ b/arch/arm/mach-msm/acpuclock-9615.c
@@ -27,6 +27,8 @@
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
 #include <mach/rpm-regulator.h>
 
 #include "acpuclock.h"
@@ -68,6 +70,7 @@
 	unsigned int	src_div;
 	unsigned int	vdd_cpu;
 	unsigned int	vdd_mem;
+	unsigned int	bw_level;
 };
 
 struct acpuclk_state {
@@ -79,12 +82,40 @@
 	.current_speed = &(struct clkctl_acpu_speed){ 0 },
 };
 
+/* Instantaneous bandwidth requests in MB/s. */
+#define BW_MBPS(_bw) \
+	{ \
+		.vectors = &(struct msm_bus_vectors){ \
+			.src = MSM_BUS_MASTER_AMPSS_M0, \
+			.dst = MSM_BUS_SLAVE_EBI_CH0, \
+			.ib = (_bw) * 1000000UL, \
+			.ab = 0, \
+		}, \
+		.num_paths = 1, \
+	}
+static struct msm_bus_paths bw_level_tbl[] = {
+	[0] =  BW_MBPS(152), /* At least  19 MHz on bus. */
+	[1] =  BW_MBPS(368), /* At least  46 MHz on bus. */
+	[2] =  BW_MBPS(552), /* At least  69 MHz on bus. */
+	[3] =  BW_MBPS(736), /* At least  92 MHz on bus. */
+	[4] = BW_MBPS(1064), /* At least 133 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_client_pdata = {
+	.usecase = bw_level_tbl,
+	.num_usecases = ARRAY_SIZE(bw_level_tbl),
+	.active_only = 1,
+	.name = "acpuclock",
+};
+
+static uint32_t bus_perf_client;
+
 static struct clkctl_acpu_speed acpu_freq_tbl[] = {
-	{ 0,  19200, SRC_CXO,  0, 0,  950000, 1050000 },
-	{ 1, 138000, SRC_PLL0, 6, 1,  950000, 1050000 },
-	{ 1, 276000, SRC_PLL0, 6, 0, 1050000, 1050000 },
-	{ 1, 384000, SRC_PLL8, 3, 0, 1150000, 1150000 },
-	{ 1, 440000, SRC_PLL9, 2, 0, 1150000, 1150000 },
+	{ 0,  19200, SRC_CXO,  0, 0,  950000, 1050000, 0 },
+	{ 1, 138000, SRC_PLL0, 6, 1,  950000, 1050000, 2 },
+	{ 1, 276000, SRC_PLL0, 6, 0, 1050000, 1050000, 2 },
+	{ 1, 384000, SRC_PLL8, 3, 0, 1150000, 1150000, 4 },
+	{ 1, 440000, SRC_PLL9, 2, 0, 1150000, 1150000, 4 },
 	{ 0 }
 };
 
@@ -104,6 +135,25 @@
 	udelay(1);
 }
 
+/* Update the bus bandwidth request. */
+static void set_bus_bw(unsigned int bw)
+{
+	int ret;
+
+	/* Bounds check. */
+	if (bw >= ARRAY_SIZE(bw_level_tbl)) {
+		pr_err("invalid bandwidth request (%d)\n", bw);
+		return;
+	}
+
+	/* Update bandwidth if request has changed. This may sleep. */
+	ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
+	if (ret)
+		pr_err("bandwidth request failed (%d)\n", ret);
+
+	return;
+}
+
 /* Apply any per-cpu voltage increases. */
 static int increase_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
 {
@@ -198,6 +248,9 @@
 	if (reason == SETRATE_SWFI || reason == SETRATE_PC)
 		goto out;
 
+	/* Update bus bandwith request. */
+	set_bus_bw(tgt_s->bw_level);
+
 	/* Drop VDD levels if we can. */
 	if (tgt_s->khz < strt_s->khz)
 		decrease_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
@@ -258,6 +311,13 @@
 	int i;
 
 	mutex_init(&drv_state.lock);
+
+	bus_perf_client = msm_bus_scale_register_client(&bus_client_pdata);
+	if (!bus_perf_client) {
+		pr_err("Unable to register bus client\n");
+		BUG();
+	}
+
 	for (i = 0; i < NUM_SRC; i++) {
 		if (clocks[i].name) {
 			clocks[i].clk = clk_get_sys(NULL, clocks[i].name);
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 0cd8a6e..80f5803 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -523,12 +523,18 @@
 	int rc = 0;
 
 	DBG("%s: opening ch %d\n", __func__, id);
-	if (!bam_mux_initialized)
+	if (!bam_mux_initialized) {
+		DBG("%s: not inititialized\n", __func__);
 		return -ENODEV;
-	if (id >= BAM_DMUX_NUM_CHANNELS)
+	}
+	if (id >= BAM_DMUX_NUM_CHANNELS) {
+		pr_err("%s: invalid channel id %d\n", __func__, id);
 		return -EINVAL;
-	if (notify == NULL)
+	}
+	if (notify == NULL) {
+		pr_err("%s: notify function is NULL\n", __func__);
 		return -EINVAL;
+	}
 
 	hdr = kmalloc(sizeof(struct bam_mux_hdr), GFP_KERNEL);
 	if (hdr == NULL) {
@@ -546,8 +552,7 @@
 		DBG("%s: Remote not open; ch: %d\n", __func__, id);
 		spin_unlock_irqrestore(&bam_ch[id].lock, flags);
 		kfree(hdr);
-		rc = -ENODEV;
-		goto open_done;
+		return -ENODEV;
 	}
 
 	bam_ch[id].notify = notify;
@@ -948,16 +953,10 @@
 
 static void vote_dfab(void)
 {
-	int rc;
-
-	rc = clk_enable(dfab_clk);
-	if (rc)
-		pr_err("bam_dmux vote for dfab failed rc = %d\n", rc);
 }
 
 static void unvote_dfab(void)
 {
-	clk_disable(dfab_clk);
 }
 
 static int restart_notifier_cb(struct notifier_block *this,
@@ -1030,6 +1029,7 @@
 	a2_props.virt_addr = a2_virt_addr;
 	a2_props.virt_size = A2_PHYS_SIZE;
 	a2_props.irq = A2_BAM_IRQ;
+	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
 	/* need to free on tear down */
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 755132b..eddd4ed 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -27,6 +27,7 @@
 #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/leds.h>
 #include <linux/leds-pm8xxx.h>
+#include <mach/msm_bus_board.h>
 #include "timer.h"
 #include "devices.h"
 #include "board-9615.h"
@@ -301,7 +302,6 @@
 		 * This is a gpio-regulator and does not support
 		 * regulator_set_voltage and regulator_set_optimum_mode
 		 */
-		.set_voltage_sup = false,
 		.high_vol_level = 2950000,
 		.low_vol_level = 2950000,
 		.hpm_uA = 600000, /* 600mA */
@@ -313,7 +313,6 @@
 	/* SDCC1 : External card slot connected */
 	[SDCC1] = {
 		.name = "sdc_vddp",
-		.set_voltage_sup = true,
 		.high_vol_level = 2950000,
 		.low_vol_level = 1850000,
 		.always_on = true,
@@ -419,7 +418,7 @@
 		.gpio      = 26,
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &sdcc2_cmd_data_0_3_actv_cfg,
-			[GPIOMUX_SUSPENDED] = &sdcc2_suspend_cfg,
+			[GPIOMUX_SUSPENDED] = &sdcc2_cmd_data_0_3_actv_cfg,
 		},
 	},
 	{
@@ -439,7 +438,7 @@
 		},
 	},
 	{
-		/* SDC2_CMD GSBI1 */
+		/* SDC2_CMD */
 		.gpio      = 29,
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &sdcc2_cmd_data_0_3_actv_cfg,
@@ -447,7 +446,7 @@
 		},
 	},
 	{
-		/* SDC2_CLK GSBI1 */
+		/* SDC2_CLK */
 		.gpio      = 30,
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &sdcc2_clk_actv_cfg,
@@ -501,7 +500,6 @@
 	.sup_clk_table	= sdc1_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc1_sup_clk_rates),
 	.pclk_src_dfab	= true,
-	.sdcc_v4_sup    = true,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
 #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
@@ -509,6 +507,9 @@
 	.status_irq	= MSM_GPIO_TO_INT(GPIO_SDC1_HW_DET),
 	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 #endif
+	.xpc_cap	= 1,
+	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+			   MMC_CAP_MAX_CURRENT_400)
 };
 static struct mmc_platform_data *msm9615_sdc1_pdata = &sdc1_data;
 #else
@@ -526,7 +527,6 @@
 	.sup_clk_table	= sdc2_sup_clk_rates,
 	.sup_clk_cnt	= ARRAY_SIZE(sdc2_sup_clk_rates),
 	.pclk_src_dfab	= 1,
-	.sdcc_v4_sup    = true,
 	.pin_data	= &mmc_slot_pin_data[SDCC2],
 #ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
 	.sdiowakeup_irq = MSM_GPIO_TO_INT(GPIO_SDC2_DAT1_WAKEUP),
@@ -603,6 +603,17 @@
 	return 0;
 }
 
+static void __init msm9615_init_buses(void)
+{
+#ifdef CONFIG_MSM_BUS_SCALING
+	msm_bus_rpm_set_mt_mask();
+	msm_bus_9615_sys_fabric_pdata.rpm_enabled = 1;
+	msm_bus_9615_sys_fabric.dev.platform_data =
+		&msm_bus_9615_sys_fabric_pdata;
+	msm_bus_def_fab.dev.platform_data = &msm_bus_9615_def_fab_pdata;
+#endif
+}
+
 static struct msm_spi_platform_data msm9615_qup_spi_gsbi3_pdata = {
 	.max_clock_speed = 24000000,
 };
@@ -636,6 +647,16 @@
 	},
 };
 
+static struct platform_device msm_wlan_ar6000_pm_device = {
+	.name           = "wlan_ar6000_pm_dev",
+	.id             = -1,
+};
+
+static int __init msm9615_init_ar6000pm(void)
+{
+	return platform_device_register(&msm_wlan_ar6000_pm_device);
+}
+
 static struct platform_device *common_devices[] = {
 	&msm9615_device_dmov,
 	&msm_device_smd,
@@ -650,6 +671,7 @@
 	&msm_device_sps,
 	&msm9615_device_tsens,
 	&msm_device_nand,
+	&msm_device_bam_dmux,
 	&msm_rpm_device,
 #ifdef CONFIG_HW_RANDOM_MSM
 	&msm_device_rng,
@@ -665,6 +687,8 @@
 	&msm9615_qcedev_device,
 #endif
 	&msm9615_device_watchdog,
+	&msm_bus_9615_sys_fabric,
+	&msm_bus_def_fab,
 };
 
 static void __init msm9615_i2c_init(void)
@@ -680,6 +704,8 @@
 	msm9615_i2c_init();
 	regulator_suppress_info_printing();
 	platform_device_register(&msm9615_device_rpm_regulator);
+	msm_clock_init(&msm9615_clock_init_data);
+	msm9615_init_buses();
 	msm9615_device_qup_spi_gsbi3.dev.platform_data =
 				&msm9615_qup_spi_gsbi3_pdata;
 	msm9615_device_ssbi_pmic1.dev.platform_data =
@@ -687,12 +713,13 @@
 	pm8018_platform_data.num_regulators = msm_pm8018_regulator_pdata_len;
 
 	msm_device_otg.dev.platform_data = &msm_otg_pdata;
-	msm_device_gadget_peripheral.dev.parent = &msm_device_otg.dev;
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 
-	msm_clock_init(&msm9615_clock_init_data);
 	acpuclk_init(&acpuclk_9615_soc_data);
 
+	/* Ensure ar6000pm device is registered before MMC/SDC */
+	msm9615_init_ar6000pm();
+
 	msm9615_init_mmc();
 	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
 	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
diff --git a/arch/arm/mach-msm/board-apq8064-regulator.c b/arch/arm/mach-msm/board-apq8064-regulator.c
index 59d0863..8448600 100644
--- a/arch/arm/mach-msm/board-apq8064-regulator.c
+++ b/arch/arm/mach-msm/board-apq8064-regulator.c
@@ -31,10 +31,14 @@
 VREG_CONSUMERS(L3) = {
 	REGULATOR_SUPPLY("8921_l3",		NULL),
 	REGULATOR_SUPPLY("HSUSB_3p3",		"msm_otg"),
+	REGULATOR_SUPPLY("HSUSB_3p3",		"msm_ehci_host.0"),
+	REGULATOR_SUPPLY("HSUSB_3p3",		"msm_ehci_host.1"),
 };
 VREG_CONSUMERS(L4) = {
 	REGULATOR_SUPPLY("8921_l4",		NULL),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_otg"),
+	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.0"),
+	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.1"),
 };
 VREG_CONSUMERS(L5) = {
 	REGULATOR_SUPPLY("8921_l5",		NULL),
@@ -108,6 +112,8 @@
 VREG_CONSUMERS(S3) = {
 	REGULATOR_SUPPLY("8921_s3",		NULL),
 	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_otg"),
+	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_ehci_host.0"),
+	REGULATOR_SUPPLY("HSUSB_VDDCX",		"msm_ehci_host.1"),
 };
 VREG_CONSUMERS(S4) = {
 	REGULATOR_SUPPLY("8921_s4",		NULL),
@@ -152,6 +158,12 @@
 VREG_CONSUMERS(NCP) = {
 	REGULATOR_SUPPLY("8921_ncp",		NULL),
 };
+VREG_CONSUMERS(8821_S0) = {
+	REGULATOR_SUPPLY("8821_s0",		NULL),
+};
+VREG_CONSUMERS(8821_S1) = {
+	REGULATOR_SUPPLY("8821_s1",		NULL),
+};
 
 #define PM8921_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
 			 _pull_down, _always_on, _supply_regulator, \
@@ -256,11 +268,17 @@
 	}
 
 /* SAW regulator constraints */
-struct regulator_init_data msm8064_saw_regulator_pdata_s5 =
+struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 =
 	/*	      ID  vreg_name	       min_uV   max_uV */
-	SAW_VREG_INIT(S5, "8921_s5",	       1050000, 1150000);
-struct regulator_init_data msm8064_saw_regulator_pdata_s6 =
-	SAW_VREG_INIT(S6, "8921_s6",	       1050000, 1150000);
+	SAW_VREG_INIT(S5, "8921_s5",	       950000, 1150000);
+struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6 =
+	SAW_VREG_INIT(S6, "8921_s6",	       950000, 1150000);
+
+struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0 =
+	/*	      ID       vreg_name	min_uV  max_uV */
+	SAW_VREG_INIT(8821_S0, "8821_s0",       950000, 1150000);
+struct regulator_init_data msm8064_saw_regulator_pdata_8821_s1 =
+	SAW_VREG_INIT(8821_S1, "8821_s1",       950000, 1150000);
 
 /* PM8921 regulator constraints */
 struct pm8921_regulator_platform_data
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index 0e30aee..b131989 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -228,7 +228,6 @@
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
 		.name = "sdc_vdd",
-		.set_voltage_sup = 1,
 		.high_vol_level = 2950000,
 		.low_vol_level = 2950000,
 		.always_on = 1,
@@ -239,7 +238,6 @@
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.name = "sdc_vdd",
-		.set_voltage_sup = 1,
 		.high_vol_level = 2950000,
 		.low_vol_level = 2950000,
 		.hpm_uA = 600000, /* 600mA */
@@ -251,7 +249,6 @@
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
 		.name = "sdc_vccq",
-		.set_voltage_sup = 1,
 		.always_on = 1,
 		.high_vol_level = 1800000,
 		.low_vol_level = 1800000,
@@ -264,7 +261,6 @@
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.name = "sdc_vddp",
-		.set_voltage_sup = 1,
 		.high_vol_level = 2950000,
 		.low_vol_level = 1850000,
 		.always_on = 1,
@@ -405,7 +401,6 @@
 	.sup_clk_cnt	= ARRAY_SIZE(sdc1_sup_clk_rates),
 	.pin_data	= &mmc_slot_pin_data[SDCC1],
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
-	.sdcc_v4_sup	= true,
 };
 static struct mmc_platform_data *apq8064_sdc1_pdata = &sdc1_data;
 #else
@@ -424,7 +419,6 @@
 	.sup_clk_cnt	= ARRAY_SIZE(sdc3_sup_clk_rates),
 	.pin_data	= &mmc_slot_pin_data[SDCC3],
 	.vreg_data	= &mmc_slot_vreg_data[SDCC3],
-	.sdcc_v4_sup	= true,
 };
 static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
 #else
@@ -481,6 +475,38 @@
 	}
 }
 
+static struct platform_device msm8064_device_saw_regulator_core0 = {
+	.name	= "saw-regulator",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &msm8064_saw_regulator_pdata_8921_s5,
+	},
+};
+
+static struct platform_device msm8064_device_saw_regulator_core1 = {
+	.name	= "saw-regulator",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &msm8064_saw_regulator_pdata_8921_s6,
+	},
+};
+
+static struct platform_device msm8064_device_saw_regulator_core2 = {
+	.name	= "saw-regulator",
+	.id	= 2,
+	.dev	= {
+		.platform_data = &msm8064_saw_regulator_pdata_8821_s0,
+	},
+};
+
+static struct platform_device msm8064_device_saw_regulator_core3 = {
+	.name	= "saw-regulator",
+	.id	= 3,
+	.dev	= {
+		.platform_data = &msm8064_saw_regulator_pdata_8821_s1,
+	},
+};
+
 static struct platform_device *common_devices[] __initdata = {
 	&apq8064_device_dmov,
 	&apq8064_device_qup_i2c_gsbi4,
@@ -496,6 +522,10 @@
 	&android_pmem_adsp_device,
 	&android_pmem_audio_device,
 	&msm8064_device_watchdog,
+	&msm8064_device_saw_regulator_core0,
+	&msm8064_device_saw_regulator_core1,
+	&msm8064_device_saw_regulator_core2,
+	&msm8064_device_saw_regulator_core3,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -508,7 +538,7 @@
 };
 
 static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
-	.max_clock_speed = 26000000,
+	.max_clock_speed = 24000000,
 };
 
 #define KS8851_IRQ_GPIO		43
@@ -724,7 +754,6 @@
 	apq8064_device_ssbi_pmic2.dev.platform_data =
 				&apq8064_ssbi_pm8821_pdata;
 	apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
-	apq8064_device_gadget_peripheral.dev.parent = &apq8064_device_otg.dev;
 	apq8064_pm8921_platform_data.num_regulators =
 					msm8064_pm8921_regulator_pdata_len;
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
diff --git a/arch/arm/mach-msm/board-apq8064.h b/arch/arm/mach-msm/board-apq8064.h
index 1d2109a..0928a58 100644
--- a/arch/arm/mach-msm/board-apq8064.h
+++ b/arch/arm/mach-msm/board-apq8064.h
@@ -32,6 +32,11 @@
 
 extern int msm8064_pm8921_regulator_pdata_len __devinitdata;
 
+extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5;
+extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6;
+extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0;
+extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s1;
+
 struct mmc_platform_data;
 int __init apq8064_add_sdcc(unsigned int controller,
 		struct mmc_platform_data *plat);
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index f35d493..a2ddeb4 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -76,6 +76,13 @@
 static struct clk_lookup msm_clocks_dummy[] = {
 	CLK_DUMMY("core_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
 	CLK_DUMMY("iface_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
+	CLK_DUMMY("core_clk",	SDC1_CLK,	NULL,			OFF),
+	CLK_DUMMY("iface_clk",	SDC1_P_CLK,	NULL,			OFF),
+	CLK_DUMMY("core_clk",	SDC3_CLK,	NULL,			OFF),
+	CLK_DUMMY("iface_clk",	SDC3_P_CLK,	NULL,			OFF),
+	CLK_DUMMY("usb_phy_clk", NULL, NULL, OFF),
+	CLK_DUMMY("usb_hs_clk", NULL, NULL, OFF),
+	CLK_DUMMY("usb_hs_pclk", NULL, NULL, OFF),
 };
 
 struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 1ede17b..1a085de 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -21,11 +21,6 @@
 #include <mach/board.h>
 #include "timer.h"
 
-#define early_machine_is_copper()	\
-	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmcopper")
-#define machine_is_copper()		\
-	of_machine_is_compatible("qcom,msmcopper")
-
 static void __init msm_dt_init_irq(void)
 {
 	if (machine_is_copper())
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index eb936e4..333d366 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -28,15 +28,12 @@
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
 
-#include <mach/mpp.h>
 #include <mach/board.h>
 #include <mach/memory.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
 #include <mach/sirc.h>
-#include <mach/pmic.h>
 
-#include <mach/vreg.h>
 #include <mach/socinfo.h>
 #include "devices.h"
 #include "timer.h"
@@ -46,7 +43,6 @@
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
 #include <linux/msm_adc.h>
-#include <linux/pmic8058-xoadc.h>
 #include <linux/m_adcproc.h>
 #include <linux/platform_data/qcom_crypto_device.h>
 
@@ -89,8 +85,11 @@
 #define FPGA_SDCC_STATUS        0x8E0001A8
 
 /* Macros assume PMIC GPIOs start at 0 */
-#define PM8058_GPIO_PM_TO_SYS(pm_gpio)	   (pm_gpio + NR_MSM_GPIOS)
-#define PM8058_GPIO_SYS_TO_PM(sys_gpio)    (sys_gpio - NR_MSM_GPIOS)
+#define PM8058_GPIO_PM_TO_SYS(pm_gpio)  (pm_gpio + NR_MSM_GPIOS)
+#define PM8058_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - NR_MSM_GPIOS)
+#define PM8058_MPP_BASE			(NR_MSM_GPIOS + 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 PMIC_GPIO_5V_PA_PWR	21	/* PMIC GPIO Number 22 */
 #define PMIC_GPIO_4_2V_PA_PWR	22	/* PMIC GPIO Number 23 */
@@ -102,19 +101,33 @@
 /*
  * PM8058
  */
+struct pm8xxx_mpp_init_info {
+	unsigned			mpp;
+	struct pm8xxx_mpp_config_data	config;
+};
+
+#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+	.mpp	= PM8058_MPP_PM_TO_SYS(_mpp), \
+	.config	= { \
+		.type		= PM8XXX_MPP_TYPE_##_type, \
+		.level		= _level, \
+		.control	= PM8XXX_MPP_##_control, \
+	} \
+}
 
 static int pm8058_gpios_init(void)
 {
 	int i;
 	int rc;
 	struct pm8058_gpio_cfg {
-		int gpio;
-		struct pm8058_gpio cfg;
+		int                gpio;
+		struct pm_gpio	   cfg;
 	};
 
 	struct pm8058_gpio_cfg gpio_cfgs[] = {
 		{				/* 5V PA Power */
-			PMIC_GPIO_5V_PA_PWR,
+			PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_5V_PA_PWR),
 			{
 				.vin_sel = 0,
 				.direction = PM_GPIO_DIR_BOTH,
@@ -127,7 +140,7 @@
 			},
 		},
 		{				/* 4.2V PA Power */
-			PMIC_GPIO_4_2V_PA_PWR,
+			PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_4_2V_PA_PWR),
 			{
 				.vin_sel = 0,
 				.direction = PM_GPIO_DIR_BOTH,
@@ -142,7 +155,7 @@
 	};
 
 	for (i = 0; i < ARRAY_SIZE(gpio_cfgs); ++i) {
-		rc = pm8058_gpio_config(gpio_cfgs[i].gpio, &gpio_cfgs[i].cfg);
+		rc = pm8xxx_gpio_config(gpio_cfgs[i].gpio, &gpio_cfgs[i].cfg);
 		if (rc < 0) {
 			pr_err("%s pmic gpio config failed\n", __func__);
 			return rc;
@@ -154,37 +167,28 @@
 
 static int pm8058_mpps_init(void)
 {
-	int rc;
+	int rc, i;
 
-	/* Set up MPP 3 and 6 as analog outputs at 1.25V */
-	rc = pm8058_mpp_config_analog_output(PMIC_MPP_3,
-			PM_MPP_AOUT_LVL_1V25_2, PM_MPP_AOUT_CTL_ENABLE);
-	if (rc) {
-		pr_err("%s: Config mpp3 on pmic 8058 failed\n", __func__);
-		return rc;
+	struct pm8xxx_mpp_init_info pm8058_mpps[] = {
+		PM8XXX_MPP_INIT(PMIC_MPP_3, A_OUTPUT,
+			PM8XXX_MPP_AOUT_LVL_1V25_2, AOUT_CTRL_ENABLE),
+		PM8XXX_MPP_INIT(PMIC_MPP_6, A_OUTPUT,
+			PM8XXX_MPP_AOUT_LVL_1V25_2, AOUT_CTRL_ENABLE),
+	};
+
+	for (i = 0; i < ARRAY_SIZE(pm8058_mpps); i++) {
+		rc = pm8xxx_mpp_config(pm8058_mpps[i].mpp,
+					&pm8058_mpps[i].config);
+		if (rc) {
+			pr_err("%s: Config %d mpp pm 8058 failed\n",
+						__func__, pm8058_mpps[i].mpp);
+			return rc;
+		}
 	}
 
-	rc = pm8058_mpp_config_analog_output(PMIC_MPP_6,
-			PM_MPP_AOUT_LVL_1V25_2, PM_MPP_AOUT_CTL_ENABLE);
-	if (rc) {
-		pr_err("%s: Config mpp5 on pmic 8058 failed\n", __func__);
-		return rc;
-	}
 	return 0;
 }
 
-static struct pm8058_gpio_platform_data pm8058_gpio_data = {
-	.gpio_base = PM8058_GPIO_PM_TO_SYS(0),
-	.irq_base = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 0),
-	.init = pm8058_gpios_init,
-};
-
-static struct pm8058_gpio_platform_data pm8058_mpp_data = {
-	.gpio_base = PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS),
-	.irq_base = PM8058_MPP_IRQ(PMIC8058_IRQ_BASE, 0),
-	.init = pm8058_mpps_init,
-};
-
 static struct regulator_consumer_supply pm8058_vreg_supply[PM8058_VREG_MAX] = {
 	[PM8058_VREG_ID_L3] = REGULATOR_SUPPLY("8058_l3", NULL),
 	[PM8058_VREG_ID_L8] = REGULATOR_SUPPLY("8058_l8", NULL),
@@ -199,7 +203,7 @@
 
 #define PM8058_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
 			_always_on, _pull_down) \
-	[_id] = { \
+	{ \
 		.init_data = { \
 			.constraints = { \
 				.valid_modes_mask = _modes, \
@@ -212,6 +216,7 @@
 			.num_consumer_supplies = 1, \
 			.consumer_supplies = &pm8058_vreg_supply[_id], \
 		}, \
+		.id = _id, \
 		.pull_down_enable = _pull_down, \
 		.pin_ctrl = 0, \
 		.pin_fn = PM8058_VREG_PIN_FN_ENABLE, \
@@ -233,7 +238,7 @@
 	PM8058_VREG_INIT(_id, _min_uV, _min_uV, REGULATOR_MODE_NORMAL, \
 			REGULATOR_CHANGE_STATUS, 0, 0, 1)
 
-static struct pm8058_vreg_pdata pm8058_vreg_init[PM8058_VREG_MAX] = {
+static struct pm8058_vreg_pdata pm8058_vreg_init[] = {
 	PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L3, 1800000, 1800000),
 	PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L8, 2200000, 2200000),
 	PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L9, 2050000, 2050000),
@@ -244,22 +249,7 @@
 	PM8058_VREG_INIT_SMPS(PM8058_VREG_ID_S4, 1300000, 1300000),
 };
 
-#define PM8058_VREG(_id) { \
-	.name = "pm8058-regulator", \
-	.id = _id, \
-	.platform_data = &pm8058_vreg_init[_id], \
-	.pdata_size    = sizeof(pm8058_vreg_init[_id]), \
-}
-
 #ifdef CONFIG_SENSORS_MSM_ADC
-static struct resource resources_adc[] = {
-	{
-		.start = PM8058_ADC_IRQ(PMIC8058_IRQ_BASE),
-		.end   = PM8058_ADC_IRQ(PMIC8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
 static struct adc_access_fn xoadc_fn = {
 	pm8058_xoadc_select_chan_and_start_conv,
 	pm8058_xoadc_read_adc_code,
@@ -298,17 +288,21 @@
 
 static void pmic8058_xoadc_mpp_config(void)
 {
-	int rc;
-
-	rc = pm8058_mpp_config_analog_input(XOADC_MPP_7,
-			PM_MPP_AIN_AMUX_CH5, PM_MPP_AOUT_CTL_DISABLE);
-	if (rc)
-		pr_err("%s: Config mpp7 on pmic 8058 failed\n", __func__);
-
-	rc = pm8058_mpp_config_analog_input(XOADC_MPP_10,
-			PM_MPP_AIN_AMUX_CH6, PM_MPP_AOUT_CTL_DISABLE);
-	if (rc)
-		pr_err("%s: Config mpp10 on pmic 8058 failed\n", __func__);
+	int rc, i;
+	struct pm8xxx_mpp_init_info xoadc_mpps[] = {
+		PM8XXX_MPP_INIT(PMIC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
+							AOUT_CTRL_DISABLE),
+		PM8XXX_MPP_INIT(PMIC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
+							AOUT_CTRL_DISABLE),
+	};
+	for (i = 0; i < ARRAY_SIZE(xoadc_mpps); i++) {
+		rc = pm8xxx_mpp_config(xoadc_mpps[i].mpp,
+					&xoadc_mpps[i].config);
+		if (rc) {
+			pr_err("%s: Config MPP %d of PM8058 failed\n",
+					__func__, xoadc_mpps[i].mpp);
+		}
+	}
 }
 
 static struct regulator *vreg_ldo18_adc;
@@ -373,7 +367,7 @@
 	.conversiontime         = 54,
 };
 
-static struct xoadc_platform_data xoadc_pdata = {
+static struct xoadc_platform_data pm8058_xoadc_pdata = {
 	.xoadc_prop = &pm8058_xoadc_data,
 	.xoadc_mpp_config = pmic8058_xoadc_mpp_config,
 	.xoadc_vreg_set = pmic8058_xoadc_vreg_config,
@@ -400,7 +394,7 @@
 };
 
 #define PM8058_XO_INIT(_id, _modes, _ops, _always_on) \
-	[PM8058_XO_ID_##_id] = { \
+	{ \
 		.init_data = { \
 			.constraints = { \
 				.valid_modes_mask = _modes, \
@@ -412,63 +406,44 @@
 				ARRAY_SIZE(xo_consumers_##_id),\
 			.consumer_supplies = xo_consumers_##_id, \
 		}, \
+		.id = PM8058_XO_ID_##_id, \
 	}
 
 #define PM8058_XO_INIT_AX(_id) \
 	PM8058_XO_INIT(_id, REGULATOR_MODE_NORMAL, REGULATOR_CHANGE_STATUS, 0)
 
-static struct pm8058_xo_pdata pm8058_xo_init_pdata[PM8058_XO_ID_MAX] = {
+static struct pm8058_xo_pdata pm8058_xo_init_pdata[] = {
 	PM8058_XO_INIT_AX(A0),
 	PM8058_XO_INIT_AX(A1),
 };
 
-#define PM8058_XO(_id) { \
-	.name = PM8058_XO_BUFFER_DEV_NAME, \
-	.id = _id, \
-	.platform_data = &pm8058_xo_init_pdata[_id], \
-	.pdata_size = sizeof(pm8058_xo_init_pdata[_id]), \
-}
+#define PM8058_GPIO_INT		47
 
-/* Put sub devices with fixed location first in sub_devices array */
-static struct mfd_cell pm8058_subdevs[] = {
-	{	.name = "pm8058-mpp",
-		.platform_data	= &pm8058_mpp_data,
-		.pdata_size	= sizeof(pm8058_mpp_data),
-	},
-	{
-		.name = "pm8058-gpio",
-		.id = -1,
-		.platform_data = &pm8058_gpio_data,
-		.pdata_size	= sizeof(pm8058_gpio_data),
-	},
-#ifdef CONFIG_SENSORS_MSM_ADC
-	{
-		.name = "pm8058-xoadc",
-		.id = -1,
-		.num_resources = ARRAY_SIZE(resources_adc),
-		.resources = resources_adc,
-		.platform_data = &xoadc_pdata,
-		.pdata_size	=sizeof(xoadc_pdata),
-	},
-#endif
-	PM8058_VREG(PM8058_VREG_ID_L3),
-	PM8058_VREG(PM8058_VREG_ID_L8),
-	PM8058_VREG(PM8058_VREG_ID_L9),
-	PM8058_VREG(PM8058_VREG_ID_L14),
-	PM8058_VREG(PM8058_VREG_ID_L15),
-	PM8058_VREG(PM8058_VREG_ID_L18),
-	PM8058_VREG(PM8058_VREG_ID_S4),
-	PM8058_VREG(PM8058_VREG_ID_LVS0),
-	PM8058_XO(PM8058_XO_ID_A0),
-	PM8058_XO(PM8058_XO_ID_A1),
+static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata = {
+	.irq_base		= PMIC8058_IRQ_BASE,
+	.devirq			= MSM_GPIO_TO_INT(PM8058_GPIO_INT),
+	.irq_trigger_flag	= IRQF_TRIGGER_LOW,
+};
+
+static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata = {
+	.gpio_base	= PM8058_GPIO_PM_TO_SYS(0),
+};
+
+static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata = {
+	.mpp_base	= PM8058_MPP_PM_TO_SYS(0),
 };
 
 static struct pm8058_platform_data pm8058_fsm9xxx_data = {
-	.irq_base = PMIC8058_IRQ_BASE,
-	.irq = MSM_GPIO_TO_INT(47),
-
-	.num_subdevs = ARRAY_SIZE(pm8058_subdevs),
-	.sub_devices = pm8058_subdevs,
+	.irq_pdata		= &pm8xxx_irq_pdata,
+	.gpio_pdata		= &pm8xxx_gpio_pdata,
+	.mpp_pdata		= &pm8xxx_mpp_pdata,
+	.regulator_pdatas	= pm8058_vreg_init,
+	.num_regulators		= ARRAY_SIZE(pm8058_vreg_init),
+	.xo_buffer_pdata	= pm8058_xo_init_pdata,
+	.num_xo_buffers		= ARRAY_SIZE(pm8058_xo_init_pdata),
+#ifdef CONFIG_SENSORS_MSM_ADC
+	.xoadc_pdata		= &pm8058_xoadc_pdata,
+#endif
 };
 
 #ifdef CONFIG_MSM_SSBI
@@ -882,13 +857,15 @@
 	msm_device_ssbi_pmic1.dev.platform_data =
 			&fsm9xxx_ssbi_pm8058_pdata;
 #endif
+	buses_init();
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 #ifdef CONFIG_MSM_SPM
 	msm_spm_init(&msm_spm_data, 1);
 #endif
-	buses_init();
+	pm8058_gpios_init();
+	pm8058_mpps_init();
 	phy_init();
 	grfc_init();
 	user_gpios_init();
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index ca1da75..1435774 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -1070,12 +1070,19 @@
 
 #ifdef CONFIG_ARCH_MSM7X27A
 #define MSM_PMEM_MDP_SIZE       0x1900000
+#define MSM7x25A_MSM_PMEM_MDP_SIZE	0x1000000
+
 #define MSM_PMEM_ADSP_SIZE      0x1000000
+#define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
+
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
 #define MSM_FB_SIZE		0x260000
+#define MSM7x25A_MSM_FB_SIZE	0xE1000
 #else
 #define MSM_FB_SIZE		0x195000
+#define MSM7x25A_MSM_FB_SIZE	0xE1000
+
 #endif
 
 #endif
@@ -2568,7 +2575,12 @@
 	void *addr;
 	unsigned long size;
 
-	size = fb_size ? : MSM_FB_SIZE;
+	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
+		fb_size = MSM7x25A_MSM_FB_SIZE;
+	else
+		fb_size = MSM_FB_SIZE;
+
+	size = fb_size;
 	addr = alloc_bootmem_align(size, 0x1000);
 	msm_fb_resources[0].start = __pa(addr);
 	msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
@@ -2589,6 +2601,15 @@
 
 static void __init size_pmem_devices(void)
 {
+
+	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
+		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
+		pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
+	} else {
+		pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+	}
+
 #ifdef CONFIG_ANDROID_PMEM
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_mdp_size;
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 9fb9fb6..eda29cd 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -23,16 +23,14 @@
 #endif
 #include <linux/msm_ssbi.h>
 #include <linux/mfd/pmic8058.h>
+#include <linux/leds.h>
 #include <linux/mfd/marimba.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/smsc911x.h>
 #include <linux/ofn_atlab.h>
 #include <linux/power_supply.h>
-#include <linux/input/pmic8058-keypad.h>
 #include <linux/i2c/isa1200.h>
-#include <linux/pwm.h>
-#include <linux/pmic8058-pwm.h>
 #include <linux/i2c/tsc2007.h>
 #include <linux/input/kp_flip_switch.h>
 #include <linux/leds-pmic8058.h>
@@ -123,6 +121,8 @@
 /* Macros assume PMIC GPIOs start at 0 */
 #define PM8058_GPIO_PM_TO_SYS(pm_gpio)     (pm_gpio + NR_GPIO_IRQS)
 #define PM8058_GPIO_SYS_TO_PM(sys_gpio)    (sys_gpio - NR_GPIO_IRQS)
+#define PM8058_MPP_BASE			   PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS)
+#define PM8058_MPP_PM_TO_SYS(pm_gpio)	   (pm_gpio + PM8058_MPP_BASE)
 
 #define PMIC_GPIO_FLASH_BOOST_ENABLE	15	/* PMIC GPIO Number 16 */
 #define PMIC_GPIO_HAP_ENABLE   16  /* PMIC GPIO Number 17 */
@@ -136,61 +136,71 @@
 #define PMIC_GPIO_QUICKVX_CLK 37 /* PMIC GPIO 38 */
 
 #define	PM_FLIP_MPP 5 /* PMIC MPP 06 */
+
+struct pm8xxx_gpio_init_info {
+	unsigned			gpio;
+	struct pm_gpio			config;
+};
+
 static int pm8058_gpios_init(void)
 {
 	int rc;
-	int pmic_gpio_hdmi_5v_en;
 
-#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
-	struct pm8058_gpio sdcc_det = {
-		.direction      = PM_GPIO_DIR_IN,
-		.pull           = PM_GPIO_PULL_UP_1P5,
-		.vin_sel        = 2,
-		.function       = PM_GPIO_FUNC_NORMAL,
-		.inv_int_pol    = 0,
-	};
-#endif
-	struct pm8058_gpio sdc4_en = {
-		.direction      = PM_GPIO_DIR_OUT,
-		.pull           = PM_GPIO_PULL_NO,
-		.vin_sel        = PM_GPIO_VIN_L5,
-		.function       = PM_GPIO_FUNC_NORMAL,
-		.inv_int_pol    = 0,
-		.out_strength   = PM_GPIO_STRENGTH_LOW,
-		.output_value   = 0,
+	struct pm8xxx_gpio_init_info sdc4_en = {
+		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_EN_N),
+		{
+			.direction      = PM_GPIO_DIR_OUT,
+			.pull           = PM_GPIO_PULL_NO,
+			.vin_sel        = PM8058_GPIO_VIN_L5,
+			.function       = PM_GPIO_FUNC_NORMAL,
+			.inv_int_pol    = 0,
+			.out_strength   = PM_GPIO_STRENGTH_LOW,
+			.output_value   = 0,
+		},
 	};
 
-	struct pm8058_gpio haptics_enable = {
-		.direction      = PM_GPIO_DIR_OUT,
-		.pull           = PM_GPIO_PULL_NO,
-		.out_strength   = PM_GPIO_STRENGTH_HIGH,
-		.function       = PM_GPIO_FUNC_NORMAL,
-		.inv_int_pol    = 0,
-		.vin_sel        = 2,
-		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
-		.output_value   = 0,
+	struct pm8xxx_gpio_init_info haptics_enable = {
+		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
+		{
+			.direction      = PM_GPIO_DIR_OUT,
+			.pull           = PM_GPIO_PULL_NO,
+			.out_strength   = PM_GPIO_STRENGTH_HIGH,
+			.function       = PM_GPIO_FUNC_NORMAL,
+			.inv_int_pol    = 0,
+			.vin_sel        = 2,
+			.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+			.output_value   = 0,
+		},
 	};
 
-	struct pm8058_gpio hdmi_5V_en = {
-		.direction      = PM_GPIO_DIR_OUT,
-		.pull           = PM_GPIO_PULL_NO,
-		.vin_sel        = PM_GPIO_VIN_VPH,
-		.function       = PM_GPIO_FUNC_NORMAL,
-		.out_strength   = PM_GPIO_STRENGTH_LOW,
-		.output_value   = 0,
+	struct pm8xxx_gpio_init_info hdmi_5V_en = {
+		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HDMI_5V_EN_V3),
+		{
+			.direction      = PM_GPIO_DIR_OUT,
+			.pull           = PM_GPIO_PULL_NO,
+			.vin_sel        = PM8058_GPIO_VIN_VPH,
+			.function       = PM_GPIO_FUNC_NORMAL,
+			.out_strength   = PM_GPIO_STRENGTH_LOW,
+			.output_value   = 0,
+		},
 	};
 
-	struct pm8058_gpio flash_boost_enable = {
-		.direction      = PM_GPIO_DIR_OUT,
-		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
-		.output_value   = 0,
-		.pull           = PM_GPIO_PULL_NO,
-		.vin_sel        = PM_GPIO_VIN_S3,
-		.out_strength   = PM_GPIO_STRENGTH_HIGH,
-		.function       = PM_GPIO_FUNC_2,
+	struct pm8xxx_gpio_init_info flash_boost_enable = {
+		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_FLASH_BOOST_ENABLE),
+		{
+			.direction      = PM_GPIO_DIR_OUT,
+			.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+			.output_value   = 0,
+			.pull           = PM_GPIO_PULL_NO,
+			.vin_sel        = PM8058_GPIO_VIN_S3,
+			.out_strength   = PM_GPIO_STRENGTH_HIGH,
+			.function        = PM_GPIO_FUNC_2,
+		},
 	};
 
-	struct pm8058_gpio gpio23 = {
+	struct pm8xxx_gpio_init_info gpio23 = {
+		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_WLAN_EXT_POR),
+		{
 			.direction      = PM_GPIO_DIR_OUT,
 			.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
 			.output_value   = 0,
@@ -198,71 +208,83 @@
 			.vin_sel        = 2,
 			.out_strength   = PM_GPIO_STRENGTH_LOW,
 			.function       = PM_GPIO_FUNC_NORMAL,
+		}
 	};
 
-
-	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
-						machine_is_msm7x30_fluid())
-		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
-	else
-		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
-
-	if (machine_is_msm7x30_fluid()) {
-		rc = pm8058_gpio_config(PMIC_GPIO_HAP_ENABLE, &haptics_enable);
-		if (rc) {
-			pr_err("%s: PMIC GPIO %d write failed\n", __func__,
-				(PMIC_GPIO_HAP_ENABLE + 1));
-			return rc;
-		}
-		rc = pm8058_gpio_config(PMIC_GPIO_FLASH_BOOST_ENABLE,
-			&flash_boost_enable);
-		if (rc) {
-			pr_err("%s: PMIC GPIO %d write failed\n", __func__,
-				(PMIC_GPIO_FLASH_BOOST_ENABLE + 1));
-			return rc;
-		}
-	}
-
 #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
-	if (machine_is_msm7x30_fluid())
-		sdcc_det.inv_int_pol = 1;
+	struct pm8xxx_gpio_init_info sdcc_det = {
+		PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SD_DET - 1),
+		{
+			.direction      = PM_GPIO_DIR_IN,
+			.pull           = PM_GPIO_PULL_UP_1P5,
+			.vin_sel        = 2,
+			.function       = PM_GPIO_FUNC_NORMAL,
+			.inv_int_pol    = 0,
+		},
+	};
 
-	rc = pm8058_gpio_config(PMIC_GPIO_SD_DET - 1, &sdcc_det);
+	if (machine_is_msm7x30_fluid())
+		sdcc_det.config.inv_int_pol = 1;
+
+	rc = pm8xxx_gpio_config(sdcc_det.gpio, &sdcc_det.config);
 	if (rc) {
 		pr_err("%s PMIC_GPIO_SD_DET config failed\n", __func__);
 		return rc;
 	}
 #endif
 
-	rc = pm8058_gpio_config(pmic_gpio_hdmi_5v_en, &hdmi_5V_en);
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
+						machine_is_msm7x30_fluid())
+		hdmi_5V_en.gpio = PMIC_GPIO_HDMI_5V_EN_V2;
+	else
+		hdmi_5V_en.gpio = PMIC_GPIO_HDMI_5V_EN_V3;
+
+	hdmi_5V_en.gpio = PM8058_GPIO_PM_TO_SYS(hdmi_5V_en.gpio);
+
+	rc = pm8xxx_gpio_config(hdmi_5V_en.gpio, &hdmi_5V_en.config);
 	if (rc) {
 		pr_err("%s PMIC_GPIO_HDMI_5V_EN config failed\n", __func__);
 		return rc;
 	}
 
 	/* Deassert GPIO#23 (source for Ext_POR on WLAN-Volans) */
-	rc = pm8058_gpio_config(PMIC_GPIO_WLAN_EXT_POR, &gpio23);
+	rc = pm8xxx_gpio_config(gpio23.gpio, &gpio23.config);
 	if (rc) {
 		pr_err("%s PMIC_GPIO_WLAN_EXT_POR config failed\n", __func__);
 		return rc;
 	}
 
 	if (machine_is_msm7x30_fluid()) {
-		rc = pm8058_gpio_config(PMIC_GPIO_SDC4_EN_N, &sdc4_en);
+		/* Haptics gpio */
+		rc = pm8xxx_gpio_config(haptics_enable.gpio,
+						&haptics_enable.config);
+		if (rc) {
+			pr_err("%s: PMIC GPIO %d write failed\n", __func__,
+							haptics_enable.gpio);
+			return rc;
+		}
+		/* Flash boost gpio */
+		rc = pm8xxx_gpio_config(flash_boost_enable.gpio,
+						&flash_boost_enable.config);
+		if (rc) {
+			pr_err("%s: PMIC GPIO %d write failed\n", __func__,
+						flash_boost_enable.gpio);
+			return rc;
+		}
+		/* SCD4 gpio */
+		rc = pm8xxx_gpio_config(sdc4_en.gpio, &sdc4_en.config);
 		if (rc) {
 			pr_err("%s PMIC_GPIO_SDC4_EN_N config failed\n",
 								 __func__);
 			return rc;
 		}
-		rc = gpio_request(PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_EN_N),
-				  "sdc4_en");
+		rc = gpio_request(sdc4_en.gpio, "sdc4_en");
 		if (rc) {
 			pr_err("%s PMIC_GPIO_SDC4_EN_N gpio_request failed\n",
 				__func__);
 			return rc;
 		}
-		gpio_set_value_cansleep(
-			PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_EN_N), 0);
+		gpio_set_value_cansleep(sdc4_en.gpio, 0);
 	}
 
 	return 0;
@@ -450,12 +472,12 @@
 
 static int pm8058_pwm_config(struct pwm_device *pwm, int ch, int on)
 {
-	struct pm8058_gpio pwm_gpio_config = {
+	struct pm_gpio pwm_gpio_config = {
 		.direction      = PM_GPIO_DIR_OUT,
 		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
 		.output_value   = 0,
 		.pull           = PM_GPIO_PULL_NO,
-		.vin_sel        = PM_GPIO_VIN_S3,
+		.vin_sel        = PM8058_GPIO_VIN_S3,
 		.out_strength   = PM_GPIO_STRENGTH_HIGH,
 		.function       = PM_GPIO_FUNC_2,
 	};
@@ -469,9 +491,10 @@
 	case 2:
 		if (on) {
 			id = 24 + ch;
-			rc = pm8058_gpio_config(id - 1, &pwm_gpio_config);
+			rc = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(id - 1),
+							&pwm_gpio_config);
 			if (rc)
-				pr_err("%s: pm8058_gpio_config(%d): rc=%d\n",
+				pr_err("%s: pm8xxx_gpio_config(%d): rc=%d\n",
 				       __func__, id, rc);
 		}
 		break;
@@ -660,78 +683,47 @@
 	KEY(11, 7, KEY_RIGHTSHIFT),
 };
 
-static struct resource resources_keypad[] = {
-	{
-		.start	= PM8058_KEYPAD_IRQ(PMIC8058_IRQ_BASE),
-		.end	= PM8058_KEYPAD_IRQ(PMIC8058_IRQ_BASE),
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.start	= PM8058_KEYSTUCK_IRQ(PMIC8058_IRQ_BASE),
-		.end	= PM8058_KEYSTUCK_IRQ(PMIC8058_IRQ_BASE),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
 static struct matrix_keymap_data surf_keymap_data = {
-        .keymap_size    = ARRAY_SIZE(surf_keymap),
-        .keymap         = surf_keymap,
+	.keymap_size    = ARRAY_SIZE(surf_keymap),
+	.keymap		= surf_keymap,
 };
 
-
-static struct pmic8058_keypad_data surf_keypad_data = {
+static struct pm8xxx_keypad_platform_data surf_keypad_data = {
 	.input_name		= "surf_keypad",
 	.input_phys_device	= "surf_keypad/input0",
 	.num_rows		= 12,
 	.num_cols		= 8,
-	.rows_gpio_start	= 8,
-	.cols_gpio_start	= 0,
-	.debounce_ms		= {8, 10},
+	.rows_gpio_start	= PM8058_GPIO_PM_TO_SYS(8),
+	.cols_gpio_start	= PM8058_GPIO_PM_TO_SYS(0),
+	.debounce_ms		= 15,
 	.scan_delay_ms		= 32,
 	.row_hold_ns		= 91500,
 	.wakeup			= 1,
-	.keymap_data            = &surf_keymap_data,
+	.keymap_data		= &surf_keymap_data,
 };
 
 static struct matrix_keymap_data fluid_keymap_data = {
-        .keymap_size    = ARRAY_SIZE(fluid_keymap),
-        .keymap         = fluid_keymap,
+	.keymap_size	= ARRAY_SIZE(fluid_keymap),
+	.keymap		= fluid_keymap,
 };
 
-
-
-static struct pmic8058_keypad_data fluid_keypad_data = {
+static struct pm8xxx_keypad_platform_data fluid_keypad_data = {
 	.input_name		= "fluid-keypad",
 	.input_phys_device	= "fluid-keypad/input0",
 	.num_rows		= 5,
 	.num_cols		= 5,
-	.rows_gpio_start	= 8,
-	.cols_gpio_start	= 0,
-	.debounce_ms		= {8, 10},
+	.rows_gpio_start	= PM8058_GPIO_PM_TO_SYS(8),
+	.cols_gpio_start	= PM8058_GPIO_PM_TO_SYS(0),
+	.debounce_ms		= 15,
 	.scan_delay_ms		= 32,
 	.row_hold_ns		= 91500,
 	.wakeup			= 1,
-	.keymap_data            = &fluid_keymap_data,
+	.keymap_data		= &fluid_keymap_data,
 };
 
 static struct pm8058_pwm_pdata pm8058_pwm_data = {
-	.config		= pm8058_pwm_config,
-	.enable		= pm8058_pwm_enable,
-};
-
-/* Put sub devices with fixed location first in sub_devices array */
-#define	PM8058_SUBDEV_KPD	0
-#define	PM8058_SUBDEV_LED	1
-
-static struct pm8058_gpio_platform_data pm8058_gpio_data = {
-	.gpio_base	= PM8058_GPIO_PM_TO_SYS(0),
-	.irq_base	= PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 0),
-	.init		= pm8058_gpios_init,
-};
-
-static struct pm8058_gpio_platform_data pm8058_mpp_data = {
-	.gpio_base	= PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS),
-	.irq_base	= PM8058_MPP_IRQ(PMIC8058_IRQ_BASE, 0),
+	.config         = pm8058_pwm_config,
+	.enable         = pm8058_pwm_enable,
 };
 
 static struct pmic8058_led pmic8058_ffa_leds[] = {
@@ -765,38 +757,6 @@
 	},
 };
 
-static struct mfd_cell pm8058_subdevs[] = {
-	{	.name = "pm8058-keypad",
-		.id		= -1,
-		.num_resources	= ARRAY_SIZE(resources_keypad),
-		.resources	= resources_keypad,
-	},
-	{	.name = "pm8058-led",
-		.id		= -1,
-	},
-	{	.name = "pm8058-gpio",
-		.id		= -1,
-		.platform_data	= &pm8058_gpio_data,
-		.pdata_size	= sizeof(pm8058_gpio_data),
-	},
-	{	.name = "pm8058-mpp",
-		.id		= -1,
-		.platform_data	= &pm8058_mpp_data,
-		.pdata_size	= sizeof(pm8058_mpp_data),
-	},
-	{	.name = "pm8058-pwm",
-		.id		= -1,
-		.platform_data	= &pm8058_pwm_data,
-		.pdata_size	= sizeof(pm8058_pwm_data),
-	},
-	{	.name = "pm8058-nfc",
-		.id		= -1,
-	},
-	{	.name = "pm8058-upl",
-		.id		= -1,
-	},
-};
-
 static struct pmic8058_leds_platform_data pm8058_surf_leds_data = {
 	.num_leds = ARRAY_SIZE(pmic8058_surf_leds),
 	.leds	= pmic8058_surf_leds,
@@ -825,13 +785,25 @@
 	.leds	= pmic8058_fluid_leds,
 };
 
-static struct pm8058_platform_data pm8058_7x30_data = {
-	.irq_base = PMIC8058_IRQ_BASE,
-	.irq = MSM_GPIO_TO_INT(PMIC_GPIO_INT),
+static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata = {
+	.irq_base		= PMIC8058_IRQ_BASE,
+	.devirq			= MSM_GPIO_TO_INT(PMIC_GPIO_INT),
+	.irq_trigger_flag       = IRQF_TRIGGER_LOW,
+};
 
-	.num_subdevs = ARRAY_SIZE(pm8058_subdevs),
-	.sub_devices = pm8058_subdevs,
-	.irq_trigger_flags = IRQF_TRIGGER_LOW,
+static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata = {
+	.gpio_base		= PM8058_GPIO_PM_TO_SYS(0),
+};
+
+static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata = {
+	.mpp_base	= PM8058_MPP_PM_TO_SYS(0),
+};
+
+static struct pm8058_platform_data pm8058_7x30_data = {
+	.irq_pdata		= &pm8xxx_irq_pdata,
+	.gpio_pdata		= &pm8xxx_gpio_pdata,
+	.mpp_pdata		= &pm8xxx_mpp_pdata,
+	.pwm_pdata		= &pm8058_pwm_data,
 };
 
 #ifdef CONFIG_MSM_SSBI
@@ -1611,15 +1583,10 @@
 		pr_err("%s: gpio_tlmm_config (gpio=%d) failed\n",
 		       __func__, PMIC_GPIO_INT);
 
-	if (machine_is_msm7x30_fluid()) {
-		pm8058_7x30_data.sub_devices[PM8058_SUBDEV_KPD].platform_data
-			= &fluid_keypad_data;
-	} else {
-		pm8058_7x30_data.sub_devices[PM8058_SUBDEV_KPD].platform_data
-			= &surf_keypad_data;
-		pm8058_7x30_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
-                        = sizeof(surf_keypad_data);
-	}
+	if (machine_is_msm8x60_fluid())
+		pm8058_7x30_data.keypad_pdata = &fluid_keypad_data;
+	else
+		pm8058_7x30_data.keypad_pdata = &surf_keypad_data;
 
 	return 0;
 }
@@ -3246,24 +3213,27 @@
 {
         int rc;
         static int vbus_is_on;
-        struct pm8058_gpio usb_vbus = {
-                .direction      = PM_GPIO_DIR_OUT,
-                .pull           = PM_GPIO_PULL_NO,
-                .output_buffer  = PM_GPIO_OUT_BUF_CMOS,
-                .output_value   = 1,
-                .vin_sel        = 2,
-                .out_strength   = PM_GPIO_STRENGTH_MED,
-                .function       = PM_GPIO_FUNC_NORMAL,
-                .inv_int_pol    = 0,
-        };
+	struct pm8xxx_gpio_init_info usb_vbus = {
+		PM8058_GPIO_PM_TO_SYS(36),
+		{
+			.direction      = PM_GPIO_DIR_OUT,
+			.pull           = PM_GPIO_PULL_NO,
+			.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+			.output_value   = 1,
+			.vin_sel        = 2,
+			.out_strength   = PM_GPIO_STRENGTH_MED,
+			.function       = PM_GPIO_FUNC_NORMAL,
+			.inv_int_pol    = 0,
+		},
+	};
 
         /* If VBUS is already on (or off), do nothing. */
         if (unlikely(on == vbus_is_on))
                 return;
 
         if (on) {
-                rc = pm8058_gpio_config(36, &usb_vbus);
-                if (rc) {
+		rc = pm8xxx_gpio_config(usb_vbus.gpio, &usb_vbus.config);
+		if (rc) {
                         pr_err("%s PMIC GPIO 36 write failed\n", __func__);
                         return;
                 }
@@ -4041,14 +4011,17 @@
 static unsigned quickvx_vlp_gpio =
 	GPIO_CFG(97, 0, GPIO_CFG_OUTPUT,  GPIO_CFG_NO_PULL,	GPIO_CFG_2MA);
 
-static struct pm8058_gpio pmic_quickvx_clk_gpio = {
-	.direction      = PM_GPIO_DIR_OUT,
-	.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
-	.output_value   = 1,
-	.pull           = PM_GPIO_PULL_NO,
-	.vin_sel        = PM_GPIO_VIN_S3,
-	.out_strength   = PM_GPIO_STRENGTH_HIGH,
-	.function       = PM_GPIO_FUNC_2,
+static struct pm8xxx_gpio_init_info pmic_quickvx_clk_gpio = {
+	PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_QUICKVX_CLK),
+	{
+		.direction      = PM_GPIO_DIR_OUT,
+		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+		.output_value   = 1,
+		.pull           = PM_GPIO_PULL_NO,
+		.vin_sel        = PM8058_GPIO_VIN_S3,
+		.out_strength   = PM_GPIO_STRENGTH_HIGH,
+		.function       = PM_GPIO_FUNC_2,
+	},
 };
 
 static int display_common_power(int on)
@@ -4088,11 +4061,11 @@
 			/* bring QuickVX VLP line low */
 			gpio_set_value(97, 0);
 
-			rc = pm8058_gpio_config(PMIC_GPIO_QUICKVX_CLK,
-				&pmic_quickvx_clk_gpio);
+			rc = pm8xxx_gpio_config(pmic_quickvx_clk_gpio.gpio,
+						&pmic_quickvx_clk_gpio.config);
 			if (rc) {
-				pr_err("%s: pm8058_gpio_config(%#x)=%d\n",
-					__func__, PMIC_GPIO_QUICKVX_CLK + 1,
+				pr_err("%s: pm8xxx_gpio_config(%#x)=%d\n",
+					__func__, pmic_quickvx_clk_gpio.gpio,
 					rc);
 				return rc;
 			}
@@ -6366,6 +6339,11 @@
 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
 	if (machine_is_msm8x55_svlte_surf())
 		msm7x30_sdc2_data.msmsdcc_fmax =  24576000;
+	if (machine_is_msm8x55_svlte_surf() ||
+			machine_is_msm8x55_svlte_ffa()) {
+		msm7x30_sdc2_data.sdiowakeup_irq = MSM_GPIO_TO_INT(68);
+		msm7x30_sdc2_data.is_sdio_al_client = 1;
+	}
 	sdcc_vreg_data[1].vreg_data = vreg_s3;
 	sdcc_vreg_data[1].level = 1800;
 	msm_add_sdcc(2, &msm7x30_sdc2_data);
@@ -6447,16 +6425,12 @@
 
 static void __init pmic8058_leds_init(void)
 {
-	if (machine_is_msm7x30_surf()) {
-		pm8058_7x30_data.sub_devices[PM8058_SUBDEV_LED].platform_data
-			= &pm8058_surf_leds_data;
-	} else if (!machine_is_msm7x30_fluid()) {
-		pm8058_7x30_data.sub_devices[PM8058_SUBDEV_LED].platform_data
-			= &pm8058_ffa_leds_data;
-	} else if (machine_is_msm7x30_fluid()) {
-		pm8058_7x30_data.sub_devices[PM8058_SUBDEV_LED].platform_data
-			= &pm8058_fluid_leds_data;
-	}
+	if (machine_is_msm7x30_surf())
+		pm8058_7x30_data.leds_pdata = &pm8058_surf_leds_data;
+	else if (!machine_is_msm7x30_fluid())
+		pm8058_7x30_data.leds_pdata = &pm8058_ffa_leds_data;
+	else if (machine_is_msm7x30_fluid())
+		pm8058_7x30_data.leds_pdata = &pm8058_fluid_leds_data;
 }
 
 static struct msm_spm_platform_data msm_spm_data __initdata = {
@@ -6775,8 +6749,14 @@
 
 static int kp_flip_mpp_config(void)
 {
-	return pm8058_mpp_config_digital_in(PM_FLIP_MPP,
-		PM8058_MPP_DIG_LEVEL_S3, PM_MPP_DIN_TO_INT);
+	struct pm8xxx_mpp_config_data kp_flip_mpp = {
+		.type = PM8XXX_MPP_TYPE_D_INPUT,
+		.level = PM8018_MPP_DIG_LEVEL_S3,
+		.control = PM8XXX_MPP_DIN_TO_INT,
+	};
+
+	return pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(PM_FLIP_MPP),
+						&kp_flip_mpp);
 }
 
 static struct flip_switch_pdata flip_switch_data = {
@@ -6987,6 +6967,10 @@
 		msm_adc_pdata.num_adc = ARRAY_SIZE(msm_adc_surf_device_names);
 	}
 
+	pmic8058_leds_init();
+
+	buses_init();
+
 #ifdef CONFIG_MSM_SSBI
 	msm_device_ssbi_pmic1.dev.platform_data =
 				&msm7x30_ssbi_pm8058_pdata;
@@ -7018,7 +7002,6 @@
 	msm_device_i2c_init();
 	msm_device_i2c_2_init();
 	qup_device_i2c_init();
-	buses_init();
 	msm7x30_init_marimba();
 #ifdef CONFIG_MSM7KV2_AUDIO
 	snddev_poweramp_gpio_init();
@@ -7066,7 +7049,8 @@
 
 	if (machine_is_msm7x30_surf())
 		platform_device_register(&flip_switch_device);
-	pmic8058_leds_init();
+
+	pm8058_gpios_init();
 
 	if (machine_is_msm7x30_fluid()) {
 		/* Initialize platform data for fluid v2 hardware */
diff --git a/arch/arm/mach-msm/board-msm8960-regulator.c b/arch/arm/mach-msm/board-msm8960-regulator.c
index 29b7460..c67e100 100644
--- a/arch/arm/mach-msm/board-msm8960-regulator.c
+++ b/arch/arm/mach-msm/board-msm8960-regulator.c
@@ -165,6 +165,7 @@
 	REGULATOR_SUPPLY("CDC_VDDA_RX",		"tabla2x-slim"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-005b"),
 	REGULATOR_SUPPLY("EXT_HUB_VDDIO",	"msm_hsic_host"),
+	REGULATOR_SUPPLY("vcc_i2c",		"10-0048"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
@@ -231,6 +232,7 @@
 	REGULATOR_SUPPLY("ext_3p3v",		NULL),
 	REGULATOR_SUPPLY("vdd",			"3-005b"),
 	REGULATOR_SUPPLY("vdd_lvds_3p3v",	"mipi_dsi.1"),
+	REGULATOR_SUPPLY("mhl_ext_3p3v",	"msm_otg"),
 };
 
 #define PM8921_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 7448cc6..e8a083f 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -39,6 +39,7 @@
 #include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/msm_tsens.h>
 #include <linux/ks8851.h>
+#include <linux/i2c/isa1200.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -173,6 +174,7 @@
 	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 PM8921 MPP configurations */
@@ -775,6 +777,30 @@
 };
 #endif
 
+#define HAP_SHIFT_LVL_OE_GPIO	47
+
+static struct gpiomux_setting hap_lvl_shft_suspended_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting hap_lvl_shft_active_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config hap_lvl_shft_config[] __initdata = {
+	{
+		.gpio = HAP_SHIFT_LVL_OE_GPIO,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &hap_lvl_shft_suspended_config,
+			[GPIOMUX_ACTIVE] = &hap_lvl_shft_active_config,
+		},
+	},
+};
+
 #if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
 enum {
 	SX150X_CAM,
@@ -817,7 +843,6 @@
 #endif
 #endif
 
-#define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
 #define MSM_PMEM_ADSP_SIZE         0x3800000
 #define MSM_PMEM_AUDIO_SIZE        0x28B000
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -828,10 +853,12 @@
 
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_ION_EBI_SIZE	MSM_PMEM_SIZE
+#define MSM_PMEM_KERNEL_EBI1_SIZE  0xB0C000
+#define MSM_ION_EBI_SIZE	(MSM_PMEM_SIZE + 0x600000)
 #define MSM_ION_ADSP_SIZE	MSM_PMEM_ADSP_SIZE
 #define MSM_ION_HEAP_NUM	4
 #else
+#define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
 #define MSM_ION_HEAP_NUM	2
 #endif
 
@@ -1053,12 +1080,22 @@
 	bank_size = msm8960_memory_bank_size();
 	low = meminfo.bank[0].start;
 	high = mb->start + mb->size;
+
+	/* Check if 32 bit overflow occured */
+	if (high < mb->start)
+		high = ~0UL;
+
 	low &= ~(bank_size - 1);
 
 	if (high - low <= bank_size)
 		return;
 	msm8960_reserve_info.low_unstable_address = low + bank_size;
-	msm8960_reserve_info.max_unstable_size = high - low - bank_size;
+	/* To avoid overflow of u32 compute max_unstable_size
+	 * by first subtracting low from mb->start)
+	 * */
+	msm8960_reserve_info.max_unstable_size = (mb->start - low) +
+						mb->size - bank_size;
+
 	msm8960_reserve_info.bank_size = bank_size;
 	pr_info("low unstable address %lx max size %lx bank size %lx\n",
 		msm8960_reserve_info.low_unstable_address,
@@ -1418,6 +1455,14 @@
 		msm_get_cam_resources(s_info);
 		platform_device_register(cam_dev[i]);
 	}
+
+	platform_device_register(&msm8960_device_csiphy0);
+	platform_device_register(&msm8960_device_csiphy1);
+	platform_device_register(&msm8960_device_csid0);
+	platform_device_register(&msm8960_device_csid1);
+	platform_device_register(&msm8960_device_ispif);
+	platform_device_register(&msm8960_device_vfe);
+	platform_device_register(&msm8960_device_vpe);
 }
 #endif
 
@@ -2068,6 +2113,14 @@
 };
 #endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
 
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+static struct platform_device wfd_panel_device = {
+	.name = "wfd_panel",
+	.id = 0,
+	.dev.platform_data = NULL,
+};
+#endif
+
 #ifdef CONFIG_MSM_BUS_SCALING
 static struct msm_bus_vectors dtv_bus_init_vectors[] = {
 	{
@@ -2682,6 +2735,10 @@
 	msm_gpiomux_install(wcnss_5wire_interface,
 			ARRAY_SIZE(wcnss_5wire_interface));
 
+	if (machine_is_msm8960_mtp() || machine_is_msm8960_fluid() ||
+		machine_is_msm8960_liquid() || machine_is_msm8960_cdp())
+		msm_gpiomux_install(hap_lvl_shft_config,
+			ARRAY_SIZE(hap_lvl_shft_config));
 	return 0;
 }
 
@@ -2794,7 +2851,6 @@
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
 		.name = "sdc_vdd",
-		.set_voltage_sup = 1,
 		.high_vol_level = 2950000,
 		.low_vol_level = 2950000,
 		.always_on = 1,
@@ -2805,7 +2861,6 @@
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.name = "sdc_vdd",
-		.set_voltage_sup = 1,
 		.high_vol_level = 2950000,
 		.low_vol_level = 2950000,
 		.hpm_uA = 600000, /* 600mA */
@@ -2817,7 +2872,6 @@
 	/* SDCC1 : eMMC card connected */
 	[SDCC1] = {
 		.name = "sdc_vccq",
-		.set_voltage_sup = 1,
 		.always_on = 1,
 		.high_vol_level = 1800000,
 		.low_vol_level = 1800000,
@@ -2830,7 +2884,6 @@
 	/* SDCC3 : External card slot connected */
 	[SDCC3] = {
 		.name = "sdc_vddp",
-		.set_voltage_sup = 1,
 		.high_vol_level = 2950000,
 		.low_vol_level = 1850000,
 		.always_on = 1,
@@ -2985,7 +3038,6 @@
 	.sup_clk_cnt	= ARRAY_SIZE(sdc1_sup_clk_rates),
 	.pclk_src_dfab	= 1,
 	.nonremovable	= 1,
-	.sdcc_v4_sup	= true,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC1],
 	.pin_data	= &mmc_slot_pin_data[SDCC1]
 };
@@ -3001,7 +3053,6 @@
 #ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
 	.wpswitch_gpio	= PM8921_GPIO_PM_TO_SYS(16),
 #endif
-	.sdcc_v4_sup	= true,
 	.vreg_data	= &mmc_slot_vreg_data[SDCC3],
 	.pin_data	= &mmc_slot_pin_data[SDCC3],
 #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
@@ -3057,15 +3108,6 @@
 	int rc;
 	static bool vbus_is_on;
 	static struct regulator *mvs_otg_switch;
-	struct pm_gpio param = {
-		.direction	= PM_GPIO_DIR_OUT,
-		.output_buffer	= PM_GPIO_OUT_BUF_CMOS,
-		.output_value	= 1,
-		.pull		= PM_GPIO_PULL_NO,
-		.vin_sel	= PM_GPIO_VIN_S4,
-		.out_strength	= PM_GPIO_STRENGTH_MED,
-		.function	= PM_GPIO_FUNC_NORMAL,
-	};
 
 	if (vbus_is_on == on)
 		return;
@@ -3085,27 +3127,29 @@
 			goto put_mvs_otg;
 		}
 
-		if (regulator_enable(mvs_otg_switch)) {
-			pr_err("unable to enable mvs_otg_switch\n");
+		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;
 		}
 
-		rc = pm8xxx_gpio_config(PM8921_GPIO_PM_TO_SYS(USB_5V_EN),
-				&param);
-		if (rc < 0) {
-			pr_err("failed to configure usb_5v_en gpio\n");
-			goto disable_mvs_otg;
+		if (regulator_enable(mvs_otg_switch)) {
+			pr_err("unable to enable mvs_otg_switch\n");
+			goto err_ldo_gpio_set_dir;
 		}
+
 		vbus_is_on = true;
 		return;
 	}
-disable_mvs_otg:
-		regulator_disable(mvs_otg_switch);
+	regulator_disable(mvs_otg_switch);
+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));
+	gpio_free(PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
 put_mvs_otg:
-		regulator_put(mvs_otg_switch);
-		vbus_is_on = false;
+	regulator_put(mvs_otg_switch);
+	vbus_is_on = false;
 }
 
 static struct msm_otg_platform_data msm_otg_pdata = {
@@ -3316,6 +3360,132 @@
 	},
 };
 
+#define PM_HAP_EN_GPIO		PM8921_GPIO_PM_TO_SYS(33)
+#define PM_HAP_LEN_GPIO		PM8921_GPIO_PM_TO_SYS(20)
+
+static struct msm_xo_voter *xo_handle_d1;
+
+static int isa1200_power(int on)
+{
+	int rc = 0;
+
+	gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !!on);
+
+	rc = on ? msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_ON) :
+			msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_OFF);
+	if (rc < 0) {
+		pr_err("%s: failed to %svote for TCXO D1 buffer%d\n",
+				__func__, on ? "" : "de-", rc);
+		goto err_xo_vote;
+	}
+
+	return 0;
+
+err_xo_vote:
+	gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !on);
+	return rc;
+}
+
+static int isa1200_dev_setup(bool enable)
+{
+	int rc = 0;
+
+	struct pm_gpio hap_gpio_config = {
+		.direction      = PM_GPIO_DIR_OUT,
+		.pull           = PM_GPIO_PULL_NO,
+		.out_strength   = PM_GPIO_STRENGTH_HIGH,
+		.function       = PM_GPIO_FUNC_NORMAL,
+		.inv_int_pol    = 0,
+		.vin_sel        = 2,
+		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+		.output_value   = 0,
+	};
+
+	if (enable == true) {
+		rc = pm8xxx_gpio_config(PM_HAP_EN_GPIO, &hap_gpio_config);
+		if (rc) {
+			pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+					__func__, PM_HAP_EN_GPIO, rc);
+			return rc;
+		}
+
+		rc = pm8xxx_gpio_config(PM_HAP_LEN_GPIO, &hap_gpio_config);
+		if (rc) {
+			pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+					__func__, PM_HAP_LEN_GPIO, rc);
+			return rc;
+		}
+
+		rc = gpio_request(HAP_SHIFT_LVL_OE_GPIO, "hap_shft_lvl_oe");
+		if (rc) {
+			pr_err("%s: unable to request gpio %d (%d)\n",
+					__func__, HAP_SHIFT_LVL_OE_GPIO, rc);
+			return rc;
+		}
+
+		rc = gpio_direction_output(HAP_SHIFT_LVL_OE_GPIO, 0);
+		if (rc) {
+			pr_err("%s: Unable to set direction\n", __func__);
+			goto free_gpio;
+		}
+
+		xo_handle_d1 = msm_xo_get(MSM_XO_TCXO_D1, "isa1200");
+		if (IS_ERR(xo_handle_d1)) {
+			rc = PTR_ERR(xo_handle_d1);
+			pr_err("%s: failed to get the handle for D1(%d)\n",
+							__func__, rc);
+			goto gpio_set_dir;
+		}
+	} else {
+		gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+
+		msm_xo_put(xo_handle_d1);
+	}
+
+	return 0;
+
+gpio_set_dir:
+	gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, 0);
+free_gpio:
+	gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+	return rc;
+}
+
+static struct isa1200_regulator isa1200_reg_data[] = {
+	{
+		.name = "vcc_i2c",
+		.min_uV = ISA_I2C_VTG_MIN_UV,
+		.max_uV = ISA_I2C_VTG_MAX_UV,
+		.load_uA = ISA_I2C_CURR_UA,
+	},
+};
+
+static struct isa1200_platform_data isa1200_1_pdata = {
+	.name = "vibrator",
+	.dev_setup = isa1200_dev_setup,
+	.power_on = isa1200_power,
+	.hap_en_gpio = PM_HAP_EN_GPIO,
+	.hap_len_gpio = PM_HAP_LEN_GPIO,
+	.max_timeout = 15000,
+	.mode_ctrl = PWM_GEN_MODE,
+	.pwm_fd = {
+		.pwm_div = 256,
+	},
+	.is_erm = false,
+	.smart_en = true,
+	.ext_clk_en = true,
+	.chip_en = 1,
+	.regulator_info = isa1200_reg_data,
+	.num_regulators = ARRAY_SIZE(isa1200_reg_data),
+};
+
+static struct i2c_board_info msm_isa1200_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("isa1200_1", 0x90>>1),
+		.platform_data = &isa1200_1_pdata,
+	},
+};
+
 #define CYTTSP_TS_GPIO_IRQ		11
 #define CYTTSP_TS_SLEEP_GPIO		50
 #define CYTTSP_TS_RESOUT_N_GPIO		52
@@ -3443,7 +3613,7 @@
 	/* T6 Object */
 	0, 0, 0, 0, 0, 0,
 	/* T38 Object */
-	11, 1, 0, 20, 10, 11, 0, 0, 0, 0,
+	11, 2, 0, 11, 11, 11, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -3453,18 +3623,18 @@
 	/* T7 Object */
 	100, 16, 50,
 	/* T8 Object */
-	8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	8, 0, 0, 0, 0, 0, 8, 14, 50, 215,
 	/* T9 Object */
-	131, 0, 0, 26, 42, 0, 32, 60, 2, 5,
-	0, 5, 5, 34, 10, 10, 10, 10, 255, 2,
-	85, 5, 18, 18, 18, 18, 0, 0, 5, 20,
-	0, 5, 45, 46,
+	131, 0, 0, 26, 42, 0, 32, 63, 3, 5,
+	0, 2, 1, 113, 10, 10, 8, 10, 255, 2,
+	85, 5, 0, 0, 20, 20, 75, 25, 202, 29,
+	10, 10, 45, 46,
 	/* T15 Object */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0,
 	/* T22 Object */
-	0, 0, 0, 0, 0, 0, 0, 0, 30, 0,
-	0, 0, 255, 255, 255, 255, 0,
+	5, 0, 0, 0, 0, 0, 0, 0, 30, 0,
+	0, 0, 5, 8, 10, 13, 0,
 	/* T24 Object */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -3474,7 +3644,7 @@
 	/* T27 Object */
 	0, 0, 0, 0, 0, 0, 0,
 	/* T28 Object */
-	0, 0, 0, 8, 8, 60,
+	0, 0, 0, 8, 12, 60,
 	/* T40 Object */
 	0, 0, 0, 0, 0,
 	/* T41 Object */
@@ -3645,6 +3815,13 @@
 	},
 };
 
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+static struct platform_device wfd_device = {
+	.name          = "msm_wfd",
+	.id            = -1,
+};
+#endif
+
 static struct tsens_platform_data msm_tsens_pdata  = {
 		.slope			= 910,
 		.tsens_factor		= 1000,
@@ -3773,14 +3950,20 @@
 	&ion_dev,
 #endif
 	&msm_rpm_log_device,
+	&msm_rpm_stat_device,
 #ifdef CONFIG_MSM_QDSS
 	&msm_etb_device,
 	&msm_tpiu_device,
 	&msm_funnel_device,
+	&msm_debug_device,
 	&msm_ptm_device,
 #endif
 	&msm_device_dspcrashd_8960,
 	&msm8960_device_watchdog,
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+	&wfd_panel_device,
+	&wfd_device,
+#endif
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -4337,6 +4520,12 @@
 		false,
 		6300, 4500, 65350000, 4800,
 	},
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(ON, HSFS_OPEN, ACTIVE, RET_HIGH),
+		false,
+		7000, 3500, 66600000, 5150,
+	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
@@ -4494,7 +4683,12 @@
 		mxt_device_info,
 		ARRAY_SIZE(mxt_device_info),
 	},
-
+	{
+		I2C_LIQUID,
+		MSM_8960_GSBI10_QUP_I2C_BUS_ID,
+		msm_isa1200_board_info,
+		ARRAY_SIZE(msm_isa1200_board_info),
+	},
 };
 #endif /* CONFIG_I2C */
 
@@ -4550,8 +4744,6 @@
 	pm8921_platform_data.keypad_pdata = &keypad_data_sim;
 
 	msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
-	msm8960_device_gadget_peripheral.dev.parent = &msm8960_device_otg.dev;
-	msm_device_hsusb_host.dev.parent = &msm8960_device_otg.dev;
 	gpiomux_init();
 	msm8960_i2c_init();
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
@@ -4625,9 +4817,9 @@
 		pr_err("Failed to initialize XO votes\n");
 	platform_device_register(&msm8960_device_rpm_regulator);
 	msm_clock_init(&msm8960_clock_init_data);
+	if (machine_is_msm8960_liquid())
+		msm_otg_pdata.mhl_enable = true;
 	msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
-	msm8960_device_gadget_peripheral.dev.parent = &msm8960_device_otg.dev;
-	msm_device_hsusb_host.dev.parent = &msm8960_device_otg.dev;
 #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-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 455644f..090605f 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -19,21 +19,11 @@
 #include <linux/msm_ssbi.h>
 #include <linux/mfd/pmic8058.h>
 
-#include <linux/input/pmic8058-keypad.h>
-#include <linux/pmic8058-batt-alarm.h>
-#include <linux/pmic8058-pwrkey.h>
-#include <linux/rtc/rtc-pm8058.h>
-#include <linux/pmic8058-vibrator.h>
 #include <linux/leds.h>
 #include <linux/pmic8058-othc.h>
 #include <linux/mfd/pmic8901.h>
-#include <linux/regulator/pmic8058-regulator.h>
 #include <linux/regulator/pmic8901-regulator.h>
 #include <linux/bootmem.h>
-#include <linux/pwm.h>
-#include <linux/pmic8058-pwm.h>
-#include <linux/leds-pmic8058.h>
-#include <linux/pmic8058-xoadc.h>
 #include <linux/msm_adc.h>
 #include <linux/m_adcproc.h>
 #include <linux/mfd/marimba.h>
@@ -274,6 +264,21 @@
 	GPIO_EPM_EXPANDER_IO15,
 };
 
+struct pm8xxx_mpp_init_info {
+	unsigned			mpp;
+	struct pm8xxx_mpp_config_data	config;
+};
+
+#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+	.mpp	= PM8058_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.
@@ -747,12 +752,14 @@
 }
 
 #define PMIC_GPIO_HAP_ENABLE   18  /* PMIC GPIO Number 19 */
+#define PMIC_GPIO_HAP_LDO_ENABLE   5  /* PMIC GPIO Number 6 */
 static struct isa1200_platform_data isa1200_1_pdata = {
 	.name = "vibrator",
 	.power_on = isa1200_power,
 	.dev_setup = isa1200_dev_setup,
 	/*gpio to enable haptic*/
 	.hap_en_gpio = PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
+	.hap_len_gpio = PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_LDO_ENABLE),
 	.max_timeout = 15000,
 	.mode_ctrl = PWM_GEN_MODE,
 	.pwm_fd = {
@@ -991,6 +998,7 @@
 static struct regulator *ldo7_1p8;
 static struct regulator *vdd_cx;
 #define PMICID_INT		PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 36)
+#define PMIC_ID_GPIO		36
 notify_vbus_state notify_vbus_state_func_ptr;
 static int usb_phy_susp_dig_vol = 750000;
 static int pmic_id_notif_supported;
@@ -1029,10 +1037,42 @@
 	return IRQ_HANDLED;
 }
 
+static int msm_hsusb_phy_id_setup_init(int init)
+{
+	unsigned ret;
+
+	if (init) {
+		ret = pm8901_mpp_config_digital_out(1,
+			PM8901_MPP_DIG_LEVEL_L5, 1);
+		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);
+		if (ret < 0)
+			pr_err("%s:MPP2 un config failed\n", __func__);
+	}
+	return ret;
+}
+
 static int msm_hsusb_pmic_id_notif_init(void (*callback)(int online), int init)
 {
 	unsigned ret = -ENODEV;
 
+	struct pm_gpio pmic_id_cfg = {
+		.direction	= PM_GPIO_DIR_IN,
+		.pull		= PM_GPIO_PULL_UP_1P5,
+		.function	= PM_GPIO_FUNC_NORMAL,
+		.vin_sel	= 2,
+		.inv_int_pol	= 0,
+	};
+	struct pm_gpio pmic_id_uncfg = {
+		.direction	= PM_GPIO_DIR_IN,
+		.pull		= PM_GPIO_PULL_NO,
+		.function	= PM_GPIO_FUNC_NORMAL,
+		.vin_sel	= 2,
+		.inv_int_pol	= 0,
+	};
 	if (!callback)
 		return -EINVAL;
 
@@ -1056,37 +1096,36 @@
 
 	if (init) {
 		notify_vbus_state_func_ptr = callback;
-		ret = pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 1);
-		if (ret) {
-			pr_err("%s: MPP2 configuration failed\n", __func__);
-			return -ENODEV;
-		}
 		INIT_DELAYED_WORK(&pmic_id_det, pmic_id_detect);
+		ret = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(PMIC_ID_GPIO),
+							&pmic_id_cfg);
+		if (ret) {
+			pr_err("%s:return val of pm8xxx_gpio_config: %d\n",
+						__func__,  ret);
+			return ret;
+		}
 		ret = request_threaded_irq(PMICID_INT, NULL, pmic_id_on_irq,
 			(IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING),
 						"msm_otg_id", NULL);
 		if (ret) {
-			pm8901_mpp_config_digital_out(1,
-					PM8901_MPP_DIG_LEVEL_L5, 0);
 			pr_err("%s:pmic_usb_id interrupt registration failed",
 					__func__);
 			return ret;
 		}
-		/* Notify the initial Id status */
-		pmic_id_detect(&pmic_id_det.work);
 		msm_otg_pdata.pmic_id_irq = PMICID_INT;
 	} else {
+		usb_phy_susp_dig_vol = 750000;
 		free_irq(PMICID_INT, 0);
+		ret = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(PMIC_ID_GPIO),
+							&pmic_id_uncfg);
+		if (ret) {
+			pr_err("%s: return val of pm8xxx_gpio_config: %d\n",
+						__func__,  ret);
+			return ret;
+		}
 		msm_otg_pdata.pmic_id_irq = 0;
 		cancel_delayed_work_sync(&pmic_id_det);
 		notify_vbus_state_func_ptr = NULL;
-		ret = pm8901_mpp_config_digital_out(1,
-			PM8901_MPP_DIG_LEVEL_L5, 0);
-		if (ret) {
-			pr_err("%s:MPP2 configuration failed\n", __func__);
-			return -ENODEV;
-		}
 	}
 	return 0;
 }
@@ -1391,6 +1430,7 @@
 	.bam_disable		 = 1,
 #ifdef CONFIG_USB_EHCI_MSM_72K
 	.pmic_id_notif_init = msm_hsusb_pmic_id_notif_init,
+	.phy_id_setup_init = msm_hsusb_phy_id_setup_init,
 #endif
 #ifdef CONFIG_USB_EHCI_MSM_72K
 	.vbus_power = msm_hsusb_vbus_power,
@@ -4449,13 +4489,6 @@
 #endif
 
 #ifdef CONFIG_SENSORS_MSM_ADC
-static struct resource resources_adc[] = {
-	{
-		.start = PM8058_ADC_IRQ(PM8058_IRQ_BASE),
-		.end   = PM8058_ADC_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-};
 
 static struct adc_access_fn xoadc_fn = {
 	pm8058_xoadc_select_chan_and_start_conv,
@@ -4804,37 +4837,33 @@
 
 static void pmic8058_xoadc_mpp_config(void)
 {
-	int rc;
+	int rc, i;
+	struct pm8xxx_mpp_init_info xoadc_mpps[] = {
+		PM8XXX_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,
+							AOUT_CTRL_DISABLE),
+		PM8XXX_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,
+							AOUT_CTRL_DISABLE),
+		PM8XXX_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
+							AOUT_CTRL_DISABLE),
+	};
 
 	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__);
 
-	rc = pm8058_mpp_config_analog_input(XOADC_MPP_3,
-			PM_MPP_AIN_AMUX_CH5, PM_MPP_AOUT_CTL_DISABLE);
-	if (rc)
-		pr_err("%s: Config mpp3 on pmic 8058 failed\n", __func__);
-
-	rc = pm8058_mpp_config_analog_input(XOADC_MPP_5,
-			PM_MPP_AIN_AMUX_CH9, PM_MPP_AOUT_CTL_DISABLE);
-	if (rc)
-		pr_err("%s: Config mpp5 on pmic 8058 failed\n", __func__);
-
-	rc = pm8058_mpp_config_analog_input(XOADC_MPP_7,
-			PM_MPP_AIN_AMUX_CH6, PM_MPP_AOUT_CTL_DISABLE);
-	if (rc)
-		pr_err("%s: Config mpp7 on pmic 8058 failed\n", __func__);
-
-	rc = pm8058_mpp_config_analog_input(XOADC_MPP_8,
-			PM_MPP_AIN_AMUX_CH8, PM_MPP_AOUT_CTL_DISABLE);
-	if (rc)
-		pr_err("%s: Config mpp8 on pmic 8058 failed\n", __func__);
-
-	rc = pm8058_mpp_config_analog_input(XOADC_MPP_10,
-			PM_MPP_AIN_AMUX_CH7, PM_MPP_AOUT_CTL_DISABLE);
-	if (rc)
-		pr_err("%s: Config mpp10 on pmic 8058 failed\n", __func__);
+	for (i = 0; i < ARRAY_SIZE(xoadc_mpps); i++) {
+		rc = pm8xxx_mpp_config(xoadc_mpps[i].mpp,
+					&xoadc_mpps[i].config);
+		if (rc) {
+			pr_err("%s: Config MPP %d of PM8058 failed\n",
+					__func__, xoadc_mpps[i].mpp);
+		}
+	}
 }
 
 static struct regulator *vreg_ldo18_adc;
@@ -4899,7 +4928,7 @@
 	.conversiontime         = 54,
 };
 
-static struct xoadc_platform_data xoadc_pdata = {
+static struct xoadc_platform_data pm8058_xoadc_pdata = {
 	.xoadc_prop = &pm8058_xoadc_data,
 	.xoadc_mpp_config = pmic8058_xoadc_mpp_config,
 	.xoadc_vreg_set = pmic8058_xoadc_vreg_config,
@@ -5281,18 +5310,28 @@
 #define EXT_CHG_VALID_MPP 10
 #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_DIG_LEVEL_S3, DIN_TO_INT),
+	PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
+		PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM),
+};
+
 #ifdef CONFIG_ISL9519_CHARGER
 static int isl_detection_setup(void)
 {
-	int ret = 0;
+	int ret = 0, i;
 
-	ret = pm8058_mpp_config_digital_in(EXT_CHG_VALID_MPP,
-					   PM8058_MPP_DIG_LEVEL_S3,
-					   PM_MPP_DIN_TO_INT);
-	ret |=  pm8058_mpp_config_bi_dir(EXT_CHG_VALID_MPP_2,
-					   PM8058_MPP_DIG_LEVEL_S3,
-					   PM_MPP_BI_PULLUP_10KOHM
-					   );
+	for (i = 0; i < ARRAY_SIZE(isl_mpp); i++) {
+		ret = pm8xxx_mpp_config(isl_mpp[i].mpp,
+					&isl_mpp[i].config);
+		if (ret) {
+			pr_err("%s: Config MPP %d of PM8058 failed\n",
+						 __func__, isl_mpp[i].mpp);
+			return ret;
+		}
+	}
+
 	return ret;
 }
 
@@ -5309,7 +5348,7 @@
 static struct i2c_board_info isl_charger_i2c_info[] __initdata = {
 	{
 		I2C_BOARD_INFO("isl9519q", 0x9),
-		.irq = PM8058_CBLPWR_IRQ(PM8058_IRQ_BASE),
+		.irq = PM8058_IRQ_BASE + PM8058_CBLPWR_IRQ,
 		.platform_data = &isl_data,
 	},
 };
@@ -5318,14 +5357,18 @@
 #if defined(CONFIG_SMB137B_CHARGER) || defined(CONFIG_SMB137B_CHARGER_MODULE)
 static int smb137b_detection_setup(void)
 {
-	int ret = 0;
+	int ret = 0, i;
 
-	ret = pm8058_mpp_config_digital_in(EXT_CHG_VALID_MPP,
-					PM8058_MPP_DIG_LEVEL_S3,
-					PM_MPP_DIN_TO_INT);
-	ret |=  pm8058_mpp_config_bi_dir(EXT_CHG_VALID_MPP_2,
-					PM8058_MPP_DIG_LEVEL_S3,
-					PM_MPP_BI_PULLUP_10KOHM);
+	for (i = 0; i < ARRAY_SIZE(isl_mpp); i++) {
+		ret = pm8xxx_mpp_config(isl_mpp[i].mpp,
+					&isl_mpp[i].config);
+		if (ret) {
+			pr_err("%s: Config MPP %d of PM8058 failed\n",
+						 __func__, isl_mpp[i].mpp);
+			return ret;
+		}
+	}
+
 	return ret;
 }
 
@@ -5338,7 +5381,7 @@
 static struct i2c_board_info smb137b_charger_i2c_info[] __initdata = {
 	{
 		I2C_BOARD_INFO("smb137b", 0x08),
-		.irq = PM8058_CBLPWR_IRQ(PM8058_IRQ_BASE),
+		.irq = PM8058_IRQ_BASE + PM8058_CBLPWR_IRQ,
 		.platform_data = &smb137b_data,
 	},
 };
@@ -5346,6 +5389,7 @@
 
 #ifdef CONFIG_PMIC8058
 #define PMIC_GPIO_SDC3_DET 22
+#define PMIC_GPIO_TOUCH_DISC_INTR 5
 
 static int pm8058_gpios_init(void)
 {
@@ -5353,12 +5397,12 @@
 	int rc;
 	struct pm8058_gpio_cfg {
 		int                gpio;
-		struct pm8058_gpio cfg;
+		struct pm_gpio	   cfg;
 	};
 
 	struct pm8058_gpio_cfg gpio_cfgs[] = {
 		{ /* FFA ethernet */
-			6,
+			PM8058_GPIO_PM_TO_SYS(6),
 			{
 				.direction      = PM_GPIO_DIR_IN,
 				.pull           = PM_GPIO_PULL_DN,
@@ -5369,7 +5413,7 @@
 		},
 #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
 		{
-			PMIC_GPIO_SDC3_DET - 1,
+			PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC3_DET - 1),
 			{
 				.direction      = PM_GPIO_DIR_IN,
 				.pull           = PM_GPIO_PULL_UP_30,
@@ -5380,47 +5424,37 @@
 		},
 #endif
 		{ /* core&surf gpio expander */
-			UI_INT1_N,
+			PM8058_GPIO_PM_TO_SYS(UI_INT1_N),
 			{
 				.direction      = PM_GPIO_DIR_IN,
 				.pull           = PM_GPIO_PULL_NO,
-				.vin_sel        = PM_GPIO_VIN_S3,
+				.vin_sel        = PM8058_GPIO_VIN_S3,
 				.function       = PM_GPIO_FUNC_NORMAL,
 				.inv_int_pol    = 0,
 			},
 		},
 		{ /* docking gpio expander */
-			UI_INT2_N,
+			PM8058_GPIO_PM_TO_SYS(UI_INT2_N),
 			{
 				.direction      = PM_GPIO_DIR_IN,
 				.pull           = PM_GPIO_PULL_NO,
-				.vin_sel        = PM_GPIO_VIN_S3,
+				.vin_sel        = PM8058_GPIO_VIN_S3,
 				.function       = PM_GPIO_FUNC_NORMAL,
 				.inv_int_pol    = 0,
 			},
 		},
 		{ /* FHA/keypad gpio expanders */
-			UI_INT3_N,
+			PM8058_GPIO_PM_TO_SYS(UI_INT3_N),
 			{
 				.direction      = PM_GPIO_DIR_IN,
 				.pull           = PM_GPIO_PULL_NO,
-				.vin_sel        = PM_GPIO_VIN_S3,
+				.vin_sel        = PM8058_GPIO_VIN_S3,
 				.function       = PM_GPIO_FUNC_NORMAL,
 				.inv_int_pol    = 0,
 			},
 		},
-		{ /* TouchDisc Interrupt */
-			5,
-			{
-				.direction      = PM_GPIO_DIR_IN,
-				.pull           = PM_GPIO_PULL_UP_1P5,
-				.vin_sel        = 2,
-				.function       = PM_GPIO_FUNC_NORMAL,
-				.inv_int_pol    = 0,
-			}
-		},
 		{ /* Timpani Reset */
-			20,
+			PM8058_GPIO_PM_TO_SYS(20),
 			{
 				.direction	= PM_GPIO_DIR_OUT,
 				.output_value	= 1,
@@ -5433,10 +5467,10 @@
 			}
 		},
 		{ /* PMIC ID interrupt */
-			36,
+			PM8058_GPIO_PM_TO_SYS(36),
 			{
 				.direction	= PM_GPIO_DIR_IN,
-				.pull		= PM_GPIO_PULL_UP_1P5,
+				.pull		= PM_GPIO_PULL_NO,
 				.function	= PM_GPIO_FUNC_NORMAL,
 				.vin_sel	= 2,
 				.inv_int_pol	= 0,
@@ -5444,28 +5478,33 @@
 		},
 	};
 
+#if defined(CONFIG_TOUCHDISC_VTD518_SHINETSU) || \
+		defined(CONFIG_TOUCHDISC_VTD518_SHINETSU_MODULE)
+	struct pm_gpio touchdisc_intr_gpio_cfg = {
+		.direction      = PM_GPIO_DIR_IN,
+		.pull           = PM_GPIO_PULL_UP_1P5,
+		.vin_sel        = 2,
+		.function       = PM_GPIO_FUNC_NORMAL,
+	};
+#endif
+
 #if defined(CONFIG_HAPTIC_ISA1200) || \
-		defined(CONFIG_HAPTIC_ISA1200_MODULE)
-
-	struct pm8058_gpio_cfg en_hap_gpio_cfg = {
-			PMIC_GPIO_HAP_ENABLE,
-			{
-				.direction      = PM_GPIO_DIR_OUT,
-				.pull           = PM_GPIO_PULL_NO,
-				.out_strength   = PM_GPIO_STRENGTH_HIGH,
-				.function       = PM_GPIO_FUNC_NORMAL,
-				.inv_int_pol    = 0,
-				.vin_sel        = 2,
-				.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
-				.output_value   = 0,
-			}
-
+			defined(CONFIG_HAPTIC_ISA1200_MODULE)
+	struct pm_gpio en_hap_gpio_cfg = {
+		.direction      = PM_GPIO_DIR_OUT,
+		.pull           = PM_GPIO_PULL_NO,
+		.out_strength   = PM_GPIO_STRENGTH_HIGH,
+		.function       = PM_GPIO_FUNC_NORMAL,
+		.inv_int_pol    = 0,
+		.vin_sel        = 2,
+		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+		.output_value   = 0,
 	};
 #endif
 
 #if defined(CONFIG_PMIC8058_OTHC) || defined(CONFIG_PMIC8058_OTHC_MODULE)
 	struct pm8058_gpio_cfg line_in_gpio_cfg = {
-			18,
+			PM8058_GPIO_PM_TO_SYS(18),
 			{
 				.direction	= PM_GPIO_DIR_IN,
 				.pull           = PM_GPIO_PULL_UP_1P5,
@@ -5479,7 +5518,7 @@
 #if defined(CONFIG_QS_S5K4E1)
 		{
 			struct pm8058_gpio_cfg qs_hc37_cam_pd_gpio_cfg = {
-			26,
+			PM8058_GPIO_PM_TO_SYS(26),
 			{
 				.direction		= PM_GPIO_DIR_OUT,
 				.output_value	= 0,
@@ -5494,14 +5533,14 @@
 #endif
 #ifdef CONFIG_FB_MSM_LCDC_NT35582_WVGA
 	struct pm8058_gpio_cfg pmic_lcdc_nt35582_gpio_cfg = {
-		GPIO_NT35582_BL_EN_HW_PIN - 1,
+		PM8058_GPIO_PM_TO_SYS(GPIO_NT35582_BL_EN_HW_PIN - 1),
 		{
 			.direction		= PM_GPIO_DIR_OUT,
 			.output_buffer	= PM_GPIO_OUT_BUF_CMOS,
 			.output_value	= 1,
 			.pull			= PM_GPIO_PULL_UP_30,
 			/* 2.9V  PM_GPIO_VIN_L2, which gives 2.6V */
-			.vin_sel		= PM_GPIO_VIN_L5,
+			.vin_sel		= PM8058_GPIO_VIN_L5,
 			.out_strength	= PM_GPIO_STRENGTH_HIGH,
 			.function		= PM_GPIO_FUNC_NORMAL,
 			.inv_int_pol	= 0,
@@ -5511,12 +5550,34 @@
 #if defined(CONFIG_HAPTIC_ISA1200) || \
 			defined(CONFIG_HAPTIC_ISA1200_MODULE)
 	if (machine_is_msm8x60_fluid()) {
-		rc = pm8058_gpio_config(en_hap_gpio_cfg.gpio,
-				&en_hap_gpio_cfg.cfg);
+		rc = pm8xxx_gpio_config(
+			PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
+			&en_hap_gpio_cfg);
 		if (rc < 0) {
-			pr_err("%s pmic haptics gpio config failed\n",
+			pr_err("%s: pmic haptics gpio config failed\n",
 							__func__);
-			return rc;
+		}
+		rc = pm8xxx_gpio_config(
+			PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_LDO_ENABLE),
+			&en_hap_gpio_cfg);
+		if (rc < 0) {
+			pr_err("%s: pmic haptics ldo gpio config failed\n",
+							__func__);
+		}
+
+	}
+#endif
+
+#if defined(CONFIG_TOUCHDISC_VTD518_SHINETSU) || \
+		defined(CONFIG_TOUCHDISC_VTD518_SHINETSU_MODULE)
+	if (machine_is_msm8x60_ffa() || machine_is_msm8x60_surf() ||
+		machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
+		rc = pm8xxx_gpio_config(
+			PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_TOUCH_DISC_INTR),
+			&touchdisc_intr_gpio_cfg);
+		if (rc < 0) {
+			pr_err("%s: Touchdisc interrupt gpio config failed\n",
+							__func__);
 		}
 	}
 #endif
@@ -5526,7 +5587,7 @@
 	if (machine_is_msm8x60_ffa() || machine_is_msm8x60_surf() ||
 		machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() ||
 		machine_is_msm8x60_fusn_ffa()) {
-		rc = pm8058_gpio_config(line_in_gpio_cfg.gpio,
+		rc = pm8xxx_gpio_config(line_in_gpio_cfg.gpio,
 				&line_in_gpio_cfg.cfg);
 		if (rc < 0) {
 			pr_err("%s pmic line_in gpio config failed\n",
@@ -5538,7 +5599,7 @@
 
 #ifdef CONFIG_FB_MSM_LCDC_NT35582_WVGA
 	if (machine_is_msm8x60_dragon()) {
-		rc = pm8058_gpio_config(pmic_lcdc_nt35582_gpio_cfg.gpio,
+		rc = pm8xxx_gpio_config(pmic_lcdc_nt35582_gpio_cfg.gpio,
 				&pmic_lcdc_nt35582_gpio_cfg.cfg);
 		if (rc < 0) {
 			pr_err("%s pmic gpio config failed\n", __func__);
@@ -5550,7 +5611,7 @@
 #if defined(CONFIG_QS_S5K4E1)
 		/* qs_cam_hc37_cam_pd only for 8660 fluid qs camera*/
 		if (machine_is_msm8x60_fluid()) {
-			rc = pm8058_gpio_config(qs_hc37_cam_pd_gpio_cfg.gpio,
+			rc = pm8xxx_gpio_config(qs_hc37_cam_pd_gpio_cfg.gpio,
 					&qs_hc37_cam_pd_gpio_cfg.cfg);
 			if (rc < 0) {
 				pr_err("%s pmic qs_hc37_cam_pd gpio config failed\n",
@@ -5562,7 +5623,7 @@
 #endif
 
 	for (i = 0; i < ARRAY_SIZE(gpio_cfgs); ++i) {
-		rc = pm8058_gpio_config(gpio_cfgs[i].gpio,
+		rc = pm8xxx_gpio_config(gpio_cfgs[i].gpio,
 				&gpio_cfgs[i].cfg);
 		if (rc < 0) {
 			pr_err("%s pmic gpio config failed\n",
@@ -5630,32 +5691,19 @@
 	KEY(4, 3, KEY_KBDILLUMTOGGLE),
 };
 
-static struct resource resources_keypad[] = {
-	{
-		.start	= PM8058_KEYPAD_IRQ(PM8058_IRQ_BASE),
-		.end	= PM8058_KEYPAD_IRQ(PM8058_IRQ_BASE),
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.start	= PM8058_KEYSTUCK_IRQ(PM8058_IRQ_BASE),
-		.end	= PM8058_KEYSTUCK_IRQ(PM8058_IRQ_BASE),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
 static struct matrix_keymap_data ffa_keymap_data = {
 	.keymap_size	= ARRAY_SIZE(ffa_keymap),
 	.keymap		= ffa_keymap,
 };
 
-static struct pmic8058_keypad_data ffa_keypad_data = {
+static struct pm8xxx_keypad_platform_data ffa_keypad_data = {
 	.input_name		= "ffa-keypad",
 	.input_phys_device	= "ffa-keypad/input0",
 	.num_rows		= 6,
 	.num_cols		= 5,
-	.rows_gpio_start	= 8,
-	.cols_gpio_start	= 0,
-	.debounce_ms		= {8, 10},
+	.rows_gpio_start	= PM8058_GPIO_PM_TO_SYS(8),
+	.cols_gpio_start	= PM8058_GPIO_PM_TO_SYS(0),
+	.debounce_ms		= 15,
 	.scan_delay_ms		= 32,
 	.row_hold_ns            = 91500,
 	.wakeup			= 1,
@@ -5667,19 +5715,20 @@
 	.keymap = dragon_keymap,
 };
 
-static struct pmic8058_keypad_data dragon_keypad_data = {
+static struct pm8xxx_keypad_platform_data dragon_keypad_data = {
 	.input_name = "dragon-keypad",
 	.input_phys_device = "dragon-keypad/input0",
 	.num_rows = 6,
 	.num_cols = 5,
-	.rows_gpio_start = 8,
-	.cols_gpio_start = 0,
-	.debounce_ms = {8, 10},
+	.rows_gpio_start	= PM8058_GPIO_PM_TO_SYS(8),
+	.cols_gpio_start	= PM8058_GPIO_PM_TO_SYS(0),
+	.debounce_ms		= 15,
 	.scan_delay_ms = 32,
 	.row_hold_ns = 91500,
 	.wakeup = 1,
 	.keymap_data = &dragon_keymap_data,
 };
+
 static const unsigned int fluid_keymap[] = {
 	KEY(0, 0, KEY_FN_F1),	 /* LS - PUSH1 */
 	KEY(0, 1, KEY_UP),	 /* NAV - UP */
@@ -5711,50 +5760,37 @@
 	.keymap		= fluid_keymap,
 };
 
-static struct pmic8058_keypad_data fluid_keypad_data = {
+static struct pm8xxx_keypad_platform_data fluid_keypad_data = {
 	.input_name		= "fluid-keypad",
 	.input_phys_device	= "fluid-keypad/input0",
 	.num_rows		= 6,
 	.num_cols		= 5,
-	.rows_gpio_start	= 8,
-	.cols_gpio_start	= 0,
-	.debounce_ms		= {8, 10},
+	.rows_gpio_start	= PM8058_GPIO_PM_TO_SYS(8),
+	.cols_gpio_start	= PM8058_GPIO_PM_TO_SYS(0),
+	.debounce_ms		= 15,
 	.scan_delay_ms		= 32,
 	.row_hold_ns            = 91500,
 	.wakeup			= 1,
 	.keymap_data		= &fluid_keymap_data,
 };
 
-static struct resource resources_pwrkey[] = {
-	{
-		.start	= PM8058_PWRKEY_REL_IRQ(PM8058_IRQ_BASE),
-		.end	= PM8058_PWRKEY_REL_IRQ(PM8058_IRQ_BASE),
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.start	= PM8058_PWRKEY_PRESS_IRQ(PM8058_IRQ_BASE),
-		.end	= PM8058_PWRKEY_PRESS_IRQ(PM8058_IRQ_BASE),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct pmic8058_pwrkey_pdata pwrkey_pdata = {
-	.pull_up		= 1,
-	.kpd_trigger_delay_us   = 970,
-	.wakeup			= 1,
-	.pwrkey_time_ms		= 500,
-};
-
-static struct pmic8058_vibrator_pdata pmic_vib_pdata = {
+static struct pm8xxx_vibrator_platform_data pm8058_vib_pdata = {
 	.initial_vibrate_ms  = 500,
 	.level_mV = 3000,
 	.max_timeout_ms = 15000,
 };
 
-#if defined(CONFIG_PMIC8058_OTHC) || defined(CONFIG_PMIC8058_OTHC_MODULE)
-#define PM8058_OTHC_CNTR_BASE0	0xA0
-#define PM8058_OTHC_CNTR_BASE1	0x134
-#define PM8058_OTHC_CNTR_BASE2	0x137
+static struct pm8xxx_rtc_platform_data pm8058_rtc_pdata = {
+	.rtc_write_enable       = false,
+	.rtc_alarm_powerup	= false,
+};
+
+static struct pm8xxx_pwrkey_platform_data pm8058_pwrkey_pdata = {
+	.pull_up		= 1,
+	.kpd_trigger_delay_us   = 970,
+	.wakeup			= 1,
+};
+
 #define PM8058_LINE_IN_DET_GPIO	PM8058_GPIO_PM_TO_SYS(18)
 
 static struct othc_accessory_info othc_accessories[]  = {
@@ -5901,42 +5937,6 @@
 	.micbias_regulator = &othc_reg,
 };
 
-static struct resource resources_othc_0[] = {
-	{
-		.name = "othc_base",
-		.start = PM8058_OTHC_CNTR_BASE0,
-		.end   = PM8058_OTHC_CNTR_BASE0,
-		.flags = IORESOURCE_IO,
-	},
-};
-
-static struct resource resources_othc_1[] = {
-	{
-		.start = PM8058_SW_1_IRQ(PM8058_IRQ_BASE),
-		.end   = PM8058_SW_1_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.start = PM8058_IR_1_IRQ(PM8058_IRQ_BASE),
-		.end   = PM8058_IR_1_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "othc_base",
-		.start = PM8058_OTHC_CNTR_BASE1,
-		.end   = PM8058_OTHC_CNTR_BASE1,
-		.flags = IORESOURCE_IO,
-	},
-};
-
-static struct resource resources_othc_2[] = {
-	{
-		.name = "othc_base",
-		.start = PM8058_OTHC_CNTR_BASE2,
-		.end   = PM8058_OTHC_CNTR_BASE2,
-		.flags = IORESOURCE_IO,
-	},
-};
 
 static void __init msm8x60_init_pm8058_othc(void)
 {
@@ -5974,143 +5974,16 @@
 		}
 	}
 }
-#endif
 
-static struct resource resources_pm8058_charger[] = {
-	{	.name = "CHGVAL",
-		.start = PM8058_CHGVAL_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_CHGVAL_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{	.name = "CHGINVAL",
-		.start = PM8058_CHGINVAL_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_CHGINVAL_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "CHGILIM",
-		.start = PM8058_CHGILIM_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_CHGILIM_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VCP",
-		.start = PM8058_VCP_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_VCP_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-		{
-		.name = "ATC_DONE",
-		.start = PM8058_ATC_DONE_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_ATC_DONE_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "ATCFAIL",
-		.start = PM8058_ATCFAIL_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_ATCFAIL_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "AUTO_CHGDONE",
-		 .start = PM8058_AUTO_CHGDONE_IRQ(PM8058_IRQ_BASE),
-		 .end = PM8058_AUTO_CHGDONE_IRQ(PM8058_IRQ_BASE),
-		 .flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "AUTO_CHGFAIL",
-		.start = PM8058_AUTO_CHGFAIL_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_AUTO_CHGFAIL_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "CHGSTATE",
-		.start = PM8058_CHGSTATE_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_CHGSTATE_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "FASTCHG",
-		.start = PM8058_FASTCHG_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_FASTCHG_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "CHG_END",
-		 .start = PM8058_CHG_END_IRQ(PM8058_IRQ_BASE),
-		 .end = PM8058_CHG_END_IRQ(PM8058_IRQ_BASE),
-		 .flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "BATTTEMP",
-		.start = PM8058_BATTTEMP_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_BATTTEMP_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "CHGHOT",
-		.start = PM8058_CHGHOT_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_CHGHOT_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "CHGTLIMIT",
-		.start = PM8058_CHGTLIMIT_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_CHGTLIMIT_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "CHG_GONE",
-		 .start = PM8058_CHG_GONE_IRQ(PM8058_IRQ_BASE),
-		 .end = PM8058_CHG_GONE_IRQ(PM8058_IRQ_BASE),
-		 .flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VCPMAJOR",
-		 .start = PM8058_VCPMAJOR_IRQ(PM8058_IRQ_BASE),
-		 .end = PM8058_VCPMAJOR_IRQ(PM8058_IRQ_BASE),
-		 .flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VBATDET",
-		 .start = PM8058_VBATDET_IRQ(PM8058_IRQ_BASE),
-		 .end = PM8058_VBATDET_IRQ(PM8058_IRQ_BASE),
-		 .flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "BATFET",
-		 .start = PM8058_BATFET_IRQ(PM8058_IRQ_BASE),
-		 .end = PM8058_BATFET_IRQ(PM8058_IRQ_BASE),
-		 .flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "BATT_REPLACE",
-		.start = PM8058_BATT_REPLACE_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_BATT_REPLACE_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "BATTCONNECT",
-		.start = PM8058_BATTCONNECT_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_BATTCONNECT_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VBATDET_LOW",
-		.start = PM8058_VBATDET_LOW_IRQ(PM8058_IRQ_BASE),
-		.end = PM8058_VBATDET_LOW_IRQ(PM8058_IRQ_BASE),
-		.flags = IORESOURCE_IRQ,
-	},
-};
 
 static int pm8058_pwm_config(struct pwm_device *pwm, int ch, int on)
 {
-	struct pm8058_gpio pwm_gpio_config = {
+	struct pm_gpio pwm_gpio_config = {
 		.direction      = PM_GPIO_DIR_OUT,
 		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
 		.output_value   = 0,
 		.pull           = PM_GPIO_PULL_NO,
-		.vin_sel        = PM_GPIO_VIN_VPH,
+		.vin_sel        = PM8058_GPIO_VIN_VPH,
 		.out_strength   = PM_GPIO_STRENGTH_HIGH,
 		.function       = PM_GPIO_FUNC_2,
 	};
@@ -6125,9 +5998,10 @@
 	case 2:
 		if (on) {
 			id = 24 + ch;
-			rc = pm8058_gpio_config(id - 1, &pwm_gpio_config);
+			rc = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(id - 1),
+							&pwm_gpio_config);
 			if (rc)
-				pr_err("%s: pm8058_gpio_config(%d): rc=%d\n",
+				pr_err("%s: pm8xxx_gpio_config(%d): rc=%d\n",
 					__func__, id, rc);
 		}
 		break;
@@ -6168,34 +6042,6 @@
 
 #define PM8058_GPIO_INT           88
 
-static struct pm8058_gpio_platform_data pm8058_gpio_data = {
-	.gpio_base	= PM8058_GPIO_PM_TO_SYS(0),
-	.irq_base	= PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 0),
-	.init		= pm8058_gpios_init,
-};
-
-static struct pm8058_gpio_platform_data pm8058_mpp_data = {
-	.gpio_base	= PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS),
-	.irq_base	= PM8058_MPP_IRQ(PM8058_IRQ_BASE, 0),
-};
-
-static struct resource resources_rtc[] = {
-       {
-		.start  = PM8058_RTC_IRQ(PM8058_IRQ_BASE),
-		.end    = PM8058_RTC_IRQ(PM8058_IRQ_BASE),
-		.flags  = IORESOURCE_IRQ,
-       },
-       {
-		.start  = PM8058_RTC_ALARM_IRQ(PM8058_IRQ_BASE),
-		.end    = PM8058_RTC_ALARM_IRQ(PM8058_IRQ_BASE),
-		.flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct pm8058_rtc_platform_data pm8058_rtc_pdata = {
-	.rtc_alarm_powerup	= false,
-};
-
 static struct pmic8058_led pmic8058_flash_leds[] = {
 	[0] = {
 		.name		= "camera:flash0",
@@ -6273,156 +6119,48 @@
 	.leds	= pmic8058_fluid_flash_leds,
 };
 
-static struct resource resources_temp_alarm[] = {
-	{
-		.start  = PM8058_TEMP_ALARM_IRQ(PM8058_IRQ_BASE),
-		.end    = PM8058_TEMP_ALARM_IRQ(PM8058_IRQ_BASE),
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource resources_pm8058_misc[] = {
-	{
-		.start  = PM8058_OSCHALT_IRQ(PM8058_IRQ_BASE),
-		.end    = PM8058_OSCHALT_IRQ(PM8058_IRQ_BASE),
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource resources_pm8058_batt_alarm[] = {
-	{
-		.start  = PM8058_BATT_ALARM_IRQ(PM8058_IRQ_BASE),
-		.end    = PM8058_BATT_ALARM_IRQ(PM8058_IRQ_BASE),
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-#define PM8058_SUBDEV_KPD 0
-#define PM8058_SUBDEV_LED 1
-#define PM8058_SUBDEV_VIB 2
-
-static struct mfd_cell pm8058_subdevs[] = {
-	{
-		.name = "pm8058-keypad",
-		.id		= -1,
-		.num_resources	= ARRAY_SIZE(resources_keypad),
-		.resources	= resources_keypad,
-	},
-	{	.name = "pm8058-led",
-		.id		= -1,
-	},
-	{
-		.name = "pm8058-vib",
-		.id = -1,
-	},
-	{	.name = "pm8058-gpio",
-		.id		= -1,
-		.platform_data	= &pm8058_gpio_data,
-		.pdata_size = sizeof(pm8058_gpio_data),
-	},
-	{	.name = "pm8058-mpp",
-		.id		= -1,
-		.platform_data	= &pm8058_mpp_data,
-		.pdata_size = sizeof(pm8058_mpp_data),
-	},
-	{	.name = "pm8058-pwrkey",
-		.id	= -1,
-		.resources = resources_pwrkey,
-		.num_resources = ARRAY_SIZE(resources_pwrkey),
-		.platform_data = &pwrkey_pdata,
-		.pdata_size = sizeof(pwrkey_pdata),
-	},
-	{
-		.name = "pm8058-pwm",
-		.id = -1,
-		.platform_data = &pm8058_pwm_data,
-		.pdata_size = sizeof(pm8058_pwm_data),
-	},
-#ifdef CONFIG_SENSORS_MSM_ADC
-	{
-		.name = "pm8058-xoadc",
-		.id = -1,
-		.num_resources = ARRAY_SIZE(resources_adc),
-		.resources = resources_adc,
-		.platform_data = &xoadc_pdata,
-		.pdata_size = sizeof(xoadc_pdata),
-	},
-#endif
-#if defined(CONFIG_PMIC8058_OTHC) || defined(CONFIG_PMIC8058_OTHC_MODULE)
-	{
-		.name = "pm8058-othc",
-		.id = 0,
-		.platform_data = &othc_config_pdata_0,
-		.pdata_size = sizeof(othc_config_pdata_0),
-		.num_resources = ARRAY_SIZE(resources_othc_0),
-		.resources = resources_othc_0,
-	},
-	{
-		/* OTHC1 module has headset/switch dection */
-		.name = "pm8058-othc",
-		.id = 1,
-		.num_resources = ARRAY_SIZE(resources_othc_1),
-		.resources = resources_othc_1,
-		.platform_data = &othc_config_pdata_1,
-		.pdata_size = sizeof(othc_config_pdata_1),
-	},
-	{
-		.name = "pm8058-othc",
-		.id = 2,
-		.platform_data = &othc_config_pdata_2,
-		.pdata_size = sizeof(othc_config_pdata_2),
-		.num_resources = ARRAY_SIZE(resources_othc_2),
-		.resources = resources_othc_2,
-	},
-#endif
-	{
-		.name = "pm8058-rtc",
-		.id = -1,
-		.num_resources  = ARRAY_SIZE(resources_rtc),
-		.resources      = resources_rtc,
-		.platform_data = &pm8058_rtc_pdata,
-	},
-	{
-		.name = "pm8058-tm",
-		.id = -1,
-		.num_resources  = ARRAY_SIZE(resources_temp_alarm),
-		.resources      = resources_temp_alarm,
-	},
-	{	.name = "pm8058-upl",
-		.id		= -1,
-	},
-	{
-		.name = "pm8058-misc",
-		.id = -1,
-		.num_resources  = ARRAY_SIZE(resources_pm8058_misc),
-		.resources      = resources_pm8058_misc,
-	},
-	{	.name = "pm8058-batt-alarm",
-		.id		= -1,
-		.num_resources  = ARRAY_SIZE(resources_pm8058_batt_alarm),
-		.resources      = resources_pm8058_batt_alarm,
-	},
-};
-
 static struct pmic8058_charger_data pmic8058_charger_dragon = {
+		.charger_data_valid = true,
 		.max_source_current = 1800,
 		.charger_type = CHG_TYPE_AC,
 };
 
-static struct mfd_cell pm8058_charger_sub_dev = {
-		.name = "pm8058-charger",
-		.id = -1,
-		.num_resources = ARRAY_SIZE(resources_pm8058_charger),
-		.resources = resources_pm8058_charger,
+static struct pmic8058_charger_data pmic8058_charger_ffa_surf = {
+		.charger_data_valid = false,
+};
+
+static struct pm8xxx_misc_platform_data pm8058_misc_pdata = {
+	.priority		= 0,
+};
+
+static struct pm8xxx_irq_platform_data pm8058_irq_pdata = {
+	.irq_base		= PM8058_IRQ_BASE,
+	.devirq			= MSM_GPIO_TO_INT(PM8058_GPIO_INT),
+	.irq_trigger_flag	= IRQF_TRIGGER_LOW,
+};
+
+static struct pm8xxx_gpio_platform_data pm8058_gpio_pdata = {
+	.gpio_base	= PM8058_GPIO_PM_TO_SYS(0),
+};
+
+static struct pm8xxx_mpp_platform_data pm8058_mpp_pdata = {
+	.mpp_base	= PM8058_MPP_PM_TO_SYS(0),
 };
 
 static struct pm8058_platform_data pm8058_platform_data = {
-	.irq_base = PM8058_IRQ_BASE,
-	.irq = MSM_GPIO_TO_INT(PM8058_GPIO_INT),
-
-	.num_subdevs = ARRAY_SIZE(pm8058_subdevs),
-	.sub_devices = pm8058_subdevs,
-	.irq_trigger_flags = IRQF_TRIGGER_LOW,
+	.irq_pdata		= &pm8058_irq_pdata,
+	.gpio_pdata		= &pm8058_gpio_pdata,
+	.mpp_pdata		= &pm8058_mpp_pdata,
+	.rtc_pdata		= &pm8058_rtc_pdata,
+	.pwrkey_pdata		= &pm8058_pwrkey_pdata,
+	.othc0_pdata		= &othc_config_pdata_0,
+	.othc1_pdata		= &othc_config_pdata_1,
+	.othc2_pdata		= &othc_config_pdata_2,
+	.pwm_pdata		= &pm8058_pwm_data,
+	.misc_pdata		= &pm8058_misc_pdata,
+#ifdef CONFIG_SENSORS_MSM_ADC
+	.xoadc_pdata		= &pm8058_xoadc_pdata,
+#endif
 };
 
 #ifdef CONFIG_MSM_SSBI
@@ -7059,10 +6797,10 @@
 static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
 {
 	int rc = 0;
-	struct pm8058_gpio cfg = {
+	struct pm_gpio cfg = {
 				.direction      = PM_GPIO_DIR_IN,
 				.pull           = PM_GPIO_PULL_NO,
-				.vin_sel        = PM_GPIO_VIN_S3,
+				.vin_sel        = PM8058_GPIO_VIN_S3,
 				.function       = PM_GPIO_FUNC_NORMAL,
 				.inv_int_pol    = 0,
 				};
@@ -7110,9 +6848,9 @@
 	}
 
 	/*GPIO 18 on PMIC is FM_IRQ*/
-	rc = pm8058_gpio_config(FM_GPIO, &cfg);
+	rc = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(FM_GPIO), &cfg);
 	if (rc) {
-		printk(KERN_ERR "%s: return val of pm8058_gpio_config: %d\n",
+		printk(KERN_ERR "%s: return val of pm8xxx_gpio_config: %d\n",
 						__func__,  rc);
 		goto fm_fail_clock;
 	}
@@ -10177,7 +9915,7 @@
 {
 	uint32_t soc_platform_version;
 
-	pmic_reset_irq = PM8058_RESOUT_IRQ(PM8058_IRQ_BASE);
+	pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
 
 	/*
 	 * Initialize RPM first as other drivers and devices may need
@@ -10273,28 +10011,12 @@
 	msm8x60_init_pm8058_othc();
 #endif
 
-	if (machine_is_msm8x60_fluid()) {
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].
-			platform_data = &fluid_keypad_data;
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
-			= sizeof(fluid_keypad_data);
-	} else if (machine_is_msm8x60_dragon()) {
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].
-			platform_data = &dragon_keypad_data;
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
-			= sizeof(dragon_keypad_data);
-	} else {
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].
-			platform_data = &ffa_keypad_data;
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
-			= sizeof(ffa_keypad_data);
-
-	}
-
-	/* Disable END_CALL simulation function of powerkey on fluid */
-	if (machine_is_msm8x60_fluid()) {
-		pwrkey_pdata.pwrkey_time_ms = 0;
-	}
+	if (machine_is_msm8x60_fluid())
+		pm8058_platform_data.keypad_pdata = &fluid_keypad_data;
+	else if (machine_is_msm8x60_dragon())
+		pm8058_platform_data.keypad_pdata = &dragon_keypad_data;
+	else
+		pm8058_platform_data.keypad_pdata = &ffa_keypad_data;
 
 	/* Specify reset pin for OV9726 */
 	if (machine_is_msm8x60_dragon()) {
@@ -10302,6 +10024,31 @@
 		ov9726_sensor_8660_info.mount_angle = 270;
 	}
 
+#ifdef CONFIG_BATTERY_MSM8X60
+	if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() ||
+		machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() ||
+		machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_fluid())
+		platform_device_register(&msm_charger_device);
+#endif
+
+	if (machine_is_msm8x60_dragon())
+		pm8058_platform_data.charger_pdata = &pmic8058_charger_dragon;
+	if (!machine_is_msm8x60_fluid())
+		pm8058_platform_data.charger_pdata = &pmic8058_charger_ffa_surf;
+
+	/* configure pmic leds */
+	if (machine_is_msm8x60_fluid())
+		pm8058_platform_data.leds_pdata = &pm8058_fluid_flash_leds_data;
+	else if (machine_is_msm8x60_dragon())
+		pm8058_platform_data.leds_pdata = &pm8058_dragon_leds_data;
+	else
+		pm8058_platform_data.leds_pdata = &pm8058_flash_leds_data;
+
+	if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa() ||
+		machine_is_msm8x60_dragon()) {
+		pm8058_platform_data.vibrator_pdata = &pm8058_vib_pdata;
+	}
+
 	if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() ||
 	    machine_is_msm8x60_fluid() || machine_is_msm8x60_fusion() ||
 	    machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_dragon()) {
@@ -10349,25 +10096,10 @@
 		machine_is_msm8x60_dragon())
 		msm8x60_cfg_isp1763();
 #endif
-#ifdef CONFIG_BATTERY_MSM8X60
-	if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() ||
-		machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() ||
-		machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_fluid())
-		platform_device_register(&msm_charger_device);
-#endif
 
 	if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
 		platform_add_devices(charm_devices, ARRAY_SIZE(charm_devices));
 
-	if (machine_is_msm8x60_dragon()) {
-		pm8058_charger_sub_dev.platform_data
-			= &pmic8058_charger_dragon;
-		pm8058_charger_sub_dev.pdata_size
-			= sizeof(pmic8058_charger_dragon);
-	}
-	if (!machine_is_msm8x60_fluid())
-		pm8058_platform_data.charger_sub_device
-			= &pm8058_charger_sub_dev;
 
 #if defined(CONFIG_SPI_QUP) || defined(CONFIG_SPI_QUP_MODULE)
 	if (machine_is_msm8x60_fluid())
@@ -10424,6 +10156,8 @@
 				msm_pm_data);
 	BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
 
+	pm8058_gpios_init();
+
 #ifdef CONFIG_SENSORS_MSM_ADC
 	if (machine_is_msm8x60_fluid()) {
 		msm_adc_pdata.dev_names = msm_adc_fluid_device_names;
@@ -10445,32 +10179,6 @@
 		platform_device_register(&gpio_leds);
 #endif
 
-	/* configure pmic leds */
-	if (machine_is_msm8x60_fluid()) {
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].
-			platform_data = &pm8058_fluid_flash_leds_data;
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].pdata_size
-			= sizeof(pm8058_fluid_flash_leds_data);
-	} else if (machine_is_msm8x60_dragon()) {
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].
-			platform_data = &pm8058_dragon_leds_data;
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].pdata_size
-			= sizeof(pm8058_dragon_leds_data);
-	} else {
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].
-			platform_data = &pm8058_flash_leds_data;
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].pdata_size
-			= sizeof(pm8058_flash_leds_data);
-	}
-
-	if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa() ||
-		machine_is_msm8x60_dragon()) {
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_VIB].
-					platform_data = &pmic_vib_pdata;
-		pm8058_platform_data.sub_devices[PM8058_SUBDEV_VIB].
-					pdata_size = sizeof(pmic_vib_pdata);
-	}
-
 	msm8x60_multi_sdio_init();
 
 	if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index e46da5b..95b69e6 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -51,6 +51,7 @@
 #include "devices-msm7x2xa.h"
 #include "pm.h"
 #include "timer.h"
+#include "pm-boot.h"
 
 #define PMEM_KERNEL_EBI1_SIZE	0x3A000
 #define MSM_PMEM_AUDIO_SIZE	0x5B000
@@ -2382,6 +2383,14 @@
 		if (rc < 0)
 			return rc;
 
+		rc = gpio_tlmm_config(GPIO_CFG(GPIO_BACKLIGHT_EN, 0,
+			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_ENABLE);
+		if (rc < 0) {
+			pr_err("failed GPIO_BACKLIGHT_EN tlmm config\n");
+			return rc;
+		}
+
 		rc = gpio_direction_output(GPIO_BACKLIGHT_EN, 1);
 		if (rc < 0) {
 			pr_err("failed to enable backlight\n");
@@ -2523,6 +2532,9 @@
 #endif
 	msm_pm_set_platform_data(msm7627a_pm_data,
 				ARRAY_SIZE(msm7627a_pm_data));
+	BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_RESET_VECTOR,
+				ioremap(0, PAGE_SIZE)));
+
 	msm_fb_add_devices();
 
 #if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 5df1700..a478b6f 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2205,6 +2205,7 @@
 static struct clk_freq_tbl clk_tbl_spi[] = {
 	F_MND8(       0,  0,  0, gnd,  1,   0,     0),
 	F_MND8( 9963243, 19, 12, pll3, 4,   2,    37),
+	F_MND8(24576000, 19, 12, lpxo, 1,   0,     0),
 	F_MND8(26331429, 19, 12, pll3, 4,   1,     7),
 	F_END,
 };
@@ -2550,7 +2551,7 @@
 }
 
 /* Sample clock for 'tcxo4_ticks' reference clock ticks. */
-static u32 run_measurement(unsigned tcxo4_ticks)
+static unsigned long run_measurement(unsigned tcxo4_ticks)
 {
 	/* TCXO4_CNT_EN and RINGOSC_CNT_EN register values. */
 	u32 reg_val_enable = readl_relaxed(MISC_CLK_CTL_BASE_REG) | 0x3;
@@ -2573,7 +2574,7 @@
 
 /* Perform a hardware rate measurement for a given clock.
    FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
 {
 	unsigned long flags;
 	u32 regval, prph_web_reg_old;
@@ -2626,7 +2627,7 @@
 	return -EINVAL;
 }
 
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
 {
 	return 0;
 }
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 37dabc8..393528b 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -57,6 +57,8 @@
 #define CLK_HALT_SFPB_MISC_STATE_REG		REG(0x2FD8)
 #define CLK_HALT_AFAB_SFAB_STATEB_REG		REG(0x2FC4)
 #define CLK_TEST_REG				REG(0x2FA0)
+#define GPn_MD_REG(n)				REG(0x2D00+(0x20*(n)))
+#define GPn_NS_REG(n)				REG(0x2D24+(0x20*(n)))
 #define GSBIn_HCLK_CTL_REG(n)			REG(0x29C0+(0x20*((n)-1)))
 #define GSBIn_QUP_APPS_MD_REG(n)		REG(0x29C8+(0x20*((n)-1)))
 #define GSBIn_QUP_APPS_NS_REG(n)		REG(0x29CC+(0x20*((n)-1)))
@@ -319,7 +321,7 @@
 
 /* MUX source input identifiers. */
 #define pxo_to_bb_mux		0
-#define cxo_to_bb_mux		pxo_to_bb_mux
+#define cxo_to_bb_mux		5
 #define pll0_to_bb_mux		2
 #define pll8_to_bb_mux		3
 #define pll6_to_bb_mux		4
@@ -1222,6 +1224,55 @@
 /*
  * Peripheral Clocks
  */
+#define CLK_GP(i, n, h_r, h_b) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = GPn_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.halt_reg = h_r, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = GPn_NS_REG(n), \
+		.md_reg = GPn_MD_REG(n), \
+		.root_en_mask = BIT(11), \
+		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_gp, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_8960, \
+			VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000), \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+#define F_GP(f, s, d, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(16, m, 0, n), \
+		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_gp[] = {
+	F_GP(        0, gnd,  1, 0, 0),
+	F_GP(  9600000, cxo,  2, 0, 0),
+	F_GP( 13500000, pxo,  2, 0, 0),
+	F_GP( 19200000, cxo,  1, 0, 0),
+	F_GP( 27000000, pxo,  1, 0, 0),
+	F_GP( 64000000, pll8, 2, 1, 3),
+	F_GP( 76800000, pll8, 1, 1, 5),
+	F_GP( 96000000, pll8, 4, 0, 0),
+	F_GP(128000000, pll8, 3, 0, 0),
+	F_GP(192000000, pll8, 2, 0, 0),
+	F_GP(384000000, pll8, 1, 0, 0),
+	F_END
+};
+
+static CLK_GP(gp0, 0, CLK_HALT_SFPB_MISC_STATE_REG, 7);
+static CLK_GP(gp1, 1, CLK_HALT_SFPB_MISC_STATE_REG, 6);
+static CLK_GP(gp2, 2, CLK_HALT_SFPB_MISC_STATE_REG, 5);
+
 #define CLK_GSBI_UART(i, n, h_r, h_b) \
 	struct rcg_clk i##_clk = { \
 		.b = { \
@@ -2934,7 +2985,7 @@
 
 struct pix_rdi_clk {
 	bool enabled;
-	unsigned cur_rate;
+	unsigned long cur_rate;
 
 	void __iomem *const s_reg;
 	u32 s_mask;
@@ -2951,7 +3002,7 @@
 	return container_of(clk, struct pix_rdi_clk, c);
 }
 
-static int pix_rdi_clk_set_rate(struct clk *c, unsigned rate)
+static int pix_rdi_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	int ret, i;
 	u32 reg;
@@ -3011,7 +3062,7 @@
 	return 0;
 }
 
-static unsigned pix_rdi_clk_get_rate(struct clk *c)
+static unsigned long pix_rdi_clk_get_rate(struct clk *c)
 {
 	return to_pix_rdi_clk(c)->cur_rate;
 }
@@ -3982,7 +4033,7 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-static unsigned hdmi_pll_clk_get_rate(struct clk *clk)
+static unsigned long hdmi_pll_clk_get_rate(struct clk *clk)
 {
 	return hdmi_pll_get_rate();
 }
@@ -4638,6 +4689,8 @@
 
 static DEFINE_CLK_VOTER(dfab_dsps_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_usb_hs_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_usb_hs3_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_usb_hs4_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sdc1_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sdc2_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sdc3_clk, &dfab_clk.c);
@@ -4679,6 +4732,9 @@
 	{ TEST_PER_LS(0x19), &sdc4_clk.c },
 	{ TEST_PER_LS(0x1A), &sdc5_p_clk.c },
 	{ TEST_PER_LS(0x1B), &sdc5_clk.c },
+	{ TEST_PER_LS(0x1F), &gp0_clk.c },
+	{ TEST_PER_LS(0x20), &gp1_clk.c },
+	{ TEST_PER_LS(0x21), &gp2_clk.c },
 	{ TEST_PER_LS(0x25), &dfab_clk.c },
 	{ TEST_PER_LS(0x25), &dfab_a_clk.c },
 	{ TEST_PER_LS(0x26), &pmem_clk.c },
@@ -4970,7 +5026,7 @@
 
 /* Perform a hardware rate measurement for a given clock.
    FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *c)
+static unsigned long measure_clk_get_rate(struct clk *c)
 {
 	unsigned long flags;
 	u32 pdm_reg_backup, ringosc_reg_backup;
@@ -5023,7 +5079,7 @@
 	return -EINVAL;
 }
 
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
 {
 	return 0;
 }
@@ -5044,7 +5100,7 @@
 	.multiplier = 1,
 };
 
-static struct clk_lookup msm_clocks_8064[] __initdata = {
+static struct clk_lookup msm_clocks_8064[] = {
 	CLK_LOOKUP("cxo",		cxo_clk.c,		NULL),
 	CLK_LOOKUP("pll2",		pll2_clk.c,		NULL),
 	CLK_LOOKUP("pll8",		pll8_clk.c,		NULL),
@@ -5068,6 +5124,9 @@
 	CLK_DUMMY("sfpb_clk",		SFPB_CLK,	NULL, 0),
 	CLK_DUMMY("sfpb_a_clk",		SFPB_A_CLK,	NULL, 0),
 
+	CLK_LOOKUP("core_clk",		gp0_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp1_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp2_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c,	NULL),
@@ -5092,8 +5151,8 @@
 	CLK_LOOKUP("ref_clk",		tsif_ref_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		tssc_clk.c,		NULL),
 	CLK_LOOKUP("usb_hs_clk",	usb_hs1_xcvr_clk.c,	NULL),
-	CLK_LOOKUP("core_clk",          usb_hs3_xcvr_clk.c,     NULL),
-	CLK_LOOKUP("core_clk",          usb_hs4_xcvr_clk.c,     NULL),
+	CLK_LOOKUP("core_clk",          usb_hs3_xcvr_clk.c,  "msm_ehci_host.0"),
+	CLK_LOOKUP("core_clk",          usb_hs4_xcvr_clk.c,  "msm_ehci_host.1"),
 	CLK_LOOKUP("usb_fs_src_clk",	usb_fs1_src_clk.c,	NULL),
 	CLK_LOOKUP("usb_fs_clk",	usb_fs1_xcvr_clk.c,	NULL),
 	CLK_LOOKUP("usb_fs_sys_clk",	usb_fs1_sys_clk.c,	NULL),
@@ -5112,8 +5171,8 @@
 	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		NULL),
 	CLK_LOOKUP("usb_fs_pclk",	usb_fs1_p_clk.c,	NULL),
 	CLK_LOOKUP("usb_hs_pclk",	usb_hs1_p_clk.c,	NULL),
-	CLK_LOOKUP("iface_clk",         usb_hs3_p_clk.c,        NULL),
-	CLK_LOOKUP("iface_clk",         usb_hs4_p_clk.c,        NULL),
+	CLK_LOOKUP("iface_clk",         usb_hs3_p_clk.c,     "msm_ehci_host.0"),
+	CLK_LOOKUP("iface_clk",         usb_hs4_p_clk.c,     "msm_ehci_host.1"),
 	CLK_LOOKUP("iface_clk",		sdc1_p_clk.c,		"msm_sdcc.1"),
 	CLK_LOOKUP("iface_clk",		sdc2_p_clk.c,		"msm_sdcc.2"),
 	CLK_LOOKUP("iface_clk",		sdc3_p_clk.c,		"msm_sdcc.3"),
@@ -5249,6 +5308,8 @@
 	CLK_LOOKUP("core_clk",		gfx3d_axi_clk.c,	NULL),
 	CLK_DUMMY("dfab_dsps_clk",	DFAB_DSPS_CLK,		NULL, 0),
 	CLK_DUMMY("dfab_usb_hs_clk",	DFAB_USB_HS_CLK,	NULL, 0),
+	CLK_DUMMY("bus_clk",		DFAB_USB_HS3_CLK, "msm_ehci_host.0", 0),
+	CLK_DUMMY("bus_clk",		DFAB_USB_HS4_CLK, "msm_ehci_host.1", 0),
 	CLK_DUMMY("bus_clk",		DFAB_SDC1_CLK,		NULL, 0),
 	CLK_DUMMY("bus_clk",		DFAB_SDC2_CLK,		NULL, 0),
 	CLK_DUMMY("bus_clk",		DFAB_SDC3_CLK,		NULL, 0),
@@ -5294,6 +5355,9 @@
 	CLK_LOOKUP("sfpb_clk",		sfpb_clk.c,	NULL),
 	CLK_LOOKUP("sfpb_a_clk",	sfpb_a_clk.c,	NULL),
 
+	CLK_LOOKUP("core_clk",		gp0_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp1_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp2_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c,	NULL),
@@ -5375,26 +5439,20 @@
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"msm_camera_imx074.0"),
 	CLK_LOOKUP("cam_clk",		cam0_clk.c,	"msm_camera_ov2720.0"),
 	CLK_LOOKUP("cam_clk",	cam0_clk.c,	"msm_camera_qs_mt9p017.0"),
-	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		NULL),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		NULL),
-	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,	"msm_camera_imx074.0"),
-	CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_camera_qs_mt9p017.0"),
-	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,	"msm_camera_ov2720.0"),
-	CLK_LOOKUP("csi_clk",		csi0_clk.c,		NULL),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,		NULL),
-	CLK_LOOKUP("csi_clk",		csi0_clk.c,	"msm_camera_imx074.0"),
-	CLK_LOOKUP("csi_clk",	csi0_clk.c,	"msm_camera_qs_mt9p017.0"),
-	CLK_LOOKUP("csi_clk",		csi1_clk.c,	"msm_camera_ov2720.0"),
-	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		NULL),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		NULL),
-	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,	"msm_camera_imx074.0"),
-	CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_camera_qs_mt9p017.0"),
-	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,	"msm_camera_ov2720.0"),
-	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		NULL),
-	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		NULL),
-	CLK_LOOKUP("csiphy_timer_src_clk", csiphy_timer_src_clk.c, NULL),
-	CLK_LOOKUP("csi0phy_timer_clk",	csi0phy_timer_clk.c,	NULL),
-	CLK_LOOKUP("csi1phy_timer_clk",	csi1phy_timer_clk.c,	NULL),
+	CLK_LOOKUP("csi_src_clk",	csi0_src_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_src_clk",	csi1_src_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_clk",		csi0_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_clk",		csi1_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_phy_clk",	csi0_phy_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_phy_clk",	csi1_phy_clk.c,		"msm_csid.1"),
+	CLK_LOOKUP("csi_pix_clk",	csi_pix_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi_clk",	csi_rdi_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.0"),
+	CLK_LOOKUP("csiphy_timer_src_clk",
+			   csiphy_timer_src_clk.c, "msm_csiphy.1"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi0phy_timer_clk.c,	"msm_csiphy.0"),
+	CLK_LOOKUP("csiphy_timer_clk",	csi1phy_timer_clk.c,	"msm_csiphy.1"),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi1_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_byte_div_clk",	dsi2_byte_clk.c,	NULL),
 	CLK_LOOKUP("dsi_esc_clk",	dsi1_esc_clk.c,		NULL),
@@ -5430,11 +5488,11 @@
 	CLK_LOOKUP("mdp_tv_clk",	mdp_tv_clk.c,		NULL),
 	CLK_LOOKUP("hdmi_clk",		hdmi_tv_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		hdmi_app_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		NULL),
+	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("core_clk",		vpe_clk.c,	"footswitch-8x60.9"),
-	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		NULL),
+	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("core_clk",		vfe_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		NULL),
+	CLK_LOOKUP("csi_vfe_clk",	csi_vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("bus_clk",		vfe_axi_clk.c,	"footswitch-8x60.8"),
 	CLK_LOOKUP("bus_clk",		mdp_axi_clk.c,	"footswitch-8x60.4"),
 	CLK_LOOKUP("bus_clk",		rot_axi_clk.c,	"footswitch-8x60.6"),
@@ -5443,7 +5501,8 @@
 	CLK_LOOKUP("bus_b_clk",        vcodec_axi_b_clk.c, "footswitch-8x60.7"),
 	CLK_LOOKUP("bus_clk",		vpe_axi_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("amp_pclk",		amp_p_clk.c,		NULL),
-	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		NULL),
+	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.0"),
+	CLK_LOOKUP("csi_pclk",		csi_p_clk.c,		"msm_csid.1"),
 	CLK_LOOKUP("dsi_m_pclk",	dsi1_m_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_s_pclk",	dsi1_s_p_clk.c,		NULL),
 	CLK_LOOKUP("dsi_m_pclk",	dsi2_m_p_clk.c,		NULL),
@@ -5468,9 +5527,9 @@
 	CLK_LOOKUP("tv_enc_pclk",	tv_enc_p_clk.c,		NULL),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"msm_vidc.0"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"footswitch-8x60.7"),
-	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		NULL),
+	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		NULL),
+	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
 	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
@@ -5522,9 +5581,9 @@
 	CLK_LOOKUP("cam_clk",		cam2_clk.c,		NULL),
 	CLK_LOOKUP("csi_src_clk",	csi2_src_clk.c,		NULL),
 	CLK_LOOKUP("csi_clk",		csi2_clk.c,		NULL),
-	CLK_LOOKUP("csi_pix1_clk",	csi_pix1_clk.c,		NULL),
-	CLK_LOOKUP("csi_rdi1_clk",	csi_rdi1_clk.c,		NULL),
-	CLK_LOOKUP("csi_rdi2_clk",	csi_rdi2_clk.c,		NULL),
+	CLK_LOOKUP("csi_pix1_clk",	csi_pix1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi1_clk",	csi_rdi1_clk.c,		"msm_ispif.0"),
+	CLK_LOOKUP("csi_rdi2_clk",	csi_rdi2_clk.c,		"msm_ispif.0"),
 	CLK_LOOKUP("csi_phy_clk",	csi2_phy_clk.c,		NULL),
 	CLK_LOOKUP("csi2phy_timer_clk",	csi2phy_timer_clk.c,	NULL),
 	CLK_LOOKUP("usb_hsic_xcvr_fs_clk", usb_hsic_xcvr_fs_clk.c,	NULL),
@@ -5966,7 +6025,7 @@
 	if (WARN(IS_ERR(mmfpb_a_clk), "mmfpb_a_clk not found (%ld)\n",
 			PTR_ERR(mmfpb_a_clk)))
 		return PTR_ERR(mmfpb_a_clk);
-	rc = clk_set_min_rate(mmfpb_a_clk, 76800000);
+	rc = clk_set_rate(mmfpb_a_clk, 76800000);
 	if (WARN(rc, "mmfpb_a_clk rate was not set (%d)\n", rc))
 		return rc;
 	rc = clk_enable(mmfpb_a_clk);
@@ -5977,7 +6036,7 @@
 	if (WARN(IS_ERR(cfpb_a_clk), "cfpb_a_clk not found (%ld)\n",
 			PTR_ERR(cfpb_a_clk)))
 		return PTR_ERR(cfpb_a_clk);
-	rc = clk_set_min_rate(cfpb_a_clk, 64000000);
+	rc = clk_set_rate(cfpb_a_clk, 64000000);
 	if (WARN(rc, "cfpb_a_clk rate was not set (%d)\n", rc))
 		return rc;
 	rc = clk_enable(cfpb_a_clk);
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index c5d3d1d..17052ae 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -55,6 +55,8 @@
 #define CLK_TEST_REG				REG(0x2FA0)
 #define EBI2_2X_CLK_CTL_REG			REG(0x2660)
 #define EBI2_CLK_CTL_REG			REG(0x2664)
+#define GPn_MD_REG(n)				REG(0x2D00+(0x20*(n)))
+#define GPn_NS_REG(n)				REG(0x2D24+(0x20*(n)))
 #define GSBIn_HCLK_CTL_REG(n)			REG(0x29C0+(0x20*((n)-1)))
 #define GSBIn_QUP_APPS_MD_REG(n)		REG(0x29C8+(0x20*((n)-1)))
 #define GSBIn_QUP_APPS_NS_REG(n)		REG(0x29CC+(0x20*((n)-1)))
@@ -207,7 +209,7 @@
 /* MUX source input identifiers. */
 #define pxo_to_bb_mux		0
 #define mxo_to_bb_mux		1
-#define cxo_to_bb_mux		pxo_to_bb_mux
+#define cxo_to_bb_mux		5
 #define pll0_to_bb_mux		2
 #define pll8_to_bb_mux		3
 #define pll6_to_bb_mux		4
@@ -1050,6 +1052,49 @@
 /*
  * Peripheral Clocks
  */
+#define CLK_GP(i, n, h_r, h_b) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = GPn_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.halt_reg = h_r, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = GPn_NS_REG(n), \
+		.md_reg = GPn_MD_REG(n), \
+		.root_en_mask = BIT(11), \
+		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_gp, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_8x60, \
+			VDD_DIG_FMAX_MAP1(LOW, 27000000), \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+#define F_GP(f, s, d, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(16, m, 0, n), \
+		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_gp[] = {
+	F_GP(        0, gnd,  1, 0, 0),
+	F_GP(  9600000, cxo,  2, 0, 0),
+	F_GP( 13500000, pxo,  2, 0, 0),
+	F_GP( 19200000, cxo,  1, 0, 0),
+	F_GP( 27000000, pxo,  1, 0, 0),
+	F_END
+};
+
+static CLK_GP(gp0, 0, CLK_HALT_SFPB_MISC_STATE_REG, 7);
+static CLK_GP(gp1, 1, CLK_HALT_SFPB_MISC_STATE_REG, 6);
+static CLK_GP(gp2, 2, CLK_HALT_SFPB_MISC_STATE_REG, 5);
+
 #define CLK_GSBI_UART(i, n, h_r, h_b) \
 	struct rcg_clk i##_clk = { \
 		.b = { \
@@ -3215,6 +3260,9 @@
 	{ TEST_PER_LS(0x1B), &sdc5_clk.c },
 	{ TEST_PER_LS(0x1D), &ebi2_2x_clk.c },
 	{ TEST_PER_LS(0x1E), &ebi2_clk.c },
+	{ TEST_PER_LS(0x1F), &gp0_clk.c },
+	{ TEST_PER_LS(0x20), &gp1_clk.c },
+	{ TEST_PER_LS(0x21), &gp2_clk.c },
 	{ TEST_PER_LS(0x25), &dfab_clk.c },
 	{ TEST_PER_LS(0x25), &dfab_a_clk.c },
 	{ TEST_PER_LS(0x26), &pmem_clk.c },
@@ -3466,7 +3514,7 @@
 
 /* Perform a hardware rate measurement for a given clock.
    FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *c)
+static unsigned long measure_clk_get_rate(struct clk *c)
 {
 	unsigned long flags;
 	u32 pdm_reg_backup, ringosc_reg_backup;
@@ -3520,7 +3568,7 @@
 	return -EINVAL;
 }
 
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
 {
 	return 0;
 }
@@ -3567,6 +3615,9 @@
 	CLK_LOOKUP("smi_clk",		smi_clk.c,	NULL),
 	CLK_LOOKUP("smi_a_clk",		smi_a_clk.c,	NULL),
 
+	CLK_LOOKUP("core_clk",		gp0_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp1_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		gp2_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		gsbi1_uart_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		gsbi2_uart_clk.c,	NULL),
 	CLK_LOOKUP("core_clk",		gsbi3_uart_clk.c, "msm_serial_hsl.2"),
@@ -3910,7 +3961,7 @@
 	if (WARN(IS_ERR(mmfpb_a_clk), "mmfpb_a_clk not found (%ld)\n",
 			PTR_ERR(mmfpb_a_clk)))
 		return PTR_ERR(mmfpb_a_clk);
-	rc = clk_set_min_rate(mmfpb_a_clk, 64000000);
+	rc = clk_set_rate(mmfpb_a_clk, 64000000);
 	if (WARN(rc, "mmfpb_a_clk rate was not set (%d)\n", rc))
 		return rc;
 	rc = clk_enable(mmfpb_a_clk);
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index d2a1df1..7e163df 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -50,6 +50,8 @@
 #define CLK_HALT_MSS_KPSS_MISC_STATE_REG	REG(0x2FDC)
 #define CLK_HALT_SFPB_MISC_STATE_REG		REG(0x2FD8)
 #define CLK_TEST_REG				REG(0x2FA0)
+#define GPn_MD_REG(n)				REG(0x2D00+(0x20*(n)))
+#define GPn_NS_REG(n)				REG(0x2D24+(0x20*(n)))
 #define GSBIn_HCLK_CTL_REG(n)			REG(0x29C0+(0x20*((n)-1)))
 #define GSBIn_QUP_APPS_MD_REG(n)		REG(0x29C8+(0x20*((n)-1)))
 #define GSBIn_QUP_APPS_NS_REG(n)		REG(0x29CC+(0x20*((n)-1)))
@@ -346,6 +348,47 @@
 /*
  * Peripheral Clocks
  */
+#define CLK_GP(i, n, h_r, h_b) \
+	struct rcg_clk i##_clk = { \
+		.b = { \
+			.ctl_reg = GPn_NS_REG(n), \
+			.en_mask = BIT(9), \
+			.halt_reg = h_r, \
+			.halt_bit = h_b, \
+		}, \
+		.ns_reg = GPn_NS_REG(n), \
+		.md_reg = GPn_MD_REG(n), \
+		.root_en_mask = BIT(11), \
+		.ns_mask = (BM(23, 16) | BM(6, 0)), \
+		.set_rate = set_rate_mnd, \
+		.freq_tbl = clk_tbl_gp, \
+		.current_freq = &rcg_dummy_freq, \
+		.c = { \
+			.dbg_name = #i "_clk", \
+			.ops = &clk_ops_rcg_9615, \
+			VDD_DIG_FMAX_MAP1(LOW, 27000000), \
+			CLK_INIT(i##_clk.c), \
+		}, \
+	}
+#define F_GP(f, s, d, m, n) \
+	{ \
+		.freq_hz = f, \
+		.src_clk = &s##_clk.c, \
+		.md_val = MD8(16, m, 0, n), \
+		.ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+		.mnd_en_mask = BIT(8) * !!(n), \
+	}
+static struct clk_freq_tbl clk_tbl_gp[] = {
+	F_GP(        0, gnd,  1, 0, 0),
+	F_GP(  9600000, cxo,  2, 0, 0),
+	F_GP( 19200000, cxo,  1, 0, 0),
+	F_END
+};
+
+static CLK_GP(gp0, 0, CLK_HALT_SFPB_MISC_STATE_REG, 7);
+static CLK_GP(gp1, 1, CLK_HALT_SFPB_MISC_STATE_REG, 6);
+static CLK_GP(gp2, 2, CLK_HALT_SFPB_MISC_STATE_REG, 5);
+
 #define CLK_GSBI_UART(i, n, h_r, h_b) \
 	struct rcg_clk i##_clk = { \
 		.b = { \
@@ -1277,6 +1320,7 @@
 static DEFINE_CLK_VOTER(dfab_sdc1_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sdc2_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
 
 /*
@@ -1297,6 +1341,9 @@
 	{ TEST_PER_LS(0x13), &sdc1_clk.c },
 	{ TEST_PER_LS(0x14), &sdc2_p_clk.c },
 	{ TEST_PER_LS(0x15), &sdc2_clk.c },
+	{ TEST_PER_LS(0x1F), &gp0_clk.c },
+	{ TEST_PER_LS(0x20), &gp1_clk.c },
+	{ TEST_PER_LS(0x21), &gp2_clk.c },
 	{ TEST_PER_LS(0x26), &pmem_clk.c },
 	{ TEST_PER_LS(0x25), &dfab_clk.c },
 	{ TEST_PER_LS(0x25), &dfab_a_clk.c },
@@ -1406,7 +1453,7 @@
 }
 
 /* Sample clock for 'ticks' reference clock ticks. */
-static u32 run_measurement(unsigned ticks)
+static unsigned long run_measurement(unsigned ticks)
 {
 	/* Stop counters and set the XO4 counter start value. */
 	writel_relaxed(ticks, RINGOSC_TCXO_CTL_REG);
@@ -1430,7 +1477,7 @@
 
 /* Perform a hardware rate measurement for a given clock.
    FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *c)
+static unsigned long measure_clk_get_rate(struct clk *c)
 {
 	unsigned long flags;
 	u32 pdm_reg_backup, ringosc_reg_backup;
@@ -1483,7 +1530,7 @@
 	return -EINVAL;
 }
 
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
 {
 	return 0;
 }
@@ -1523,6 +1570,10 @@
 	CLK_LOOKUP("sfpb_clk",		sfpb_clk.c,	NULL),
 	CLK_LOOKUP("sfpb_a_clk",	sfpb_a_clk.c,	NULL),
 
+	CLK_LOOKUP("core_clk",		gp0_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gp1_clk.c,	NULL),
+	CLK_LOOKUP("core_clk",		gp2_clk.c,	NULL),
+
 	CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, NULL),
 	CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, NULL),
 	CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, NULL),
@@ -1585,7 +1636,7 @@
 	CLK_LOOKUP("bus_clk",		dfab_sdc1_clk.c,	"msm_sdcc.1"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc2_clk.c,	"msm_sdcc.2"),
 	CLK_LOOKUP("dfab_clk",		dfab_sps_clk.c,		"msm_sps"),
-
+	CLK_LOOKUP("bus_clk",		dfab_bam_dmux_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("ebi1_msmbus_clk",	ebi1_msmbus_clk.c, NULL),
 	CLK_LOOKUP("mem_clk",		ebi1_adm_clk.c, "msm_dmov"),
 
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 78586a8..4990c81 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -33,13 +33,10 @@
 	 * for debugging purposes so we don't check for error. */
 	if (clock->flags & CLKFLAG_MAX)
 		clk_set_max_rate(clock, val);
-	if (clock->flags & CLKFLAG_MIN)
-		ret = clk_set_min_rate(clock, val);
-	else
-		ret = clk_set_rate(clock, val);
-	if (ret != 0)
-		printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
-			(clock->flags & CLKFLAG_MIN) ? "_min" : "", ret);
+	ret = clk_set_rate(clock, val);
+	if (ret)
+		pr_err("clk_set_rate failed (%d)\n", ret);
+
 	return ret;
 }
 
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
index 1798a3c..feef984 100644
--- a/arch/arm/mach-msm/clock-dummy.c
+++ b/arch/arm/mach-msm/clock-dummy.c
@@ -17,17 +17,17 @@
 	return 0;
 }
 
-static int dummy_clk_set_rate(struct clk *clk, unsigned rate)
+static int dummy_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	return 0;
 }
 
-static int dummy_clk_set_min_rate(struct clk *clk, unsigned rate)
+static int dummy_clk_set_min_rate(struct clk *clk, unsigned long rate)
 {
 	return 0;
 }
 
-static int dummy_clk_set_max_rate(struct clk *clk, unsigned rate)
+static int dummy_clk_set_max_rate(struct clk *clk, unsigned long rate)
 {
 	return 0;
 }
@@ -37,12 +37,12 @@
 	return 0;
 }
 
-static unsigned dummy_clk_get_rate(struct clk *clk)
+static unsigned long dummy_clk_get_rate(struct clk *clk)
 {
 	return 0;
 }
 
-static long dummy_clk_round_rate(struct clk *clk, unsigned rate)
+static long dummy_clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	return rate;
 }
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 7489ea7..c1cfb55 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -508,7 +508,7 @@
 }
 
 /* Set a clock to an exact rate. */
-int rcg_clk_set_rate(struct clk *c, unsigned rate)
+int rcg_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	struct clk_freq_tbl *nf;
@@ -524,7 +524,7 @@
 }
 
 /* Set a clock to a rate greater than some minimum. */
-int rcg_clk_set_min_rate(struct clk *c, unsigned rate)
+int rcg_clk_set_min_rate(struct clk *c, unsigned long rate)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	struct clk_freq_tbl *nf;
@@ -540,7 +540,7 @@
 }
 
 /* Get the currently-set rate of a clock in Hz. */
-unsigned rcg_clk_get_rate(struct clk *c)
+unsigned long rcg_clk_get_rate(struct clk *c)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	unsigned long flags;
@@ -567,7 +567,7 @@
 }
 
 /* Return a supported rate that's at least the specified rate. */
-long rcg_clk_round_rate(struct clk *c, unsigned rate)
+long rcg_clk_round_rate(struct clk *c, unsigned long rate)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	struct clk_freq_tbl *f;
@@ -673,7 +673,7 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-static unsigned pll_vote_clk_get_rate(struct clk *clk)
+static unsigned long pll_vote_clk_get_rate(struct clk *clk)
 {
 	struct pll_vote_clk *pll = to_pll_vote_clk(clk);
 	return pll->rate;
@@ -753,7 +753,7 @@
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 }
 
-static unsigned pll_clk_get_rate(struct clk *clk)
+static unsigned long pll_clk_get_rate(struct clk *clk)
 {
 	struct pll_clk *pll = to_pll_clk(clk);
 	return pll->rate;
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 9887bb1..16a9955 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -143,12 +143,12 @@
 
 int rcg_clk_enable(struct clk *clk);
 void rcg_clk_disable(struct clk *clk);
-int rcg_clk_set_rate(struct clk *clk, unsigned rate);
-int rcg_clk_set_min_rate(struct clk *clk, unsigned rate);
-unsigned rcg_clk_get_rate(struct clk *clk);
+int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
+int rcg_clk_set_min_rate(struct clk *clk, unsigned long rate);
+unsigned long rcg_clk_get_rate(struct clk *clk);
 int rcg_clk_list_rate(struct clk *clk, unsigned n);
 int rcg_clk_is_enabled(struct clk *clk);
-long rcg_clk_round_rate(struct clk *clk, unsigned rate);
+long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
 struct clk *rcg_clk_get_parent(struct clk *c);
 int rcg_clk_handoff(struct clk *c);
 
@@ -167,7 +167,7 @@
 	return container_of(clk, struct fixed_clk, c);
 }
 
-static inline unsigned fixed_clk_get_rate(struct clk *clk)
+static inline unsigned long fixed_clk_get_rate(struct clk *clk)
 {
 	struct fixed_clk *f = to_fixed_clk(clk);
 	return f->rate;
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index f7f3666..79fe662 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -74,28 +74,29 @@
 	return pc_clk_reset(id, action);
 }
 
-static int pc_clk_set_rate(struct clk *clk, unsigned rate)
+static int pc_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	/* The rate _might_ be rounded off to the nearest KHz value by the
 	 * remote function. So a return value of 0 doesn't necessarily mean
 	 * that the exact rate was set successfully.
 	 */
+	unsigned r = rate;
 	int id = to_pcom_clk(clk)->id;
-	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
+	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &r);
 	if (rc < 0)
 		return rc;
 	else
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-static int pc_clk_set_min_rate(struct clk *clk, unsigned rate)
+static int pc_clk_set_min_rate(struct clk *clk, unsigned long rate)
 {
 	int rc;
 	int id = to_pcom_clk(clk)->id;
 	bool ignore_error = (cpu_is_msm7x27() && id == P_EBI1_CLK &&
 				rate >= INT_MAX);
-
-	rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
+	unsigned r = rate;
+	rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &r);
 	if (rc < 0)
 		return rc;
 	else if (ignore_error)
@@ -104,10 +105,11 @@
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-static int pc_clk_set_max_rate(struct clk *clk, unsigned rate)
+static int pc_clk_set_max_rate(struct clk *clk, unsigned long rate)
 {
 	int id = to_pcom_clk(clk)->id;
-	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
+	unsigned r = rate;
+	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &r);
 	if (rc < 0)
 		return rc;
 	else
@@ -124,17 +126,18 @@
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-static int pc_clk_set_ext_config(struct clk *clk, unsigned config)
+static int pc_clk_set_ext_config(struct clk *clk, unsigned long config)
 {
 	int id = to_pcom_clk(clk)->id;
-	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_EXT_CONFIG, &id, &config);
+	unsigned c = config;
+	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_EXT_CONFIG, &id, &c);
 	if (rc < 0)
 		return rc;
 	else
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-static unsigned pc_clk_get_rate(struct clk *clk)
+static unsigned long pc_clk_get_rate(struct clk *clk)
 {
 	int id = to_pcom_clk(clk)->id;
 	if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
@@ -152,7 +155,7 @@
 		return id;
 }
 
-static long pc_clk_round_rate(struct clk *clk, unsigned rate)
+static long pc_clk_round_rate(struct clk *clk, unsigned long rate)
 {
 
 	/* Not really supported; pc_clk_set_rate() does rounding on it's own. */
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 2ccebb4..75cba59 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -26,8 +26,8 @@
 	struct msm_rpm_iv_pair iv;
 	int rc = 0;
 	struct rpm_clk *r = to_rpm_clk(clk);
-	unsigned this_khz, this_sleep_khz;
-	unsigned peer_khz = 0, peer_sleep_khz = 0;
+	unsigned long this_khz, this_sleep_khz;
+	unsigned long peer_khz = 0, peer_sleep_khz = 0;
 	struct rpm_clk *peer = r->peer;
 
 	spin_lock_irqsave(&rpm_clock_lock, flags);
@@ -78,7 +78,7 @@
 	if (r->last_set_khz) {
 		struct msm_rpm_iv_pair iv;
 		struct rpm_clk *peer = r->peer;
-		unsigned peer_khz = 0, peer_sleep_khz = 0;
+		unsigned long peer_khz = 0, peer_sleep_khz = 0;
 		int rc;
 
 		iv.id = r->rpm_clk_id;
@@ -104,11 +104,11 @@
 	return;
 }
 
-static int rpm_clk_set_min_rate(struct clk *clk, unsigned rate)
+static int rpm_clk_set_min_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long flags;
 	struct rpm_clk *r = to_rpm_clk(clk);
-	unsigned this_khz, this_sleep_khz;
+	unsigned long this_khz, this_sleep_khz;
 	int rc = 0;
 
 	this_khz = DIV_ROUND_UP(rate, 1000);
@@ -129,7 +129,7 @@
 	if (r->enabled) {
 		struct msm_rpm_iv_pair iv;
 		struct rpm_clk *peer = r->peer;
-		unsigned peer_khz = 0, peer_sleep_khz = 0;
+		unsigned long peer_khz = 0, peer_sleep_khz = 0;
 
 		iv.id = r->rpm_clk_id;
 
@@ -158,7 +158,7 @@
 	return rc;
 }
 
-static unsigned rpm_clk_get_rate(struct clk *clk)
+static unsigned long rpm_clk_get_rate(struct clk *clk)
 {
 	struct rpm_clk *r = to_rpm_clk(clk);
 	struct msm_rpm_iv_pair iv = { r->rpm_status_id };
@@ -175,7 +175,7 @@
 	return !!(rpm_clk_get_rate(clk));
 }
 
-static long rpm_clk_round_rate(struct clk *clk, unsigned rate)
+static long rpm_clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	/* Not supported. */
 	return rate;
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index e754752..2624f6c 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -21,10 +21,10 @@
 static DEFINE_SPINLOCK(voter_clk_lock);
 
 /* Aggregate the rate of clocks that are currently on. */
-static unsigned voter_clk_aggregate_rate(const struct clk *parent)
+static unsigned long voter_clk_aggregate_rate(const struct clk *parent)
 {
 	struct clk *clk;
-	unsigned rate = 0;
+	unsigned long rate = 0;
 
 	list_for_each_entry(clk, &parent->children, siblings) {
 		struct clk_voter *v = to_clk_voter(clk);
@@ -34,13 +34,13 @@
 	return rate;
 }
 
-static int voter_clk_set_rate(struct clk *clk, unsigned rate)
+static int voter_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	int ret = 0;
 	unsigned long flags;
 	struct clk *clkp;
 	struct clk_voter *clkh, *v = to_clk_voter(clk);
-	unsigned cur_rate, new_rate, other_rate = 0;
+	unsigned long cur_rate, new_rate, other_rate = 0;
 
 	spin_lock_irqsave(&voter_clk_lock, flags);
 
@@ -61,7 +61,7 @@
 		new_rate = max(other_rate, rate);
 
 		if (new_rate != cur_rate) {
-			ret = clk_set_min_rate(parent, new_rate);
+			ret = clk_set_rate(parent, new_rate);
 			if (ret)
 				goto unlock;
 		}
@@ -77,7 +77,7 @@
 {
 	int ret = 0;
 	unsigned long flags;
-	unsigned cur_rate;
+	unsigned long cur_rate;
 	struct clk *parent;
 	struct clk_voter *v = to_clk_voter(clk);
 
@@ -90,7 +90,7 @@
 	 */
 	cur_rate = voter_clk_aggregate_rate(parent);
 	if (v->rate > cur_rate) {
-		ret = clk_set_min_rate(parent, v->rate);
+		ret = clk_set_rate(parent, v->rate);
 		if (ret)
 			goto out;
 	}
@@ -103,10 +103,9 @@
 
 static void voter_clk_disable(struct clk *clk)
 {
-	unsigned long flags;
+	unsigned long flags, cur_rate, new_rate;
 	struct clk *parent;
 	struct clk_voter *v = to_clk_voter(clk);
-	unsigned cur_rate, new_rate;
 
 	spin_lock_irqsave(&voter_clk_lock, flags);
 	parent = v->parent;
@@ -120,15 +119,14 @@
 	cur_rate = max(new_rate, v->rate);
 
 	if (new_rate < cur_rate)
-		clk_set_min_rate(parent, new_rate);
+		clk_set_rate(parent, new_rate);
 
 	spin_unlock_irqrestore(&voter_clk_lock, flags);
 }
 
-static unsigned voter_clk_get_rate(struct clk *clk)
+static unsigned long voter_clk_get_rate(struct clk *clk)
 {
-	unsigned rate;
-	unsigned long flags;
+	unsigned long rate, flags;
 	struct clk_voter *v = to_clk_voter(clk);
 
 	spin_lock_irqsave(&voter_clk_lock, flags);
@@ -144,7 +142,7 @@
 	return v->enabled;
 }
 
-static long voter_clk_round_rate(struct clk *clk, unsigned rate)
+static long voter_clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	struct clk_voter *v = to_clk_voter(clk);
 	return clk_round_rate(v->parent, rate);
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index 64baf3b..10353d4 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -19,7 +19,7 @@
 
 struct clk_voter {
 	bool enabled;
-	unsigned rate;
+	unsigned long rate;
 	struct clk *parent;
 	struct clk c;
 };
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 4f3ad95..d4f3e45 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -133,7 +133,7 @@
 int clk_enable(struct clk *clk)
 {
 	int ret = 0;
-	unsigned long flags, rate;
+	unsigned long flags;
 	struct clk *parent;
 
 	if (!clk)
@@ -142,7 +142,6 @@
 	spin_lock_irqsave(&clk->lock, flags);
 	if (clk->count == 0) {
 		parent = clk_get_parent(clk);
-		rate = clk_get_rate(clk);
 
 		ret = clk_enable(parent);
 		if (ret)
@@ -151,7 +150,7 @@
 		if (ret)
 			goto err_enable_depends;
 
-		ret = vote_rate_vdd(clk, rate);
+		ret = vote_rate_vdd(clk, clk->rate);
 		if (ret)
 			goto err_vote_vdd;
 		if (clk->ops->enable)
@@ -175,7 +174,7 @@
 	return 0;
 
 err_enable_clock:
-	unvote_rate_vdd(clk, rate);
+	unvote_rate_vdd(clk, clk->rate);
 err_vote_vdd:
 	clk_disable(clk->depends);
 err_enable_depends:
@@ -198,11 +197,10 @@
 		goto out;
 	if (clk->count == 1) {
 		struct clk *parent = clk_get_parent(clk);
-		unsigned long rate = clk_get_rate(clk);
 
 		if (clk->ops->disable)
 			clk->ops->disable(clk);
-		unvote_rate_vdd(clk, rate);
+		unvote_rate_vdd(clk, clk->rate);
 		clk_disable(clk->depends);
 		clk_disable(parent);
 	}
@@ -231,7 +229,7 @@
 EXPORT_SYMBOL(clk_get_rate);
 
 static int _clk_set_rate(struct clk *clk, unsigned long rate,
-			 int (*set_fn)(struct clk *, unsigned))
+			 int (*set_fn)(struct clk *, unsigned long))
 {
 	unsigned long start_rate, flags;
 	int rc;
@@ -241,7 +239,7 @@
 
 	spin_lock_irqsave(&clk->lock, flags);
 	if (clk->count) {
-		start_rate = clk_get_rate(clk);
+		start_rate = clk->rate;
 		/* Enforce vdd requirements for target frequency. */
 		rc = vote_rate_vdd(clk, rate);
 		if (rc)
@@ -254,6 +252,10 @@
 	} else {
 		rc = set_fn(clk, rate);
 	}
+
+	if (!rc)
+		clk->rate = rate;
+
 	spin_unlock_irqrestore(&clk->lock, flags);
 	return rc;
 
@@ -275,7 +277,10 @@
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	return _clk_set_rate(clk, rate, clk->ops->set_rate);
+	if (clk->flags & CLKFLAG_MIN)
+		return _clk_set_rate(clk, rate, clk->ops->set_min_rate);
+	else
+		return _clk_set_rate(clk, rate, clk->ops->set_rate);
 }
 EXPORT_SYMBOL(clk_set_rate);
 
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index ed5c9c6..81f12c6 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -47,7 +47,7 @@
 	const char *class_name;
 	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
 	int level_votes[MAX_VDD_LEVELS];
-	unsigned cur_level;
+	unsigned long cur_level;
 	spinlock_t lock;
 };
 
@@ -65,14 +65,14 @@
 	void (*auto_off)(struct clk *clk);
 	int (*handoff)(struct clk *clk);
 	int (*reset)(struct clk *clk, enum clk_reset_action action);
-	int (*set_rate)(struct clk *clk, unsigned rate);
-	int (*set_min_rate)(struct clk *clk, unsigned rate);
-	int (*set_max_rate)(struct clk *clk, unsigned rate);
+	int (*set_rate)(struct clk *clk, unsigned long rate);
+	int (*set_min_rate)(struct clk *clk, unsigned long rate);
+	int (*set_max_rate)(struct clk *clk, unsigned long rate);
 	int (*set_flags)(struct clk *clk, unsigned flags);
-	unsigned (*get_rate)(struct clk *clk);
+	unsigned long (*get_rate)(struct clk *clk);
 	int (*list_rate)(struct clk *clk, unsigned n);
 	int (*is_enabled)(struct clk *clk);
-	long (*round_rate)(struct clk *clk, unsigned rate);
+	long (*round_rate)(struct clk *clk, unsigned long rate);
 	int (*set_parent)(struct clk *clk, struct clk *parent);
 	struct clk *(*get_parent)(struct clk *clk);
 	bool (*is_local)(struct clk *clk);
@@ -93,6 +93,7 @@
 	struct clk *depends;
 	struct clk_vdd_class *vdd_class;
 	unsigned long fmax[MAX_VDD_LEVELS];
+	unsigned long rate;
 
 	struct list_head children;
 	struct list_head siblings;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index f1a0404..9b8d5ac 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -71,18 +71,18 @@
 
 static struct resource msm_dmov_resource[] = {
 	{
-		.start = ADM_0_SCSS_0_IRQ,
+		.start = ADM_0_SCSS_1_IRQ,
 		.flags = IORESOURCE_IRQ,
 	},
 	{
-		.start = 0x18300000,
-		.end = 0x18300000 + SZ_1M - 1,
+		.start = 0x18320000,
+		.end = 0x18320000 + SZ_1M - 1,
 		.flags = IORESOURCE_MEM,
 	},
 };
 
 static struct msm_dmov_pdata msm_dmov_pdata = {
-	.sd = 0,
+	.sd = 1,
 	.sd_size = 0x800,
 };
 
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4e047c5..af48067 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -15,6 +15,7 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/msm_rotator.h>
+#include <linux/ion.h>
 #include <linux/gpio.h>
 #include <asm/clkdev.h>
 #include <linux/msm_kgsl.h>
@@ -36,6 +37,7 @@
 #include "devices-msm8x60.h"
 #include "footswitch.h"
 #include "msm_watchdog.h"
+#include "rpm_stats.h"
 
 #ifdef CONFIG_MSM_MPM
 #include "mpm.h"
@@ -413,13 +415,13 @@
 		.src = MSM_BUS_MASTER_HD_CODEC_PORT0,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
 		.ab  = 372244480,
-		.ib  = 1861222400,
+		.ib  = 2560000000U,
 	},
 	{
 		.src = MSM_BUS_MASTER_HD_CODEC_PORT1,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
 		.ab  = 501219328,
-		.ib  = 2004877312,
+		.ib  = 2560000000U,
 	},
 	{
 		.src = MSM_BUS_MASTER_AMPSS_M0,
@@ -439,13 +441,13 @@
 		.src = MSM_BUS_MASTER_HD_CODEC_PORT0,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
 		.ab  = 222298112,
-		.ib  = 1778384896,
+		.ib  = 2560000000U,
 	},
 	{
 		.src = MSM_BUS_MASTER_HD_CODEC_PORT1,
 		.dst = MSM_BUS_SLAVE_EBI_CH0,
 		.ab  = 330301440,
-		.ib  = 1321205760,
+		.ib  = 2560000000U,
 	},
 	{
 		.src = MSM_BUS_MASTER_AMPSS_M0,
@@ -536,7 +538,13 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	.vidc_bus_client_pdata = &vidc_bus_client_data,
 #endif
-	.memtype = MEMTYPE_EBI1
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	.memtype = ION_HEAP_EBI_ID,
+	.enable_ion = 1,
+#else
+	.memtype = MEMTYPE_EBI1,
+	.enable_ion = 0,
+#endif
 };
 
 struct platform_device msm_device_vidc = {
@@ -977,34 +985,116 @@
 #ifdef CONFIG_MSM_CAMERA
 struct resource msm_camera_resources[] = {
 	{
-		.name	= "vfe",
-		.start	= 0x04500000,
-		.end	= 0x04500000 + SZ_1M - 1,
+		.name   = "s3d_rw",
+		.start  = 0x008003E0,
+		.end    = 0x008003E0 + SZ_16 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "s3d_ctl",
+		.start  = 0x008020B8,
+		.end    = 0x008020B8 + SZ_16 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+int __init msm_get_cam_resources(struct msm_camera_sensor_info *s_info)
+{
+	s_info->resource = msm_camera_resources;
+	s_info->num_resources = ARRAY_SIZE(msm_camera_resources);
+	return 0;
+}
+
+static struct resource msm_csiphy0_resources[] = {
+	{
+		.name	= "csiphy",
+		.start	= 0x04800C00,
+		.end	= 0x04800C00 + SZ_1K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.name	= "vfe",
-		.start	= VFE_IRQ,
-		.end	= VFE_IRQ,
+		.name	= "csiphy",
+		.start	= CSIPHY_4LN_IRQ,
+		.end	= CSIPHY_4LN_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
+};
+
+static struct resource msm_csiphy1_resources[] = {
 	{
-		.name	= "vpe",
-		.start	= 0x05300000,
-		.end	= 0x05300000 + SZ_1M - 1,
+		.name	= "csiphy",
+		.start	= 0x04801000,
+		.end	= 0x04801000 + SZ_1K - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.name	= "vpe",
-		.start	= VPE_IRQ,
-		.end	= VPE_IRQ,
+		.name	= "csiphy",
+		.start	= MSM8960_CSIPHY_2LN_IRQ,
+		.end	= MSM8960_CSIPHY_2LN_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
+};
+
+struct platform_device msm8960_device_csiphy0 = {
+	.name           = "msm_csiphy",
+	.id             = 0,
+	.resource       = msm_csiphy0_resources,
+	.num_resources  = ARRAY_SIZE(msm_csiphy0_resources),
+};
+
+struct platform_device msm8960_device_csiphy1 = {
+	.name           = "msm_csiphy",
+	.id             = 1,
+	.resource       = msm_csiphy1_resources,
+	.num_resources  = ARRAY_SIZE(msm_csiphy1_resources),
+};
+
+static struct resource msm_csid0_resources[] = {
 	{
-		.name	= "vid_buf",
-		.flags	= IORESOURCE_DMA,
+		.name	= "csid",
+		.start	= 0x04800000,
+		.end	= 0x04800000 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
 	},
 	{
+		.name	= "csid",
+		.start	= CSI_0_IRQ,
+		.end	= CSI_0_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_csid1_resources[] = {
+	{
+		.name	= "csid",
+		.start	= 0x04800400,
+		.end	= 0x04800400 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "csid",
+		.start	= CSI_1_IRQ,
+		.end	= CSI_1_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8960_device_csid0 = {
+	.name           = "msm_csid",
+	.id             = 0,
+	.resource       = msm_csid0_resources,
+	.num_resources  = ARRAY_SIZE(msm_csid0_resources),
+};
+
+struct platform_device msm8960_device_csid1 = {
+	.name           = "msm_csid",
+	.id             = 1,
+	.resource       = msm_csid1_resources,
+	.num_resources  = ARRAY_SIZE(msm_csid1_resources),
+};
+
+struct resource msm_ispif_resources[] = {
+	{
 		.name	= "ispif",
 		.start	= 0x04800800,
 		.end	= 0x04800800 + SZ_1K - 1,
@@ -1016,75 +1106,58 @@
 		.end	= ISPIF_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
-	{
-		.name	= "csid0",
-		.start	= 0x04800000,
-		.end	= 0x04800000 + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "csid0",
-		.start	= CSI_0_IRQ,
-		.end	= CSI_0_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.name	= "csiphy0",
-		.start	= 0x04800C00,
-		.end	= 0x04800C00 + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "csiphy0",
-		.start	= CSIPHY_4LN_IRQ,
-		.end	= CSIPHY_4LN_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.name	= "csid1",
-		.start	= 0x04800400,
-		.end	= 0x04800400 + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "csid1",
-		.start	= CSI_1_IRQ,
-		.end	= CSI_1_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.name	= "csiphy1",
-		.start	= 0x04801000,
-		.end	= 0x04801000 + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "csiphy1",
-		.start	= MSM8960_CSIPHY_2LN_IRQ,
-		.end	= MSM8960_CSIPHY_2LN_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.name   = "s3d_rw",
-		.start  = 0x008003E0,
-		.end    = 0x008003E0 + SZ_16 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "s3d_ctl",
-		.start  = 0x008020B8,
-		.end    = 0x008020B8 + SZ_16 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-
 };
 
-int __init msm_get_cam_resources(struct msm_camera_sensor_info *s_info)
-{
-	s_info->resource = msm_camera_resources;
-	s_info->num_resources = ARRAY_SIZE(msm_camera_resources);
-	return 0;
-}
+struct platform_device msm8960_device_ispif = {
+	.name           = "msm_ispif",
+	.id             = 0,
+	.resource       = msm_ispif_resources,
+	.num_resources  = ARRAY_SIZE(msm_ispif_resources),
+};
+
+static struct resource msm_vfe_resources[] = {
+	{
+		.name	= "vfe32",
+		.start	= 0x04500000,
+		.end	= 0x04500000 + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "vfe32",
+		.start	= VFE_IRQ,
+		.end	= VFE_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8960_device_vfe = {
+	.name           = "msm_vfe",
+	.id             = 0,
+	.resource       = msm_vfe_resources,
+	.num_resources  = ARRAY_SIZE(msm_vfe_resources),
+};
+
+static struct resource msm_vpe_resources[] = {
+	{
+		.name	= "vpe",
+		.start	= 0x05300000,
+		.end	= 0x05300000 + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "vpe",
+		.start	= VPE_IRQ,
+		.end	= VPE_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8960_device_vpe = {
+	.name           = "msm_vpe",
+	.id             = 0,
+	.resource       = msm_vpe_resources,
+	.num_resources  = ARRAY_SIZE(msm_vpe_resources),
+};
 #endif
 
 static struct resource resources_ssbi_pm8921[] = {
@@ -1968,18 +2041,22 @@
 			{
 				.gpu_freq = 400000000,
 				.bus_freq = 4,
+				.io_fraction = 0,
 			},
 			{
 				.gpu_freq = 300000000,
 				.bus_freq = 3,
+				.io_fraction = 33,
 			},
 			{
 				.gpu_freq = 200000000,
 				.bus_freq = 2,
+				.io_fraction = 100,
 			},
 			{
 				.gpu_freq = 128000000,
 				.bus_freq = 1,
+				.io_fraction = 100,
 			},
 			{
 				.gpu_freq = 27000000,
@@ -2245,6 +2322,18 @@
 	.id     = -1,
 };
 
+static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
+	.phys_addr_base = 0x0010D204,
+	.phys_size = SZ_8K,
+};
+
+struct platform_device msm_rpm_stat_device = {
+	.name = "msm_rpm_stat",
+	.id = -1,
+	.dev = {
+		.platform_data = &msm_rpm_stat_pdata,
+	},
+};
 
 struct platform_device msm_bus_sys_fabric = {
 	.name  = "msm_bus_fabric",
@@ -2323,6 +2412,7 @@
 #define MSM_ETB_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x1000)
 #define MSM_TPIU_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x3000)
 #define MSM_FUNNEL_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x4000)
+#define MSM_DEBUG_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x10000)
 #define MSM_PTM_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x1C000)
 
 static struct resource msm_etb_resources[] = {
@@ -2370,6 +2460,26 @@
 	.resource      = msm_funnel_resources,
 };
 
+static struct resource msm_debug_resources[] = {
+	{
+		.start = MSM_DEBUG_PHYS_BASE,
+		.end   = MSM_DEBUG_PHYS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MSM_DEBUG_PHYS_BASE + (SZ_4K * 2),
+		.end   = MSM_DEBUG_PHYS_BASE + (SZ_4K * 2) + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm_debug_device = {
+	.name          = "msm_debug",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(msm_debug_resources),
+	.resource      = msm_debug_resources,
+};
+
 static struct resource msm_ptm_resources[] = {
 	{
 		.start = MSM_PTM_PHYS_BASE,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 3cf7d48..47e33d0 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -26,6 +26,7 @@
 #include <mach/irqs.h>
 #include <mach/socinfo.h>
 #include <mach/rpm.h>
+#include <mach/msm_bus_board.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <mach/msm_sps.h>
 #include <mach/dma.h>
@@ -332,6 +333,11 @@
 	.id		= -1,
 };
 
+struct platform_device msm_device_bam_dmux = {
+	.name		= "BAM_RMNT",
+	.id		= -1,
+};
+
 #ifdef CONFIG_HW_RANDOM_MSM
 /* PRNG device */
 #define MSM_PRNG_PHYS		0x1A500000
@@ -784,20 +790,32 @@
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
 		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
 		true,
-		1, 8000, 100000, 1,
+		100, 8000, 100000, 1,
 	},
 
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
 		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
 		true,
-		1500, 5000, 60100000, 3000,
+		2000, 5000, 60100000, 3000,
 	},
 	{
 		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
 		MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
 		false,
-		2800, 5000, 60350000, 3500,
+		6300, 5000, 60350000, 3500,
+	},
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE),
+		false,
+		13300, 2000, 71850000, 6800,
+	},
+	{
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+		MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW),
+		false,
+		28300, 0, 76350000, 9800,
 	},
 };
 
@@ -843,3 +861,13 @@
 			irq_set_handler(i, handle_percpu_irq);
 	}
 }
+
+struct platform_device msm_bus_9615_sys_fabric = {
+	.name  = "msm_bus_fabric",
+	.id    =  MSM_BUS_FAB_SYSTEM,
+};
+
+struct platform_device msm_bus_def_fab = {
+	.name  = "msm_bus_fabric",
+	.id    =  MSM_BUS_FAB_DEFAULT,
+};
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index b76a844..017eed9 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -548,8 +548,8 @@
 	},
 	{
 		.name	= "vbus_on",
-		.start	= PM8058_CHGVAL_IRQ(PMIC8058_IRQ_BASE),
-		.end	= PM8058_CHGVAL_IRQ(PMIC8058_IRQ_BASE),
+		.start	= PMIC8058_IRQ_BASE + PM8058_CHGVAL_IRQ,
+		.end	= PMIC8058_IRQ_BASE + PM8058_CHGVAL_IRQ,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -789,7 +789,8 @@
 };
 
 struct msm_vidc_platform_data vidc_platform_data = {
-	.memtype = MEMTYPE_EBI0
+	.memtype = MEMTYPE_EBI0,
+	.enable_ion = 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 def2558..0ab9811 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
+#include <linux/ion.h>
 #include <mach/irqs.h>
 #include <mach/dma.h>
 #include <asm/mach/mmc.h>
@@ -657,18 +658,22 @@
 			{
 				.gpu_freq = 266667000,
 				.bus_freq = 4,
+				.io_fraction = 0,
 			},
 			{
 				.gpu_freq = 228571000,
 				.bus_freq = 3,
+				.io_fraction = 33,
 			},
 			{
 				.gpu_freq = 200000000,
 				.bus_freq = 2,
+				.io_fraction = 100,
 			},
 			{
 				.gpu_freq = 177778000,
-				.bus_freq = 1
+				.bus_freq = 1,
+				.io_fraction = 100,
 			},
 			{
 				.gpu_freq = 27000000,
@@ -2146,7 +2151,13 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	.vidc_bus_client_pdata = &vidc_bus_client_data,
 #endif
-	.memtype = MEMTYPE_SMI_KERNEL
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	.memtype = ION_HEAP_SMI_ID,
+	.enable_ion = 1,
+#else
+	.memtype = MEMTYPE_SMI_KERNEL,
+	.enable_ion = 0,
+#endif
 };
 
 struct platform_device msm_device_vidc = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.h b/arch/arm/mach-msm/devices-msm8x60.h
index 6b7d141..1d5dee1 100644
--- a/arch/arm/mach-msm/devices-msm8x60.h
+++ b/arch/arm/mach-msm/devices-msm8x60.h
@@ -69,12 +69,6 @@
 #ifdef CONFIG_MSM_DSPS
 extern struct platform_device msm_dsps_device;
 #endif
-#ifdef CONFIG_MSM_QDSS
-extern struct platform_device msm_etb_device;
-extern struct platform_device msm_tpiu_device;
-extern struct platform_device msm_funnel_device;
-extern struct platform_device msm_ptm_device;
-#endif
 
 #if defined(CONFIG_MSM_RPM_STATS_LOG)
 extern struct platform_device msm_rpm_stat_device;
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index c490574..48686f0 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -58,6 +58,13 @@
 extern struct platform_device msm8960_device_qup_i2c_gsbi12;
 extern struct platform_device msm8960_device_qup_spi_gsbi1;
 extern struct platform_device msm8960_gemini_device;
+extern struct platform_device msm8960_device_csiphy0;
+extern struct platform_device msm8960_device_csiphy1;
+extern struct platform_device msm8960_device_csid0;
+extern struct platform_device msm8960_device_csid1;
+extern struct platform_device msm8960_device_ispif;
+extern struct platform_device msm8960_device_vfe;
+extern struct platform_device msm8960_device_vpe;
 
 extern struct platform_device apq8064_device_uart_gsbi1;
 extern struct platform_device apq8064_device_uart_gsbi3;
@@ -72,6 +79,8 @@
 extern struct platform_device msm9615_device_qup_spi_gsbi3;
 extern struct platform_device msm9615_device_ssbi_pmic1;
 extern struct platform_device msm9615_device_tsens;
+extern struct platform_device msm_bus_9615_sys_fabric;
+extern struct platform_device msm_bus_def_fab;
 
 extern struct platform_device msm_device_sdc1;
 extern struct platform_device msm_device_sdc2;
@@ -191,6 +200,7 @@
 
 extern struct platform_device ion_dev;
 extern struct platform_device msm_rpm_device;
+extern struct platform_device msm_rpm_stat_device;
 extern struct platform_device msm_device_rng;
 
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
@@ -206,4 +216,10 @@
 extern struct platform_device msm8660_device_watchdog;
 extern struct platform_device msm8064_device_watchdog;
 extern struct platform_device msm9615_device_watchdog;
+
+extern struct platform_device msm_etb_device;
+extern struct platform_device msm_tpiu_device;
+extern struct platform_device msm_funnel_device;
+extern struct platform_device msm_debug_device;
+extern struct platform_device msm_ptm_device;
 #endif
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index a6e8fdb..aab93f4 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -32,14 +32,11 @@
 #endif
 
 ENTRY(msm_arch_idle)
-#ifdef CONFIG_MSM_JTAG_V7
-	stmfd   sp!, {lr}
-	bl      msm_save_jtag_debug
-#endif
 	wfi
-#ifdef CONFIG_MSM_JTAG_V7
-	bl      msm_restore_jtag_debug
-	ldmfd   sp!, {lr}
+#ifdef CONFIG_ARCH_MSM8X60
+	mrc	p14, 1, r1, c1, c5, 4 /* read ETM PDSR to clear sticky bit */
+	mrc     p14, 0, r1, c1, c5, 4 /* read DBG PRSR to clear sticky bit */
+	isb
 #endif
 	bx	lr
 
@@ -85,7 +82,7 @@
 	stmia   r0!, {r1-r3}
 #endif
 
-#ifdef CONFIG_MSM_JTAG_V7
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
 	bl      msm_save_jtag_debug
 #endif
 #ifdef CONFIG_MSM_TRACE_ACROSS_PC
@@ -132,7 +129,7 @@
 #ifdef CONFIG_MSM_TRACE_ACROSS_PC
 	bl	etm_restore_reg_check
 #endif
-#ifdef CONFIG_MSM_JTAG_V7
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
 	bl	msm_restore_jtag_debug
 #endif
 	ldr     r0, =saved_state        /* restore registers */
@@ -220,7 +217,7 @@
 #ifdef CONFIG_MSM_TRACE_ACROSS_PC
 	bl      etm_restore_reg_check
 #endif
-#ifdef CONFIG_MSM_JTAG_V7
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
 	bl      msm_restore_jtag_debug
 #endif
 	ldmfd   sp!, {lr}
diff --git a/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h b/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
index 5c9bfb5..1970d0b 100644
--- a/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
+++ b/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -202,6 +202,11 @@
 #define LPAIF_DMA_SET_BUFF_CNT(x)	DMA_CTRL_ADDR(x, 0x20)
 #define	LPAIF_DMA_SET_PER_CNT(x)	DMA_CTRL_ADDR(x, 0x24)
 
+#define LPAIF_DMA_PER_CNT_PER_CNT_MASK		0x000FFFFF
+#define LPAIF_DMA_PER_CNT_PER_CNT_SHIFT		0
+#define LPAIF_DMA_PER_CNT_FIFO_WORDCNT_MASK	0x00F00000
+#define LPAIF_DMA_PER_CNT_FIFO_WORDCNT_SHIFT	20
+
 /* channel assignments */
 
 #define DMA_CH_0		0
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index e7f156e..2116ee7 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -404,6 +404,7 @@
 
 struct msm_vidc_platform_data {
 	int memtype;
+	u32 enable_ion;
 #ifdef CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *vidc_bus_client_pdata;
 #endif
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 1c91d94..1745f26 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -42,7 +42,7 @@
 #define NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS 16
 #define NUM_STAT_OUTPUT_BUFFERS      3
 #define NUM_AF_STAT_OUTPUT_BUFFERS      3
-#define max_control_command_size 260
+#define max_control_command_size 512
 #define CROP_LEN 36
 
 enum vfe_mode_of_operation{
@@ -617,6 +617,11 @@
 	MODE_DUAL
 };
 
+struct msm_cam_clk_info {
+	const char *clk_name;
+	long clk_rate;
+};
+
 int msm_camio_enable(struct platform_device *dev);
 int msm_camio_jpeg_clk_enable(void);
 int msm_camio_jpeg_clk_disable(void);
@@ -665,4 +670,7 @@
 void *msm_isp_sync_alloc(int size, gfp_t gfp);
 
 void msm_isp_sync_free(void *ptr);
+
+int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct clk **clk_ptr, int num_clk, int enable);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 905a254..5112888 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -1,4 +1,4 @@
-/* arch/arm/mach-msm7200/include/mach/debug-macro.S
+/*
  *
  * Copyright (C) 2007 Google, Inc.
  * Author: Brian Swetland <swetland@google.com>
@@ -19,7 +19,7 @@
 #include <mach/hardware.h>
 #include <mach/msm_iomap.h>
 
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef MSM_DEBUG_UART_PHYS
        .macro  addruart, rp, rv
 	ldr     \rp, =MSM_DEBUG_UART_PHYS
 	ldr     \rv, =MSM_DEBUG_UART_BASE
diff --git a/arch/arm/mach-msm/include/mach/diag_bridge.h b/arch/arm/mach-msm/include/mach/diag_bridge.h
index 92eb1b9..281a1a6 100644
--- a/arch/arm/mach-msm/include/mach/diag_bridge.h
+++ b/arch/arm/mach-msm/include/mach/diag_bridge.h
@@ -1,4 +1,3 @@
-
 /* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -11,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-
 #ifndef __LINUX_USB_DIAG_BRIDGE_H__
 #define __LINUX_USB_DIAG_BRIDGE_H__
 
@@ -23,9 +21,33 @@
 			size_t buf_size, size_t actual);
 };
 
-extern int diag_read(char *data, size_t size);
-extern int diag_write(char *data, size_t size);
-extern int diag_open(struct diag_bridge_ops *ops);
-extern void diag_close(void);
+#if defined(CONFIG_USB_QCOM_DIAG_BRIDGE) \
+	|| defined(CONFIG_USB_QCOM_DIAG_BRIDGE_MODULE)
+
+extern int diag_bridge_read(char *data, size_t size);
+extern int diag_bridge_write(char *data, size_t size);
+extern int diag_bridge_open(struct diag_bridge_ops *ops);
+extern void diag_bridge_close(void);
+
+#else
+
+static int __maybe_unused diag_bridge_read(char *data, size_t size)
+{
+	return -ENODEV;
+}
+
+static int __maybe_unused diag_bridge_write(char *data, size_t size)
+{
+	return -ENODEV;
+}
+
+static int __maybe_unused diag_bridge_open(struct diag_bridge_ops *ops)
+{
+	return -ENODEV;
+}
+
+static void __maybe_unused diag_bridge_close(void) { }
+
+#endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 5cd7013..d5a2ed4 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -17,15 +17,7 @@
 #include <linux/clk.h>
 #include <mach/socinfo.h>
 
-/* Sharability attributes of MSM IOMMU mappings */
-#define MSM_IOMMU_ATTR_NON_SH		0x0
-#define MSM_IOMMU_ATTR_SH		0x4
-
-/* Cacheability attributes of MSM IOMMU mappings */
-#define MSM_IOMMU_ATTR_NONCACHED	0x0
-#define MSM_IOMMU_ATTR_CACHED_WB_WA	0x1
-#define MSM_IOMMU_ATTR_CACHED_WB_NWA	0x2
-#define MSM_IOMMU_ATTR_CACHED_WT	0x3
+extern pgprot_t     pgprot_kernel;
 
 /* Domain attributes */
 #define MSM_IOMMU_DOMAIN_PT_CACHEABLE	0x1
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 28e98de..48eae0c 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -44,6 +44,12 @@
 extern unsigned long msm_subsystem_get_partition_no(int subsys_id);
 
 extern int msm_use_iommu(void);
+
+extern int msm_iommu_map_extra(struct iommu_domain *domain,
+						unsigned long start_iova,
+						unsigned long size,
+						int cached);
+
 #else
 static inline struct iommu_domain
 	*msm_get_iommu_domain(int subsys_id) { return NULL; }
@@ -74,6 +80,14 @@
 {
 	return 0;
 }
+
+static inline int msm_iommu_map_extra(struct iommu_domain *domain,
+						unsigned long start_iova,
+						unsigned long size,
+						int cached)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index 8b62632..74e5847 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -71,8 +71,8 @@
 #define MSMC_SC_PRI_CE_IRQ			(GIC_SPI_START + 32)
 #define SLIMBUS0_CORE_EE1_IRQ			(GIC_SPI_START + 33)
 #define SLIMBUS0_BAM_EE1_IRQ			(GIC_SPI_START + 34)
-#define Q6FW_WDOG_EXPIRED			(GIC_SPI_START + 35)
-#define Q6SW_WDOG_EXPIRED			(GIC_SPI_START + 36)
+#define Q6FW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 35)
+#define Q6SW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 36)
 #define MSS_TO_APPS_IRQ_0			(GIC_SPI_START + 37)
 #define MSS_TO_APPS_IRQ_1			(GIC_SPI_START + 38)
 #define MSS_TO_APPS_IRQ_2			(GIC_SPI_START + 39)
diff --git a/arch/arm/mach-msm/include/mach/msm72k_otg.h b/arch/arm/mach-msm/include/mach/msm72k_otg.h
index 43f487a..4509dad 100644
--- a/arch/arm/mach-msm/include/mach/msm72k_otg.h
+++ b/arch/arm/mach-msm/include/mach/msm72k_otg.h
@@ -25,6 +25,7 @@
 
 #define OTGSC_BSVIE            (1 << 27)
 #define OTGSC_IDIE             (1 << 24)
+#define OTGSC_IDPU             (1 << 5)
 #define OTGSC_BSVIS            (1 << 19)
 #define OTGSC_ID               (1 << 8)
 #define OTGSC_IDIS             (1 << 16)
@@ -148,7 +149,6 @@
 	struct wake_lock wlock;
 	unsigned long b_last_se0_sess; /* SRP initial condition check */
 	unsigned long inputs;
-	int pmic_id_status;
 	unsigned long tmouts;
 	u8 active_tmout;
 	struct hrtimer timer;
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index 2eb504a..b0d69c7 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -70,6 +70,8 @@
 extern struct msm_bus_fabric_registration msm_bus_8064_sys_fpb_pdata;
 extern struct msm_bus_fabric_registration msm_bus_8064_cpss_fpb_pdata;
 
+extern struct msm_bus_fabric_registration msm_bus_9615_sys_fabric_pdata;
+extern struct msm_bus_fabric_registration msm_bus_9615_def_fab_pdata;
 void msm_bus_rpm_set_mt_mask(void);
 int msm_bus_board_rpm_get_il_ids(uint16_t *id);
 int msm_bus_board_get_iid(int id);
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 97dad67..3965a75 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -14,5 +14,6 @@
 #define __MSM_HDMI_AUDIO_H
 
 int hdmi_audio_enable(bool on , u32 fifo_water_mark);
+int hdmi_audio_packet_enable(bool on);
 
 #endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/include/mach/msm_hsusb.h b/arch/arm/mach-msm/include/mach/msm_hsusb.h
index 26f1cdd..3e8ab55 100644
--- a/arch/arm/mach-msm/include/mach/msm_hsusb.h
+++ b/arch/arm/mach-msm/include/mach/msm_hsusb.h
@@ -158,6 +158,7 @@
 	/* pmic notfications apis */
 	int (*pmic_vbus_notif_init) (void (*callback)(int online), int init);
 	int (*pmic_id_notif_init) (void (*callback)(int online), int init);
+	int (*phy_id_setup_init) (int init);
 	int (*pmic_register_vbus_sn) (void (*callback)(int online));
 	void (*pmic_unregister_vbus_sn) (void (*callback)(int online));
 	int (*pmic_enable_ldo) (int);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
index d1aef0a..333df32 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
@@ -83,18 +83,6 @@
 #define MSM_UART3_PHYS        0xA9C00000
 #define MSM_UART3_SIZE        SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE   0xF9000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS   MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS   MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS   MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE   SZ_4K
-#endif
-
 #define MSM_SDC1_PHYS         0xA0400000
 #define MSM_SDC1_SIZE         SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index e49e870..acd668b 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -91,18 +91,6 @@
 #define MSM_UART3_PHYS        0xACC00000
 #define MSM_UART3_SIZE        SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE   0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS   MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS   MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS   MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE   SZ_4K
-#endif
-
 #define MSM_MDC_BASE	      IOMEM(0xFA200000)
 #define MSM_MDC_PHYS	      0xAA500000
 #define MSM_MDC_SIZE	      SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
index d7dc4f4..d545a5f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
@@ -79,18 +79,6 @@
 #define MSM_UART3_PHYS        0xA9C00000
 #define MSM_UART3_SIZE        SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE   0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS   MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS   MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS   MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE   SZ_4K
-#endif
-
 #define MSM_MDC_BASE	      IOMEM(0xFA200000)
 #define MSM_MDC_PHYS	      0xAA500000
 #define MSM_MDC_SIZE	      SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8930.h b/arch/arm/mach-msm/include/mach/msm_iomap-8930.h
index 8e50824..f3f8b8f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8930.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8930.h
@@ -101,14 +101,10 @@
 #define MSM8930_HDMI_PHYS		0x04A00000
 #define MSM8930_HDMI_SIZE		SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8930_UART
 #define MSM_DEBUG_UART_BASE		IOMEM(0xFA740000)
-#define MSM_DEBUG_UART_SIZE		SZ_4K
-
-#ifdef CONFIG_MSM_DEBUG_UART1
 #define MSM_DEBUG_UART_PHYS		0x16440000
 #endif
-#endif
 
 #define MSM8930_QFPROM_PHYS		0x00700000
 #define MSM8930_QFPROM_SIZE		SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
index 24505ae..b70cacc 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
@@ -98,14 +98,10 @@
 #define MSM8960_HDMI_PHYS		0x04A00000
 #define MSM8960_HDMI_SIZE		SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8960_UART
 #define MSM_DEBUG_UART_BASE		IOMEM(0xFA740000)
-#define MSM_DEBUG_UART_SIZE		SZ_4K
-
-#ifdef CONFIG_MSM_DEBUG_UART1
 #define MSM_DEBUG_UART_PHYS		0x16440000
 #endif
-#endif
 
 #define MSM8960_QFPROM_PHYS		0x00700000
 #define MSM8960_QFPROM_SIZE		SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
index a073d6a..a1b32ec 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
@@ -83,18 +83,6 @@
 #define MSM_UART3_PHYS        0xA9C00000
 #define MSM_UART3_SIZE        SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE   0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS   MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS   MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS   MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE   SZ_4K
-#endif
-
 #define MSM_MDC_BASE	      IOMEM(0xFA200000)
 #define MSM_MDC_PHYS	      0xAA500000
 #define MSM_MDC_SIZE	      SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index c1cf221..723f3d8 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -126,11 +126,9 @@
 #define MSM_HDMI_PHYS		0x04A00000
 #define MSM_HDMI_SIZE		SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
-
+#ifdef CONFIG_DEBUG_MSM8660_UART
 #define MSM_DEBUG_UART_BASE	0xFBC40000
 #define MSM_DEBUG_UART_PHYS	0x19C40000
-#define MSM_DEBUG_UART_SIZE	SZ_4K
-
 #endif
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h b/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
index 57bfd58..c30c9e4 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
@@ -81,14 +81,4 @@
 #define MSM_UART2_PHYS        0x94100000
 #define MSM_UART2_SIZE        SZ_4K
 
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE   0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS   MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS   MSM_UART2_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE   SZ_4K
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 256099b..dd01c62 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -43,6 +43,8 @@
 #define IOMEM(x)	((void __force __iomem *)(x))
 #endif
 
+#define MSM_DEBUG_UART_SIZE	SZ_4K
+
 #if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
 	defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
 	defined(CONFIG_ARCH_MSMCOPPER)
@@ -103,6 +105,17 @@
 #include "msm_iomap-7xxx.h"
 #endif
 
+#if defined(CONFIG_DEBUG_MSM_UART1)
+#define MSM_DEBUG_UART_BASE	0xFB000000
+#define MSM_DEBUG_UART_PHYS	MSM_UART1_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART2)
+#define MSM_DEBUG_UART_BASE	0xFB000000
+#define MSM_DEBUG_UART_PHYS	MSM_UART2_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART3)
+#define MSM_DEBUG_UART_BASE	0xFB000000
+#define MSM_DEBUG_UART_PHYS	MSM_UART3_PHYS
+#endif
+
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index 4641479..0c2cd4b 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -82,6 +82,8 @@
 #define SMSM_WKUP_REASON_TIMER	0x00000008
 #define SMSM_WKUP_REASON_ALARM	0x00000010
 #define SMSM_WKUP_REASON_RESET	0x00000020
+#define SMSM_A2_FORCE_SHUTDOWN 0x00002000
+#define SMSM_A2_RESET_BAM      0x00004000
 
 #define SMSM_VENDOR             0x00020000
 
diff --git a/arch/arm/mach-msm/include/mach/msm_subsystem_map.h b/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
index 0e74235..ebb2327 100644
--- a/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
+++ b/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
@@ -25,6 +25,11 @@
 /* ioremaps in the kernel address space are uncached */
 #define MSM_SUBSYSTEM_MAP_UNCACHED	0x8
 /*
+ * Will map 2x the length requested.
+ */
+#define MSM_SUBSYSTEM_MAP_IOMMU_2X 0x10
+
+/*
  * Shortcut flags for alignment.
  * The flag must be equal to the alignment requested.
  * e.g. for 8k alignment the flags must be (0x2000 | other flags)
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
index 8309953..62d7a33 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
@@ -76,7 +76,8 @@
 #define APR_SVC_ADSP_MVM	0x09
 #define APR_SVC_ADSP_CVS	0x0A
 #define APR_SVC_ADSP_CVP	0x0B
-#define APR_SVC_MAX		0x0C
+#define APR_SVC_USM		0x0C
+#define APR_SVC_MAX		0x0D
 
 /* Modem Service IDs */
 #define APR_SVC_MVS		0x3
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h
new file mode 100644
index 0000000..444d7ad
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h
@@ -0,0 +1,156 @@
+/* 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 __APR_US_H__
+#define __APR_US_H__
+
+#include <mach/qdsp6v2/apr.h>
+
+/* ======================================================================= */
+/*  Session Level commands */
+#define USM_SESSION_CMD_MEMORY_MAP			0x00012304
+struct usm_stream_cmd_memory_map {
+	struct apr_hdr	hdr;
+	u32		buf_add;
+	u32		buf_size;
+	u16		mempool_id;
+	u16		reserved;
+} __packed;
+
+#define USM_SESSION_CMD_MEMORY_UNMAP			0x00012305
+struct usm_stream_cmd_memory_unmap {
+	struct apr_hdr  hdr;
+	u32             buf_add;
+} __packed;
+
+#define USM_SESSION_CMD_RUN				0x00012306
+struct usm_stream_cmd_run {
+	struct apr_hdr hdr;
+	u32            flags;
+	u32            msw_ts;
+	u32            lsw_ts;
+} __packed;
+
+/* Stream level commands */
+#define USM_STREAM_CMD_OPEN_READ			0x00012309
+struct usm_stream_cmd_open_read {
+	struct apr_hdr hdr;
+	u32            uMode;
+	u32            src_endpoint;
+	u32            pre_proc_top;
+	u32            format;
+} __packed;
+
+#define USM_STREAM_CMD_OPEN_WRITE			0x00011271
+struct usm_stream_cmd_open_write {
+	struct apr_hdr hdr;
+	u32            format;
+} __packed;
+
+
+#define USM_STREAM_CMD_CLOSE				0x0001230A
+
+/* Encoder configuration definitions */
+#define USM_STREAM_CMD_SET_ENC_PARAM			0x0001230B
+/* Decoder configuration definitions */
+#define USM_DATA_CMD_MEDIA_FORMAT_UPDATE		0x00011272
+
+/* Encoder/decoder configuration block */
+#define USM_PARAM_ID_ENCDEC_ENC_CFG_BLK			0x0001230D
+
+/* Parameter structures used in  USM_STREAM_CMD_SET_ENCDEC_PARAM command */
+/* common declarations */
+struct usm_cfg_common {
+	u16 ch_cfg;
+	u16 bits_per_sample;
+	u32 sample_rate;
+	u32 dev_id;
+	u32 data_map;
+} __packed;
+
+/* Max number of static located transparent data (bytes) */
+#define USM_MAX_CFG_DATA_SIZE 20
+struct usm_encode_cfg_blk {
+	u32 frames_per_buf;
+	u32 format_id;
+	/* <cfg_size> = sizeof(usm_cfg_common)+|tarnsp_data| */
+	u32 cfg_size;
+	struct usm_cfg_common cfg_common;
+	/* Transparent configuration data for specific encoder */
+	u8  transp_data[USM_MAX_CFG_DATA_SIZE];
+} __packed;
+
+struct usm_stream_cmd_encdec_cfg_blk {
+	struct apr_hdr hdr;
+	u32 param_id;
+	u32 param_size;
+	struct usm_encode_cfg_blk enc_blk;
+} __packed;
+
+struct us_encdec_cfg {
+	u32 format_id;
+	struct usm_cfg_common cfg_common;
+	u16 params_size;
+	u8 *params;
+} __packed;
+
+struct usm_stream_media_format_update {
+	struct apr_hdr hdr;
+	u32 format_id;
+	/* <cfg_size> = sizeof(usm_cfg_common)+|tarnsp_data| */
+	u32 cfg_size;
+	struct usm_cfg_common cfg_common;
+	/* Transparent configuration data for specific encoder */
+	u8  transp_data[USM_MAX_CFG_DATA_SIZE];
+} __packed;
+
+
+#define USM_DATA_CMD_READ				0x0001230E
+struct usm_stream_cmd_read {
+	struct apr_hdr  hdr;
+	u32                 buf_add;
+	u32                 buf_size;
+	u32                 uid;
+	u32                 counter;
+} __packed;
+
+#define USM_DATA_EVENT_READ_DONE			0x0001230F
+struct usm_data_event_read_done {
+	u32            status;
+	u32            buffer_add;
+	u32            enc_frame_size;
+	u32            offset;
+	u32            msw_ts;
+	u32            lsw_ts;
+	u32            flags;
+	u32            num_frames;
+	u32            id;
+} __packed;
+
+#define USM_DATA_CMD_WRITE				0x00011273
+struct usm_stream_cmd_write {
+	struct apr_hdr hdr;
+	u32 buf_add;
+	u32 buf_size;
+	u32 uid;
+	u32 msw_ts;
+	u32 lsw_ts;
+	u32 flags;
+} __packed;
+
+#define USM_DATA_EVENT_WRITE_DONE			0x00011274
+struct usm_data_event_write_done {
+	u32 buf_add;
+	u32 status;
+} __packed;
+
+#endif /* __APR_US_H__ */
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
new file mode 100644
index 0000000..346dc0d
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
@@ -0,0 +1,185 @@
+/* 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 __USF_H__
+#define __USF_H__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define USF_IOCTL_MAGIC 'U'
+
+#define US_SET_TX_INFO   _IOW(USF_IOCTL_MAGIC, 0, \
+				struct us_tx_info_type)
+#define US_START_TX      _IO(USF_IOCTL_MAGIC, 1)
+#define US_GET_TX_UPDATE _IOWR(USF_IOCTL_MAGIC, 2, \
+				struct us_tx_update_info_type)
+#define US_SET_RX_INFO   _IOW(USF_IOCTL_MAGIC, 3, \
+				struct us_rx_info_type)
+#define US_SET_RX_UPDATE _IOWR(USF_IOCTL_MAGIC, 4, \
+				struct us_rx_update_info_type)
+#define US_START_RX      _IO(USF_IOCTL_MAGIC, 5)
+
+#define US_STOP_TX      _IO(USF_IOCTL_MAGIC, 6)
+#define US_STOP_RX      _IO(USF_IOCTL_MAGIC, 7)
+
+
+/* Encoder (TX), decoder (RX) supported US data formats */
+#define USF_POINT_EPOS_FORMAT	0
+#define USF_RAW_FORMAT		    1
+
+/* Types of events, produced by the calculators */
+#define USF_TSC_EVENT 1
+#define USF_MOUSE_EVENT 2
+#define USF_KEYBOARD_EVENT 4
+#define USF_ALL_EVENTS (USF_TSC_EVENT | USF_MOUSE_EVENT | USF_KEYBOARD_EVENT)
+
+/* Max size of the client name */
+#define USF_MAX_CLIENT_NAME_SIZE	20
+/* Info structure common for TX and RX */
+struct us_xx_info_type {
+/* Input:  general info */
+/* Name of the client - event calculator */
+	const char *client_name;
+/* Selected device identification, accepted in the kernel's CAD */
+	uint32_t dev_id;
+/* 0 - point_epos type; (e.g. 1 - gr_mmrd) */
+	uint32_t stream_format;
+/* Required sample rate in Hz */
+	uint32_t sample_rate;
+/* Size of a buffer (bytes) for US data transfer between the module and USF */
+	uint32_t buf_size;
+/* Number of the buffers for the US data transfer */
+	uint16_t buf_num;
+/* Number of the microphones (TX) or speakers(RX) */
+	uint16_t port_cnt;
+/* Microphones(TX) or speakers(RX) indexes in their enumeration */
+	uint8_t  port_id[4];
+/* Bits per sample 16 or 32 */
+	uint16_t bits_per_sample;
+/* Input:  Transparent info for encoder in the LPASS */
+/* Parameters data size in bytes */
+	uint16_t params_data_size;
+/* Pointer to the parameters */
+	uint8_t *params_data;
+};
+
+struct us_input_info_type {
+	/* Touch screen dimensions: min & max;for input module */
+	int tsc_x_dim[2];
+	int tsc_y_dim[2];
+    /* Touch screen fuzz; for input module */
+	int tsc_x_fuzz;
+	int tsc_y_fuzz;
+	/* Touch screen pressure limits: min & max; for input module */
+	int tsc_pressure[2];
+	/* Bitmap of types of events (USF_X_EVENT), produced by calculator */
+	uint16_t event_types;
+};
+
+struct us_tx_info_type {
+	/* Common info */
+	struct us_xx_info_type us_xx_info;
+	/* Info specific for TX*/
+	struct us_input_info_type input_info;
+};
+
+struct us_rx_info_type {
+	/* Common info */
+	struct us_xx_info_type us_xx_info;
+	/* Info specific for RX*/
+};
+
+
+#define	USF_PIX_COORDINATE  0 /* unit is pixel */
+#define	USF_CMM_COORDINATE  1 /* unit is 0.01 mm */
+struct point_event_type {
+/* Pen coordinates (x, y) in units, defined by <coordinates_type>  */
+	int coordinates[2];
+/* {x;y}  in degrees [-90; 90] */
+	uint32_t inclinations[2];
+/* [0-1023] (10bits); 0 - pen up */
+	uint32_t pressure;
+/* 0 - mapped in the display pixel. 1 - raw in 0.01 mm (only for log); */
+	uint8_t coordinates_type;
+};
+
+/* Mouse buttons, supported by USF */
+#define USF_BUTTON_LEFT_MASK   1
+#define USF_BUTTON_MIDDLE_MASK 2
+#define USF_BUTTON_RIGHT_MASK  4
+struct mouse_event_type {
+/* The mouse relative movement (dX, dY, dZ) */
+	int rels[3];
+/* Bitmap of mouse buttons states: 1 - down, 0 - up; */
+	uint16_t buttons_states;
+};
+
+struct key_event_type {
+/*  Calculated MS key- see input.h. */
+	uint32_t key;
+/* Keyboard's key state: 1 - down, 0 - up; */
+	uint8_t key_state;
+};
+
+struct usf_event_type {
+/* Event sequence number */
+	uint32_t seq_num;
+/* Event generation system time */
+	uint32_t timestamp;
+/* Destination input event type (e.g. touch screen, mouse, key) */
+	uint16_t event_type;
+	union {
+		struct point_event_type point_event;
+		struct mouse_event_type mouse_event;
+		struct key_event_type   key_event;
+	} event_data;
+};
+
+struct us_tx_update_info_type {
+/* Input  general: */
+/* Number of calculated events */
+	uint16_t event_counter;
+/* Calculated events or NULL */
+	struct usf_event_type *event;
+/* Pointer (read index) to the end of available region */
+/* in the shared US data memory */
+	uint32_t free_region;
+/* Input  transparent data: */
+/* Parameters size */
+	uint16_t params_data_size;
+/* Pointer to the parameters */
+	uint8_t *params_data;
+/* Output parameters: */
+/* Pointer (write index) to the end of ready US data region */
+/* in the shared memory */
+	uint32_t ready_region;
+};
+
+struct us_rx_update_info_type {
+/* Input  general: */
+/* Pointer (write index) to the end of ready US data region */
+/* in the shared memory */
+	uint32_t ready_region;
+/* Input  transparent data: */
+/* Parameters size */
+	uint16_t params_data_size;
+/* pPointer to the parameters */
+	uint8_t *params_data;
+/* Output parameters: */
+/* Pointer (read index) to the end of available region */
+/* in the shared US data memory */
+	uint32_t free_region;
+};
+
+#endif /* __USF_H__ */
diff --git a/arch/arm/mach-msm/include/mach/rpm-8960.h b/arch/arm/mach-msm/include/mach/rpm-8960.h
index d5ebba0..11862ea 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8960.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8960.h
@@ -305,14 +305,14 @@
 	MSM_RPMRS_VDD_MEM_RET_LOW	=  750000,
 	MSM_RPMRS_VDD_MEM_RET_HIGH	=  750000,
 	MSM_RPMRS_VDD_MEM_ACTIVE	= 1050000,
-	MSM_RPMRS_VDD_MEM_MAX		= 1250000,
+	MSM_RPMRS_VDD_MEM_MAX		= 1150000,
 };
 
 enum {
 	MSM_RPMRS_VDD_DIG_RET_LOW	=  500000,
 	MSM_RPMRS_VDD_DIG_RET_HIGH	=  750000,
-	MSM_RPMRS_VDD_DIG_ACTIVE	= 1050000,
-	MSM_RPMRS_VDD_DIG_MAX		= 1250000,
+	MSM_RPMRS_VDD_DIG_ACTIVE	=  950000,
+	MSM_RPMRS_VDD_DIG_MAX		= 1150000,
 };
 
 /* RPM status ID enum */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index dbde068..fba6efe2 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -16,6 +16,9 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/of_fdt.h>
+#include <linux/of.h>
 
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
@@ -28,6 +31,16 @@
 #define SOCINFO_VERSION_MAJOR(ver) ((ver & 0xffff0000) >> 16)
 #define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
 
+#ifdef CONFIG_OF
+#define early_machine_is_copper()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmcopper")
+#define machine_is_copper()		\
+	of_machine_is_compatible("qcom,msmcopper")
+#else
+#define early_machine_is_copper()	0
+#define machine_is_copper()		0
+#endif
+
 enum msm_cpu {
 	MSM_CPU_UNKNOWN = 0,
 	MSM_CPU_7X01,
@@ -47,6 +60,7 @@
 	MSM_CPU_8930,
 	MSM_CPU_7X27AA,
 	MSM_CPU_9615,
+	MSM_CPU_COPPER,
 };
 
 enum msm_cpu socinfo_get_msm_cpu(void);
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index f6cba0d..34729b3 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -65,6 +65,8 @@
 #define SPS_BAM_OPT_IRQ_DISABLED    (1UL << 1)
 /* BAM peripheral is a BAM-DMA */
 #define SPS_BAM_OPT_BAMDMA          (1UL << 2)
+/* BAM IRQ is registered for apps wakeup */
+#define SPS_BAM_OPT_IRQ_WAKEUP      (1UL << 3)
 
 /* BAM device management flags */
 
@@ -1133,4 +1135,36 @@
 		   struct sps_timer_ctrl *timer_ctrl,
 		   struct sps_timer_result *timer_result);
 
+/**
+ * Find the handle of a BAM device based on the physical address
+ *
+ * This function finds a BAM device in the BAM registration list that
+ * matches the specified physical address, and returns its handle.
+ *
+ * @phys_addr - physical address of the BAM
+ *
+ * @h - device handle of the BAM
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_phy2h(u32 phys_addr, u32 *handle);
+
+/**
+ * Setup desc/data FIFO for bam-to-bam connection
+ *
+ * @mem_buffer - Pointer to struct for allocated memory properties.
+ *
+ * @addr - address of FIFO
+ *
+ * @size - FIFO size
+ *
+ * @use_offset - use address offset instead of absolute address
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
+		  u32 addr, u32 size, int use_offset);
+
 #endif /* _SPS_H_ */
diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h
index c8513b2..74cbda1 100644
--- a/arch/arm/mach-msm/include/mach/uncompress.h
+++ b/arch/arm/mach-msm/include/mach/uncompress.h
@@ -22,33 +22,30 @@
 
 #include <mach/msm_iomap.h>
 
-bool msm_serial_hsl;
-
 #ifndef CONFIG_DEBUG_ICEDCC
 static void putc(int c)
 {
 #if defined(MSM_DEBUG_UART_PHYS)
 	unsigned long base = MSM_DEBUG_UART_PHYS;
 
-	if (msm_serial_hsl) {
-		/*
-		 * Wait for TX_READY to be set; but skip it if we have a
-		 * TX underrun.
-		 */
-		if (__raw_readl(base + 0x08) & 0x08)
-			while (!(__raw_readl(base + 0x14) & 0x80))
-				cpu_relax();
-
-		__raw_writel(0x300, base + 0x10);
-		__raw_writel(0x1, base + 0x40);
-		__raw_writel(c, base + 0x70);
-
-	} else {
-		/* Wait for TX_READY to be set */
-		while (!(__raw_readl(base + 0x08) & 0x04))
+#ifdef CONFIG_SERIAL_MSM_HSL
+	/*
+	 * Wait for TX_READY to be set; but skip it if we have a
+	 * TX underrun.
+	 */
+	if (__raw_readl(base + 0x08) & 0x08)
+		while (!(__raw_readl(base + 0x14) & 0x80))
 			cpu_relax();
-		__raw_writel(c, base + 0x0c);
-	}
+
+	__raw_writel(0x300, base + 0x10);
+	__raw_writel(0x1, base + 0x40);
+	__raw_writel(c, base + 0x70);
+#else
+	/* Wait for TX_READY to be set */
+	while (!(__raw_readl(base + 0x08) & 0x04))
+		cpu_relax();
+	__raw_writel(c, base + 0x0c);
+#endif
 #endif
 }
 #endif
@@ -57,28 +54,8 @@
 {
 }
 
-#define DEBUG_LL_HS_ENTRY(machine)		\
-	if (machine_is_##machine()) {		\
-		msm_serial_hsl = true;		\
-		break;				\
-	}
-
 static inline void arch_decomp_setup(void)
 {
-	do {
-		DEBUG_LL_HS_ENTRY(msm8x60_fluid);
-		DEBUG_LL_HS_ENTRY(msm8x60_surf);
-		DEBUG_LL_HS_ENTRY(msm8x60_ffa);
-		DEBUG_LL_HS_ENTRY(msm8x60_fusion);
-		DEBUG_LL_HS_ENTRY(msm8x60_fusn_ffa);
-		DEBUG_LL_HS_ENTRY(msm8x60_qrdc);
-		DEBUG_LL_HS_ENTRY(msm8x60_qt);
-		DEBUG_LL_HS_ENTRY(msm8960_cdp);
-		DEBUG_LL_HS_ENTRY(msm8960_mtp);
-		DEBUG_LL_HS_ENTRY(msm8960_fluid);
-		DEBUG_LL_HS_ENTRY(msm8960_apq);
-		DEBUG_LL_HS_ENTRY(msm8960_liquid);
-	} while (0);
 }
 
 static inline void arch_decomp_wdog(void)
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 65f5da0..8a79af7 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -66,7 +66,8 @@
 	MSM_DEVICE(CLK_CTL),
 	MSM_DEVICE(AD5),
 	MSM_DEVICE(MDC),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_DEVICE(DEBUG_UART),
 #endif
 #ifdef CONFIG_CACHE_L2X0
@@ -113,7 +114,8 @@
 	MSM_DEVICE(AD5),
 	MSM_DEVICE(MDC),
 	MSM_DEVICE(TCSR),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_DEVICE(DEBUG_UART),
 #endif
 	{
@@ -151,7 +153,7 @@
 	MSM_DEVICE(TCSR),
 	MSM_DEVICE(IMEM),
 	MSM_DEVICE(HDMI),
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8660_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
 	MSM_DEVICE(SIC_NON_SECURE),
@@ -196,7 +198,7 @@
 		.length =   MSM_SHARED_RAM_SIZE,
 		.type =     MT_DEVICE,
 	},
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8960_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
 	MSM_CHIP_DEVICE(QFPROM, MSM8960),
@@ -235,7 +237,7 @@
 		.length =   MSM_SHARED_RAM_SIZE,
 		.type =     MT_DEVICE,
 	},
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8930_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
 	MSM_CHIP_DEVICE(QFPROM, MSM8930),
@@ -307,7 +309,8 @@
 	MSM_DEVICE(SAW),
 	MSM_DEVICE(GCC),
 	MSM_DEVICE(TCSR),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_DEVICE(DEBUG_UART),
 #endif
 	{
@@ -337,7 +340,8 @@
 	MSM_DEVICE(GRFC),
 	MSM_DEVICE(QFP_FUSE),
 	MSM_DEVICE(HH),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_DEVICE(DEBUG_UART),
 #endif
 	{
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index e874663..16c0790 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -38,6 +38,17 @@
 #define RCP15_PRRR(reg)		MRC(reg, p15, 0, c10, c2, 0)
 #define RCP15_NMRR(reg)		MRC(reg, p15, 0, c10, c2, 1)
 
+/* Sharability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NON_SH		0x0
+#define MSM_IOMMU_ATTR_SH		0x4
+
+/* Cacheability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NONCACHED	0x0
+#define MSM_IOMMU_ATTR_CACHED_WB_WA	0x1
+#define MSM_IOMMU_ATTR_CACHED_WB_NWA	0x2
+#define MSM_IOMMU_ATTR_CACHED_WT	0x3
+
+
 static inline void clean_pte(unsigned long *start, unsigned long *end)
 {
 	dmac_flush_range(start, end);
@@ -407,21 +418,23 @@
 static int __get_pgprot(int prot, int len)
 {
 	unsigned int pgprot;
-	int tex, sh;
+	int tex;
 
-	sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
-	tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
+	if (prot & IOMMU_CACHE)
+		tex = (pgprot_kernel >> 2) & 0x07;
+	else
+		tex = msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED];
 
 	if (tex < 0 || tex > NUM_TEX_CLASS - 1)
 		return 0;
 
 	if (len == SZ_16M || len == SZ_1M) {
-		pgprot = sh ? FL_SHARED : 0;
+		pgprot = FL_SHARED;
 		pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
 		pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
 		pgprot |= tex & 0x04 ? FL_TEX0 : 0;
 	} else	{
-		pgprot = sh ? SL_SHARED : 0;
+		pgprot = SL_SHARED;
 		pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
 		pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
 		pgprot |= tex & 0x04 ? SL_TEX0 : 0;
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index d1dd3ed..1982082 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -24,7 +24,6 @@
 
 #include <mach/iommu_hw-8xxx.h>
 #include <mach/iommu.h>
-#include <mach/clk.h>
 
 struct iommu_ctx_iter_data {
 	/* input */
@@ -164,8 +163,10 @@
 	iommu_clk = clk_get(&pdev->dev, "core_clk");
 
 	if (!IS_ERR(iommu_clk))	{
-		if (clk_get_rate(iommu_clk) == 0)
-			clk_set_min_rate(iommu_clk, 1);
+		if (clk_get_rate(iommu_clk) == 0) {
+			ret = clk_round_rate(iommu_clk, 1);
+			clk_set_rate(iommu_clk, ret);
+		}
 
 		ret = clk_enable(iommu_clk);
 		if (ret) {
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index e849cdb..600a2e9 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -20,6 +20,9 @@
 #include <mach/iommu_domains.h>
 #include <mach/socinfo.h>
 
+/* dummy 4k for overmapping */
+char iommu_dummy[2*PAGE_SIZE-4];
+
 struct msm_iommu_domain {
 	/* iommu domain to map in */
 	struct iommu_domain *domain;
@@ -159,6 +162,41 @@
 	}
 };
 
+int msm_iommu_map_extra(struct iommu_domain *domain,
+				unsigned long start_iova,
+				unsigned long size,
+				int cached)
+{
+	int i, ret;
+	unsigned long temp_iova;
+
+	for (i = size, temp_iova = start_iova; i > 0; i -= SZ_4K,
+						temp_iova += SZ_4K) {
+		ret = iommu_map(domain, temp_iova,
+				PFN_ALIGN(virt_to_phys(iommu_dummy)),
+				get_order(SZ_4K),
+				0);
+
+		if (ret) {
+			pr_err("%s: could not map %lx to dummy page in domain"
+				" %p\n",
+				__func__, temp_iova, domain);
+			goto out;
+		}
+	}
+
+	return 0;
+
+out:
+
+	for ( ; i < size; i += SZ_4K, temp_iova -= SZ_4K)
+		iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+	return -EINVAL;
+
+}
+
+
 struct iommu_domain *msm_get_iommu_domain(int domain_num)
 {
 	if (domain_num >= 0 && domain_num < MAX_DOMAINS)
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 467c2c2..093d044 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -276,8 +276,6 @@
 	lock_sock(sk);
 
 	ret = msm_ipc_router_register_server(port_ptr, &addr->address);
-	if (!ret)
-		sk->sk_rcvtimeo = DEFAULT_RCV_TIMEO;
 
 	release_sock(sk);
 	return ret;
diff --git a/arch/arm/mach-msm/lpass-8960.c b/arch/arm/mach-msm/lpass-8960.c
index 0f2559e..294e9c0 100644
--- a/arch/arm/mach-msm/lpass-8960.c
+++ b/arch/arm/mach-msm/lpass-8960.c
@@ -178,7 +178,7 @@
 		ret = -ENOMEM;
 		goto out;
 	}
-	pr_info("%s: 8960 lpass SSR driver init'ed.\n", __func__);
+	pr_info("%s: lpass SSR driver init'ed.\n", __func__);
 out:
 	return ret;
 }
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index b9c963f..00f315d 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -219,8 +219,18 @@
 static unsigned long stable_size(struct membank *mb,
 	unsigned long unstable_limit)
 {
-	if (!unstable_limit || mb->start + mb->size <= unstable_limit)
+	unsigned long upper_limit = mb->start + mb->size;
+
+	if (!unstable_limit)
 		return mb->size;
+
+	/* Check for 32 bit roll-over */
+	if (upper_limit >= mb->start) {
+		/* If we didn't roll over we can safely make the check below */
+		if (upper_limit <= unstable_limit)
+			return mb->size;
+	}
+
 	if (mb->start >= unstable_limit)
 		return 0;
 	return unstable_limit - mb->start;
@@ -296,7 +306,7 @@
 			size = stable_size(mb,
 				reserve_info->low_unstable_address);
 			if (size >= mt->size) {
-				mt->start = mb->start + size - mt->size;
+				mt->start = mb->start + (size - mt->size);
 				ret = memblock_remove(mt->start, mt->size);
 				BUG_ON(ret);
 				break;
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index 7bcd844..f0aa13c 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -26,7 +26,6 @@
 #include <mach/peripheral-loader.h>
 #include <mach/subsystem_restart.h>
 #include <mach/subsystem_notif.h>
-#include <mach/irqs-8960.h>
 #include <mach/socinfo.h>
 
 #include "smd_private.h"
@@ -227,7 +226,7 @@
 {
 	int ret;
 
-	if (!cpu_is_msm8960() && !cpu_is_msm8930())
+	if (!cpu_is_msm8960() && !cpu_is_msm8930() && !cpu_is_msm9615())
 		return -ENODEV;
 
 	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
@@ -266,7 +265,7 @@
 
 	ret = modem_debugfs_init();
 
-	pr_info("%s: 8960 modem fatal driver init'ed.\n", __func__);
+	pr_info("%s: modem fatal driver init'ed.\n", __func__);
 out:
 	return ret;
 }
diff --git a/arch/arm/mach-msm/mpm.c b/arch/arm/mach-msm/mpm.c
index 040e126..70ee39b 100644
--- a/arch/arm/mach-msm/mpm.c
+++ b/arch/arm/mach-msm/mpm.c
@@ -260,6 +260,9 @@
 		uint32_t index = MSM_MPM_IRQ_INDEX(mpm_irq);
 		uint32_t mask = MSM_MPM_IRQ_MASK(mpm_irq);
 
+		if (index >= MSM_MPM_REG_WIDTH)
+			return -EFAULT;
+
 		if (flow_type & IRQ_TYPE_EDGE_BOTH)
 			msm_mpm_detect_ctl[index] |= mask;
 		else
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index c8600d5..c1155c9 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -4,4 +4,5 @@
 obj-y += msm_bus_core.o msm_bus_fabric.o msm_bus_config.o msm_bus_arb.o msm_bus_rpm.o
 obj-$(CONFIG_ARCH_MSM8X60) += msm_bus_board_8660.o
 obj-$(CONFIG_ARCH_MSM8960) += msm_bus_board_8960.o
+obj-$(CONFIG_ARCH_MSM9615) += msm_bus_board_9615.o
 obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
index ff2876c..d284b70 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
@@ -22,7 +22,7 @@
 #include "msm_bus_core.h"
 
 #define NMASTERS 39
-#define NSLAVES 67
+#define NSLAVES 68
 #define NFAB_8660 5
 
 enum msm_bus_fabric_tiered_slave_type {
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
new file mode 100644
index 0000000..a941a89
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
@@ -0,0 +1,311 @@
+/* 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/rpm.h>
+#include "msm_bus_core.h"
+
+#define NMASTERS 14
+#define NSLAVES 12
+#define NFAB_9615 2
+
+enum msm_bus_fabric_tiered_slave_type {
+	MSM_BUS_TIERED_SLAVE_EBI1_CH0 = 1,
+};
+
+enum msm_bus_9615_master_ports_type {
+	MSM_BUS_MASTER_PORT_SPS = 0,
+	MSM_BUS_MASTER_PORT_APSS_PROC,
+	MSM_BUS_MASTER_PORT_ADM_PORT0,
+	MSM_BUS_MASTER_PORT_ADM_PORT1,
+	MSM_BUS_MASTER_PORT_LPASS_PROC,
+	MSM_BUS_MASTER_PORT_MSS,
+	MSM_BUS_MASTER_PORT_MSS_SW_PROC,
+	MSM_BUS_MASTER_PORT_MSS_FW_PROC,
+	MSM_BUS_MASTER_PORT_LPASS,
+	MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,
+	MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,
+};
+
+enum msm_bus_9615_slave_ports_type {
+	MSM_BUS_SLAVE_PORT_SPS = 0,
+	MSM_BUS_SLAVE_PORT_EBI1_CH0,
+	MSM_BUS_SLAVE_PORT_APSS_L2,
+	MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,
+	MSM_BUS_SLAVE_PORT_CORESIGHT,
+	MSM_BUS_SLAVE_PORT_APSS,
+	MSM_BUS_SLAVE_PORT_MSS,
+	MSM_BUS_SLAVE_PORT_LPASS,
+	MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,
+	MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,
+};
+
+static int tier2[] = {MSM_BUS_BW_TIER2,};
+static uint32_t master_iids[NMASTERS];
+static uint32_t slave_iids[NSLAVES];
+
+static int sport_ebi1_ch0[] = {MSM_BUS_SLAVE_PORT_EBI1_CH0,};
+static int sport_apss_l2[] = {MSM_BUS_SLAVE_PORT_APSS_L2,};
+
+static int tiered_slave_ebi1_ch0[] = {MSM_BUS_TIERED_SLAVE_EBI1_CH0,};
+
+static int mport_sps[] = {MSM_BUS_MASTER_PORT_SPS,};
+static int mport_apss_proc[] = {MSM_BUS_MASTER_PORT_APSS_PROC,};
+static int mport_adm_port0[] = {MSM_BUS_MASTER_PORT_ADM_PORT0,};
+static int mport_adm_port1[] = {MSM_BUS_MASTER_PORT_ADM_PORT1,};
+static int mport_mss[] = {MSM_BUS_MASTER_PORT_MSS,};
+static int mport_lpass_proc[] = {MSM_BUS_MASTER_PORT_LPASS_PROC,};
+static int mport_mss_sw_proc[] = {MSM_BUS_MASTER_PORT_MSS_SW_PROC,};
+static int mport_mss_fw_proc[] = {MSM_BUS_MASTER_PORT_MSS_FW_PROC,};
+static int mport_lpass[] = {MSM_BUS_MASTER_PORT_LPASS,};
+static int system_mport_adm_ahb_ci[] = {MSM_BUS_SYSTEM_MASTER_PORT_ADM_AHB_CI,};
+static int mport_system_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_SYSTEM_FPB,};
+static int system_mport_cpss_fpb[] = {MSM_BUS_SYSTEM_MASTER_PORT_CPSS_FPB,};
+
+static int system_sport_system_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_SYSTEM_FPB,};
+static int system_sport_cpss_fpb[] = {MSM_BUS_SYSTEM_SLAVE_PORT_CPSS_FPB,};
+static int sport_sps[] = {MSM_BUS_SLAVE_PORT_SPS,};
+static int sport_system_imem[] = {MSM_BUS_SLAVE_PORT_SYSTEM_IMEM,};
+static int sport_coresight[] = {MSM_BUS_SLAVE_PORT_CORESIGHT,};
+static int sport_apss[] = {MSM_BUS_SLAVE_PORT_APSS,};
+static int sport_mss[] = {MSM_BUS_SLAVE_PORT_MSS,};
+static int sport_lpass[] = {MSM_BUS_SLAVE_PORT_LPASS,};
+
+static struct msm_bus_node_info system_fabric_info[]  = {
+	{
+		.id = MSM_BUS_MASTER_SPS,
+		.masterp = mport_sps,
+		.num_mports = ARRAY_SIZE(mport_sps),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM_PORT0,
+		.masterp = mport_adm_port0,
+		.num_mports = ARRAY_SIZE(mport_adm_port0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM_PORT1,
+		.masterp = mport_adm_port1,
+		.num_mports = ARRAY_SIZE(mport_adm_port1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_LPASS_PROC,
+		.masterp = mport_lpass_proc,
+		.num_mports = ARRAY_SIZE(mport_lpass_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS,
+		.masterp = mport_mss,
+		.num_mports = ARRAY_SIZE(mport_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_AMPSS_M0,
+		.masterp = mport_apss_proc,
+		.num_mports = ARRAY_SIZE(mport_apss_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_SW_PROC,
+		.masterp = mport_mss_sw_proc,
+		.num_mports = ARRAY_SIZE(mport_mss_sw_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_FW_PROC,
+		.masterp = mport_mss_fw_proc,
+		.num_mports = ARRAY_SIZE(mport_mss_fw_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_LPASS,
+		.masterp = mport_lpass,
+		.num_mports = ARRAY_SIZE(mport_lpass),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_MASTER_ADM0_CI,
+		.masterp = system_mport_adm_ahb_ci,
+		.num_mports = ARRAY_SIZE(system_mport_adm_ahb_ci),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+	},
+	{
+		.id = MSM_BUS_FAB_SYSTEM_FPB,
+		.gateway = 1,
+		.slavep = system_sport_system_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_system_fpb),
+		.masterp = mport_system_fpb,
+		.num_mports = ARRAY_SIZE(mport_system_fpb),
+		.buswidth = 4,
+	},
+	{
+		.id = MSM_BUS_FAB_CPSS_FPB,
+		.gateway = 1,
+		.slavep = system_sport_cpss_fpb,
+		.num_sports = ARRAY_SIZE(system_sport_cpss_fpb),
+		.masterp = system_mport_cpss_fpb,
+		.num_mports = ARRAY_SIZE(system_mport_cpss_fpb),
+		.buswidth = 4,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SPS,
+		.slavep = sport_sps,
+		.num_sports = ARRAY_SIZE(sport_sps),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI_CH0,
+		.slavep = sport_ebi1_ch0,
+		.num_sports = ARRAY_SIZE(sport_ebi1_ch0),
+		.tier = tiered_slave_ebi1_ch0,
+		.num_tiers = ARRAY_SIZE(tiered_slave_ebi1_ch0),
+		.buswidth = 8,
+		.slaveclk[DUAL_CTX] = "ebi1_msmbus_clk",
+		.slaveclk[ACTIVE_CTX] = "ebi1_a_clk",
+	},
+	{
+		.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
+		.slavep = sport_system_imem,
+		.num_sports = ARRAY_SIZE(sport_system_imem),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_CORESIGHT,
+		.slavep = sport_coresight,
+		.num_sports = ARRAY_SIZE(sport_coresight),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_AMPSS,
+		.slavep = sport_apss,
+		.num_sports = ARRAY_SIZE(sport_apss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_AMPSS_L2,
+		.slavep = sport_apss_l2,
+		.num_sports = ARRAY_SIZE(sport_apss_l2),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MSS,
+		.slavep = sport_mss,
+		.num_sports = ARRAY_SIZE(sport_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+	{
+		.id = MSM_BUS_SLAVE_LPASS,
+		.slavep = sport_lpass,
+		.num_sports = ARRAY_SIZE(sport_lpass),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+	},
+};
+
+static void msm_bus_board_assign_iids(struct msm_bus_fabric_registration
+	*fabreg, int fabid)
+{
+	int i;
+	for (i = 0; i < fabreg->len; i++) {
+		if (!fabreg->info[i].gateway) {
+			fabreg->info[i].priv_id = fabid + fabreg->info[i].id;
+			if (fabreg->info[i].id < SLAVE_ID_KEY)
+				master_iids[fabreg->info[i].id] =
+					fabreg->info[i].priv_id;
+			else
+				slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)]
+					= fabreg->info[i].priv_id;
+		} else
+			fabreg->info[i].priv_id = fabreg->info[i].id;
+	}
+}
+
+static int msm_bus_board_9615_get_iid(int id)
+{
+	if ((id < SLAVE_ID_KEY && id >= NMASTERS) ||
+		id >= (SLAVE_ID_KEY + NSLAVES)) {
+		MSM_BUS_ERR("Cannot get iid. Invalid id %d passed\n", id);
+		return -EINVAL;
+	}
+
+	return ((id < SLAVE_ID_KEY) ? master_iids[id] : slave_iids[id -
+		SLAVE_ID_KEY]);
+}
+
+static struct msm_bus_board_algorithm msm_bus_board_algo = {
+	.board_nfab = NFAB_9615,
+	.get_iid = msm_bus_board_9615_get_iid,
+	.assign_iids = msm_bus_board_assign_iids,
+};
+
+struct msm_bus_fabric_registration msm_bus_9615_sys_fabric_pdata = {
+	.id = MSM_BUS_FAB_SYSTEM,
+	.name = "msm_sys_fab",
+	system_fabric_info,
+	ARRAY_SIZE(system_fabric_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "sfab_clk",
+	.fabclk[ACTIVE_CTX] = "sfab_a_clk",
+	.haltid = MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+	.offset = MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
+	.nmasters = 12,
+	.nslaves = 10,
+	.ntieredslaves = 1,
+	.board_algo = &msm_bus_board_algo,
+};
+
+struct msm_bus_fabric_registration msm_bus_9615_def_fab_pdata = {
+	.id = MSM_BUS_FAB_DEFAULT,
+	.name = "msm_def_fab",
+	.ahb = 1,
+	.nmasters = 0,
+	.nslaves = 0,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+};
+
+int msm_bus_board_rpm_get_il_ids(uint16_t id[])
+{
+	return -ENXIO;
+}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 1747425..fd82111 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/radix-tree.h>
-#include <mach/clk.h>
 #include <mach/board.h>
 #include <mach/rpm.h>
 #include "msm_bus_core.h"
@@ -344,7 +343,7 @@
 	int i, status = 0;
 	for (i = 0; i < NUM_CTX; i++)
 		if (info->nodeclk[i].dirty) {
-			status = clk_set_min_rate(info->nodeclk[i].clk, info->
+			status = clk_set_rate(info->nodeclk[i].clk, info->
 				nodeclk[i].rate);
 			if (enable && !(info->nodeclk[i].enable)) {
 				clk_enable(info->nodeclk[i].clk);
@@ -359,7 +358,7 @@
 		}
 
 	if (info->memclk.dirty) {
-		status = clk_set_min_rate(info->memclk.clk, info->memclk.rate);
+		status = clk_set_rate(info->memclk.clk, info->memclk.rate);
 		if (enable && !(info->memclk.enable)) {
 			clk_enable(info->memclk.clk);
 			info->memclk.dirty = false;
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index 425000d..9daaaba 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -160,20 +160,20 @@
 
 	for (i = 0; i < attr_count - 1 ; i++) {
 		if (!attribs[i])
-			goto rel;
+			goto rel2;
 	}
 
 	rq_info.attr_group = kzalloc(sizeof(struct attribute_group),
 						GFP_KERNEL);
 	if (!rq_info.attr_group)
-		goto rel;
+		goto rel3;
 	rq_info.attr_group->attrs = attribs;
 
 	/* Create /sys/devices/system/cpu/cpu0/rq-stats/... */
 	rq_info.kobj = kobject_create_and_add("rq-stats",
 			&get_cpu_sysdev(0)->kobj);
 	if (!rq_info.kobj)
-		goto rel;
+		goto rel3;
 
 	err = sysfs_create_group(rq_info.kobj, rq_info.attr_group);
 	if (err)
@@ -184,12 +184,14 @@
 	if (!err)
 		return err;
 
-rel:
-	for (i = 0; i < attr_count - 1 ; i++)
-		kfree(attribs[i]);
-	kfree(attribs);
+rel3:
 	kfree(rq_info.attr_group);
 	kfree(rq_info.kobj);
+rel2:
+	for (i = 0; i < attr_count - 1; i++)
+		kfree(attribs[i]);
+rel:
+	kfree(attribs);
 
 	return -ENOMEM;
 }
diff --git a/arch/arm/mach-msm/nand_partitions.c b/arch/arm/mach-msm/nand_partitions.c
index bd0e474..499ad99 100644
--- a/arch/arm/mach-msm/nand_partitions.c
+++ b/arch/arm/mach-msm/nand_partitions.c
@@ -4,7 +4,7 @@
  * bootloader.
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009,2011 Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -48,7 +48,7 @@
 	__u32 flags;
 };
 
-#define MSM_MAX_PARTITIONS 8
+#define MSM_MAX_PARTITIONS 18
 
 static struct mtd_partition msm_nand_partitions[MSM_MAX_PARTITIONS];
 static char msm_nand_names[MSM_MAX_PARTITIONS * 16];
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index ad6da6a..8db21f9 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -384,6 +384,9 @@
 	else
 		i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
 
+	if (i >= CONFIG_MSM_IDLE_STATS_BUCKET_COUNT)
+		i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
+
 	stats[id].bucket[i]++;
 
 	if (t < stats[id].min_time[i] || !stats[id].max_time[i])
@@ -1111,6 +1114,7 @@
 		return 0;
 	}
 	etm_restore_reg_check();
+	msm_restore_jtag_debug();
 #ifdef CONFIG_VFP
 	vfp_reinit();
 #endif
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index d392cce..33c5a53 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -55,7 +55,6 @@
 
 #include <linux/io.h>
 #include <mach/msm_iomap.h>
-#include <mach/clk.h>
 #include <mach/msm_adsp.h>
 #include "adsp.h"
 
@@ -1018,7 +1017,7 @@
 int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate)
 {
 	if (module->clk && clk_rate)
-		return clk_set_min_rate(module->clk, clk_rate);
+		return clk_set_rate(module->clk, clk_rate);
 
 	return -EINVAL;
 }
@@ -1196,8 +1195,7 @@
 		else
 			mod->clk = NULL;
 		if (mod->clk && adsp_info.module[i].clk_rate)
-			clk_set_min_rate(mod->clk,
-						adsp_info.module[i].clk_rate);
+			clk_set_rate(mod->clk, adsp_info.module[i].clk_rate);
 		mod->verify_cmd = adsp_info.module[i].verify_cmd;
 		mod->patch_event = adsp_info.module[i].patch_event;
 		INIT_HLIST_HEAD(&mod->pmem_regions);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp.c b/arch/arm/mach-msm/qdsp5v2/adsp.c
index 6d4d074..b7b56c8 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp.c
@@ -34,7 +34,6 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <mach/msm_iomap.h>
-#include <mach/clk.h>
 #include <mach/msm_adsp.h>
 #include "adsp.h"
 #include <mach/debug_mm.h>
@@ -851,7 +850,7 @@
 int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate)
 {
 	if (module->clk && clk_rate)
-		return clk_set_min_rate(module->clk, clk_rate);
+		return clk_set_rate(module->clk, clk_rate);
 
 	return -EINVAL;
 }
@@ -1015,8 +1014,7 @@
 		else
 			mod->clk = NULL;
 		if (mod->clk && adsp_info.module[i].clk_rate)
-			clk_set_min_rate(mod->clk,
-						adsp_info.module[i].clk_rate);
+			clk_set_rate(mod->clk, adsp_info.module[i].clk_rate);
 		mod->verify_cmd = adsp_info.module[i].verify_cmd;
 		mod->patch_event = adsp_info.module[i].patch_event;
 		INIT_HLIST_HEAD(&mod->pmem_regions);
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 5e88927..7759c74 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -16,3 +16,4 @@
 obj-y += audio_acdb.o
 obj-y += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
 obj-y += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
+obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index c4eb205..13d92d1 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -191,6 +191,7 @@
 		if (svc == APR_SVC_AFE || svc == APR_SVC_ASM ||
 			svc == APR_SVC_VSM || svc == APR_SVC_VPM ||
 			svc == APR_SVC_ADM || svc == APR_SVC_ADSP_CORE ||
+			svc == APR_SVC_USM ||
 			svc == APR_SVC_TEST_CLIENT || svc == APR_SVC_ADSP_MVM ||
 			svc == APR_SVC_ADSP_CVS || svc == APR_SVC_ADSP_CVP)
 			clnt = APR_CLIENT_AUDIO;
@@ -265,23 +266,23 @@
 	if ((dest_id == APR_DEST_QDSP6) &&
 				(atomic_read(&dsp_state) == 0)) {
 		pr_info("%s: Wait for Lpass to bootup\n", __func__);
-		rc = wait_event_interruptible(dsp_wait,
-				(atomic_read(&dsp_state) == 1));
-		if (rc < 0) {
+		rc = wait_event_interruptible_timeout(dsp_wait,
+				(atomic_read(&dsp_state) == 1), (1 * HZ));
+		if (rc == 0) {
 			pr_err("%s: DSP is not Up\n", __func__);
 			return NULL;
 		}
-		pr_debug("%s: Lpass Up\n", __func__);
+		pr_info("%s: Lpass Up\n", __func__);
 	} else if ((dest_id == APR_DEST_MODEM) &&
 					(atomic_read(&modem_state) == 0)) {
 		pr_info("%s: Wait for modem to bootup\n", __func__);
-		rc = wait_event_interruptible(modem_wait,
-			(atomic_read(&modem_state) == 1));
-		if (rc < 0) {
+		rc = wait_event_interruptible_timeout(modem_wait,
+			(atomic_read(&modem_state) == 1), (1 * HZ));
+		if (rc == 0) {
 			pr_err("%s: Modem is not Up\n", __func__);
 			return NULL;
 		}
-		pr_debug("%s: modem Up\n", __func__);
+		pr_info("%s: modem Up\n", __func__);
 	}
 
 	if (!strcmp(svc_name, "AFE")) {
@@ -355,6 +356,10 @@
 		client_id = APR_CLIENT_VOICE;
 		svc_idx = 6;
 		svc_id = APR_SVC_SRD;
+	} else if (!strncmp(svc_name, "USM", 3)) {
+		client_id = APR_CLIENT_AUDIO;
+		svc_idx = 8;
+		svc_id = APR_SVC_USM;
 	} else {
 		pr_err("APR: Wrong svc name\n");
 		goto done;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index a1b1070..c1b5e8b 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -1009,8 +1009,8 @@
 			/* EOS buffer handled in driver */
 			list_add_tail(&buf_node->list, &audio->out_queue);
 			spin_unlock_irqrestore(&audio->dsp_lock, flags);
-		}
-		if (buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOS_SET) {
+		} else if (buf_node->meta_info.meta_in.nflags
+				   & AUDIO_DEC_EOS_SET) {
 			if (!audio->wflush) {
 				pr_debug("%s[%p]:Send EOS cmd at i/p\n",
 					__func__, audio);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
index 37cbfac..98d1b30 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
@@ -109,7 +109,8 @@
 			rc = -EINVAL;
 			break;
 		}
-		if (wmapro_config->validbitspersample == 16) {
+		if ((wmapro_config->validbitspersample == 16) ||
+			(wmapro_config->validbitspersample == 24)) {
 			wmapro_cfg.valid_bits_per_sample =
 				wmapro_config->validbitspersample;
 		} else {
diff --git a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
index 28e2962..16258eb 100644
--- a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
@@ -74,8 +74,6 @@
 	pending = (intrsrc
 		   & (UNDER_CH(dma_ch) | PER_CH(dma_ch) | ERR_CH(dma_ch)));
 
-	pr_debug("pending = 0x%08x\n", pending);
-
 	if (pending & UNDER_CH(dma_ch))
 		pr_err("under run\n");
 	if (pending & ERR_CH(dma_ch))
@@ -104,10 +102,9 @@
 
 	dai_start_hdmi(lpa_if->dma_ch);
 
-	mb();
-
 	hdmi_audio_enable(1, HDMI_AUDIO_FIFO_WATER_MARK);
-	mb();
+
+	hdmi_audio_packet_enable(1);
 	return 0;
 }
 
@@ -121,7 +118,7 @@
 	dma_params.period_size = lpa_if->dma_period_sz;
 	dma_params.channels = 2;
 
-	lpa_if->dma_ch = 0;
+	lpa_if->dma_ch = 4;
 	dai_set_params(lpa_if->dma_ch, &dma_params);
 
 	register_dma_irq_handler(lpa_if->dma_ch, lpa_if_irq, (void *)lpa_if);
@@ -228,8 +225,11 @@
 
 	file->private_data = lpa_if_ptr;
 	dma_buf_index = 0;
+	lpa_if_ptr->cpu_buf = 0;
+	lpa_if_ptr->dma_buf = 0;
 
 	core_req_bus_bandwith(AUDIO_IF_BUS_ID, 100000, 0);
+	mb();
 
 	return 0;
 }
@@ -242,9 +242,6 @@
 	const char __user *start = buf;
 	int xfer, rc;
 
-	pr_debug("count %u cpu_buf %d dma_buf %d\n",
-		(unsigned int)count, lpa_if->cpu_buf, lpa_if->dma_buf);
-
 	mutex_lock(&lpa_if->lock);
 
 	if (dma_buf_index < 2) {
@@ -257,6 +254,7 @@
 			goto end;
 
 		}
+		mb();
 		pr_debug("prefill: count %u  audio_buf[%u].size %u\n",
 			 count, dma_buf_index, ab->size);
 
@@ -313,15 +311,20 @@
 static int lpa_if_release(struct inode *inode, struct file *file)
 {
 	struct lpa_if *lpa_if = file->private_data;
-	hdmi_audio_enable(0, HDMI_AUDIO_FIFO_WATER_MARK);
 
-	smp_mb();
+	hdmi_audio_packet_enable(0);
+
+	wait_for_dma_cnt_stop(lpa_if->dma_ch);
+
+	hdmi_audio_enable(0, HDMI_AUDIO_FIFO_WATER_MARK);
 
 	if (lpa_if->config) {
 		unregister_dma_irq_handler(lpa_if->dma_ch);
 		dai_stop_hdmi(lpa_if->dma_ch);
 		lpa_if->config = 0;
 	}
+	core_req_bus_bandwith(AUDIO_IF_BUS_ID, 0, 0);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index 1ab615a..058e281 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.c
@@ -2499,17 +2499,6 @@
 
 	pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port);
 
-	v = voice_get_session(data->dest_port);
-	if (v == NULL) {
-		pr_err("%s: v is NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	pr_debug("%s: common data 0x%x, session 0x%x\n",
-		 __func__, (unsigned int)c, (unsigned int)v);
-	pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
-				data->payload_size, data->opcode);
-
 	if (data->opcode == RESET_EVENTS) {
 		pr_debug("%s:Reset event received in Voice service\n",
 					__func__);
@@ -2525,6 +2514,17 @@
 		return 0;
 	}
 
+	v = voice_get_session(data->dest_port);
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: common data 0x%x, session 0x%x\n",
+		 __func__, (unsigned int)c, (unsigned int)v);
+	pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
+				data->payload_size, data->opcode);
+
 	if (data->opcode == APR_BASIC_RSP_RESULT) {
 		if (data->payload_size) {
 			ptr = data->payload;
@@ -2614,17 +2614,6 @@
 
 	pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port);
 
-	v = voice_get_session(data->dest_port);
-	if (v == NULL) {
-		pr_err("%s: v is NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	pr_debug("%s: common data 0x%x, session 0x%x\n",
-		 __func__, (unsigned int)c, (unsigned int)v);
-	pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
-					data->payload_size, data->opcode);
-
 	if (data->opcode == RESET_EVENTS) {
 		pr_debug("%s:Reset event received in Voice service\n",
 					__func__);
@@ -2640,6 +2629,17 @@
 		return 0;
 	}
 
+	v = voice_get_session(data->dest_port);
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: common data 0x%x, session 0x%x\n",
+		 __func__, (unsigned int)c, (unsigned int)v);
+	pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
+					data->payload_size, data->opcode);
+
 	if (data->opcode == APR_BASIC_RSP_RESULT) {
 		if (data->payload_size) {
 			ptr = data->payload;
@@ -2812,17 +2812,6 @@
 
 	pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port);
 
-	v = voice_get_session(data->dest_port);
-	if (v == NULL) {
-		pr_err("%s: v is NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	pr_debug("%s: common data 0x%x, session 0x%x\n",
-		 __func__, (unsigned int)c, (unsigned int)v);
-	pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
-				data->payload_size, data->opcode);
-
 	if (data->opcode == RESET_EVENTS) {
 		pr_debug("%s:Reset event received in Voice service\n",
 					__func__);
@@ -2838,6 +2827,17 @@
 		return 0;
 	}
 
+	v = voice_get_session(data->dest_port);
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: common data 0x%x, session 0x%x\n",
+		 __func__, (unsigned int)c, (unsigned int)v);
+	pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
+				data->payload_size, data->opcode);
+
 	if (data->opcode == APR_BASIC_RSP_RESULT) {
 		if (data->payload_size) {
 			ptr = data->payload;
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c b/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
index 4eeb654..9b8346d 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
@@ -102,7 +102,7 @@
 	snddev_hdmi_active = 0;
 
 	if (snddev_hdmi_data->on_apps) {
-		pr_debug("%s open done\n", dev_info->name);
+		pr_debug("%s Closed\n", dev_info->name);
 
 		mutex_unlock(&snddev_hdmi_lock);
 		return 0;
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile b/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile
new file mode 100644
index 0000000..540119b
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile
@@ -0,0 +1,2 @@
+obj-y += q6usm.o usf.o
+EXTRA_CFLAGS += -I$(src)/..
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
new file mode 100644
index 0000000..d48df06
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
@@ -0,0 +1,1162 @@
+/* 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.
+ *
+ */
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/msm_audio.h>
+#include <sound/apr_audio.h>
+#include "q6usm.h"
+
+/* The driver version*/
+#define DRV_VERSION "1.0"
+
+#define SESSION_MAX 0x02 /* aDSP:USM limit */
+
+#define READDONE_IDX_STATUS     0
+#define READDONE_IDX_BUFFER     1
+#define READDONE_IDX_SIZE       2
+#define READDONE_IDX_OFFSET     3
+#define READDONE_IDX_MSW_TS     4
+#define READDONE_IDX_LSW_TS     5
+#define READDONE_IDX_FLAGS      6
+#define READDONE_IDX_NUMFRAMES  7
+#define READDONE_IDX_ID         8
+
+#define WRITEDONE_IDX_STATUS    0
+
+/* Standard timeout in the asynchronous ops */
+#define Q6USM_TIMEOUT_JIFFIES	(3*HZ) /* 3 sec */
+
+/* cyclic buffer with 1 gap support */
+#define USM_MIN_BUF_CNT 3
+
+static DEFINE_MUTEX(session_lock);
+
+static struct us_client *session[SESSION_MAX];
+static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv);
+static int32_t q6usm_callback(struct apr_client_data *data, void *priv);
+static void q6usm_add_hdr(struct us_client *usc, struct apr_hdr *hdr,
+			  uint32_t pkt_size, bool cmd_flg);
+
+struct usm_mmap {
+	atomic_t ref_cnt;
+	atomic_t cmd_state;
+	wait_queue_head_t cmd_wait;
+	void *apr;
+};
+
+static struct usm_mmap this_mmap;
+
+static int q6usm_session_alloc(struct us_client *usc)
+{
+	int ind = 0;
+
+	mutex_lock(&session_lock);
+	for (ind = 0; ind < SESSION_MAX; ++ind) {
+		if (!session[ind]) {
+			session[ind] = usc;
+			mutex_unlock(&session_lock);
+			++ind; /* session id: 0 reserved */
+			pr_debug("%s: session[%d] was allocated\n",
+				  __func__, ind);
+			return ind;
+		}
+	}
+	mutex_unlock(&session_lock);
+	return -ENOMEM;
+}
+
+static void q6usm_session_free(struct us_client *usc)
+{
+	/* Session index was incremented during allocation */
+	uint16_t ind = (uint16_t)usc->session - 1;
+
+	pr_debug("%s: to free session[%d]\n", __func__, ind);
+	if (ind < SESSION_MAX) {
+		mutex_lock(&session_lock);
+		session[ind] = 0;
+		mutex_unlock(&session_lock);
+	}
+}
+
+int q6usm_us_client_buf_free(unsigned int dir,
+			     struct us_client *usc)
+{
+	struct us_port_data *port;
+	int rc = 0;
+	uint32_t size = 0;
+
+	if ((usc == NULL) ||
+	    ((dir != IN) && (dir != OUT)))
+		return -EINVAL;
+
+	mutex_lock(&usc->cmd_lock);
+	port = &usc->port[dir];
+	if (port == NULL) {
+		mutex_unlock(&usc->cmd_lock);
+		return -EINVAL;
+	}
+
+	if (port->data == NULL) {
+		mutex_unlock(&usc->cmd_lock);
+		return 0;
+	}
+
+	rc = q6usm_memory_unmap(usc, port->phys, dir);
+	if (rc)
+		pr_err("%s: CMD Memory_unmap* failed\n", __func__);
+
+	pr_debug("%s: data[%p]phys[%p][%p]\n", __func__,
+		 (void *)port->data, (void *)port->phys, (void *)&port->phys);
+	size = port->buf_size * port->buf_cnt;
+	dma_free_coherent(NULL, size, port->data, port->phys);
+	port->data = NULL;
+	port->phys = 0;
+	port->buf_size = 0;
+	port->buf_cnt = 0;
+
+	mutex_unlock(&usc->cmd_lock);
+	return 0;
+}
+
+void q6usm_us_client_free(struct us_client *usc)
+{
+	int loopcnt = 0;
+	struct us_port_data *port;
+
+	if ((usc == NULL) ||
+	    !(usc->session))
+		return;
+
+	for (loopcnt = 0; loopcnt <= OUT; ++loopcnt) {
+		port = &usc->port[loopcnt];
+		if (port->data == NULL)
+			continue;
+		pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
+		q6usm_us_client_buf_free(loopcnt, usc);
+	}
+	q6usm_session_free(usc);
+	apr_deregister(usc->apr);
+
+	pr_debug("%s: APR De-Register\n", __func__);
+
+	if (atomic_read(&this_mmap.ref_cnt) <= 0) {
+		pr_err("%s: APR Common Port Already Closed\n", __func__);
+		goto done;
+	}
+
+	atomic_dec(&this_mmap.ref_cnt);
+	if (atomic_read(&this_mmap.ref_cnt) == 0) {
+		apr_deregister(this_mmap.apr);
+		pr_debug("%s: APR De-Register common port\n", __func__);
+	}
+done:
+	kfree(usc);
+	pr_debug("%s:\n", __func__);
+	return;
+}
+
+struct us_client *q6usm_us_client_alloc(
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *),
+	void *priv)
+{
+	struct us_client *usc;
+	int n;
+	int lcnt = 0;
+
+	usc = kzalloc(sizeof(struct us_client), GFP_KERNEL);
+	if (usc == NULL)
+		return NULL;
+	n = q6usm_session_alloc(usc);
+	if (n <= 0)
+		goto fail_session;
+	usc->session = n;
+	usc->cb = cb;
+	usc->priv = priv;
+	usc->apr = apr_register("ADSP", "USM", \
+				(apr_fn)q6usm_callback,\
+				((usc->session) << 8 | 0x0001),\
+				usc);
+
+	if (usc->apr == NULL) {
+		pr_err("%s: Registration with APR failed\n", __func__);
+		goto fail;
+	}
+	pr_info("%s: Registering the common port with APR\n", __func__);
+	if (atomic_read(&this_mmap.ref_cnt) == 0) {
+		this_mmap.apr = apr_register("ADSP", "USM",
+					     (apr_fn)q6usm_mmapcallback,
+					     0x0FFFFFFFF, &this_mmap);
+		if (this_mmap.apr == NULL) {
+			pr_err("%s: USM port registration failed\n",
+			       __func__);
+			goto fail;
+		}
+	}
+
+	atomic_inc(&this_mmap.ref_cnt);
+	init_waitqueue_head(&usc->cmd_wait);
+	mutex_init(&usc->cmd_lock);
+	for (lcnt = 0; lcnt <= OUT; ++lcnt) {
+		mutex_init(&usc->port[lcnt].lock);
+		spin_lock_init(&usc->port[lcnt].dsp_lock);
+	}
+	atomic_set(&usc->cmd_state, 0);
+
+	return usc;
+fail:
+	q6usm_us_client_free(usc);
+	return NULL;
+fail_session:
+	kfree(usc);
+	return NULL;
+}
+
+int q6usm_us_client_buf_alloc(unsigned int dir,
+			      struct us_client *usc,
+			      unsigned int bufsz,
+			      unsigned int bufcnt)
+{
+	int rc = 0;
+	struct us_port_data *port = NULL;
+	unsigned int size = bufsz*bufcnt;
+
+	if ((usc == NULL) ||
+	    ((dir != IN) && (dir != OUT)) || (size == 0) ||
+	    (usc->session <= 0 || usc->session > SESSION_MAX) ||
+	    (bufcnt < USM_MIN_BUF_CNT)) {
+		pr_err("%s: wrong parameters: size=%d; bufcnt=%d\n",
+		       __func__, size, bufcnt);
+		return -EINVAL;
+	}
+
+	mutex_lock(&usc->cmd_lock);
+
+	port = &usc->port[dir];
+
+	port->data = dma_alloc_coherent(NULL, size, &(port->phys), GFP_KERNEL);
+	if (port->data == NULL) {
+		pr_err("%s: US region allocation failed\n", __func__);
+		mutex_unlock(&usc->cmd_lock);
+		return -ENOMEM;
+	}
+
+	port->buf_cnt = bufcnt;
+	port->buf_size = bufsz;
+	pr_debug("%s: data[%p]; phys[%p]; [%p]\n", __func__,
+		 (void *)port->data,
+		 (void *)port->phys,
+		 (void *)&port->phys);
+
+	rc = q6usm_memory_map(usc, port->phys, dir, size, 1);
+	if (rc < 0) {
+		pr_err("%s: CMD Memory_map failed\n", __func__);
+		mutex_unlock(&usc->cmd_lock);
+		q6usm_us_client_buf_free(dir, usc);
+	} else {
+		mutex_unlock(&usc->cmd_lock);
+		rc = 0;
+	}
+
+	return rc;
+}
+
+static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv)
+{
+	uint32_t token;
+	uint32_t *payload = data->payload;
+
+	pr_debug("%s: ptr0[0x%x]; ptr1[0x%x]; opcode[0x%x];"
+		 "token[0x%x]; payload_s[%d]; src[%d]; dest[%d];\n",
+		 __func__, payload[0], payload[1], data->opcode, data->token,
+		 data->payload_size, data->src_port, data->dest_port);
+
+	if (data->opcode == APR_BASIC_RSP_RESULT) {
+		/* status field check */
+		if (payload[1]) {
+			pr_err("%s: wrong response[%d] on cmd [%d]\n",
+			       __func__, payload[1], payload[0]);
+		} else {
+			token = data->token;
+			switch (payload[0]) {
+			case USM_SESSION_CMD_MEMORY_MAP:
+			case USM_SESSION_CMD_MEMORY_UNMAP:
+				pr_debug("%s: cmd[0x%x]; result[0x%x]\n",
+					 __func__, payload[0], payload[1]);
+				if (atomic_read(&this_mmap.cmd_state)) {
+					atomic_set(&this_mmap.cmd_state, 0);
+					wake_up(&this_mmap.cmd_wait);
+				}
+				break;
+			default:
+				pr_debug("%s: wrong command[0x%x]\n",
+					 __func__, payload[0]);
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+
+static int32_t q6usm_callback(struct apr_client_data *data, void *priv)
+{
+	struct us_client *usc = (struct us_client *)priv;
+	unsigned long dsp_flags;
+	uint32_t *payload = data->payload;
+	uint32_t token = data->token;
+
+	if (usc == NULL) {
+		pr_err("%s: client info is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (data->opcode == APR_BASIC_RSP_RESULT) {
+		/* status field check */
+		if (payload[1]) {
+			pr_err("%s: wrong response[%d] on cmd [%d]\n",
+			       __func__, payload[1], payload[0]);
+			if (usc->cb)
+				usc->cb(data->opcode, token,
+					(uint32_t *)data->payload, usc->priv);
+		} else {
+			switch (payload[0]) {
+			case USM_SESSION_CMD_RUN:
+			case USM_STREAM_CMD_CLOSE:
+				if (token != usc->session) {
+					pr_err("%s: wrong token[%d]",
+					       __func__, token);
+					break;
+				}
+			case USM_STREAM_CMD_OPEN_READ:
+			case USM_STREAM_CMD_OPEN_WRITE:
+			case USM_STREAM_CMD_SET_ENC_PARAM:
+			case USM_DATA_CMD_MEDIA_FORMAT_UPDATE:
+				if (atomic_read(&usc->cmd_state)) {
+					atomic_set(&usc->cmd_state, 0);
+					wake_up(&usc->cmd_wait);
+				}
+				if (usc->cb)
+					usc->cb(data->opcode, token,
+						(uint32_t *)data->payload,
+						usc->priv);
+				break;
+			default:
+				pr_debug("%s: command[0x%x] wrong response\n",
+					 __func__, payload[0]);
+				break;
+			}
+		}
+		return 0;
+	}
+
+	switch (data->opcode) {
+	case USM_DATA_EVENT_READ_DONE: {
+		struct us_port_data *port = &usc->port[OUT];
+
+		pr_debug("%s: R-D: stat=%d; buff=%x; size=%d; off=%d\n",
+			 __func__,
+			 payload[READDONE_IDX_STATUS],
+			 payload[READDONE_IDX_BUFFER],
+			 payload[READDONE_IDX_SIZE],
+			 payload[READDONE_IDX_OFFSET]);
+		pr_debug("msw_ts=%d; lsw_ts=%d; flags=%d; id=%d; num=%d\n",
+			 payload[READDONE_IDX_MSW_TS],
+			 payload[READDONE_IDX_LSW_TS],
+			 payload[READDONE_IDX_FLAGS],
+			 payload[READDONE_IDX_ID],
+			 payload[READDONE_IDX_NUMFRAMES]);
+
+		spin_lock_irqsave(&port->dsp_lock, dsp_flags);
+		if (payload[READDONE_IDX_STATUS]) {
+			pr_err("%s: wrong READDONE[%d]; token[%d]\n",
+			       __func__,
+			       payload[READDONE_IDX_STATUS],
+			       token);
+			token = USM_WRONG_TOKEN;
+			spin_unlock_irqrestore(&port->dsp_lock,
+					       dsp_flags);
+			break;
+		}
+
+		if (port->expected_token != token) {
+			u32 cpu_buf = port->cpu_buf;
+			pr_err("%s: expected[%d] != token[%d]\n",
+				__func__, port->expected_token, token);
+			pr_info("%s: dsp_buf=%d; cpu_buf=%d;\n",
+				__func__,   port->dsp_buf, cpu_buf);
+
+			token = USM_WRONG_TOKEN;
+			/* To prevent data handle continiue */
+			port->expected_token = USM_WRONG_TOKEN;
+			spin_unlock_irqrestore(&port->dsp_lock,
+					       dsp_flags);
+			break;
+		} /* port->expected_token != data->token */
+
+		port->expected_token = token + 1;
+		if (port->expected_token == port->buf_cnt)
+			port->expected_token = 0;
+
+		/* gap support */
+		if (port->expected_token != port->cpu_buf) {
+			port->dsp_buf = port->expected_token;
+			token = port->dsp_buf; /* for callback */
+		} else
+			port->dsp_buf = token;
+
+		spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
+		break;
+	} /* case USM_DATA_EVENT_READ_DONE */
+
+	case USM_DATA_EVENT_WRITE_DONE: {
+		struct us_port_data *port = &usc->port[IN];
+
+		pr_debug("%s W-D: code[0x%x]; status[0x%x]; token[%d]",
+			 __func__,
+			 payload[0], payload[1], token);
+
+		if (payload[WRITEDONE_IDX_STATUS]) {
+			pr_err("%s: wrong WRITEDONE_IDX_STATUS[%d]\n",
+			       __func__,
+			       payload[WRITEDONE_IDX_STATUS]);
+			break;
+		}
+
+		spin_lock_irqsave(&port->dsp_lock, dsp_flags);
+		port->dsp_buf = token + 1;
+		if (port->dsp_buf == port->buf_cnt)
+			port->dsp_buf = 0;
+		spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
+
+		pr_info("%s: WRITE_DONE: token=%d; dsp_buf=%d; cpu_buf=%d\n",
+			__func__,
+			token, port->dsp_buf, port->cpu_buf);
+
+		break;
+	} /* case USM_DATA_EVENT_WRITE_DONE */
+
+	default:
+		pr_debug("%s: not supported code [0x%x]",
+			 __func__, data->opcode);
+		return 0;
+
+	} /* switch */
+
+	if (usc->cb)
+		usc->cb(data->opcode, token,
+			data->payload, usc->priv);
+
+	return 0;
+}
+
+uint32_t q6usm_get_ready_data(int dir, struct us_client *usc)
+{
+	uint32_t ret = 0xffffffff;
+
+	if ((usc != NULL) && ((dir == IN) || (dir == OUT)))
+		ret = usc->port[dir].dsp_buf;
+	return ret;
+}
+
+uint32_t q6usm_get_virtual_address(int dir,
+				   struct us_client *usc,
+				   struct vm_area_struct *vms)
+{
+	uint32_t ret = 0xffffffff;
+
+	if (vms && (usc != NULL) && ((dir == IN) || (dir == OUT))) {
+		struct us_port_data *port = &usc->port[dir];
+		ret = dma_mmap_coherent(NULL, vms,
+					port->data, port->phys,
+					port->buf_size * port->buf_cnt);
+	}
+	return ret;
+}
+
+static void q6usm_add_hdr(struct us_client *usc, struct apr_hdr *hdr,
+			  uint32_t pkt_size, bool cmd_flg)
+{
+	pr_debug("%s: pkt size=%d; cmd_flg=%d\n",
+		 __func__, pkt_size, cmd_flg);
+	pr_debug("**************\n");
+	mutex_lock(&usc->cmd_lock);
+	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
+				       APR_HDR_LEN(sizeof(struct apr_hdr)),\
+				       APR_PKT_VER);
+	hdr->src_svc = ((struct apr_svc *)usc->apr)->id;
+	hdr->src_domain = APR_DOMAIN_APPS;
+	hdr->dest_svc = APR_SVC_USM;
+	hdr->dest_domain = APR_DOMAIN_ADSP;
+	hdr->src_port = (usc->session << 8) | 0x0001;
+	hdr->dest_port = (usc->session << 8) | 0x0001;
+	if (cmd_flg) {
+		hdr->token = usc->session;
+		atomic_set(&usc->cmd_state, 1);
+	}
+	hdr->pkt_size  = APR_PKT_SIZE(APR_HDR_SIZE, pkt_size);
+	mutex_unlock(&usc->cmd_lock);
+	return;
+}
+
+static void q6usm_add_mmaphdr(struct us_client *usc, struct apr_hdr *hdr,
+			      uint32_t pkt_size, bool cmd_flg)
+{
+	pr_debug("%s: pkt size=%d cmd_flg=%d\n",
+		 __func__, pkt_size, cmd_flg);
+	pr_debug("**************\n");
+	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
+				       APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	hdr->src_port = 0;
+	hdr->dest_port = 0;
+	if (cmd_flg) {
+		hdr->token = 0;
+		atomic_set(&this_mmap.cmd_state, 1);
+	}
+	hdr->pkt_size  = pkt_size;
+	return;
+}
+
+static uint32_t q6usm_ext2int_format(uint32_t ext_format)
+{
+	uint32_t int_format = INVALID_FORMAT;
+	switch (ext_format) {
+	case FORMAT_USPS_EPOS:
+		int_format = US_POINT_EPOS_FORMAT;
+		break;
+	case FORMAT_USRAW:
+		int_format = US_RAW_FORMAT;
+		break;
+	default:
+		pr_err("%s: Invalid format[%d]\n", __func__, ext_format);
+		break;
+	}
+
+	return int_format;
+}
+
+int q6usm_open_read(struct us_client *usc,
+		    uint32_t format)
+{
+	uint32_t int_format = INVALID_FORMAT;
+	int rc = 0x00;
+	struct usm_stream_cmd_open_read open;
+
+	pr_debug("%s: session[%d]", __func__, usc->session);
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: client or its apr is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	q6usm_add_hdr(usc, &open.hdr, sizeof(open), true);
+	open.hdr.opcode = USM_STREAM_CMD_OPEN_READ;
+	open.src_endpoint = 0; /* AFE */
+	open.pre_proc_top = 0; /* No preprocessing required */
+
+	int_format = q6usm_ext2int_format(format);
+	if (int_format == INVALID_FORMAT)
+		return -EINVAL;
+
+	open.uMode = STREAM_PRIORITY_NORMAL;
+	open.format = int_format;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &open);
+	if (rc < 0) {
+		pr_err("%s: open failed op[0x%x]rc[%d]\n",
+		       __func__, open.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout, waited for OPEN_READ rc[%d]\n",
+		       __func__, rc);
+		goto fail_cmd;
+	} else
+		rc = 0;
+fail_cmd:
+	return rc;
+}
+
+
+int q6usm_enc_cfg_blk(struct us_client *usc, struct us_encdec_cfg* us_cfg)
+{
+	uint32_t int_format = INVALID_FORMAT;
+	struct usm_stream_cmd_encdec_cfg_blk  enc_cfg_obj;
+	struct usm_stream_cmd_encdec_cfg_blk  *enc_cfg = &enc_cfg_obj;
+	int rc = 0;
+	uint32_t total_cfg_size =
+		sizeof(struct usm_stream_cmd_encdec_cfg_blk);
+	uint32_t round_params_size = 0;
+	uint8_t  is_allocated = 0;
+
+
+	if ((usc == NULL) || (us_cfg == NULL)) {
+		pr_err("%s: wrong input", __func__);
+		return -EINVAL;
+	}
+
+	int_format = q6usm_ext2int_format(us_cfg->format_id);
+	if (int_format == INVALID_FORMAT) {
+		pr_err("%s: wrong input format[%d]",
+		       __func__, us_cfg->format_id);
+		return -EINVAL;
+	}
+
+	/* Transparent configuration data is after enc_cfg */
+	/* Integer number of u32s is requred */
+	round_params_size = ((us_cfg->params_size + 3)/4) * 4;
+	if (round_params_size > USM_MAX_CFG_DATA_SIZE) {
+		/* Dynamic allocated encdec_cfg_blk is required */
+		/* static part use */
+		round_params_size -= USM_MAX_CFG_DATA_SIZE;
+		total_cfg_size += round_params_size;
+		enc_cfg = kzalloc(total_cfg_size, GFP_KERNEL);
+		if (enc_cfg == NULL) {
+			pr_err("%s: enc_cfg[%d] allocation failed\n",
+			       __func__, total_cfg_size);
+			return -ENOMEM;
+		}
+		is_allocated = 1;
+	} else
+		round_params_size = 0;
+
+	q6usm_add_hdr(usc, &enc_cfg->hdr, total_cfg_size - APR_HDR_SIZE, true);
+
+	enc_cfg->hdr.opcode = USM_STREAM_CMD_SET_ENC_PARAM;
+	enc_cfg->param_id = USM_PARAM_ID_ENCDEC_ENC_CFG_BLK;
+	enc_cfg->param_size = sizeof(struct usm_encode_cfg_blk)+
+				round_params_size;
+	enc_cfg->enc_blk.frames_per_buf = 1;
+	enc_cfg->enc_blk.format_id = int_format;
+	enc_cfg->enc_blk.cfg_size = sizeof(struct usm_cfg_common)+
+				    USM_MAX_CFG_DATA_SIZE +
+				    round_params_size;
+	memcpy(&(enc_cfg->enc_blk.cfg_common), &(us_cfg->cfg_common),
+	       sizeof(struct usm_cfg_common));
+
+	/* Transparent data copy */
+	memcpy(enc_cfg->enc_blk.transp_data, us_cfg->params,
+	       us_cfg->params_size);
+	pr_info("%s: cfg_size[%d], params_size[%d]\n",
+		__func__,
+		enc_cfg->enc_blk.cfg_size,
+		us_cfg->params_size);
+	pr_info("%s: params[%d,%d,%d,%d, %d,%d,%d,%d]\n",
+		__func__,
+		enc_cfg->enc_blk.transp_data[0],
+		enc_cfg->enc_blk.transp_data[1],
+		enc_cfg->enc_blk.transp_data[2],
+		enc_cfg->enc_blk.transp_data[3],
+		enc_cfg->enc_blk.transp_data[4],
+		enc_cfg->enc_blk.transp_data[5],
+		enc_cfg->enc_blk.transp_data[6],
+		enc_cfg->enc_blk.transp_data[7]
+	       );
+	pr_info("%s: srate:%d, ch=%d, bps= %d; dmap:0x%x; dev_id=0x%x\n",
+		__func__, enc_cfg->enc_blk.cfg_common.sample_rate,
+		enc_cfg->enc_blk.cfg_common.ch_cfg,
+		enc_cfg->enc_blk.cfg_common.bits_per_sample,
+		enc_cfg->enc_blk.cfg_common.data_map,
+		enc_cfg->enc_blk.cfg_common.dev_id);
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) enc_cfg);
+	if (rc < 0) {
+		pr_err("%s:Comamnd open failed\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout opcode[0x%x]\n",
+		       __func__, enc_cfg->hdr.opcode);
+	} else
+		rc = 0;
+
+fail_cmd:
+	if (is_allocated == 1)
+		kfree(enc_cfg);
+
+	return rc;
+}
+
+int q6usm_dec_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg)
+{
+
+	uint32_t int_format = INVALID_FORMAT;
+	struct usm_stream_media_format_update dec_cfg_obj;
+	struct usm_stream_media_format_update *dec_cfg = &dec_cfg_obj;
+
+	int rc = 0;
+	uint32_t total_cfg_size = sizeof(struct usm_stream_media_format_update);
+	uint32_t round_params_size = 0;
+	uint8_t  is_allocated = 0;
+
+
+	if ((usc == NULL) || (us_cfg == NULL)) {
+		pr_err("%s: wrong input", __func__);
+		return -EINVAL;
+	}
+
+	int_format = q6usm_ext2int_format(us_cfg->format_id);
+	if (int_format == INVALID_FORMAT) {
+		pr_err("%s: wrong input format[%d]",
+		       __func__, us_cfg->format_id);
+		return -EINVAL;
+	}
+
+	/* Transparent configuration data is after enc_cfg */
+	/* Integer number of u32s is requred */
+	round_params_size = ((us_cfg->params_size + 3)/4) * 4;
+	if (round_params_size > USM_MAX_CFG_DATA_SIZE) {
+		/* Dynamic allocated encdec_cfg_blk is required */
+		/* static part use */
+		round_params_size -= USM_MAX_CFG_DATA_SIZE;
+		total_cfg_size += round_params_size;
+		dec_cfg = kzalloc(total_cfg_size, GFP_KERNEL);
+		if (dec_cfg == NULL) {
+			pr_err("%s:dec_cfg[%d] allocation failed\n",
+			       __func__, total_cfg_size);
+			return -ENOMEM;
+		}
+		is_allocated = 1;
+	} else { /* static transp_data is enough */
+		round_params_size = 0;
+	}
+
+	q6usm_add_hdr(usc, &dec_cfg->hdr, total_cfg_size - APR_HDR_SIZE, true);
+
+	dec_cfg->hdr.opcode = USM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+	dec_cfg->format_id = int_format;
+	dec_cfg->cfg_size = sizeof(struct usm_cfg_common) +
+			    USM_MAX_CFG_DATA_SIZE +
+			    round_params_size;
+	memcpy(&(dec_cfg->cfg_common), &(us_cfg->cfg_common),
+	       sizeof(struct usm_cfg_common));
+	/* Transparent data copy */
+	memcpy(dec_cfg->transp_data, us_cfg->params, us_cfg->params_size);
+	pr_info("%s: cfg_size[%d], params_size[%d]; parambytes[%d,%d,%d,%d]\n",
+		__func__,
+		dec_cfg->cfg_size,
+		us_cfg->params_size,
+		dec_cfg->transp_data[0],
+		dec_cfg->transp_data[1],
+		dec_cfg->transp_data[2],
+		dec_cfg->transp_data[3]
+	       );
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) dec_cfg);
+	if (rc < 0) {
+		pr_err("%s:Comamnd open failed\n", __func__);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout opcode[0x%x]\n",
+		       __func__, dec_cfg->hdr.opcode);
+	} else
+		rc = 0;
+
+fail_cmd:
+	if (is_allocated == 1)
+		kfree(dec_cfg);
+
+	return rc;
+}
+
+int q6usm_open_write(struct us_client *usc,
+		     uint32_t format)
+{
+	int rc = 0;
+	uint32_t int_format = INVALID_FORMAT;
+	struct usm_stream_cmd_open_write open;
+
+	pr_debug("%s: session[%d]", __func__, usc->session);
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	q6usm_add_hdr(usc, &open.hdr, sizeof(open), true);
+	open.hdr.opcode = USM_STREAM_CMD_OPEN_WRITE;
+
+	int_format = q6usm_ext2int_format(format);
+	if (int_format == INVALID_FORMAT) {
+		pr_err("%s: wrong format[%d]", __func__, format);
+		return -EINVAL;
+	}
+
+	open.format = int_format;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &open);
+	if (rc < 0) {
+		pr_err("%s:open failed op[0x%x]rc[%d]\n", \
+		       __func__, open.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s:timeout. waited for OPEN_WRITR rc[%d]\n",
+		       __func__, rc);
+		goto fail_cmd;
+	} else
+		rc = 0;
+
+fail_cmd:
+	return rc;
+}
+
+int q6usm_run(struct us_client *usc, uint32_t flags,
+	      uint32_t msw_ts, uint32_t lsw_ts)
+{
+	struct usm_stream_cmd_run run;
+	int rc = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	q6usm_add_hdr(usc, &run.hdr, sizeof(run), true);
+
+	run.hdr.opcode = USM_SESSION_CMD_RUN;
+	run.flags    = flags;
+	run.msw_ts   = msw_ts;
+	run.lsw_ts   = lsw_ts;
+
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &run);
+	if (rc < 0) {
+		pr_err("%s: Commmand run failed[%d]\n", __func__, rc);
+		goto fail_cmd;
+	}
+
+	rc = wait_event_timeout(usc->cmd_wait,
+				(atomic_read(&usc->cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout. waited for run success rc[%d]\n",
+		       __func__, rc);
+	} else
+		rc = 0;
+
+fail_cmd:
+	return rc;
+}
+
+
+int q6usm_memory_map(struct us_client *usc, uint32_t buf_add, int dir,
+		     uint32_t bufsz, uint32_t bufcnt)
+{
+	struct usm_stream_cmd_memory_map mem_map;
+	int rc = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL) || (this_mmap.apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	q6usm_add_mmaphdr(usc, &mem_map.hdr,
+			  sizeof(struct usm_stream_cmd_memory_map), true);
+	mem_map.hdr.opcode = USM_SESSION_CMD_MEMORY_MAP;
+
+	mem_map.buf_add = buf_add;
+	mem_map.buf_size = bufsz * bufcnt;
+	mem_map.mempool_id = 0;
+
+	pr_debug("%s: buf add[%x]  buf_add_parameter[%x]\n",
+		 __func__, mem_map.buf_add, buf_add);
+
+	rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_map);
+	if (rc < 0) {
+		pr_err("%s: mem_map op[0x%x]rc[%d]\n",
+		       __func__, mem_map.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+
+	rc = wait_event_timeout(this_mmap.cmd_wait,
+				(atomic_read(&this_mmap.cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout. waited for memory_map\n", __func__);
+	} else
+		rc = 0;
+fail_cmd:
+	return rc;
+}
+
+int q6usm_memory_unmap(struct us_client *usc, uint32_t buf_add, int dir)
+{
+	struct usm_stream_cmd_memory_unmap mem_unmap;
+	int rc = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL) || (this_mmap.apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	q6usm_add_mmaphdr(usc, &mem_unmap.hdr,
+			  sizeof(struct usm_stream_cmd_memory_unmap), true);
+	mem_unmap.hdr.opcode = USM_SESSION_CMD_MEMORY_UNMAP;
+	mem_unmap.buf_add = buf_add;
+
+	rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_unmap);
+	if (rc < 0) {
+		pr_err("%s:mem_unmap op[0x%x]rc[%d]\n",
+		       __func__, mem_unmap.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+
+	rc = wait_event_timeout(this_mmap.cmd_wait,
+				(atomic_read(&this_mmap.cmd_state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s: timeout. waited for memory_map\n", __func__);
+	} else
+		rc = 0;
+fail_cmd:
+	return rc;
+}
+
+int q6usm_read(struct us_client *usc, uint32_t read_ind)
+{
+	struct usm_stream_cmd_read read;
+	struct us_port_data *port = NULL;
+	int rc = 0;
+	u32 read_counter = 0;
+	u32 loop_ind = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	port = &usc->port[OUT];
+
+	if (read_ind > port->buf_cnt) {
+		pr_err("%s: wrong read_ind[%d]\n",
+		       __func__, read_ind);
+		return -EINVAL;
+	}
+	if (read_ind == port->cpu_buf) {
+		pr_err("%s: no free region\n", __func__);
+		return 0;
+	}
+
+	if (read_ind > port->cpu_buf) { /* 1 range */
+		read_counter = read_ind - port->cpu_buf;
+	} else { /* 2 ranges */
+		read_counter = (port->buf_cnt - port->cpu_buf) + read_ind;
+	}
+
+	q6usm_add_hdr(usc, &read.hdr, (sizeof(read) - APR_HDR_SIZE), false);
+
+	read.hdr.opcode = USM_DATA_CMD_READ;
+	read.buf_size = port->buf_size;
+
+	for (loop_ind = 0; loop_ind < read_counter; ++loop_ind) {
+		u32 temp_cpu_buf = port->cpu_buf;
+
+		read.buf_add = (uint32_t)(port->phys) +
+			       port->buf_size * (port->cpu_buf);
+		read.uid = port->cpu_buf;
+		read.hdr.token = port->cpu_buf;
+		read.counter = 1;
+
+		++(port->cpu_buf);
+		if (port->cpu_buf == port->buf_cnt)
+			port->cpu_buf = 0;
+
+		rc = apr_send_pkt(usc->apr, (uint32_t *) &read);
+
+		if (rc < 0) {
+			port->cpu_buf = temp_cpu_buf;
+
+			pr_err("%s:read op[0x%x]rc[%d]\n",
+			       __func__, read.hdr.opcode, rc);
+			break;
+		} else
+			rc = 0;
+	} /* bufs loop */
+
+	return rc;
+}
+
+int q6usm_write(struct us_client *usc, uint32_t write_ind)
+{
+	int rc = 0;
+	struct usm_stream_cmd_write cmd_write;
+	struct us_port_data *port = NULL;
+	u32 current_dsp_buf = 0;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	port = &usc->port[IN];
+
+	current_dsp_buf = port->dsp_buf;
+	/* free region, caused by new dsp_buf report from DSP, */
+	/* can be only extended */
+	if (port->cpu_buf >= current_dsp_buf) {
+		/* 2 -part free region, including empty buffer */
+		if ((write_ind <= port->cpu_buf)  &&
+		    (write_ind > current_dsp_buf)) {
+			pr_err("%s: wrong w_ind[%d]; d_buf=%d; c_buf=%d\n",
+			       __func__, write_ind,
+			       current_dsp_buf, port->cpu_buf);
+			return -EINVAL;
+		}
+	} else {
+		/* 1 -part free region */
+		if ((write_ind <= port->cpu_buf)  ||
+		    (write_ind > current_dsp_buf)) {
+			pr_err("%s: wrong w_ind[%d]; d_buf=%d; c_buf=%d\n",
+			       __func__, write_ind,
+			       current_dsp_buf, port->cpu_buf);
+			return -EINVAL;
+		}
+	}
+
+	q6usm_add_hdr(usc, &cmd_write.hdr,
+		      (sizeof(cmd_write) - APR_HDR_SIZE), false);
+
+	cmd_write.hdr.opcode = USM_DATA_CMD_WRITE;
+	cmd_write.buf_size = port->buf_size;
+
+	while (port->cpu_buf != write_ind) {
+		u32 temp_cpu_buf = port->cpu_buf;
+
+		cmd_write.buf_add = (uint32_t)(port->phys) +
+				    port->buf_size * (port->cpu_buf);
+		cmd_write.uid = port->cpu_buf;
+		cmd_write.hdr.token = port->cpu_buf;
+
+		pr_debug("%s:buf addr[0x%x] size[%d] token[%d] uid[%d]\n",
+			 __func__, cmd_write.buf_add, cmd_write.buf_size,
+			 cmd_write.hdr.token, cmd_write.uid);
+		pr_debug("%s: data=0x%p\n", __func__, port->data);
+
+		++(port->cpu_buf);
+		if (port->cpu_buf == port->buf_cnt)
+			port->cpu_buf = 0;
+
+		rc = apr_send_pkt(usc->apr, (uint32_t *) &cmd_write);
+
+		if (rc < 0) {
+			port->cpu_buf = temp_cpu_buf;
+			pr_err("%s:write op[0x%x];rc[%d];cpu_buf[%d]\n",
+			       __func__, cmd_write.hdr.opcode,
+			       rc, port->cpu_buf);
+			break;
+		}
+
+		rc = 0;
+	}
+
+	pr_debug("%s:exit: rc=%d; write_ind=%d; cpu_buf=%d; dsp_buf=%d\n",
+		__func__, rc, write_ind, port->cpu_buf, port->dsp_buf);
+
+	return rc;
+}
+
+bool q6usm_is_write_buf_full(struct us_client *usc, uint32_t* free_region)
+{
+	struct us_port_data *port = NULL;
+	u32 cpu_buf = 0;
+
+	if ((usc == NULL) || !free_region) {
+		pr_err("%s: input data wrong\n", __func__);
+		return false;
+	}
+	port = &usc->port[IN];
+	cpu_buf = port->cpu_buf + 1;
+	if (cpu_buf == port->buf_cnt)
+		cpu_buf = 0;
+
+	*free_region = port->dsp_buf;
+
+	return cpu_buf == *free_region;
+}
+
+int q6usm_cmd(struct us_client *usc, int cmd)
+{
+	struct apr_hdr hdr;
+	int rc = 0;
+	atomic_t *state;
+
+	if ((usc == NULL) || (usc->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	q6usm_add_hdr(usc, &hdr, (sizeof(hdr) - APR_HDR_SIZE), true);
+	switch (cmd) {
+	case CMD_CLOSE:
+		hdr.opcode = USM_STREAM_CMD_CLOSE;
+		state = &usc->cmd_state;
+		break;
+
+	default:
+		pr_err("%s:Invalid format[%d]\n", __func__, cmd);
+		goto fail_cmd;
+	}
+
+	pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
+		 usc->session,  hdr.opcode);
+	rc = apr_send_pkt(usc->apr, (uint32_t *) &hdr);
+	if (rc < 0) {
+		pr_err("%s: Command 0x%x failed\n", __func__, hdr.opcode);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(usc->cmd_wait, (atomic_read(state) == 0),
+				Q6USM_TIMEOUT_JIFFIES);
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s:timeout. waited for response opcode[0x%x]\n",
+		       __func__, hdr.opcode);
+	} else
+		rc = 0;
+fail_cmd:
+	return rc;
+}
+
+static int __init q6usm_init(void)
+{
+	pr_debug("%s\n", __func__);
+	init_waitqueue_head(&this_mmap.cmd_wait);
+	memset(session, 0, sizeof(session));
+	return 0;
+}
+
+device_initcall(q6usm_init);
+
+MODULE_DESCRIPTION("Interface with QDSP6:USM");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h
new file mode 100644
index 0000000..fe12ee1
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h
@@ -0,0 +1,109 @@
+/* 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 __Q6_USM_H__
+#define __Q6_USM_H__
+
+#include <mach/qdsp6v2/apr_us.h>
+
+#define FORMAT_USPS_EPOS	0x00000000
+#define FORMAT_USRAW		0x00000001
+#define INVALID_FORMAT		0xffffffff
+
+#define IN			0x000
+#define OUT			0x001
+
+#define USM_WRONG_TOKEN		0xffffffff
+#define USM_UNDEF_TOKEN		0xfffffffe
+
+#define CMD_CLOSE		0x0004
+
+/* bit 0:1 represents priority of stream */
+#define STREAM_PRIORITY_NORMAL	0x0000
+#define STREAM_PRIORITY_LOW	0x0001
+#define STREAM_PRIORITY_HIGH	0x0002
+
+/* bit 4 represents META enable of encoded data buffer */
+#define BUFFER_META_ENABLE	0x0010
+
+struct us_region {
+	dma_addr_t	phys;
+	/* If == NULL, the region isn't allocated */
+	void		*data;
+	/* number of buffers in the region */
+	uint32_t	buf_cnt;
+	/* size of buffer */
+	uint32_t	buf_size;
+};
+
+struct us_port_data {
+	dma_addr_t	phys;
+	/* cyclic region of buffers with 1 gap */
+	void		*data;
+	/* number of buffers in the region */
+	uint32_t	buf_cnt;
+	/* size of buffer */
+	uint32_t	buf_size;
+	/* TX: write index */
+	uint32_t	dsp_buf;
+	/* TX: read index */
+	uint32_t	cpu_buf;
+	/* expected token from dsp */
+	uint32_t	expected_token;
+	/* read or write locks */
+	struct mutex	lock;
+	spinlock_t	dsp_lock;
+};
+
+struct us_client {
+	int			session;
+	/* idx:1 out port, 0: in port*/
+	struct us_port_data	port[2];
+
+	struct apr_svc		*apr;
+	struct mutex		cmd_lock;
+
+	atomic_t		cmd_state;
+	atomic_t		eos_state;
+	wait_queue_head_t	cmd_wait;
+
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *);
+	void			*priv;
+};
+
+int q6usm_run(struct us_client *usc, uint32_t flags,
+	      uint32_t msw_ts, uint32_t lsw_ts);
+int q6usm_cmd(struct us_client *usc, int cmd);
+int q6usm_us_client_buf_alloc(unsigned int dir, struct us_client *usc,
+			      unsigned int bufsz, unsigned int bufcnt);
+int q6usm_enc_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg);
+int q6usm_dec_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg);
+int q6usm_read(struct us_client *usc, uint32_t read_ind);
+struct us_client *q6usm_us_client_alloc(
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *),
+	void *priv);
+int q6usm_open_read(struct us_client *usc, uint32_t format);
+void q6usm_us_client_free(struct us_client *usc);
+int q6usm_memory_map(struct us_client *usc, uint32_t buf_add,
+		     int dir, uint32_t bufsz, uint32_t bufcnt);
+int q6usm_memory_unmap(struct us_client *usc, uint32_t buf_add,
+		       int dir);
+
+uint32_t q6usm_get_ready_data(int dir, struct us_client *usc);
+uint32_t q6usm_get_virtual_address(int dir, struct us_client *usc,
+				   struct vm_area_struct *vms);
+
+int q6usm_open_write(struct us_client *usc,  uint32_t format);
+int q6usm_write(struct us_client *usc, uint32_t write_ind);
+bool q6usm_is_write_buf_full(struct us_client *usc, uint32_t* free_region);
+
+#endif /* __Q6_USM_H__ */
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
new file mode 100644
index 0000000..bfe0006
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -0,0 +1,1006 @@
+/* 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.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+#include <linux/time.h>
+#include <asm/mach-types.h>
+#include <sound/apr_audio.h>
+#include <mach/qdsp6v2/usf.h>
+#include "q6usm.h"
+
+/* The driver version*/
+#define DRV_VERSION "1.0"
+
+/* Standard timeout in the asynchronous ops */
+#define USF_TIMEOUT_JIFFIES (3*HZ) /* 3 sec */
+
+/* Undefined USF device */
+#define USF_UNDEF_DEV_ID 0xffff
+
+/* RX memory mapping flag */
+#define	USF_VM_WRITE	2
+
+/* The driver states */
+enum usf_state_type {
+	USF_IDLE_STATE,
+	USF_OPENED_STATE,
+	USF_CONFIGURED_STATE,
+	USF_WORK_STATE,
+	USF_ERROR_STATE
+};
+
+struct usf_xx_type {
+	/* Name of the client - event calculator */
+	char client_name[USF_MAX_CLIENT_NAME_SIZE];
+	/* The driver state in TX or RX direction */
+	enum usf_state_type usf_state;
+	/* wait for q6 events mechanism */
+	wait_queue_head_t wait;
+	/* IF with q6usm info */
+	struct us_client *usc;
+	/* Q6:USM' Encoder/decoder configuration */
+	struct us_encdec_cfg encdec_cfg;
+	/* Shared buffer (with Q6:USM) size */
+	uint32_t buffer_size;
+	/* Number of the shared buffers (with Q6:USM) */
+	uint32_t buffer_count;
+	/* Shared memory (Cyclic buffer with 1 gap) control */
+	uint32_t new_region;
+	uint32_t prev_region;
+	/* Q6:USM's events handler */
+	void (*cb)(uint32_t, uint32_t, uint32_t *, void *);
+	/* User's update info isn't acceptable */
+	u8 user_upd_info_na;
+};
+
+struct usf_type {
+	/* TX device component configuration & control */
+	struct usf_xx_type usf_tx;
+	/* RX device component configuration & control */
+	struct usf_xx_type usf_rx;
+	/* Index into the opened device container */
+	/* To prevent mutual usage of the same device */
+	uint16_t dev_ind;
+	/* Event types, supported by device */
+	uint16_t event_types;
+	/*  The device is "input" module registered client */
+	struct input_dev *input_if;
+};
+
+/* The MAX number of the supported devices */
+#define MAX_DEVS_NUMBER	1
+
+/* The opened devices container */
+static int s_opened_devs[MAX_DEVS_NUMBER];
+
+static void usf_rx_cb(uint32_t opcode, uint32_t token,
+		      uint32_t *payload, void *priv)
+{
+	struct usf_xx_type *usf_xx = (struct usf_xx_type *) priv;
+
+	if (usf_xx == NULL) {
+		pr_err("%s: the private data is NULL\n", __func__);
+		return;
+	}
+
+	switch (opcode) {
+	case USM_DATA_EVENT_WRITE_DONE:
+		wake_up(&usf_xx->wait);
+		break;
+	default:
+		break;
+	}
+}
+
+static void usf_tx_cb(uint32_t opcode, uint32_t token,
+		      uint32_t *payload, void *priv)
+{
+	struct usf_xx_type *usf_xx = (struct usf_xx_type *) priv;
+
+	if (usf_xx == NULL) {
+		pr_err("%s: the private data is NULL\n", __func__);
+		return;
+	}
+
+	switch (opcode) {
+	case USM_DATA_EVENT_READ_DONE:
+		if (token == USM_WRONG_TOKEN)
+			usf_xx->usf_state = USF_ERROR_STATE;
+		usf_xx->new_region = token;
+		wake_up(&usf_xx->wait);
+		break;
+
+	case APR_BASIC_RSP_RESULT:
+		if (payload[1]) {
+			usf_xx->usf_state = USF_ERROR_STATE;
+			usf_xx->new_region = USM_WRONG_TOKEN;
+			wake_up(&usf_xx->wait);
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void release_xx(struct usf_xx_type *usf_xx)
+{
+	if (usf_xx != NULL) {
+		if (usf_xx->usc) {
+			q6usm_us_client_free(usf_xx->usc);
+			usf_xx->usc = NULL;
+		}
+
+		if (usf_xx->encdec_cfg.params != NULL) {
+			kfree(usf_xx->encdec_cfg.params);
+			usf_xx->encdec_cfg.params = NULL;
+		}
+	}
+}
+
+static void usf_disable(struct usf_xx_type *usf_xx)
+{
+	if (usf_xx != NULL) {
+		if ((usf_xx->usf_state != USF_IDLE_STATE) &&
+		    (usf_xx->usf_state != USF_OPENED_STATE)) {
+			(void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+			usf_xx->usf_state = USF_OPENED_STATE;
+			wake_up(&usf_xx->wait);
+		}
+		release_xx(usf_xx);
+	}
+}
+
+static int config_xx(struct usf_xx_type *usf_xx, struct us_xx_info_type *config)
+{
+	int rc = 0;
+	uint16_t data_map_size = 0;
+
+	if ((usf_xx == NULL) ||
+	    (config == NULL))
+		return -EINVAL;
+
+	data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map);
+
+	if (config->client_name != NULL) {
+		if (strncpy_from_user(usf_xx->client_name,
+				      config->client_name,
+				      sizeof(usf_xx->client_name) - 1) < 0) {
+			pr_err("%s: get client name failed\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	pr_info("%s: name=%s; buf_size:%d; dev_id:0x%x; sample_rate:%d\n",
+		__func__, usf_xx->client_name, config->buf_size,
+		config->dev_id, config->sample_rate);
+
+	pr_info("%s: buf_num:%d; format:%d; port_cnt:%d; data_size=%d\n",
+		__func__, config->buf_num, config->stream_format,
+		config->port_cnt, config->params_data_size);
+
+	pr_debug("%s: p_id[0]=%d, p_id[1]=%d, p_id[2]=%d, p_id[3]=%d\n",
+		__func__,
+		config->port_id[0],
+		config->port_id[1],
+		config->port_id[2],
+		config->port_id[3]);
+
+	if (data_map_size < config->port_cnt) {
+		pr_err("%s: number of supported ports:%d < requested:%d\n",
+			__func__,
+			data_map_size,
+			config->port_cnt);
+		return -EINVAL;
+	}
+
+	/* q6usm allocation & configuration */
+	usf_xx->buffer_size = config->buf_size;
+	usf_xx->buffer_count = config->buf_num;
+	usf_xx->encdec_cfg.cfg_common.bits_per_sample =
+				config->bits_per_sample;
+	usf_xx->encdec_cfg.cfg_common.sample_rate = config->sample_rate;
+	/* AFE port e.g. AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX */
+	usf_xx->encdec_cfg.cfg_common.dev_id = config->dev_id;
+
+	usf_xx->encdec_cfg.cfg_common.ch_cfg = config->port_cnt;
+	memcpy((void *)&usf_xx->encdec_cfg.cfg_common.data_map,
+	       (void *)config->port_id,
+	       config->port_cnt);
+	if (rc) {
+		pr_err("%s: ports offsets copy failure\n", __func__);
+		return -EINVAL;
+	}
+
+	usf_xx->encdec_cfg.format_id = config->stream_format;
+	usf_xx->encdec_cfg.params_size = config->params_data_size;
+	usf_xx->user_upd_info_na = 1; /* it's used in US_GET_TX_UPDATE */
+
+	if (config->params_data_size > 0) { /* transparent data copy */
+		usf_xx->encdec_cfg.params = kzalloc(config->params_data_size,
+						    GFP_KERNEL);
+		if (usf_xx->encdec_cfg.params == NULL) {
+			pr_err("%s: params memory alloc[%d] failure\n",
+				__func__,
+				config->params_data_size);
+			return -ENOMEM;
+		}
+		rc = copy_from_user(usf_xx->encdec_cfg.params,
+				    config->params_data,
+				    config->params_data_size);
+		if (rc) {
+			pr_err("%s: transparent data copy failure\n",
+			       __func__);
+			kfree(usf_xx->encdec_cfg.params);
+			usf_xx->encdec_cfg.params = NULL;
+			return -EINVAL;
+		}
+		pr_debug("%s: params_size[%d]; params[%d,%d,%d,%d, %d]\n",
+			 __func__,
+			 config->params_data_size,
+			 usf_xx->encdec_cfg.params[0],
+			 usf_xx->encdec_cfg.params[1],
+			 usf_xx->encdec_cfg.params[2],
+			 usf_xx->encdec_cfg.params[3],
+			 usf_xx->encdec_cfg.params[4]
+			);
+	}
+
+	usf_xx->usc = q6usm_us_client_alloc(usf_xx->cb, (void *)usf_xx);
+	if (!usf_xx->usc) {
+		pr_err("%s: Could not allocate q6usm client\n", __func__);
+		rc = -EFAULT;
+	}
+
+	return rc;
+}
+
+static int register_input_device(struct usf_type *usf_info,
+				 struct us_input_info_type *input_info)
+{
+	int rc = 0;
+	struct input_dev *input_dev = NULL;
+
+	if ((usf_info == NULL) ||
+	    (input_info == NULL) ||
+	    !(input_info->event_types & USF_ALL_EVENTS)) {
+		pr_err("%s: wrong input parameter(s)\n", __func__);
+		return -EINVAL;
+	}
+
+	if (usf_info->input_if != NULL) {
+		pr_err("%s: input_if is already allocated\n", __func__);
+		return -EFAULT;
+	}
+
+	input_dev = input_allocate_device();
+	if (input_dev == NULL) {
+		pr_err("%s: input_allocate_device() failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* Common part configuration */
+	input_dev->name = (const char *)(usf_info->usf_tx.client_name);
+	input_dev->phys = NULL;
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor  = 0x0001;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0001;
+
+	if (input_info->event_types & USF_TSC_EVENT) {
+		/* TSC part configuration */
+		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+		input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+		input_set_abs_params(input_dev, ABS_X,
+				     input_info->tsc_x_dim[0],
+				     input_info->tsc_x_dim[1],
+				     input_info->tsc_x_fuzz, 0);
+		input_set_abs_params(input_dev, ABS_Y,
+				     input_info->tsc_y_dim[0],
+				     input_info->tsc_y_dim[1],
+				     input_info->tsc_y_fuzz, 0);
+
+		input_set_abs_params(input_dev, ABS_PRESSURE,
+				     input_info->tsc_pressure[0],
+				     input_info->tsc_pressure[1], 0, 0);
+
+	}
+
+	if (input_info->event_types & USF_MOUSE_EVENT) {
+		/* Mouse part configuration */
+		input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+
+		input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+							BIT_MASK(BTN_RIGHT) |
+							BIT_MASK(BTN_MIDDLE);
+		input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+	}
+
+	if (input_info->event_types & USF_KEYBOARD_EVENT) {
+		/* Keyboard part configuration */
+		input_dev->evbit[0] |= BIT_MASK(EV_KEY);
+
+		/* All keys are permitted */
+		memset(input_dev->keybit, 0xff, sizeof(input_dev->keybit));
+	}
+
+	rc = input_register_device(input_dev);
+	if (rc) {
+		pr_err("%s: input_register_device() failed; rc=%d\n",
+		       __func__, rc);
+		input_free_device(input_dev);
+	} else {
+		usf_info->input_if = input_dev;
+		usf_info->event_types = input_info->event_types;
+		pr_info("%s: input device[%s] was registered\n",
+			__func__, input_dev->name);
+	}
+
+	return rc;
+
+}
+
+static void notify_tsc_event(struct input_dev *input_if,
+			     int x, int y, int pressure)
+{
+	if (pressure) {
+		input_report_abs(input_if, ABS_X, x);
+		input_report_abs(input_if, ABS_Y, y);
+		input_report_abs(input_if, ABS_PRESSURE, pressure);
+		input_report_key(input_if, BTN_TOUCH, !!pressure);
+	} else {
+		input_report_abs(input_if, ABS_PRESSURE, 0);
+		input_report_key(input_if, BTN_TOUCH, 0);
+	}
+
+	input_sync(input_if);
+
+	pr_debug("%s: TSC event: x[%d], y[%d], pressure[%d]\n",
+		 __func__, x, y, pressure);
+}
+
+static void notify_mouse_event(struct input_dev *input_if,
+			       struct mouse_event_type *me)
+{
+	if (me == NULL) {
+		pr_err("%s: mouse event is NULL\n", __func__);
+		return;
+	}
+
+	input_report_rel(input_if, REL_X, me->rels[0]);
+	input_report_rel(input_if, REL_Y, me->rels[1]);
+
+	input_report_key(input_if, BTN_LEFT,
+			 me->buttons_states & USF_BUTTON_LEFT_MASK);
+	input_report_key(input_if, BTN_MIDDLE,
+			 me->buttons_states & USF_BUTTON_MIDDLE_MASK);
+	input_report_key(input_if, BTN_RIGHT,
+			 me->buttons_states & USF_BUTTON_RIGHT_MASK);
+
+	input_sync(input_if);
+
+	pr_debug("%s: mouse event: dx[%d], dy[%d], buttons_states[%d]\n",
+		 __func__, me->rels[0], me->rels[1], me->buttons_states);
+}
+
+static void notify_key_event(struct input_dev *input_if,
+			       struct key_event_type *ke)
+{
+	if (ke == NULL) {
+		pr_err("%s: key event is NULL\n", __func__);
+		return;
+	}
+
+	input_report_key(input_if, ke->key, ke->key_state);
+	input_sync(input_if);
+	pr_debug("%s: key event: key[%d], state[%d]\n",
+		 __func__,
+		 ke->key,
+		 ke->key_state);
+
+}
+
+static void handle_input_event(struct usf_type *usf_info,
+			       uint16_t event_counter,
+			       struct usf_event_type *event)
+{
+	struct input_dev *input_if = NULL;
+	uint16_t ind = 0;
+
+	if ((usf_info == NULL) || (usf_info->input_if == NULL) ||
+	    (event == NULL) || (!event_counter)) {
+		return;
+	}
+
+	input_if = usf_info->input_if;
+
+	for (ind = 0; ind < event_counter; ++ind) {
+		event += ind;
+		if (event->event_type & usf_info->event_types) {
+			/* the event is supported */
+			if (event->event_type & USF_TSC_EVENT) {
+				struct point_event_type *pe =
+					&(event->event_data.point_event);
+				if (pe->coordinates_type ==
+				    USF_PIX_COORDINATE) {
+					notify_tsc_event(input_if,
+							 pe->coordinates[0],
+							 pe->coordinates[1],
+							 pe->pressure);
+				} else
+					pr_debug("%s: wrong coord type:%d\n",
+						 __func__,
+						 pe->coordinates_type);
+
+				continue;
+			}
+
+			if (event->event_type & USF_MOUSE_EVENT) {
+				notify_mouse_event(input_if,
+					&(event->event_data.mouse_event));
+				continue;
+			}
+
+			if (event->event_type & USF_KEYBOARD_EVENT) {
+				notify_key_event(input_if,
+					&(event->event_data.key_event));
+				continue;
+			}
+		} /* the event is supported */
+	}
+}
+
+static int usf_start_tx(struct usf_xx_type *usf_xx)
+{
+	int rc = q6usm_run(usf_xx->usc, 0, 0, 0);
+
+	pr_debug("%s: tx: q6usm_run; rc=%d\n", __func__, rc);
+	if (!rc) {
+		/* supply all buffers */
+		rc = q6usm_read(usf_xx->usc,
+				usf_xx->buffer_count);
+		pr_debug("%s: q6usm_read[%d]\n",
+			 __func__, rc);
+
+		if (rc)
+			pr_err("%s: buf read failed",
+			       __func__);
+		else
+			usf_xx->usf_state =
+				USF_WORK_STATE;
+	}
+
+	return rc;
+} /* usf_start_tx */
+
+static int usf_start_rx(struct usf_xx_type *usf_xx)
+{
+	int rc = q6usm_run(usf_xx->usc, 0, 0, 0);
+
+	pr_debug("%s: rx: q6usm_run; rc=%d\n",
+		 __func__, rc);
+	if (!rc)
+		usf_xx->usf_state = USF_WORK_STATE;
+
+	return rc;
+} /* usf_start_rx */
+
+static int usf_set_tx_info(struct usf_type *usf, unsigned long arg)
+{
+	struct us_tx_info_type config_tx;
+	const char *name = NULL;
+	struct usf_xx_type *usf_xx =  &usf->usf_tx;
+	int rc = copy_from_user(&config_tx,
+			    (void *) arg,
+			    sizeof(config_tx));
+
+	if (rc) {
+		pr_err("%s: copy error[%d]\n",
+			__func__, rc);
+		return -EINVAL;
+	}
+
+	name = config_tx.us_xx_info.client_name;
+
+	usf_xx->new_region = USM_UNDEF_TOKEN;
+	usf_xx->prev_region = USM_UNDEF_TOKEN;
+	usf_xx->cb = usf_tx_cb;
+
+	init_waitqueue_head(&usf_xx->wait);
+
+	if (name != NULL) {
+		int res = strncpy_from_user(
+			usf_xx->client_name,
+			name,
+			sizeof(usf_xx->client_name)-1);
+		if (res < 0) {
+			pr_err("%s: get client name failed\n",
+			       __func__);
+			return -EINVAL;
+		}
+	}
+
+	rc = config_xx(usf_xx, &config_tx.us_xx_info);
+	if (rc)
+		return rc;
+
+	rc = q6usm_open_read(usf_xx->usc,
+			     usf_xx->encdec_cfg.format_id);
+	if (rc)
+		return rc;
+
+	rc = q6usm_us_client_buf_alloc(OUT, usf_xx->usc,
+				       usf_xx->buffer_size,
+				       usf_xx->buffer_count);
+	if (rc)
+		return rc;
+
+	rc = q6usm_enc_cfg_blk(usf_xx->usc,
+			       &usf_xx->encdec_cfg);
+	if (!rc) {
+		rc = register_input_device(usf,
+					   &config_tx.input_info);
+		if (!rc)
+			usf_xx->usf_state = USF_CONFIGURED_STATE;
+	}
+
+	return rc;
+} /* usf_set_tx_info */
+
+static int usf_set_rx_info(struct usf_type *usf, unsigned long arg)
+{
+	struct us_rx_info_type config_rx;
+	struct usf_xx_type *usf_xx =  &usf->usf_rx;
+	int rc = copy_from_user(&config_rx,
+			    (void *) arg,
+			    sizeof(config_rx));
+
+	if (rc) {
+		pr_err("%s: copy_from_user() failed[%d]\n",
+			__func__, rc);
+		return -EINVAL;
+	}
+
+	usf_xx->new_region = USM_UNDEF_TOKEN;
+	usf_xx->prev_region = USM_UNDEF_TOKEN;
+
+	usf_xx->cb = usf_rx_cb;
+
+	rc = config_xx(usf_xx, &config_rx.us_xx_info);
+	if (rc)
+		return rc;
+
+	rc = q6usm_open_write(usf_xx->usc,
+			      usf_xx->encdec_cfg.format_id);
+	if (rc)
+		return rc;
+
+	if (usf_xx->buffer_size && usf_xx->buffer_count) {
+		rc = q6usm_us_client_buf_alloc(
+					IN,
+					usf_xx->usc,
+					usf_xx->buffer_size,
+					usf_xx->buffer_count);
+		if (rc)
+			return rc;
+	}
+
+	rc = q6usm_dec_cfg_blk(usf_xx->usc,
+			       &usf_xx->encdec_cfg);
+	if (!rc) {
+		init_waitqueue_head(&usf_xx->wait);
+		usf_xx->usf_state = USF_CONFIGURED_STATE;
+	}
+
+	return rc;
+} /* usf_set_rx_info */
+
+
+static int usf_get_tx_update(struct usf_type *usf, unsigned long arg)
+{
+	struct us_tx_update_info_type upd_tx_info;
+	unsigned long prev_jiffies = 0;
+	struct usf_xx_type *usf_xx =  &usf->usf_tx;
+	int rc = copy_from_user(&upd_tx_info, (void *) arg,
+			    sizeof(upd_tx_info));
+
+	if (rc) {
+		pr_err("%s: get_update: copy_from_user() failed[%d]\n",
+		       __func__, rc);
+		return -EINVAL;
+	}
+
+	if (!usf_xx->user_upd_info_na) {
+		handle_input_event(usf,
+				   upd_tx_info.event_counter,
+				   upd_tx_info.event);
+
+		/* Release available regions */
+		rc = q6usm_read(usf_xx->usc,
+				upd_tx_info.free_region);
+		if (rc)
+			return rc;
+	} else
+		usf_xx->user_upd_info_na = 0;
+
+	/* Get data ready regions */
+	prev_jiffies = jiffies;
+	rc = wait_event_timeout(usf_xx->wait,
+				(usf_xx->prev_region !=
+				 usf_xx->new_region) ||
+				(usf_xx->usf_state !=
+				 USF_WORK_STATE),
+				USF_TIMEOUT_JIFFIES);
+
+	if (!rc) {
+		pr_debug("%s: timeout. prev_j=%lu; j=%lu\n",
+			__func__, prev_jiffies, jiffies);
+		pr_debug("%s: timeout. prev=%d; new=%d\n",
+			__func__, usf_xx->prev_region,
+			usf_xx->new_region);
+		pr_debug("%s: timeout. free_region=%d;\n",
+			__func__, upd_tx_info.free_region);
+		if (usf_xx->prev_region ==
+		    usf_xx->new_region) {
+			pr_err("%s:read data: timeout\n",
+			       __func__);
+			return -ETIME;
+		}
+	}
+
+	if (usf_xx->usf_state != USF_WORK_STATE) {
+		pr_err("%s: TX device is in not work state[%d]\n",
+		       __func__, usf_xx->usf_state);
+		return -EINTR;
+	}
+
+	upd_tx_info.ready_region = usf_xx->new_region;
+	rc = copy_to_user((void __user *)arg, &upd_tx_info,
+			  sizeof(upd_tx_info));
+	if (upd_tx_info.ready_region == USM_WRONG_TOKEN) {
+		pr_err("%s: TX path corrupted; prev=%d\n",
+		       __func__, usf_xx->prev_region);
+		rc = -EIO;
+	}
+	usf_xx->prev_region = upd_tx_info.ready_region;
+
+	return rc;
+} /* usf_get_tx_update */
+
+static int usf_set_rx_update(struct usf_xx_type *usf_xx, unsigned long arg)
+{
+	struct us_rx_update_info_type upd_rx_info;
+	int rc = copy_from_user(&upd_rx_info, (void *) arg,
+			    sizeof(upd_rx_info));
+
+	if (rc) {
+		pr_err("%s: get_update: copy_from_user() failed[%d]\n",
+		       __func__, rc);
+		return -EINVAL;
+	}
+
+	/* Send available data regions */
+	if (upd_rx_info.ready_region !=
+	    usf_xx->buffer_count) {
+		rc = q6usm_write(
+			usf_xx->usc,
+			upd_rx_info.ready_region);
+		if (rc)
+			return rc;
+	}
+
+	/* Get free regions */
+	rc = wait_event_timeout(
+		usf_xx->wait,
+		!q6usm_is_write_buf_full(
+			usf_xx->usc,
+			&upd_rx_info.free_region) ||
+		(usf_xx->usf_state == USF_IDLE_STATE),
+		USF_TIMEOUT_JIFFIES);
+
+	if (!rc) {
+		rc = -ETIME;
+		pr_err("%s:timeout. wait for write buf not full\n",
+		       __func__);
+	} else {
+		if (usf_xx->usf_state !=
+		    USF_WORK_STATE) {
+			pr_err("%s: RX: state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EINTR;
+		} else
+			rc = copy_to_user(
+				(void __user *)arg,
+				&upd_rx_info,
+				sizeof(upd_rx_info));
+	}
+
+	return rc;
+} /* usf_set_rx_update */
+
+static int usf_stop_tx(struct usf_type *usf)
+{
+	struct usf_xx_type *usf_xx =  &usf->usf_tx;
+
+	if (usf->input_if != NULL) {
+		input_unregister_device(usf->input_if);
+		usf->input_if = NULL;
+		pr_info("%s input_unregister_device",
+			__func__);
+	}
+	usf_disable(usf_xx);
+
+	return 0;
+} /* usf_stop_tx */
+
+static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int rc = 0;
+	struct usf_type *usf = file->private_data;
+	struct usf_xx_type *usf_xx = NULL;
+
+	switch (cmd) {
+	case US_START_TX: {
+		usf_xx = &usf->usf_tx;
+		if (usf_xx->usf_state == USF_CONFIGURED_STATE)
+			rc = usf_start_tx(usf_xx);
+		else {
+			pr_err("%s: start_tx: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	}
+
+	case US_START_RX: {
+		usf_xx = &usf->usf_rx;
+		if (usf_xx->usf_state == USF_CONFIGURED_STATE)
+			rc = usf_start_rx(usf_xx);
+		else {
+			pr_err("%s: start_rx: wrong state[%d]\n",
+				__func__,
+				usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	}
+
+	case US_SET_TX_INFO: {
+		usf_xx = &usf->usf_tx;
+		if (usf_xx->usf_state == USF_OPENED_STATE)
+			rc = usf_set_tx_info(usf, arg);
+		else {
+			pr_err("%s: set_tx_info: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+
+		break;
+	} /* US_SET_TX_INFO */
+
+	case US_SET_RX_INFO: {
+		usf_xx = &usf->usf_rx;
+		if (usf_xx->usf_state == USF_OPENED_STATE)
+			rc = usf_set_rx_info(usf, arg);
+		else {
+			pr_err("%s: set_rx_info: wrong state[%d]\n",
+				__func__,
+				usf_xx->usf_state);
+			return -EBADFD;
+		}
+
+		break;
+	} /* US_SET_RX_INFO */
+
+	case US_GET_TX_UPDATE: {
+		struct usf_xx_type *usf_xx = &usf->usf_tx;
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_get_tx_update(usf, arg);
+		else {
+			pr_err("%s: get_tx_update: wrong state[%d]\n", __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_GET_TX_UPDATE */
+
+	case US_SET_RX_UPDATE: {
+		struct usf_xx_type *usf_xx = &usf->usf_rx;
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_set_rx_update(usf_xx, arg);
+		else {
+			pr_err("%s: set_rx_update: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			rc = -EBADFD;
+		}
+		break;
+	} /* US_SET_RX_UPDATE */
+
+	case US_STOP_TX: {
+		usf_xx = &usf->usf_tx;
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			rc = usf_stop_tx(usf);
+		else {
+			pr_err("%s: stop_tx: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	} /* US_STOP_TX */
+
+	case US_STOP_RX: {
+		usf_xx = &usf->usf_rx;
+		if (usf_xx->usf_state == USF_WORK_STATE)
+			usf_disable(usf_xx);
+		else {
+			pr_err("%s: stop_rx: wrong state[%d]\n",
+			       __func__,
+			       usf_xx->usf_state);
+			return -EBADFD;
+		}
+		break;
+	} /* US_STOP_RX */
+
+	default:
+		rc = -EINVAL;
+		break;
+	}
+
+	if (rc &&
+	    ((cmd == US_SET_TX_INFO) ||
+	     (cmd == US_SET_RX_INFO)))
+		release_xx(usf_xx);
+
+	return rc;
+} /* usf_ioctl */
+
+static int usf_mmap(struct file *file, struct vm_area_struct *vms)
+{
+	struct usf_type *usf = file->private_data;
+	int dir = OUT;
+	struct usf_xx_type *usf_xx = &usf->usf_tx;
+
+	if (vms->vm_flags & USF_VM_WRITE) { /* RX buf mapping */
+		dir = IN;
+		usf_xx = &usf->usf_rx;
+	}
+
+	return q6usm_get_virtual_address(dir, usf_xx->usc, vms);
+}
+
+static uint16_t add_opened_dev(int minor)
+{
+	uint16_t ind = 0;
+
+	for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
+		if (minor == s_opened_devs[ind]) {
+			pr_err("%s: device %d is already opened\n",
+			       __func__, minor);
+			return USF_UNDEF_DEV_ID;
+		}
+
+		if (s_opened_devs[ind] == 0) {
+			s_opened_devs[ind] = minor;
+			pr_info("%s: device %d is added; ind=%d\n",
+				__func__, minor, ind);
+			return ind;
+		}
+	}
+
+	pr_err("%s: there is no place for device %d\n",
+	       __func__, minor);
+	return USF_UNDEF_DEV_ID;
+}
+
+static int usf_open(struct inode *inode, struct file *file)
+{
+	struct usf_type *usf =  NULL;
+	uint16_t dev_ind = 0;
+	int minor = MINOR(inode->i_rdev);
+
+	dev_ind = add_opened_dev(minor);
+	if (dev_ind == USF_UNDEF_DEV_ID)
+		return -EBUSY;
+
+	usf = kzalloc(sizeof(struct usf_type), GFP_KERNEL);
+	if (usf == NULL) {
+		pr_err("%s:usf allocation failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	file->private_data = usf;
+	usf->dev_ind = dev_ind;
+
+	usf->usf_tx.usf_state = USF_OPENED_STATE;
+	usf->usf_rx.usf_state = USF_OPENED_STATE;
+
+	pr_info("%s:usf in open\n", __func__);
+	return 0;
+}
+
+
+static int usf_release(struct inode *inode, struct file *file)
+{
+	struct usf_type *usf = file->private_data;
+
+	pr_info("%s: release entry\n", __func__);
+
+	if (usf->input_if != NULL) {
+		input_unregister_device(usf->input_if);
+		usf->input_if = NULL;
+		pr_info("%s input_unregister_device\n",  __func__);
+	}
+
+	usf_disable(&usf->usf_tx);
+	usf_disable(&usf->usf_rx);
+
+	s_opened_devs[usf->dev_ind] = 0;
+
+	kfree(usf);
+	pr_info("%s: release exit\n", __func__);
+	return 0;
+}
+
+static const struct file_operations usf_fops = {
+	.owner                  = THIS_MODULE,
+	.open                   = usf_open,
+	.release                = usf_release,
+	.unlocked_ioctl = usf_ioctl,
+	.mmap                   = usf_mmap,
+};
+
+struct miscdevice usf_misc[MAX_DEVS_NUMBER] = {
+	{
+		.minor  = MISC_DYNAMIC_MINOR,
+		.name   = "usf1",
+		.fops   = &usf_fops,
+	},
+};
+
+static int __init usf_init(void)
+{
+	int rc = 0;
+	uint16_t ind = 0;
+
+	pr_info("%s: USF SW version %s.\n", __func__, DRV_VERSION);
+	pr_info("%s: Max %d devs registration\n", __func__, MAX_DEVS_NUMBER);
+
+	for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
+		rc = misc_register(&usf_misc[ind]);
+		if (rc) {
+			pr_err("%s: misc_register() failed ind=%d; rc = %d\n",
+			       __func__, ind, rc);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+device_initcall(usf_init);
+
+MODULE_DESCRIPTION("Ultrasound framework driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdss-debug.c b/arch/arm/mach-msm/qdss-debug.c
new file mode 100644
index 0000000..b2d38b1
--- /dev/null
+++ b/arch/arm/mach-msm/qdss-debug.c
@@ -0,0 +1,285 @@
+/* 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+
+#include "qdss.h"
+
+#define debug_writel(debug, cpu, val, off)	\
+			__raw_writel((val), debug.base[cpu] + off)
+#define debug_readl(debug, cpu, off)		\
+			__raw_readl(debug.base[cpu] + off)
+
+#define DBGDIDR			(0x000)
+#define DBGWFAR			(0x018)
+#define DBGVCR			(0x01C)
+#define DBGECR			(0x024)
+#define DBGDTRRX		(0x080)
+#define DBGITR			(0x084)
+#define DBGDSCR			(0x088)
+#define DBGDTRTX		(0x08C)
+#define DBGDRCR			(0x090)
+#define DBGEACR			(0x094)
+#define DBGPCSR			(0x0A0)
+#define DBGCIDSR		(0x0A4)
+#define DBGVIDSR		(0x0A8)
+#define DBGBVRm(n)		(0x100 + (n * 4))
+#define DBGBCRm(n)		(0x140 + (n * 4))
+#define DBGWVRm(n)		(0x180 + (n * 4))
+#define DBGWCRm(n)		(0x1C0 + (n * 4))
+#define DBGBXVRm(n)		(0x240 + (n * 4))
+#define DBGOSLAR		(0x300)
+#define DBGOSLSR		(0x304)
+#define DBGPRCR			(0x310)
+#define DBGPRSR			(0x314)
+
+
+#define DEBUG_LOCK(cpu)							\
+do {									\
+	mb();								\
+	debug_writel(debug, cpu, MAGIC2, CS_LAR);			\
+} while (0)
+#define DEBUG_UNLOCK(cpu)						\
+do {									\
+	debug_writel(debug, cpu, MAGIC1, CS_LAR);			\
+	mb();								\
+} while (0)
+
+#define DEBUG_OS_LOCK(cpu)						\
+do {									\
+	debug_writel(debug, cpu, MAGIC1, DBGOSLAR);			\
+	mb();								\
+} while (0)
+#define DEBUG_OS_UNLOCK(cpu)						\
+do {									\
+	mb();								\
+	debug_writel(debug, cpu, MAGIC2, DBGOSLAR);			\
+	mb();								\
+} while (0)
+
+#define MAX_DEBUG_REGS		(90)
+#define MAX_STATE_SIZE		(MAX_DEBUG_REGS * num_possible_cpus())
+#define DBGDSCR_MASK		(0x6C30FC3C)
+
+struct debug_config {
+	/* read only config register */
+	uint32_t	dbg_id;
+	/* derived values */
+	uint8_t		nr_watch_pts;
+	uint8_t		nr_brk_pts;
+	uint8_t		nr_ctx_comp;
+};
+
+struct debug_ctx {
+	struct debug_config		cfg;
+	void __iomem			**base;
+	uint32_t			*state;
+	struct device			*dev;
+};
+
+static struct debug_ctx debug;
+
+static void debug_save_reg(int cpu)
+{
+	uint32_t i;
+	int j;
+
+	DEBUG_UNLOCK(cpu);
+	DEBUG_OS_LOCK(cpu);
+
+	i = cpu * MAX_DEBUG_REGS;
+
+	debug.state[i++] = debug_readl(debug, cpu, DBGWFAR);
+	for (j = 0; j < debug.cfg.nr_brk_pts; j++) {
+		debug.state[i++] = debug_readl(debug, cpu, DBGBCRm(j));
+		debug.state[i++] = debug_readl(debug, cpu, DBGBVRm(j));
+	}
+	for (j = 0; j < debug.cfg.nr_ctx_comp; j++)
+		debug.state[i++] = debug_readl(debug, cpu, DBGBXVRm(j));
+	for (j = 0; j < debug.cfg.nr_watch_pts; j++) {
+		debug.state[i++] = debug_readl(debug, cpu, DBGWVRm(j));
+		debug.state[i++] = debug_readl(debug, cpu, DBGWCRm(j));
+	}
+	debug.state[i++] = debug_readl(debug, cpu, DBGVCR);
+	debug.state[i++] = debug_readl(debug, cpu, CS_CLAIMSET);
+	debug.state[i++] = debug_readl(debug, cpu, CS_CLAIMCLR);
+	debug.state[i++] = debug_readl(debug, cpu, DBGDTRTX);
+	debug.state[i++] = debug_readl(debug, cpu, DBGDTRRX);
+	debug.state[i++] = debug_readl(debug, cpu, DBGDSCR);
+
+	DEBUG_LOCK(cpu);
+}
+
+static void debug_restore_reg(int cpu)
+{
+	uint32_t i;
+	int j;
+
+	DEBUG_UNLOCK(cpu);
+	DEBUG_OS_LOCK(cpu);
+
+	i = cpu * MAX_DEBUG_REGS;
+
+	debug_writel(debug, cpu, debug.state[i++], DBGWFAR);
+	for (j = 0; j < debug.cfg.nr_brk_pts; j++) {
+		debug_writel(debug, cpu, debug.state[i++], DBGBCRm(j));
+		debug_writel(debug, cpu, debug.state[i++], DBGBVRm(j));
+	}
+	for (j = 0; j < debug.cfg.nr_ctx_comp; j++)
+		debug_writel(debug, cpu, debug.state[i++], DBGBXVRm(j));
+	for (j = 0; j < debug.cfg.nr_watch_pts; j++) {
+		debug_writel(debug, cpu, debug.state[i++], DBGWVRm(j));
+		debug_writel(debug, cpu, debug.state[i++], DBGWCRm(j));
+	}
+	debug_writel(debug, cpu, debug.state[i++], DBGVCR);
+	debug_writel(debug, cpu, debug.state[i++], CS_CLAIMSET);
+	debug_writel(debug, cpu, debug.state[i++], CS_CLAIMCLR);
+	debug_writel(debug, cpu, debug.state[i++], DBGDTRTX);
+	debug_writel(debug, cpu, debug.state[i++], DBGDTRRX);
+	debug_writel(debug, cpu, debug.state[i++] & DBGDSCR_MASK, DBGDSCR);
+
+	DEBUG_OS_UNLOCK(cpu);
+	DEBUG_LOCK(cpu);
+}
+
+/* msm_save_jtag_debug and msm_restore_jtag_debug should be fast
+ *
+ * These functions will be called either from:
+ * 1. per_cpu idle thread context for idle power collapses.
+ * 2. per_cpu idle thread context for hotplug/suspend power collapse for
+ *    nonboot cpus.
+ * 3. suspend thread context for core0.
+ *
+ * In all cases we are guaranteed to be running on the same cpu for the
+ * entire duration.
+ */
+void msm_save_jtag_debug(void)
+{
+	int cpu = smp_processor_id();
+	debug_save_reg(cpu);
+}
+
+void msm_restore_jtag_debug(void)
+{
+	int cpu = smp_processor_id();
+	debug_restore_reg(cpu);
+}
+
+static void debug_cfg_ro_init(void)
+{
+	/* use cpu 0 for setup */
+	int cpu = 0;
+
+	DEBUG_UNLOCK(cpu);
+
+	debug.cfg.dbg_id = debug_readl(debug, cpu, DBGDIDR);
+	debug.cfg.nr_ctx_comp = BMVAL(debug.cfg.dbg_id, 20, 23) + 1;
+	debug.cfg.nr_brk_pts = BMVAL(debug.cfg.dbg_id, 24, 27) + 1;
+	debug.cfg.nr_watch_pts = BMVAL(debug.cfg.dbg_id, 28, 31) + 1;
+
+	DEBUG_LOCK(cpu);
+}
+
+static int __devinit debug_probe(struct platform_device *pdev)
+{
+	int i, ret;
+	struct resource *res;
+
+	debug.base = kzalloc(pdev->num_resources * sizeof(void *), GFP_KERNEL);
+	if (!debug.base) {
+		ret = -ENOMEM;
+		goto err_base_kzalloc;
+	}
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			ret = -EINVAL;
+			goto err_res;
+		}
+
+		debug.base[i] = ioremap_nocache(res->start, resource_size(res));
+		if (!debug.base[i]) {
+			ret = -EINVAL;
+			goto err_ioremap;
+		}
+	}
+
+	debug.dev = &pdev->dev;
+
+	debug.state = kzalloc(MAX_STATE_SIZE * sizeof(uint32_t), GFP_KERNEL);
+	if (!debug.state) {
+		ret = -ENOMEM;
+		goto err_state_kzalloc;
+	}
+
+	debug_cfg_ro_init();
+
+	dev_info(debug.dev, "Debug intialized.\n");
+
+	return 0;
+
+err_state_kzalloc:
+err_ioremap:
+err_res:
+	while (i) {
+		iounmap(debug.base[i-1]);
+		i--;
+	}
+	kfree(debug.base);
+err_base_kzalloc:
+	return ret;
+}
+
+static int __devexit debug_remove(struct platform_device *pdev)
+{
+	int i;
+
+	kfree(debug.state);
+	for (i = pdev->num_resources; i > 0; i--)
+		iounmap(debug.base[i-1]);
+	kfree(debug.base);
+
+	return 0;
+}
+
+static struct platform_driver debug_driver = {
+	.probe          = debug_probe,
+	.remove         = __devexit_p(debug_remove),
+	.driver         = {
+		.name   = "msm_debug",
+	},
+};
+
+static int __init debug_init(void)
+{
+	return platform_driver_register(&debug_driver);
+}
+module_init(debug_init);
+
+static void __exit debug_exit(void)
+{
+	platform_driver_unregister(&debug_driver);
+}
+module_exit(debug_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Coresight Debug driver");
diff --git a/arch/arm/mach-msm/qdss-ptm.c b/arch/arm/mach-msm/qdss-ptm.c
index 4e8add7..0d971d7 100644
--- a/arch/arm/mach-msm/qdss-ptm.c
+++ b/arch/arm/mach-msm/qdss-ptm.c
@@ -119,6 +119,7 @@
 } while (0)
 #define PTM_OS_UNLOCK(cpu)						\
 do {									\
+	mb();								\
 	ptm_writel(ptm, cpu, MAGIC2, ETMOSLAR);				\
 	mb();								\
 } while (0)
diff --git a/arch/arm/mach-msm/qdss.h b/arch/arm/mach-msm/qdss.h
index a41d7e2..8d346c4 100644
--- a/arch/arm/mach-msm/qdss.h
+++ b/arch/arm/mach-msm/qdss.h
@@ -56,6 +56,13 @@
 void funnel_enable(uint8_t id, uint32_t port_mask);
 void funnel_disable(uint8_t id, uint32_t port_mask);
 
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
+extern void msm_save_jtag_debug(void);
+extern void msm_restore_jtag_debug(void);
+#else
+static inline void msm_save_jtag_debug(void) {}
+static inline void msm_restore_jtag_debug(void) {}
+#endif
 #ifdef CONFIG_MSM_TRACE_ACROSS_PC
 extern void etm_save_reg_check(void);
 extern void etm_restore_reg_check(void);
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index 962371b..53128ad 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -198,8 +198,8 @@
 		return NULL;
 	}
 
-	strncpy(rd_dev->name, "ramdump_", 256);
-	strncat(rd_dev->name, dev_name, 256);
+	snprintf(rd_dev->name, ARRAY_SIZE(rd_dev->name), "ramdump_%s",
+		 dev_name);
 
 	init_completion(&rd_dev->ramdump_complete);
 
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 00be696..28bf064 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -120,11 +120,11 @@
 #ifdef CONFIG_MSM_DLOAD_MODE
 	set_dload_mode(0);
 #endif
-	if (cpu_is_msm8x60()) {
-		pm8058_reset_pwr_off(0);
-		pm8901_reset_pwr_off(0);
-	}
 	pm8xxx_reset_pwr_off(0);
+
+	if (cpu_is_msm8x60())
+		pm8901_reset_pwr_off(0);
+
 	if (lower_pshold) {
 		__raw_writel(0, PSHOLD_CTL_SU);
 		mdelay(10000);
@@ -202,8 +202,6 @@
 
 	printk(KERN_NOTICE "Going down for restart now\n");
 
-	if (cpu_is_msm8x60())
-		pm8058_reset_pwr_off(1);
 	pm8xxx_reset_pwr_off(1);
 
 	if (cmd != NULL) {
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index bee3c3d..ef2956a 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.c
@@ -264,7 +264,7 @@
 	DECLARE_COMPLETION_ONSTACK(ack);
 	unsigned long flags;
 	uint32_t ctx_mask = msm_rpm_get_ctx_mask(ctx);
-	uint32_t ctx_mask_ack;
+	uint32_t ctx_mask_ack = 0;
 	uint32_t sel_masks_ack[MSM_RPM_SEL_MASK_SIZE];
 	int i;
 
@@ -320,8 +320,9 @@
 	unsigned int irq = msm_rpm_platform->irq_ack;
 	unsigned long flags;
 	uint32_t ctx_mask = msm_rpm_get_ctx_mask(ctx);
-	uint32_t ctx_mask_ack;
+	uint32_t ctx_mask_ack = 0;
 	uint32_t sel_masks_ack[MSM_RPM_SEL_MASK_SIZE];
+	struct irq_chip *irq_chip = NULL;
 	int i;
 
 	msm_rpm_request_poll_mode.req = req;
@@ -331,7 +332,12 @@
 	msm_rpm_request_poll_mode.done = NULL;
 
 	spin_lock_irqsave(&msm_rpm_irq_lock, flags);
-	irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
+	irq_chip = irq_get_chip(irq);
+	if (!irq_chip) {
+		spin_unlock_irqrestore(&msm_rpm_irq_lock, flags);
+		return -ENOSPC;
+	}
+	irq_chip->irq_mask(irq_get_irq_data(irq));
 
 	if (msm_rpm_request) {
 		msm_rpm_busy_wait_for_request_completion(true);
@@ -356,7 +362,7 @@
 	msm_rpm_busy_wait_for_request_completion(false);
 	BUG_ON(msm_rpm_request);
 
-	irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+	irq_chip->irq_unmask(irq_get_irq_data(irq));
 	spin_unlock_irqrestore(&msm_rpm_irq_lock, flags);
 
 	BUG_ON((ctx_mask_ack & ~(msm_rpm_get_ctx_mask(MSM_RPM_CTX_REJECTED)))
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 0cc2272..3e6a7e5 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -306,7 +306,7 @@
 		vdd_mem = MSM_RPMRS_VDD_MEM_ACTIVE;
 	}
 
-	return MSM_RPMRS_VDD(vdd_mem) >=
+	return MSM_RPMRS_VDD(vdd_mem) >
 				MSM_RPMRS_VDD(limits->vdd_mem_upper_bound);
 }
 
@@ -357,7 +357,7 @@
 		vdd_dig = MSM_RPMRS_VDD_DIG_ACTIVE;
 	}
 
-	return MSM_RPMRS_VDD(vdd_dig) >=
+	return MSM_RPMRS_VDD(vdd_dig) >
 				MSM_RPMRS_VDD(limits->vdd_dig_upper_bound);
 }
 
@@ -396,7 +396,7 @@
 		bool irqs_detect, bool gpio_detect)
 {
 
-	if (limits->vdd_dig <= MSM_RPMRS_VDD_DIG_RET_HIGH)
+	if (limits->vdd_dig_upper_bound <= MSM_RPMRS_VDD_DIG_RET_HIGH)
 		return irqs_detect;
 
 	if (limits->pxo == MSM_RPMRS_PXO_OFF)
diff --git a/arch/arm/mach-msm/sdio_al.c b/arch/arm/mach-msm/sdio_al.c
index 891d655..356ce90 100644
--- a/arch/arm/mach-msm/sdio_al.c
+++ b/arch/arm/mach-msm/sdio_al.c
@@ -1223,7 +1223,7 @@
 		   We need to keep reading mailbox to wait for the appropriate
 		   write avail and cannot sleep. Ignore SMEM channel that has
 		   only one direction. */
-		if (strcmp(ch->name, "SDIO_SMEM"))
+		if (strncmp(ch->name, "SDIO_SMEM", CHANNEL_NAME_SIZE))
 			any_write_pending |=
 			(new_write_avail < ch->ch_config.max_tx_threshold);
 	}
@@ -2686,7 +2686,8 @@
 			if (sdio_al_dev->channel[i].state ==
 					SDIO_CHANNEL_STATE_INVALID)
 				continue;
-			if (strcmp(sdio_al_dev->channel[i].name, name) == 0) {
+			if (strncmp(sdio_al_dev->channel[i].name, name,
+					CHANNEL_NAME_SIZE) == 0) {
 				ch = &sdio_al_dev->channel[i];
 				break;
 			}
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index f64fdad..7c7a822 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -154,7 +154,7 @@
 
 	smd_pkt_devp->is_open = 0;
 
-	wake_up_interruptible(&smd_pkt_devp->ch_read_wait_queue);
+	wake_up(&smd_pkt_devp->ch_read_wait_queue);
 	wake_up_interruptible(&smd_pkt_devp->ch_write_wait_queue);
 	wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
 }
@@ -208,6 +208,7 @@
 {
 	int r;
 	int bytes_read;
+	int pkt_size;
 	struct smd_pkt_dev *smd_pkt_devp;
 	struct smd_channel *chl;
 
@@ -228,8 +229,7 @@
 wait_for_packet:
 	r = wait_event_interruptible(smd_pkt_devp->ch_read_wait_queue,
 				     (smd_cur_packet_size(chl) > 0 &&
-				      smd_read_avail(chl) >=
-				      smd_cur_packet_size(chl)) ||
+				      smd_read_avail(chl)) ||
 				     smd_pkt_devp->has_reset);
 
 	if (smd_pkt_devp->has_reset)
@@ -253,35 +253,41 @@
 	/* Here we have a whole packet waiting for us */
 
 	mutex_lock(&smd_pkt_devp->rx_lock);
-	bytes_read = smd_cur_packet_size(smd_pkt_devp->ch);
+	pkt_size = smd_cur_packet_size(smd_pkt_devp->ch);
 
-	D(KERN_ERR "%s: after wait_event_interruptible bytes_read = %i\n",
-	  __func__, bytes_read);
-
-	if (bytes_read == 0 ||
-	    bytes_read < smd_read_avail(smd_pkt_devp->ch)) {
+	if (!pkt_size) {
 		D(KERN_ERR "%s: Nothing to read\n", __func__);
 		mutex_unlock(&smd_pkt_devp->rx_lock);
 		goto wait_for_packet;
 	}
 
-	if (bytes_read > count) {
-		printk(KERN_ERR "packet size %i > buffer size %i, "
-		       "dropping packet!", bytes_read, count);
-		smd_read(smd_pkt_devp->ch, 0, bytes_read);
+	if (pkt_size > count) {
+		pr_err("packet size %i > buffer size %i,", pkt_size, count);
 		mutex_unlock(&smd_pkt_devp->rx_lock);
-		return -EINVAL;
+		return -ETOOSMALL;
 	}
 
-	if (smd_read_user_buffer(smd_pkt_devp->ch, buf, bytes_read)
-	    != bytes_read) {
-		mutex_unlock(&smd_pkt_devp->rx_lock);
-		if (smd_pkt_devp->has_reset)
+	bytes_read = 0;
+	do {
+		r = smd_read_user_buffer(smd_pkt_devp->ch,
+					 (buf + bytes_read),
+					 (pkt_size - bytes_read));
+		if (r < 0) {
+			mutex_unlock(&smd_pkt_devp->rx_lock);
+			if (smd_pkt_devp->has_reset)
+				return notify_reset(smd_pkt_devp);
+			return r;
+		}
+		bytes_read += r;
+		if (pkt_size != bytes_read)
+			wait_event(smd_pkt_devp->ch_read_wait_queue,
+				   smd_read_avail(smd_pkt_devp->ch) ||
+				   smd_pkt_devp->has_reset);
+		if (smd_pkt_devp->has_reset) {
+			mutex_unlock(&smd_pkt_devp->rx_lock);
 			return notify_reset(smd_pkt_devp);
-
-		printk(KERN_ERR "user read: not enough data?!\n");
-		return -EINVAL;
-	}
+		}
+	} while (pkt_size != bytes_read);
 	D_DUMP_BUFFER("read: ", bytes_read, buf);
 	mutex_unlock(&smd_pkt_devp->rx_lock);
 
@@ -425,15 +431,15 @@
 		D(KERN_ERR "%s: packet size is 0\n", __func__);
 		return;
 	}
-	if (sz > smd_read_avail(smd_pkt_devp->ch)) {
+	if (!smd_read_avail(smd_pkt_devp->ch)) {
 		D(KERN_ERR "%s: packet size is %i - "
-		  "the whole packet isn't here\n",
+		  "but the data isn't here\n",
 		  __func__, sz);
 		return;
 	}
 
 	/* here we have a packet of size sz ready */
-	wake_up_interruptible(&smd_pkt_devp->ch_read_wait_queue);
+	wake_up(&smd_pkt_devp->ch_read_wait_queue);
 	D(KERN_ERR "%s: after wake_up\n", __func__);
 }
 
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 206dfd2..96a4563 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -225,6 +225,9 @@
 	/* 8060A ID */
 	[124] = MSM_CPU_8960,
 
+	/* Copper IDs */
+	[126] = MSM_CPU_COPPER,
+
 	/* Uninitialized IDs are not known to run Linux.
 	   MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
 	   considered as unknown CPU. */
@@ -591,6 +594,8 @@
 		dummy_socinfo.id = 109;
 	else if (machine_is_msm9615_mtp() || machine_is_msm9615_cdp())
 		dummy_socinfo.id = 104;
+	else if (early_machine_is_copper())
+		dummy_socinfo.id = 126;
 	return (void *) &dummy_socinfo;
 }
 
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index 11fe26c..db9ab30 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -236,6 +236,7 @@
 	int i = 0, j = 0, ret;
 	unsigned long iova_start = 0, temp_phys, temp_va = 0;
 	struct iommu_domain *d = NULL;
+	int map_size = length;
 
 	if (!((flags & MSM_SUBSYSTEM_MAP_KADDR) ||
 		(flags & MSM_SUBSYSTEM_MAP_IOVA))) {
@@ -302,6 +303,11 @@
 
 		length = round_up(length, SZ_4K);
 
+		if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
+			map_size = 2 * length;
+		else
+			map_size = length;
+
 		buf->iova = kzalloc(sizeof(unsigned long)*nsubsys, GFP_ATOMIC);
 		if (!buf->iova) {
 			err = ERR_PTR(-ENOMEM);
@@ -337,7 +343,7 @@
 
 			iova_start = msm_allocate_iova_address(domain_no,
 						partition_no,
-						length,
+						map_size,
 						max(min_align, SZ_4K));
 
 			if (!iova_start) {
@@ -363,13 +369,17 @@
 				}
 			}
 			buf->iova[i] = iova_start;
+
+			if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
+				msm_iommu_map_extra
+					(d, temp_va, length, 0);
 		}
 
 	}
 
 	node->buf = buf;
 	node->subsystems = subsys_ids;
-	node->length = length;
+	node->length = map_size;
 	node->nsubsys = nsubsys;
 
 	if (add_buffer(node)) {
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index ff699e2..37469f8 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -139,6 +139,11 @@
 	int ret;
 	int old_val = restart_level;
 
+	if (cpu_is_msm9615()) {
+		pr_err("Only Phase 1 subsystem restart is supported\n");
+		return -EINVAL;
+	}
+
 	ret = param_set_int(val, kp);
 	if (ret)
 		return ret;
@@ -252,6 +257,8 @@
 		goto out;
 
 	r_log = kmalloc(sizeof(struct restart_log), GFP_KERNEL);
+	if (!r_log)
+		goto out;
 	r_log->subsys = subsys;
 	do_gettimeofday(&r_log->time);
 	curr_time = &r_log->time;
@@ -569,7 +576,7 @@
 		n_restart_orders = ARRAY_SIZE(orders_8x60_all);
 	}
 
-	if (cpu_is_msm8960() || cpu_is_msm8930()) {
+	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615()) {
 		restart_orders = restart_orders_8960;
 		n_restart_orders = ARRAY_SIZE(restart_orders_8960);
 	}
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index d9488ec..8f24d81 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -166,13 +166,6 @@
 		.regbase = MSM_TMR_BASE + 0x4,
 		.freq = 32768,
 		.index = MSM_CLOCK_GPT,
-		.flags =
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_ARCH_MSM7X27A)
-			MSM_CLOCK_FLAGS_UNSTABLE_COUNT |
-			MSM_CLOCK_FLAGS_ODD_MATCH_WRITE |
-			MSM_CLOCK_FLAGS_DELAYED_WRITE_POST |
-#endif
-			0,
 		.write_delay = 9,
 	},
 	[MSM_CLOCK_DGT] = {
@@ -226,32 +219,32 @@
 
 static uint32_t msm_read_timer_count(struct msm_clock *clock, int global)
 {
-	uint32_t t1, t2;
+	uint32_t t1, t2, t3;
 	int loop_count = 0;
-
-	if (global)
-		t1 = __raw_readl(clock->regbase + TIMER_COUNT_VAL +
-				 global_timer_offset);
-	else
-		t1 = __raw_readl(clock->regbase + TIMER_COUNT_VAL);
+	void __iomem *addr = clock->regbase + TIMER_COUNT_VAL +
+		global*global_timer_offset;
 
 	if (!(clock->flags & MSM_CLOCK_FLAGS_UNSTABLE_COUNT))
-		return t1;
+		return __raw_readl(addr);
+
+	t1 = __raw_readl(addr);
+	t2 = __raw_readl(addr);
+	if ((t2-t1) <= 1)
+		return t2;
 	while (1) {
-		if (global)
-			t2 = __raw_readl(clock->regbase + TIMER_COUNT_VAL +
-					 global_timer_offset);
-		else
-			t2 = __raw_readl(clock->regbase + TIMER_COUNT_VAL);
-		if (t1 == t2)
-			return t1;
-		if (loop_count++ > 10) {
-			printk(KERN_ERR "msm_read_timer_count timer %s did not"
-			       "stabilize %u != %u\n", clock->clockevent.name,
-			       t2, t1);
+		t1 = __raw_readl(addr);
+		t2 = __raw_readl(addr);
+		t3 = __raw_readl(addr);
+		if ((t3-t2) <= 1)
+			return t3;
+		if ((t2-t1) <= 1)
 			return t2;
+		if (++loop_count == 10) {
+			pr_err("msm_read_timer_count timer %s did not "
+			       "stabilize: %u -> %u -> %u\n",
+			       clock->clockevent.name, t1, t2, t3);
+			return t3;
 		}
-		t1 = t2;
 	}
 }
 
@@ -939,12 +932,19 @@
 
 static DEFINE_CLOCK_DATA(cd);
 
+/*
+ * Store the most recent timestamp read from hardware
+ * in last_ns. This is useful for debugging crashes.
+ */
+static u64 last_ns;
+
 unsigned long long notrace sched_clock(void)
 {
 	struct msm_clock *clock = &msm_clocks[msm_global_timer];
 	struct clocksource *cs = &clock->clocksource;
 	u32 cyc = cs->read(cs);
-	return cyc_to_sched_clock(&cd, cyc, ((u32)~0 >> clock->shift));
+	last_ns = cyc_to_sched_clock(&cd, cyc, ((u32)~0 >> clock->shift));
+	return last_ns;
 }
 
 static void notrace msm_update_sched_clock(void)
@@ -987,6 +987,9 @@
 		dgt->clocksource.shift = 24 - MSM_DGT_SHIFT;
 		gpt->regbase = MSM_TMR_BASE;
 		dgt->regbase = MSM_TMR_BASE + 0x10;
+		gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT
+			   |  MSM_CLOCK_FLAGS_ODD_MATCH_WRITE
+			   |  MSM_CLOCK_FLAGS_DELAYED_WRITE_POST;
 	} else if (cpu_is_qsd8x50()) {
 		dgt->freq = 4800000;
 		gpt->regbase = MSM_TMR_BASE;
@@ -1005,6 +1008,8 @@
 		gpt->freq = 32765;
 		gpt_hz = 32765;
 		sclk_hz = 32765;
+		gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+		dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 	} else if (cpu_is_msm8960() || cpu_is_apq8064() || cpu_is_msm8930()) {
 		global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
 		dgt->freq = 6750000;
@@ -1012,9 +1017,12 @@
 		gpt->freq = 32765;
 		gpt_hz = 32765;
 		sclk_hz = 32765;
+		gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+		dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 	} else {
 		WARN_ON("Timer running on unknown hardware. Configure this! "
 			"Assuming default configuration.\n");
+		global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
 		dgt->freq = 6750000;
 	}
 
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index ca501ef..7cd02ff 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -121,7 +121,14 @@
 			else
 				shared += page_count(page) - 1;
 			page++;
+#ifdef CONFIG_SPARSEMEM
+			pfn1++;
+			if (!(pfn1 % PAGES_PER_SECTION))
+				page = pfn_to_page(pfn1);
+		} while (pfn1 < pfn2);
+#else
 		} while (page < end);
+#endif
 	}
 
 	printk("%d pages of RAM\n", total);
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 449d463..46729ee 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -292,12 +292,20 @@
  *	It is assumed that:
  *	- cache type register is implemented
  */
+__v7_ca5mp_setup:
 __v7_ca9mp_setup:
-#if defined(CONFIG_SMP)
-	mrc	p15, 0, r0, c1, c0, 1
+	mov     r10, #(1 << 0)                  @ TLB ops broadcasting
+	b       1f
+__v7_ca15mp_setup:
+	mov     r10, #0
+1:
+#ifdef CONFIG_SMP
+	ALT_SMP(mrc     p15, 0, r0, c1, c0, 1)
+	ALT_UP(mov      r0, #(1 << 6))          @ fake it for UP
 	tst	r0, #(1 << 6)			@ SMP/nAMP mode enabled?
-	orreq	r0, r0, #(1 << 6) | (1 << 0)	@ Enable SMP/nAMP mode and
-	mcreq	p15, 0, r0, c1, c0, 1		@ TLB ops broadcasting
+	orreq   r0, r0, #(1 << 6)               @ Enable SMP/nAMP mode
+	orreq   r0, r0, r10                     @ Enable CPU-specific SMP bits
+	mcreq   p15, 0, r0, c1, c0, 1
 #endif
 __v7_setup:
 	adr	r12, __v7_setup_stack		@ the local stack
@@ -483,35 +491,58 @@
 
 	.section ".proc.info.init", #alloc, #execinstr
 
-	.type   __v7_ca9mp_proc_info, #object
-__v7_ca9mp_proc_info:
-	.long	0x410fc090		@ Required ID value
-	.long	0xff0ffff0		@ Mask for ID
-	ALT_SMP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_SMP)
-	ALT_UP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_UP)
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_XN | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	W(b)	__v7_ca9mp_setup
+	/*
+	 * Standard v7 proc info content
+	 */
+.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0
+	ALT_SMP(.long	PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
+			PMD_FLAGS_SMP | \mm_mmuflags)
+	ALT_UP(.long	PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
+			PMD_FLAGS_UP | \mm_mmuflags)
+	.long	PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ | \io_mmuflags
+	W(b)	\initfunc
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \
+		HWCAP_EDSP | HWCAP_TLS | \hwcaps
 	.long	cpu_v7_name
 	.long	v7_processor_functions
 	.long	v7wbi_tlb_fns
 	.long	v6_user_fns
 	.long	v7_cache_fns
+.endm
+
+	/*
+	 * ARM Ltd. Cortex A5 processor.
+	 */
+	.type   __v7_ca5mp_proc_info, #object
+__v7_ca5mp_proc_info:
+	.long	0x410fc050
+	.long	0xff0ffff0
+	__v7_proc __v7_ca5mp_setup
+	.size	__v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info
+
+	/*
+	 * ARM Ltd. Cortex A9 processor.
+	 */
+	.type   __v7_ca9mp_proc_info, #object
+__v7_ca9mp_proc_info:
+	.long	0x410fc090
+	.long	0xff0ffff0
+	__v7_proc __v7_ca9mp_setup
 	.size	__v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
 
+        /*
+	 * ARM Ltd. Cortex A15 processor.
+	 */
+	.type   __v7_ca15mp_proc_info, #object
+__v7_ca15mp_proc_info:
+	.long   0x410fc0f0
+	.long   0xff0ffff0
+	__v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
+	.size   __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
+
 	/*
 	 * Match any ARMv7 processor core.
 	 */
@@ -519,27 +550,5 @@
 __v7_proc_info:
 	.long	0x000f0000		@ Required ID value
 	.long	0x000f0000		@ Mask for ID
-	ALT_SMP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_SMP)
-	ALT_UP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_UP)
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_XN | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	W(b)	__v7_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
-	.long	cpu_v7_name
-	.long	v7_processor_functions
-	.long	v7wbi_tlb_fns
-	.long	v6_user_fns
-	.long	v7_cache_fns
+	__v7_proc __v7_setup
 	.size	__v7_proc_info, . - __v7_proc_info
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 190f707..2c6957d 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1129,3 +1129,5 @@
 msm7627a_qrd1		MACH_MSM7627A_QRD1	MSM7627A_QRD1		3756
 msm7625a_ffa		MACH_MSM7625A_FFA	MSM7625A_FFA		3771
 msm7625a_surf		MACH_MSM7625A_SURF	MSM7625A_SURF		3772
+msm8627_cdp		MACH_MSM8627_CDP	MSM8627_CDP		3861
+msm8627_mtp		MACH_MSM8627_MTP	MSM8627_MTP		3862
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 3554500..a8a8925 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -612,7 +612,6 @@
 				elf_hwcap |= HWCAP_VFPv3D16;
 		}
 #endif
-#ifdef CONFIG_NEON
 		/*
 		 * Check for the presence of the Advanced SIMD
 		 * load/store instructions, integer and single
@@ -620,10 +619,13 @@
 		 * for NEON if the hardware has the MVFR registers.
 		 */
 		if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
+#ifdef CONFIG_NEON
 			if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
 				elf_hwcap |= HWCAP_NEON;
-		}
 #endif
+			if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000)
+				elf_hwcap |= HWCAP_VFPv4;
+		}
 	}
 	return 0;
 }
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 77f9c79..118bbb3 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -443,6 +443,9 @@
 	smd_close(hs.event_channel);
 	smd_close(hs.data_channel);
 
+	if (wake_lock_active(&hs.wake_lock_rx))
+		wake_unlock(&hs.wake_lock_rx);
+
 	/*Destroy the timer used to monitor the Rx queue for emptiness */
 	del_timer_sync(&hs.rx_q_timer);
 	tasklet_kill(&hs.hci_event_task);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 0ae987a..cac5c81 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -826,8 +826,8 @@
 		return 0;
 	}
 	/* Check for download command */
-	else if ((cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_msm8930())
-							 && (*buf == 0x3A)) {
+	else if ((cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_msm8930()
+		|| cpu_is_msm9615()) && (*buf == 0x3A)) {
 		/* send response back */
 		driver->apps_rsp_buf[0] = *buf;
 		ENCODE_RSP_AND_SEND(0);
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index bb31b6a..696a7bd 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -29,6 +29,7 @@
 #include <linux/file.h>
 #include <linux/major.h>
 #include <linux/regulator/consumer.h>
+#include <linux/ion.h>
 
 #define DRIVER_NAME "msm_rotator"
 
@@ -123,6 +124,7 @@
 	struct mutex imem_lock;
 	int imem_owner;
 	wait_queue_head_t wq;
+	struct ion_client *client;
 };
 
 #define COMPONENT_5BITS 1
@@ -709,57 +711,82 @@
 	return 0;
 }
 
-static int get_img(int memory_id, unsigned long *start, unsigned long *len,
-		struct file **pp_file)
+static int get_img(struct msmfb_data *fbd, unsigned long *start,
+	unsigned long *len, struct file **p_file, struct ion_handle **p_ihdl)
 {
 	int ret = 0;
 #ifdef CONFIG_FB
-	struct file *file;
+	struct file *file = NULL;
 	int put_needed, fb_num;
 #endif
 #ifdef CONFIG_ANDROID_PMEM
 	unsigned long vstart;
 #endif
 
-#ifdef CONFIG_ANDROID_PMEM
-	if (!get_pmem_file(memory_id, start, &vstart, len, pp_file))
-		return 0;
-#endif
 #ifdef CONFIG_FB
-	file = fget_light(memory_id, &put_needed);
-	if (file == NULL)
-		return -1;
+	if (fbd->flags & MDP_MEMORY_ID_TYPE_FB) {
+		file = fget_light(fbd->memory_id, &put_needed);
+		if (file == NULL)
+			return -EINVAL;
 
-	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
-		fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
-		if (get_fb_phys_info(start, len, fb_num))
+		if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+			if (get_fb_phys_info(start, len, fb_num))
+				ret = -1;
+			else
+				*p_file = file;
+		} else
 			ret = -1;
-		else
-			*pp_file = file;
-	} else
-		ret = -1;
-	if (ret)
-		fput_light(file, put_needed);
+		if (ret)
+			fput_light(file, put_needed);
+		return ret;
+	}
 #endif
-	return ret;
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	*p_ihdl = ion_import_fd(msm_rotator_dev->client,
+		fbd->memory_id);
+	if (IS_ERR_OR_NULL(*p_ihdl))
+		return PTR_ERR(*p_ihdl);
+	if (!ion_phys(msm_rotator_dev->client, *p_ihdl, start,
+		(size_t *) len))
+		return 0;
+	else
+		return -ENOMEM;
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+	if (!get_pmem_file(fbd->memory_id, start, &vstart, len, p_file))
+		return 0;
+	else
+		return -ENOMEM;
+#endif
+
 }
 
+static void put_img(struct file *p_file, struct ion_handle *p_ihdl)
+{
+#ifdef CONFIG_ANDROID_PMEM
+	if (p_file != NULL)
+		put_pmem_file(p_file);
+#endif
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	if (!IS_ERR_OR_NULL(p_ihdl))
+		ion_free(msm_rotator_dev->client, p_ihdl);
+#endif
+}
 static int msm_rotator_do_rotate(unsigned long arg)
 {
-	int rc = 0;
-	unsigned int status;
+	unsigned int status, format;
 	struct msm_rotator_data_info info;
 	unsigned int in_paddr, out_paddr;
 	unsigned long src_len, dst_len;
-	struct file *src_file = 0;
-	struct file *dst_file = 0;
-	int use_imem = 0;
-	int s;
-	struct file *src_chroma_file = 0;
-	struct file *dst_chroma_file = 0;
+	int use_imem = 0, rc = 0, s;
+	struct file *srcp0_file = NULL, *dstp0_file = NULL;
+	struct file *srcp1_file = NULL, *dstp1_file = NULL;
+	struct ion_handle *srcp0_ihdl = NULL, *dstp0_ihdl = NULL;
+	struct ion_handle *srcp1_ihdl = NULL, *dstp1_ihdl = NULL;
 	unsigned int in_chroma_paddr = 0, out_chroma_paddr = 0;
 	unsigned int in_chroma2_paddr = 0;
-	uint32_t format;
 	struct msm_rotator_img_info *img_info;
 	struct msm_rotator_mem_planes src_planes, dst_planes;
 
@@ -808,16 +835,16 @@
 		goto do_rotate_unlock_mutex;
 	}
 
-	rc = get_img(info.src.memory_id, (unsigned long *)&in_paddr,
-			(unsigned long *)&src_len, &src_file);
+	rc = get_img(&info.src, (unsigned long *)&in_paddr,
+			(unsigned long *)&src_len, &srcp0_file, &srcp0_ihdl);
 	if (rc) {
 		pr_err("%s: in get_img() failed id=0x%08x\n",
 			DRIVER_NAME, info.src.memory_id);
 		goto do_rotate_unlock_mutex;
 	}
 
-	rc = get_img(info.dst.memory_id, (unsigned long *)&out_paddr,
-			(unsigned long *)&dst_len, &dst_file);
+	rc = get_img(&info.dst, (unsigned long *)&out_paddr,
+			(unsigned long *)&dst_len, &dstp0_file, &dstp0_ihdl);
 	if (rc) {
 		pr_err("%s: out get_img() failed id=0x%08x\n",
 		       DRIVER_NAME, info.dst.memory_id);
@@ -845,18 +872,20 @@
 			goto do_rotate_unlock_mutex;
 		}
 
-		rc = get_img(info.src_chroma.memory_id,
+		rc = get_img(&info.src_chroma,
 				(unsigned long *)&in_chroma_paddr,
-				(unsigned long *)&src_len, &src_chroma_file);
+				(unsigned long *)&src_len, &srcp1_file,
+				&srcp1_ihdl);
 		if (rc) {
 			pr_err("%s: in chroma get_img() failed id=0x%08x\n",
 				DRIVER_NAME, info.src_chroma.memory_id);
 			goto do_rotate_unlock_mutex;
 		}
 
-		rc = get_img(info.dst_chroma.memory_id,
+		rc = get_img(&info.dst_chroma,
 				(unsigned long *)&out_chroma_paddr,
-				(unsigned long *)&dst_len, &dst_chroma_file);
+				(unsigned long *)&dst_len, &dstp1_file,
+				&dstp1_ihdl);
 		if (rc) {
 			pr_err("%s: out chroma get_img() failed id=0x%08x\n",
 				DRIVER_NAME, info.dst_chroma.memory_id);
@@ -1019,14 +1048,10 @@
 #endif
 	schedule_delayed_work(&msm_rotator_dev->rot_clk_work, HZ);
 do_rotate_unlock_mutex:
-	if (dst_chroma_file)
-		put_pmem_file(dst_chroma_file);
-	if (src_chroma_file)
-		put_pmem_file(src_chroma_file);
-	if (dst_file)
-		put_pmem_file(dst_file);
-	if (src_file)
-		put_pmem_file(src_file);
+	put_img(dstp1_file, dstp1_ihdl);
+	put_img(srcp1_file, srcp1_ihdl);
+	put_img(dstp0_file, dstp0_ihdl);
+	put_img(srcp0_file, srcp0_ihdl);
 	mutex_unlock(&msm_rotator_dev->rotator_lock);
 	dev_dbg(msm_rotator_dev->device, "%s() returning rc = %d\n",
 		__func__, rc);
@@ -1361,7 +1386,9 @@
 			  msm_rotator_rot_clk_work_f);
 
 	mutex_init(&msm_rotator_dev->rotator_lock);
-
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	msm_rotator_dev->client = msm_ion_client_create(-1, pdev->name);
+#endif
 	platform_set_drvdata(pdev, msm_rotator_dev);
 
 
@@ -1387,9 +1414,9 @@
 	if (msm_rotator_dev->imem_clk)
 		clk_disable(msm_rotator_dev->imem_clk);
 #endif
-	if (ver != pdata->hardware_version_number) {
+	if (ver != pdata->hardware_version_number)
 		pr_info("%s: invalid HW version\n", DRIVER_NAME);
-	}
+
 	msm_rotator_dev->irq = platform_get_irq(pdev, 0);
 	if (msm_rotator_dev->irq < 0) {
 		printk(KERN_ALERT "%s: could not get IORESOURCE_IRQ\n",
diff --git a/drivers/gpio/pm8xxx-gpio.c b/drivers/gpio/pm8xxx-gpio.c
index 377510f..53305e3 100644
--- a/drivers/gpio/pm8xxx-gpio.c
+++ b/drivers/gpio/pm8xxx-gpio.c
@@ -432,7 +432,7 @@
 
 	return rc;
 }
-EXPORT_SYMBOL_GPL(pm8xxx_gpio_config);
+EXPORT_SYMBOL(pm8xxx_gpio_config);
 
 static struct platform_driver pm_gpio_driver = {
 	.probe		= pm_gpio_probe,
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 60bc276..50420ba 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -618,7 +618,6 @@
 			unsigned int cmd)
 {
 	struct ion_buffer *buffer;
-	unsigned long start, end;
 	int ret = -EINVAL;
 
 	mutex_lock(&client->lock);
@@ -643,14 +642,6 @@
 		goto out;
 	}
 
-	start = (unsigned long) uaddr;
-	end = (unsigned long) uaddr + len;
-
-	if (check_vaddr_bounds(start, end)) {
-		pr_err("%s: virtual address %p is out of bounds\n",
-			__func__, uaddr);
-		goto out;
-	}
 
 	ret = buffer->heap->ops->cache_op(buffer->heap, buffer, uaddr,
 						offset, len, cmd);
@@ -1102,6 +1093,10 @@
 			return -EFAULT;
 		data.handle = ion_alloc(client, data.len, data.align,
 					     data.flags);
+
+		if (IS_ERR_OR_NULL(data.handle))
+			return PTR_ERR(data.handle);
+
 		if (copy_to_user((void __user *)arg, &data, sizeof(data)))
 			return -EFAULT;
 		break;
@@ -1174,11 +1169,21 @@
 	case ION_IOC_CLEAN_INV_CACHES:
 	{
 		struct ion_flush_data data;
+		unsigned long start, end;
 
 		if (copy_from_user(&data, (void __user *)arg,
 				sizeof(struct ion_flush_data)))
 			return -EFAULT;
 
+		start = (unsigned long) data.vaddr;
+		end = (unsigned long) data.vaddr + data.length;
+
+		if (check_vaddr_bounds(start, end)) {
+			pr_err("%s: virtual address %p is out of bounds\n",
+				__func__, data.vaddr);
+			return -EINVAL;
+		}
+
 		return ion_do_cache_op(client, data.handle, data.vaddr,
 					data.offset, data.length, cmd);
 
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b13190d..4138e06 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -114,8 +114,10 @@
 	},
 	.pfp_fw = NULL,
 	.pm4_fw = NULL,
+	.wait_timeout = 10000, /* in milliseconds */
 };
 
+
 /*
  * This is the master list of all GPU cores that are supported by this
  * driver.
@@ -435,8 +437,6 @@
 	adreno_dev = ADRENO_DEVICE(device);
 	device->parentdev = &pdev->dev;
 
-	adreno_dev->wait_timeout = 10000; /* default value in milliseconds */
-
 	init_completion(&device->recovery_gate);
 
 	status = adreno_ringbuffer_init(device);
@@ -1080,6 +1080,7 @@
 {
 	long status = 0;
 	uint io = 1;
+	static uint io_cnt;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 
@@ -1097,12 +1098,9 @@
 		goto done;
 	}
 	if (!kgsl_check_timestamp(device, timestamp)) {
-		if (pwr->active_pwrlevel) {
-			int low_pwrlevel = pwr->num_pwrlevels -
-					KGSL_PWRLEVEL_LOW_OFFSET;
-			if (pwr->active_pwrlevel == low_pwrlevel)
-				io = 0;
-		}
+		io_cnt = (io_cnt + 1) % 100;
+		if (io_cnt < pwr->pwrlevels[pwr->active_pwrlevel].io_fraction)
+			io = 0;
 		mutex_unlock(&device->mutex);
 		/* We need to make sure that the process is placed in wait-q
 		 * before its condition is called */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index c6fceaa..e84d473 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -348,6 +348,12 @@
 			KGSL_PWR_WARN(device, "state -> SUSPEND, device %d\n",
 				device->id);
 			break;
+		case KGSL_STATE_SLUMBER:
+			INIT_COMPLETION(device->hwaccess_gate);
+			device->state = KGSL_STATE_SUSPEND;
+			KGSL_PWR_WARN(device, "state -> SUSPEND, device %d\n",
+				device->id);
+			break;
 		default:
 			KGSL_PWR_ERR(device, "suspend fail, device %d\n",
 					device->id);
@@ -374,28 +380,16 @@
 	KGSL_PWR_WARN(device, "resume start\n");
 	mutex_lock(&device->mutex);
 	if (device->state == KGSL_STATE_SUSPEND) {
-		device->requested_state = KGSL_STATE_ACTIVE;
-		kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
-		status = device->ftbl->start(device, 0);
-		if (status == 0) {
-			device->state = KGSL_STATE_ACTIVE;
-			KGSL_PWR_WARN(device,
-					"state -> ACTIVE, device %d\n",
-					device->id);
-		} else {
-			KGSL_PWR_ERR(device,
-					"resume failed, device %d\n",
-					device->id);
-			device->state = KGSL_STATE_INIT;
-			goto end;
-		}
+		device->state = KGSL_STATE_SLUMBER;
+		status = 0;
+		KGSL_PWR_WARN(device,
+				"state -> SLUMBER, device %d\n",
+				device->id);
 		complete_all(&device->hwaccess_gate);
 	}
 	device->requested_state = KGSL_STATE_NONE;
 
-end:
 	mutex_unlock(&device->mutex);
-	kgsl_check_idle(device);
 	KGSL_PWR_WARN(device, "resume end\n");
 	return status;
 }
@@ -436,9 +430,12 @@
 {
 	struct kgsl_device *device = container_of(h,
 					struct kgsl_device, display_off);
+	KGSL_PWR_WARN(device, "early suspend start\n");
 	mutex_lock(&device->mutex);
-	kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+	device->requested_state = KGSL_STATE_SLUMBER;
+	kgsl_pwrctrl_sleep(device);
 	mutex_unlock(&device->mutex);
+	KGSL_PWR_WARN(device, "early suspend end\n");
 }
 EXPORT_SYMBOL(kgsl_early_suspend_driver);
 
@@ -461,9 +458,13 @@
 {
 	struct kgsl_device *device = container_of(h,
 					struct kgsl_device, display_off);
+	KGSL_PWR_WARN(device, "late resume start\n");
 	mutex_lock(&device->mutex);
-	kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
+	kgsl_pwrctrl_wake(device);
+	device->pwrctrl.restore_slumber = 0;
 	mutex_unlock(&device->mutex);
+	kgsl_check_idle(device);
+	KGSL_PWR_WARN(device, "late resume end\n");
 }
 EXPORT_SYMBOL(kgsl_late_resume_driver);
 
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index e261b84..6ae9258 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -46,6 +46,7 @@
 #define KGSL_STATE_SUSPEND	0x00000010
 #define KGSL_STATE_HUNG		0x00000020
 #define KGSL_STATE_DUMP_AND_RECOVER	0x00000040
+#define KGSL_STATE_SLUMBER	0x00000080
 
 #define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK  0x1000000
 
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 30365a3..e4e561c 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -262,12 +262,12 @@
 	iommu_virt_addr = memdesc->gpuaddr;
 
 	ret = iommu_map_range(domain, iommu_virt_addr, memdesc->sg,
-				memdesc->size, MSM_IOMMU_ATTR_NONCACHED);
+				memdesc->size, 0);
 	if (ret) {
 		KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) "
 				"failed with err: %d\n", domain,
 				iommu_virt_addr, memdesc->sg, memdesc->size,
-				MSM_IOMMU_ATTR_NONCACHED, ret);
+				0, ret);
 		return ret;
 	}
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 343a39a..8ec9572 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -340,7 +340,6 @@
 		}
 	}
 }
-EXPORT_SYMBOL(kgsl_pwrctrl_clk);
 
 void kgsl_pwrctrl_axi(struct kgsl_device *device, int state)
 {
@@ -377,8 +376,6 @@
 		}
 	}
 }
-EXPORT_SYMBOL(kgsl_pwrctrl_axi);
-
 
 void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state)
 {
@@ -402,7 +399,6 @@
 		}
 	}
 }
-EXPORT_SYMBOL(kgsl_pwrctrl_pwrrail);
 
 void kgsl_pwrctrl_irq(struct kgsl_device *device, int state)
 {
@@ -479,6 +475,8 @@
 					   gpu_freq) : 0;
 		pwr->pwrlevels[i].bus_freq =
 			pdata_pwr->pwrlevel[i].bus_freq;
+		pwr->pwrlevels[i].io_fraction =
+			pdata_pwr->pwrlevel[i].io_fraction;
 	}
 	/* Do not set_rate for targets in sync with AXI */
 	if (pwr->pwrlevels[0].gpu_freq > 0)
@@ -583,7 +581,8 @@
 
 	mutex_lock(&device->mutex);
 	if (device->state & (KGSL_STATE_ACTIVE | KGSL_STATE_NAP)) {
-		if (device->requested_state != KGSL_STATE_SLEEP)
+		if ((device->requested_state != KGSL_STATE_SLEEP) &&
+			(device->requested_state != KGSL_STATE_SLUMBER))
 			kgsl_pwrscale_idle(device);
 
 		if (kgsl_pwrctrl_sleep(device) != 0) {
@@ -621,7 +620,8 @@
 void kgsl_pre_hwaccess(struct kgsl_device *device)
 {
 	BUG_ON(!mutex_is_locked(&device->mutex));
-	if (device->state & (KGSL_STATE_SLEEP | KGSL_STATE_NAP))
+	if (device->state & (KGSL_STATE_SLEEP | KGSL_STATE_NAP |
+				KGSL_STATE_SLUMBER))
 		kgsl_pwrctrl_wake(device);
 }
 EXPORT_SYMBOL(kgsl_pre_hwaccess);
@@ -633,14 +633,46 @@
 		mutex_unlock(&device->mutex);
 		wait_for_completion(&device->hwaccess_gate);
 		mutex_lock(&device->mutex);
-	}
-	if (device->state == KGSL_STATE_DUMP_AND_RECOVER) {
+	} else if (device->state == KGSL_STATE_DUMP_AND_RECOVER) {
 		mutex_unlock(&device->mutex);
 		wait_for_completion(&device->recovery_gate);
 		mutex_lock(&device->mutex);
-	}
- }
+	} else if (device->state == KGSL_STATE_SLUMBER)
+		kgsl_pwrctrl_wake(device);
+}
 
+static int
+_slumber(struct kgsl_device *device)
+{
+	int status = -EINVAL;
+	if (!device)
+		return -EINVAL;
+	KGSL_PWR_WARN(device, "Slumber start\n");
+
+	device->requested_state = KGSL_STATE_SLUMBER;
+	del_timer(&device->idle_timer);
+	switch (device->state) {
+	case KGSL_STATE_ACTIVE:
+		/* Wait for the device to become idle */
+		device->ftbl->idle(device, KGSL_TIMEOUT_DEFAULT);
+	case KGSL_STATE_NAP:
+	case KGSL_STATE_SLEEP:
+		device->ftbl->suspend_context(device);
+		device->ftbl->stop(device);
+		device->state = KGSL_STATE_SLUMBER;
+		device->pwrctrl.restore_slumber = 1;
+		KGSL_PWR_WARN(device, "state -> SLUMBER, device %d\n",
+				device->id);
+		break;
+	default:
+		break;
+	}
+	status = 0;
+	/* Don't set requested state to NONE
+	It's done in kgsl_pwrctrl_sleep*/
+	KGSL_PWR_WARN(device, "Done going to slumber\n");
+	return status;
+}
 
 /******************************************************************/
 /* Caller must hold the device mutex. */
@@ -650,18 +682,32 @@
 	KGSL_PWR_INFO(device, "sleep device %d\n", device->id);
 
 	/* Work through the legal state transitions */
-	if (device->requested_state == KGSL_STATE_NAP) {
-		if (device->ftbl->isidle(device))
+	if ((device->requested_state == KGSL_STATE_NAP)) {
+		if (device->pwrctrl.restore_slumber) {
+			device->requested_state = KGSL_STATE_NONE;
+			return 0;
+		} else if (device->ftbl->isidle(device))
 			goto nap;
 	} else if (device->requested_state == KGSL_STATE_SLEEP) {
 		if (device->state == KGSL_STATE_NAP ||
-			device->ftbl->isidle(device))
-			goto sleep;
+			device->ftbl->isidle(device)) {
+			if (!device->pwrctrl.restore_slumber)
+				goto sleep;
+			else
+				goto slumber;
+			}
+	} else if (device->requested_state == KGSL_STATE_SLUMBER) {
+		if (device->ftbl->isidle(device))
+			goto slumber;
 	}
 
 	device->requested_state = KGSL_STATE_NONE;
 	return -EBUSY;
 
+
+slumber:
+	_slumber(device);
+
 sleep:
 	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
 	kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
@@ -693,6 +739,24 @@
 }
 EXPORT_SYMBOL(kgsl_pwrctrl_sleep);
 
+static int
+_wake_from_slumber(struct kgsl_device *device)
+{
+	int status = -EINVAL;
+	if (!device)
+		return -EINVAL;
+
+	KGSL_PWR_WARN(device, "wake from slumber start\n");
+
+	device->requested_state = KGSL_STATE_ACTIVE;
+	kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+	status = device->ftbl->start(device, 0);
+	device->requested_state = KGSL_STATE_NONE;
+
+	KGSL_PWR_WARN(device, "Done waking from slumber\n");
+	return status;
+}
+
 /******************************************************************/
 /* Caller must hold the device mutex. */
 void kgsl_pwrctrl_wake(struct kgsl_device *device)
@@ -700,6 +764,9 @@
 	if (device->state == KGSL_STATE_SUSPEND)
 		return;
 
+	if (device->state == KGSL_STATE_SLUMBER)
+		_wake_from_slumber(device);
+
 	if (device->state != KGSL_STATE_NAP) {
 		kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
 		kgsl_pwrscale_wake(device);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 127a19b..9bf3c0f 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -21,7 +21,6 @@
 
 #define KGSL_PWRLEVEL_TURBO 0
 #define KGSL_PWRLEVEL_NOMINAL 1
-#define KGSL_PWRLEVEL_LOW_OFFSET 2
 
 #define KGSL_MAX_CLKS 5
 
@@ -56,11 +55,9 @@
 	const char *src_clk_name;
 	s64 time;
 	struct kgsl_busy busy;
+	unsigned int restore_slumber;
 };
 
-void kgsl_pwrctrl_clk(struct kgsl_device *device, int state);
-void kgsl_pwrctrl_axi(struct kgsl_device *device, int state);
-void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state);
 void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
 int kgsl_pwrctrl_init(struct kgsl_device *device);
 void kgsl_pwrctrl_close(struct kgsl_device *device);
diff --git a/drivers/hwmon/msm_adc.c b/drivers/hwmon/msm_adc.c
index 42bcd07..b8d581e 100644
--- a/drivers/hwmon/msm_adc.c
+++ b/drivers/hwmon/msm_adc.c
@@ -98,6 +98,8 @@
 /* Needed to support file_op interfaces */
 static struct msm_adc_drv *msm_adc_drv;
 
+static bool conv_first_request;
+
 static ssize_t msm_adc_show_curr(struct device *dev,
 				struct device_attribute *devattr, char *buf);
 
@@ -726,6 +728,16 @@
 	struct msm_adc_platform_data *pdata =
 					msm_adc_drv->pdev->dev.platform_data;
 	struct msm_adc_channels *channel = &pdata->channel[hwmon_chan];
+	int ret = 0;
+
+	if (conv_first_request) {
+		ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
+		if (ret) {
+			pr_err("pmic8058 xoadc calibration failed, retry\n");
+			return ret;
+		}
+		conv_first_request = false;
+	}
 
 	channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
 									&slot);
@@ -813,6 +825,16 @@
 					msm_adc_drv->pdev->dev.platform_data;
 	struct msm_adc_channels *channel = &pdata->channel[client->adc_chan];
 	struct adc_conv_slot *slot;
+	int ret;
+
+	if (conv_first_request) {
+		ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
+		if (ret) {
+			pr_err("pmic8058 xoadc calibration failed, retry\n");
+			return ret;
+		}
+		conv_first_request = false;
+	}
 
 	channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
 									&slot);
@@ -871,46 +893,6 @@
 	return rc;
 }
 
-int32_t adc_calib_request(void *h, struct completion *calib_complete_evt)
-{
-	struct msm_client_data *client = (struct msm_client_data *)h;
-	struct msm_adc_platform_data *pdata =
-					msm_adc_drv->pdev->dev.platform_data;
-	struct msm_adc_channels *channel = &pdata->channel[client->adc_chan];
-	struct adc_conv_slot *slot;
-	int rc, calib_status;
-
-	channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
-				&slot);
-	if (slot) {
-		slot->conv.result.chan = client->adc_chan;
-		slot->blocking = 0;
-		slot->compk = calib_complete_evt;
-		slot->adc_request = START_OF_CALIBRATION;
-		slot->chan_path = channel->chan_path_type;
-		slot->chan_adc_config = channel->adc_config_type;
-		slot->chan_adc_calib = channel->adc_calib_type;
-		rc = channel->adc_access_fn->adc_calibrate(
-			channel->adc_dev_instance, slot, &calib_status);
-
-		if (calib_status == CALIB_NOT_REQUIRED) {
-			channel->adc_access_fn->adc_restore_slot(
-					channel->adc_dev_instance, slot);
-			/* client will always wait in case when
-				calibration is not required */
-			complete(calib_complete_evt);
-		} else {
-			atomic_inc(&msm_adc_drv->total_outst);
-			mutex_lock(&client->lock);
-			client->num_outstanding++;
-			mutex_unlock(&client->lock);
-		}
-
-		return rc;
-	}
-	return -EBUSY;
-}
-
 static void msm_rpc_adc_conv_cb(void *context, u32 param,
 			    void *evt_buf, u32 len)
 {
@@ -1458,6 +1440,7 @@
 		else
 			msm_rpc_adc_init(pdev);
 	}
+	conv_first_request = true;
 
 	pr_info("msm_adc successfully registered\n");
 
diff --git a/drivers/hwmon/pm8xxx-adc-scale.c b/drivers/hwmon/pm8xxx-adc-scale.c
index 40ade69..7b27f72 100644
--- a/drivers/hwmon/pm8xxx-adc-scale.c
+++ b/drivers/hwmon/pm8xxx-adc-scale.c
@@ -34,81 +34,89 @@
 };
 
 static const struct pm8xxx_adc_map_pt adcmap_btm_threshold[] = {
-	{-30,	41001},
-	{-20,	40017},
-	{-10,	38721},
-	{0,	37186},
-	{10,	35554},
-	{11,	35392},
-	{12,	35230},
-	{13,	35070},
-	{14,	34910},
-	{15,	34751},
-	{16,	34594},
-	{17,	34438},
-	{18,	34284},
-	{19,	34131},
-	{20,	33980},
-	{21,	33830},
-	{22,	33683},
-	{23,	33538},
-	{24,	33394},
-	{25,	33253},
-	{26,	33114},
-	{27,	32977},
-	{28,	32842},
-	{29,	32710},
-	{30,	32580},
-	{31,	32452},
-	{32,	32327},
-	{33,	32204},
-	{34,	32084},
-	{35,	31966},
-	{36,	31850},
-	{37,	31737},
-	{38,	31627},
-	{39,	31518},
-	{40,	31412},
-	{41,	31309},
-	{42,	31208},
-	{43,	31109},
-	{44,	31013},
-	{45,	30918},
-	{46,	30827},
-	{47,	30737},
-	{48,	30649},
-	{49,	30564},
-	{50,	30481},
-	{51,	30400},
-	{52,	30321},
-	{53,	30244},
-	{54,	30169},
-	{55,	30096},
-	{56,	30025},
-	{57,	29956},
-	{58,	29889},
-	{59,	29823},
-	{60,	29759},
-	{61,	29697},
-	{62,	29637},
-	{63,	29578},
-	{64,	29521},
-	{65,	29465},
-	{66,	29411},
-	{67,	29359},
-	{68,	29308},
-	{69,	29258},
-	{70,	29209},
-	{71,	29162},
-	{72,	29117},
-	{73,	29072},
-	{74,	29029},
-	{75,	28987},
-	{76,	28946},
-	{77,	28906},
-	{78,	28868},
-	{79,	28830},
-	{80,	28794}
+	{-30,	1642},
+	{-20,	1544},
+	{-10,	1414},
+	{0,	1260},
+	{1,	1244},
+	{2,	1228},
+	{3,	1212},
+	{4,	1195},
+	{5,	1179},
+	{6,	1162},
+	{7,	1146},
+	{8,	1129},
+	{9,	1113},
+	{10,	1097},
+	{11,	1080},
+	{12,	1064},
+	{13,	1048},
+	{14,	1032},
+	{15,	1016},
+	{16,	1000},
+	{17,	985},
+	{18,	969},
+	{19,	954},
+	{20,	939},
+	{21,	924},
+	{22,	909},
+	{23,	894},
+	{24,	880},
+	{25,	866},
+	{26,	852},
+	{27,	838},
+	{28,	824},
+	{29,	811},
+	{30,	798},
+	{31,	785},
+	{32,	773},
+	{33,	760},
+	{34,	748},
+	{35,	736},
+	{36,	725},
+	{37,	713},
+	{38,	702},
+	{39,	691},
+	{40,	681},
+	{41,	670},
+	{42,	660},
+	{43,	650},
+	{44,	640},
+	{45,	631},
+	{46,	622},
+	{47,	613},
+	{48,	604},
+	{49,	595},
+	{50,	587},
+	{51,	579},
+	{52,	571},
+	{53,	563},
+	{54,	556},
+	{55,	548},
+	{56,	541},
+	{57,	534},
+	{58,	527},
+	{59,	521},
+	{60,	514},
+	{61,	508},
+	{62,	502},
+	{63,	496},
+	{64,	490},
+	{65,	485},
+	{66,	281},
+	{67,	274},
+	{68,	267},
+	{69,	260},
+	{70,	254},
+	{71,	247},
+	{72,	241},
+	{73,	235},
+	{74,	229},
+	{75,	224},
+	{76,	218},
+	{77,	213},
+	{78,	208},
+	{79,	203}
 };
 
 static const struct pm8xxx_adc_map_pt adcmap_pa_therm[] = {
@@ -597,7 +605,9 @@
 }
 EXPORT_SYMBOL_GPL(pm8xxx_adc_tdkntcg_therm);
 
-int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *btm_param)
+int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *btm_param,
+		const struct pm8xxx_adc_properties *adc_properties,
+		const struct pm8xxx_adc_chan_properties *chan_properties)
 {
 	int rc;
 
@@ -606,14 +616,29 @@
 		ARRAY_SIZE(adcmap_btm_threshold),
 		btm_param->low_thr_temp,
 		&btm_param->low_thr_voltage);
+	if (rc)
+		return rc;
 
-	if (!rc) {
-		rc = pm8xxx_adc_map_linear(
-			adcmap_btm_threshold,
-			ARRAY_SIZE(adcmap_btm_threshold),
-			btm_param->high_thr_temp,
-			&btm_param->high_thr_voltage);
-	}
+	btm_param->low_thr_voltage *=
+		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
+	do_div(btm_param->low_thr_voltage, adc_properties->adc_vdd_reference);
+	btm_param->low_thr_voltage +=
+		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
+
+	rc = pm8xxx_adc_map_linear(
+		adcmap_btm_threshold,
+		ARRAY_SIZE(adcmap_btm_threshold),
+		btm_param->high_thr_temp,
+		&btm_param->high_thr_voltage);
+	if (rc)
+		return rc;
+
+	btm_param->high_thr_voltage *=
+		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
+	do_div(btm_param->high_thr_voltage, adc_properties->adc_vdd_reference);
+	btm_param->high_thr_voltage +=
+		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
+
 
 	return rc;
 }
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 152eb40..5da80d9 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -121,6 +121,7 @@
 #define PM8XXX_ADC_PA_THERM_VREG_UV_MIN			1800000
 #define PM8XXX_ADC_PA_THERM_VREG_UV_MAX			1800000
 #define PM8XXX_ADC_PA_THERM_VREG_UA_LOAD		100000
+#define PM8XXX_ADC_HWMON_NAME_LENGTH			32
 
 struct pm8xxx_adc {
 	struct device				*dev;
@@ -654,6 +655,10 @@
 					(calib_read_1 - calib_read_2);
 	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].dx =
 					adc_pmic->adc_prop->adc_vdd_reference;
+	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_vref =
+					calib_read_1;
+	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd =
+					calib_read_2;
 calib_fail:
 	rc = pm8xxx_adc_arb_cntrl(0, CHANNEL_NONE);
 	if (rc < 0) {
@@ -694,11 +699,12 @@
 	if (channel < PM8XXX_CHANNEL_MPP_SCALE1_IDX) {
 		mpp_scale = PREMUX_MPP_SCALE_0;
 		adc_pmic->conv->amux_channel = channel;
-	} else if (channel >= PM8XXX_CHANNEL_MPP_SCALE1_IDX) {
+	} else if (channel >= PM8XXX_CHANNEL_MPP_SCALE1_IDX &&
+			channel < PM8XXX_CHANNEL_MPP_SCALE3_IDX) {
 		mpp_scale = PREMUX_MPP_SCALE_1;
 		adc_pmic->conv->amux_channel = channel %
 				PM8XXX_CHANNEL_MPP_SCALE1_IDX;
-	} else if (channel >= PM8XXX_CHANNEL_MPP_SCALE3_IDX) {
+	} else {
 		mpp_scale = PREMUX_MPP_SCALE_1_DIV3;
 		adc_pmic->conv->amux_channel = channel %
 				PM8XXX_CHANNEL_MPP_SCALE3_IDX;
@@ -830,7 +836,8 @@
 		return -EINVAL;
 	}
 
-	rc = pm8xxx_adc_batt_scaler(btm_param);
+	rc = pm8xxx_adc_batt_scaler(btm_param, adc_pmic->adc_prop,
+					adc_pmic->conv->chan_prop);
 	if (rc < 0) {
 		pr_err("Failed to lookup the BTM thresholds\n");
 		return rc;
@@ -1014,9 +1021,8 @@
 	if (rc)
 		return 0;
 
-	return snprintf(buf, sizeof(struct pm8xxx_adc_chan_result),
-				"Result:%lld Raw:%d\n",
-				result.physical, result.adc_code);
+	return snprintf(buf, PM8XXX_ADC_HWMON_NAME_LENGTH,
+		"Result:%lld Raw:%d\n", result.physical, result.adc_code);
 }
 
 static int get_adc(void *data, u64 *val)
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 7a3df4d1..3dbbf15 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -477,7 +477,7 @@
 							addr) << 16),
 					dev->base + QUP_OUT_FIFO_BASE);
 
-			qup_verify_fifo(dev, *carry_over | QUP_OUT_DATA << 16 |
+			qup_verify_fifo(dev, *carry_over | QUP_OUT_START << 16 |
 				addr << 16, (uint32_t)dev->base +
 				QUP_OUT_FIFO_BASE + (*idx) - 2, 0);
 		} else
@@ -541,14 +541,15 @@
 					QUP_OUT_FIFO_BASE + (*idx), 0);
 				*idx += 2;
 			} else if (next->flags == 0 && dev->pos == msg->len - 1
-					&& *idx < (dev->wr_sz*2)) {
+					&& *idx < (dev->wr_sz*2) &&
+					(next->addr != msg->addr)) {
 				/* Last byte of an intermittent write */
-				writel_relaxed((last_entry |
+				writel_relaxed((QUP_OUT_STOP |
 						msg->buf[dev->pos]),
 					dev->base + QUP_OUT_FIFO_BASE);
 
 				qup_verify_fifo(dev,
-					last_entry | msg->buf[dev->pos],
+					QUP_OUT_STOP | msg->buf[dev->pos],
 					(uint32_t)dev->base +
 					QUP_OUT_FIFO_BASE + (*idx), 0);
 				*idx += 2;
@@ -605,7 +606,7 @@
 	struct i2c_msg *next = NULL;
 	if (rem > 1)
 		next = dev->msg + 1;
-	while (rem > 1 && next->flags == 0) {
+	while (rem > 1 && next->flags == 0 && (next->addr == dev->msg->addr)) {
 		len += next->len + 1;
 		next = next + 1;
 		rem--;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 0822866..6db0da1 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -401,17 +401,6 @@
 	  Say Y here to enable the driver for the keypad matrix interface
 	  on the Qualcomm PM8058 power management I/C device.
 
-config KEYBOARD_PMIC8XXX
-	tristate "Qualcomm PMIC8XXX keypad support"
-	depends on MFD_PM8XXX
-	help
-	  Say Y here if you want to enable the driver for the PMIC8XXX
-	  keypad provided as a reference design from Qualcomm. This is intended
-	  to support upto 18x8 matrix based keypad design.
-
-	  To compile this driver as a module, choose M here: the module will
-	  be called pmic8xxx-keypad.
-
 config KEYBOARD_PXA27x
 	tristate "PXA27x/PXA3xx keypad support"
 	depends on PXA27x || PXA3xx || ARCH_MMP
diff --git a/drivers/input/misc/pmic8058-othc.c b/drivers/input/misc/pmic8058-othc.c
index c6be119..a28e8e1 100644
--- a/drivers/input/misc/pmic8058-othc.c
+++ b/drivers/input/misc/pmic8058-othc.c
@@ -27,7 +27,7 @@
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 
-#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/pmic8058-othc.h>
 #include <linux/msm_adc.h>
 
@@ -68,6 +68,7 @@
 	void *adc_handle;
 	void *accessory_adc_handle;
 	spinlock_t lock;
+	struct device *dev;
 	struct regulator *othc_vreg;
 	struct input_dev *othc_ipd;
 	struct switch_dev othc_sdev;
@@ -75,7 +76,6 @@
 	struct othc_accessory_info *accessory_info;
 	struct hrtimer timer;
 	struct othc_n_switch_config *switch_config;
-	struct pm8058_chip *pm_chip;
 	struct work_struct switch_work;
 	struct delayed_work detect_work;
 	struct delayed_work hs_work;
@@ -149,7 +149,7 @@
 		return -EINVAL;
 	}
 
-	rc = pm8058_read(dd->pm_chip, dd->othc_base + 1, &reg, 1);
+	rc = pm8xxx_readb(dd->dev->parent, dd->othc_base + 1, &reg);
 	if (rc < 0) {
 		pr_err("PM8058 read failed\n");
 		return rc;
@@ -158,7 +158,7 @@
 	reg &= PM8058_OTHC_EN_SIG_MASK;
 	reg |= (enable << PM8058_OTHC_EN_SIG_SHIFT);
 
-	rc = pm8058_write(dd->pm_chip, dd->othc_base + 1, &reg, 1);
+	rc = pm8xxx_writeb(dd->dev->parent, dd->othc_base + 1, reg);
 	if (rc < 0) {
 		pr_err("PM8058 write failed\n");
 		return rc;
@@ -446,7 +446,7 @@
 
 	if (dd->ir_gpio < 0) {
 		/* Check the MIC_BIAS status */
-		rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir);
+		rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_ir);
 		if (rc < 0) {
 			pr_err("Unable to read IR status from PMIC\n");
 			goto fail_ir_accessory;
@@ -462,7 +462,7 @@
 	}
 
 	/* Check the switch status */
-	rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_sw);
+	rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_sw);
 	if (rc < 0) {
 		pr_err("Unable to read SWITCH status\n");
 		goto fail_ir_accessory;
@@ -576,7 +576,7 @@
 	}
 	spin_unlock_irqrestore(&dd->lock, flags);
 
-	level = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_sw);
+	level = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_sw);
 	if (level < 0) {
 		pr_err("Unable to read IRQ status register\n");
 		return IRQ_HANDLED;
@@ -641,7 +641,7 @@
 	disable_irq_nosync(dd->othc_irq_ir);
 
 	/* Check the MIC_BIAS status, to check if inserted or removed */
-	rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir);
+	rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_ir);
 	if (rc < 0) {
 		pr_err("Unable to read IR status\n");
 		goto fail_ir;
@@ -666,7 +666,7 @@
 
 	/* Intialize the OTHC module */
 	/* Control Register 1*/
-	rc = pm8058_read(dd->pm_chip, base_addr, &reg, 1);
+	rc = pm8xxx_readb(dd->dev->parent, base_addr, &reg);
 	if (rc < 0) {
 		pr_err("PM8058 read failed\n");
 		return rc;
@@ -676,14 +676,14 @@
 	value = (hsed_config->othc_highcurr_thresh_uA / 100) - 2;
 	reg =  (reg & PM8058_OTHC_HIGH_CURR_MASK) | value;
 
-	rc = pm8058_write(dd->pm_chip, base_addr, &reg, 1);
+	rc = pm8xxx_writeb(dd->dev->parent, base_addr, reg);
 	if (rc < 0) {
 		pr_err("PM8058 read failed\n");
 		return rc;
 	}
 
 	/* Control register 2*/
-	rc = pm8058_read(dd->pm_chip, base_addr + 1, &reg, 1);
+	rc = pm8xxx_readb(dd->dev->parent, base_addr + 1, &reg);
 	if (rc < 0) {
 		pr_err("PM8058 read failed\n");
 		return rc;
@@ -718,14 +718,14 @@
 	}
 	reg = (reg &  PM8058_OTHC_CLK_PREDIV_MASK) | (value - 1);
 
-	rc = pm8058_write(dd->pm_chip, base_addr + 1, &reg, 1);
+	rc = pm8xxx_writeb(dd->dev->parent, base_addr + 1, reg);
 	if (rc < 0) {
 		pr_err("PM8058 read failed\n");
 		return rc;
 	}
 
 	/* Control register 3 */
-	rc = pm8058_read(dd->pm_chip, base_addr + 2 , &reg, 1);
+	rc = pm8xxx_readb(dd->dev->parent, base_addr + 2 , &reg);
 	if (rc < 0) {
 		pr_err("PM8058 read failed\n");
 		return rc;
@@ -748,7 +748,7 @@
 	}
 	reg = (reg & PM8058_OTHC_PERIOD_CLK_MASK) | value;
 
-	rc = pm8058_write(dd->pm_chip, base_addr + 2, &reg, 1);
+	rc = pm8xxx_writeb(dd->dev->parent, base_addr + 2, reg);
 	if (rc < 0) {
 		pr_err("PM8058 read failed\n");
 		return rc;
@@ -1006,7 +1006,7 @@
 
 	/* Check if the accessory is already inserted during boot up */
 	if (dd->ir_gpio < 0) {
-		rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir);
+		rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_ir);
 		if (rc < 0) {
 			pr_err("Unable to get accessory status at boot\n");
 			goto fail_ir_status;
@@ -1061,22 +1061,9 @@
 {
 	int rc;
 	struct pm8058_othc *dd;
-	struct pm8058_chip *chip;
 	struct resource *res;
 	struct pmic8058_othc_config_pdata *pdata = pd->dev.platform_data;
 
-	chip = dev_get_drvdata(pd->dev.parent);
-	if (chip == NULL) {
-		pr_err("Invalid driver information\n");
-		return  -EINVAL;
-	}
-
-	/* Check PMIC8058 version. A0 version is not supported */
-	if (pm8058_rev(chip) == PM_8058_REV_1p0) {
-		pr_err("PMIC8058 version not supported\n");
-		return -ENODEV;
-	}
-
 	if (pdata == NULL) {
 		pr_err("Platform data not present\n");
 		return -EINVAL;
@@ -1101,8 +1088,8 @@
 		goto fail_get_res;
 	}
 
+	dd->dev = &pd->dev;
 	dd->othc_pdata = pdata;
-	dd->pm_chip = chip;
 	dd->othc_base = res->start;
 	if (pdata->micbias_regulator == NULL) {
 		pr_err("OTHC regulator not specified\n");
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 4c19222..790a9e1 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -835,18 +835,19 @@
 	/* Get object table information */
 	error = mxt_get_object_table(data);
 	if (error)
-		return error;
+		goto free_object_table;
 
 	/* Check register init values */
 	error = mxt_check_reg_init(data);
 	if (error)
-		return error;
+		goto free_object_table;
 
 	/* Store T7 and T9 locally, used in suspend/resume operations */
 	t7_object = mxt_get_object(data, MXT_GEN_POWER);
 	if (!t7_object) {
 		dev_err(&client->dev, "Failed to get T7 object\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto free_object_table;
 	}
 
 	data->t7_start_addr = t7_object->start_address;
@@ -854,14 +855,14 @@
 				T7_DATA_SIZE, data->t7_data);
 	if (error < 0) {
 		dev_err(&client->dev,
-			"failed to save current power state\n");
-		return error;
+			"Failed to save current power state\n");
+		goto free_object_table;
 	}
 	error = mxt_read_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_CTRL,
 			&data->t9_ctrl);
 	if (error < 0) {
-		dev_err(&client->dev, "failed to save current touch object\n");
-		return error;
+		dev_err(&client->dev, "Failed to save current touch object\n");
+		goto free_object_table;
 	}
 
 	/* Backup to memory */
@@ -874,12 +875,13 @@
 					MXT_COMMAND_BACKUPNV,
 					&command_register);
 		if (error)
-			return error;
+			goto free_object_table;
 		usleep_range(1000, 2000);
 	} while ((command_register != 0) && (++timeout_counter <= 100));
 	if (timeout_counter > 100) {
 		dev_err(&client->dev, "No response after backup!\n");
-		return -EIO;
+		error = -EIO;
+		goto free_object_table;
 	}
 
 
@@ -892,12 +894,12 @@
 	/* Update matrix size at info struct */
 	error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
 	if (error)
-		return error;
+		goto free_object_table;
 	info->matrix_xsize = val;
 
 	error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
 	if (error)
-		return error;
+		goto free_object_table;
 	info->matrix_ysize = val;
 
 	dev_info(&client->dev,
@@ -911,6 +913,10 @@
 			info->object_num);
 
 	return 0;
+
+free_object_table:
+	kfree(data->object_table);
+	return error;
 }
 
 static ssize_t mxt_object_show(struct device *dev,
@@ -1484,7 +1490,7 @@
 		error = mxt_regulator_configure(data, true);
 	if (error) {
 		dev_err(&client->dev, "Failed to intialize hardware\n");
-		goto err_free_object;
+		goto err_free_mem;
 	}
 
 	if (pdata->power_on)
@@ -1504,7 +1510,7 @@
 			pdata->irqflags, client->dev.driver->name, data);
 	if (error) {
 		dev_err(&client->dev, "Failed to register interrupt\n");
-		goto err_power_on;
+		goto err_free_object;
 	}
 
 	error = mxt_make_highchg(data);
@@ -1534,6 +1540,8 @@
 	input_dev = NULL;
 err_free_irq:
 	free_irq(client->irq, data);
+err_free_object:
+	kfree(data->object_table);
 err_power_on:
 	if (pdata->power_on)
 		pdata->power_on(false);
@@ -1544,8 +1552,6 @@
 		pdata->init_hw(false);
 	else
 		mxt_regulator_configure(data, false);
-err_free_object:
-	kfree(data->object_table);
 err_free_mem:
 	input_free_device(input_dev);
 	kfree(data);
diff --git a/drivers/input/touchscreen/cy8c_ts.c b/drivers/input/touchscreen/cy8c_ts.c
index ac4138e..f708582 100644
--- a/drivers/input/touchscreen/cy8c_ts.c
+++ b/drivers/input/touchscreen/cy8c_ts.c
@@ -197,8 +197,7 @@
 	input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
 	input_report_abs(ts->input, ABS_MT_POSITION_X, x);
 	input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
-	input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, pressure);
-	input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, ts->dd->finger_size);
+	input_report_abs(ts->input, ABS_MT_PRESSURE, pressure);
 	input_mt_sync(ts->input);
 }
 
@@ -227,8 +226,7 @@
 	}
 
 	for (i = 0; i < ts->prev_touches - touches; i++) {
-		input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 0);
-		input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 0);
+		input_report_abs(ts->input, ABS_MT_PRESSURE, 0);
 		input_mt_sync(ts->input);
 	}
 
@@ -263,8 +261,7 @@
 		}
 	} else {
 		for (i = 0; i < ts->prev_touches; i++) {
-			input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,	0);
-			input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR,	0);
+			input_report_abs(ts->input, ABS_MT_PRESSURE,	0);
 			input_mt_sync(ts->input);
 		}
 	}
@@ -402,10 +399,8 @@
 			ts->pdata->dis_min_x, ts->pdata->dis_max_x, 0, 0);
 	input_set_abs_params(input_device, ABS_MT_POSITION_Y,
 			ts->pdata->dis_min_y, ts->pdata->dis_max_y, 0, 0);
-	input_set_abs_params(input_device, ABS_MT_TOUCH_MAJOR,
+	input_set_abs_params(input_device, ABS_MT_PRESSURE,
 			ts->pdata->min_touch, ts->pdata->max_touch, 0, 0);
-	input_set_abs_params(input_device, ABS_MT_WIDTH_MAJOR,
-			ts->pdata->min_width, ts->pdata->max_width, 0, 0);
 	input_set_abs_params(input_device, ABS_MT_TRACKING_ID,
 			ts->pdata->min_tid, ts->pdata->max_tid, 0, 0);
 
diff --git a/drivers/input/touchscreen/cyttsp-i2c.c b/drivers/input/touchscreen/cyttsp-i2c.c
index aefce3e..9df1189 100644
--- a/drivers/input/touchscreen/cyttsp-i2c.c
+++ b/drivers/input/touchscreen/cyttsp-i2c.c
@@ -36,7 +36,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
-#include <linux/workqueue.h>
 #include <linux/byteorder/generic.h>
 #include <linux/bitops.h>
 #include <linux/pm_runtime.h>
@@ -61,7 +60,6 @@
 struct cyttsp {
 	struct i2c_client *client;
 	struct input_dev *input;
-	struct work_struct work;
 	struct timer_list timer;
 	struct mutex mutex;
 	char phys[32];
@@ -93,13 +91,10 @@
 static void cyttsp_late_resume(struct early_suspend *handler);
 #endif /* CONFIG_HAS_EARLYSUSPEND */
 
-static struct workqueue_struct *cyttsp_ts_wq;
-
 
 /* ****************************************************************************
  * Prototypes for static functions
  * ************************************************************************** */
-static void cyttsp_xy_worker(struct work_struct *work);
 static irqreturn_t cyttsp_irq(int irq, void *handle);
 static int cyttsp_inlist(u16 prev_track[],
 			u8 cur_trk_id, u8 *prev_loc, u8 num_touches);
@@ -690,11 +685,6 @@
 	else
 		disable_irq(ts->client->irq);
 
-	rc = cancel_work_sync(&ts->work);
-
-	if (rc && ts->client->irq)
-		enable_irq(ts->client->irq);
-
 	/* enter bootloader idle mode */
 	rc = cyttsp_soft_reset(ts);
 
@@ -922,12 +912,8 @@
 static DEVICE_ATTR(cyttsp_fw_name, 0664, cyttsp_fw_name_show,
 					cyttsp_fw_name_store);
 
-/* The cyttsp_xy_worker function reads the XY coordinates and sends them to
- * the input layer.  It is scheduled from the interrupt (or timer).
- */
-void cyttsp_xy_worker(struct work_struct *work)
+static void cyttsp_xy_handler(struct cyttsp *ts)
 {
-	struct cyttsp *ts = container_of(work, struct cyttsp, work);
 	u8 id, tilt, rev_x, rev_y;
 	u8 i, loc;
 	u8 prv_tch;		/* number of previous touches */
@@ -949,8 +935,9 @@
 	u16 st_x2, st_y2;
 	u8 st_z2;
 	s32 retval;
+	int val;
 
-	cyttsp_xdebug("TTSP worker start 1:\n");
+	cyttsp_xdebug("TTSP handler start 1:\n");
 
 	/* get event data from CYTTSP device */
 	i = CY_NUM_RETRY;
@@ -963,10 +950,10 @@
 	if (retval < CY_OK) {
 		/* return immediately on
 		 * failure to read device on the i2c bus */
-		goto exit_xy_worker;
+		goto exit_xy_handler;
 	}
 
-	cyttsp_xdebug("TTSP worker start 2:\n");
+	cyttsp_xdebug("TTSP handler start 2:\n");
 
 	/* compare own irq counter with the device irq counter */
 	if (ts->client->irq) {
@@ -1043,7 +1030,7 @@
 				tries++ < 100);
 			cyttsp_putbl(ts, 2, true, false, false);
 		}
-		goto exit_xy_worker;
+		goto exit_xy_handler;
 	} else {
 		cur_tch = GET_NUM_TOUCHES(g_xy_data.tt_stat);
 		if (IS_LARGE_AREA(g_xy_data.tt_stat)) {
@@ -1126,7 +1113,7 @@
 	if ((prv_tch == CY_NTCH) &&
 		((cur_tch == CY_NTCH) ||
 		(cur_tch > CY_NUM_MT_TCH_ID))) {
-		goto exit_xy_worker;
+		goto exit_xy_handler;
 	}
 
 	cyttsp_debug("prev=%d  curr=%d\n", prv_tch, cur_tch);
@@ -1253,16 +1240,20 @@
 			FLIP_XY(g_xy_data.x4, g_xy_data.y4);
 
 		if (rev_x) {
-			g_xy_data.x4 = INVERT_X(g_xy_data.x4,
-						ts->platform_data->panel_maxx);
-			if (g_xy_data.x4 < 0)
+			val = INVERT_X(g_xy_data.x4,
+					ts->platform_data->panel_maxx);
+			if (val >= 0)
+				g_xy_data.x4 = val;
+			else
 				pr_debug("X value is negative. Please configure"
 					" maxx in platform data structure\n");
 		}
 		if (rev_y) {
-			g_xy_data.y4 = INVERT_X(g_xy_data.y4,
-						ts->platform_data->panel_maxy);
-			if (g_xy_data.y4 < 0)
+			val = INVERT_X(g_xy_data.y4,
+					ts->platform_data->panel_maxy);
+			if (val >= 0)
+				g_xy_data.y4 = val;
+			else
 				pr_debug("Y value is negative. Please configure"
 					" maxy in platform data structure\n");
 
@@ -1307,17 +1298,21 @@
 			FLIP_XY(g_xy_data.x3, g_xy_data.y3);
 
 		if (rev_x) {
-			g_xy_data.x3 = INVERT_X(g_xy_data.x3,
-						ts->platform_data->panel_maxx);
-			if (g_xy_data.x3 < 0)
+			val = INVERT_X(g_xy_data.x3,
+					ts->platform_data->panel_maxx);
+			if (val >= 0)
+				g_xy_data.x3 = val;
+			else
 				pr_debug("X value is negative. Please configure"
 					" maxx in platform data structure\n");
 
 		}
 		if (rev_y) {
-			g_xy_data.y3 = INVERT_X(g_xy_data.y3,
-						ts->platform_data->panel_maxy);
-			if (g_xy_data.y3 < 0)
+			val = INVERT_X(g_xy_data.y3,
+					ts->platform_data->panel_maxy);
+			if (val >= 0)
+				g_xy_data.y3 = val;
+			else
 				pr_debug("Y value is negative. Please configure"
 					" maxy in platform data structure\n");
 
@@ -1362,16 +1357,20 @@
 			FLIP_XY(g_xy_data.x2, g_xy_data.y2);
 
 		if (rev_x) {
-			g_xy_data.x2 = INVERT_X(g_xy_data.x2,
-						ts->platform_data->panel_maxx);
-			if (g_xy_data.x2 < 0)
+			val = INVERT_X(g_xy_data.x2,
+					ts->platform_data->panel_maxx);
+			if (val >= 0)
+				g_xy_data.x2 = val;
+			else
 				pr_debug("X value is negative. Please configure"
 					" maxx in platform data structure\n");
 		}
 		if (rev_y) {
-			g_xy_data.y2 = INVERT_X(g_xy_data.y2,
-						ts->platform_data->panel_maxy);
-			if (g_xy_data.y2 < 0)
+			val = INVERT_X(g_xy_data.y2,
+					ts->platform_data->panel_maxy);
+			if (val >= 0)
+				g_xy_data.y2 = val;
+			else
 				pr_debug("Y value is negative. Please configure"
 					" maxy in platform data structure\n");
 		}
@@ -1415,16 +1414,20 @@
 			FLIP_XY(g_xy_data.x1, g_xy_data.y1);
 
 		if (rev_x) {
-			g_xy_data.x1 = INVERT_X(g_xy_data.x1,
-						ts->platform_data->panel_maxx);
-			if (g_xy_data.x1 < 0)
+			val = INVERT_X(g_xy_data.x1,
+					ts->platform_data->panel_maxx);
+			if (val >= 0)
+				g_xy_data.x1 = val;
+			else
 				pr_debug("X value is negative. Please configure"
 					" maxx in platform data structure\n");
 		}
 		if (rev_y) {
-			g_xy_data.y1 = INVERT_X(g_xy_data.y1,
-						ts->platform_data->panel_maxy);
-			if (g_xy_data.y1 < 0)
+			val = INVERT_X(g_xy_data.y1,
+					ts->platform_data->panel_maxy);
+			if (val >= 0)
+				g_xy_data.y1 = val;
+			else
 				pr_debug("Y value is negative. Please configure"
 					" maxy in platform data structure");
 		}
@@ -1816,19 +1819,10 @@
 		ts->act_trk[id] = cur_trk[id];
 	}
 
-exit_xy_worker:
-	if (cyttsp_disable_touch) {
-		/* Turn off the touch interrupts */
-		cyttsp_debug("Not enabling touch\n");
-	} else {
-		if (ts->client->irq == 0) {
-			/* restart event timer */
-			mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
-		} else {
-			/* re-enable the interrupt after processing */
-			enable_irq(ts->client->irq);
-		}
-	}
+exit_xy_handler:
+	/* restart event timer */
+	if (ts->client->irq == 0)
+		mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
 	return;
 }
 
@@ -1882,7 +1876,7 @@
 	cyttsp_xdebug("TTSP Device timer event\n");
 
 	/* schedule motion signal handling */
-	queue_work(cyttsp_ts_wq, &ts->work);
+	cyttsp_xy_handler(ts);
 
 	return;
 }
@@ -1899,11 +1893,8 @@
 
 	cyttsp_xdebug("%s: Got IRQ\n", CY_I2C_NAME);
 
-	/* disable further interrupts until this interrupt is processed */
-	disable_irq_nosync(ts->client->irq);
+	cyttsp_xy_handler(ts);
 
-	/* schedule motion signal handling */
-	queue_work(cyttsp_ts_wq, &ts->work);
 	return IRQ_HANDLED;
 }
 
@@ -2565,9 +2556,6 @@
 		goto error_free_device;
 	}
 
-	/* Prepare our worker structure prior to setting up the timer/ISR */
-	INIT_WORK(&ts->work, cyttsp_xy_worker);
-
 	if (gpio_is_valid(ts->platform_data->resout_gpio)) {
 		/* configure touchscreen reset out gpio */
 		retval = gpio_request(ts->platform_data->resout_gpio,
@@ -2664,9 +2652,8 @@
 		mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
 	} else {
 		cyttsp_info("Setting up interrupt\n");
-		/* request_irq() will also call enable_irq() */
-		error = request_irq(client->irq, cyttsp_irq,
-			IRQF_TRIGGER_FALLING,
+		error = request_threaded_irq(client->irq, NULL, cyttsp_irq,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 			client->dev.driver->name, ts);
 		if (error) {
 			cyttsp_alert("error: could not request irq\n");
@@ -2774,7 +2761,7 @@
 	ts = kzalloc(sizeof(struct cyttsp), GFP_KERNEL);
 	if (ts == NULL) {
 		cyttsp_xdebug1("err kzalloc for cyttsp\n");
-		retval = -ENOMEM;
+		return -ENOMEM;
 	}
 
 	/* Enable runtime PM ops, start in ACTIVE mode */
@@ -2809,10 +2796,8 @@
 		error = cyttsp_initialize(client, ts);
 		if (error) {
 			cyttsp_xdebug1("err cyttsp_initialize\n");
-			if (ts != NULL) {
-				/* deallocate memory */
-				kfree(ts);
-			}
+			/* deallocate memory */
+			kfree(ts);
 /*
 			i2c_del_driver(&cyttsp_driver);
 */
@@ -2988,15 +2973,10 @@
 		return 0;
 	}
 
-	/* disable worker */
 	if (ts->client->irq == 0)
 		del_timer(&ts->timer);
 	else
-		disable_irq_nosync(ts->client->irq);
-	retval = cancel_work_sync(&ts->work);
-
-	if (retval)
-		enable_irq(ts->client->irq);
+		disable_irq(ts->client->irq);
 
 	if (!(retval < CY_OK)) {
 		if (ts->platform_data->use_sleep &&
@@ -3058,10 +3038,6 @@
 	device_remove_file(&client->dev, &dev_attr_cyttsp_force_update_fw);
 	device_remove_file(&client->dev, &dev_attr_cyttsp_fw_name);
 
-	/* Start cleaning up by removing any delayed work and the timer */
-	if (cancel_delayed_work((struct delayed_work *)&ts->work) < CY_OK)
-		cyttsp_alert("error: could not remove work from workqueue\n");
-
 	/* free up timer or irq */
 	if (ts->client->irq == 0) {
 		err = del_timer(&ts->timer);
@@ -3093,8 +3069,7 @@
 		gpio_free(ts->platform_data->irq_gpio);
 
 	/* housekeeping */
-	if (ts != NULL)
-		kfree(ts);
+	kfree(ts);
 
 	cyttsp_alert("Leaving\n");
 
@@ -3127,12 +3102,6 @@
 	cyttsp_info("I2C Touchscreen Driver (Built %s @ %s)\n", \
 		__DATE__, __TIME__);
 
-	cyttsp_ts_wq = create_singlethread_workqueue("cyttsp_ts_wq");
-	if (cyttsp_ts_wq == NULL) {
-		cyttsp_debug("No memory for cyttsp_ts_wq\n");
-		return -ENOMEM;
-	}
-
 	ret = i2c_add_driver(&cyttsp_driver);
 
 	return ret;
@@ -3140,8 +3109,6 @@
 
 static void cyttsp_exit(void)
 {
-	if (cyttsp_ts_wq)
-		destroy_workqueue(cyttsp_ts_wq);
 	return i2c_del_driver(&cyttsp_driver);
 }
 
diff --git a/drivers/leds/leds-pmic8058.c b/drivers/leds/leds-pmic8058.c
index d1aed3f..3b3a24a 100644
--- a/drivers/leds/leds-pmic8058.c
+++ b/drivers/leds/leds-pmic8058.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 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
@@ -15,7 +15,7 @@
 #include <linux/leds.h>
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
-#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/leds-pmic8058.h>
 
 #define SSBI_REG_ADDR_DRV_KEYPAD	0x48
@@ -41,11 +41,11 @@
 #define PMIC8058_LED_OFFSET(id) ((id) - PMIC8058_ID_LED_0)
 
 struct pmic8058_led_data {
+	struct device		*dev;
 	struct led_classdev	cdev;
 	int			id;
 	enum led_brightness	brightness;
 	u8			flags;
-	struct pm8058_chip	*pm_chip;
 	struct work_struct	work;
 	struct mutex		lock;
 	spinlock_t		value_lock;
@@ -72,8 +72,8 @@
 	led->reg_kp |= level;
 	spin_unlock_irqrestore(&led->value_lock, flags);
 
-	rc = pm8058_write(led->pm_chip, SSBI_REG_ADDR_DRV_KEYPAD,
-				 &led->reg_kp, 1);
+	rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_DRV_KEYPAD,
+						led->reg_kp);
 	if (rc)
 		pr_err("%s: can't set keypad backlight level\n", __func__);
 }
@@ -105,8 +105,8 @@
 	tmp |= level;
 	spin_unlock_irqrestore(&led->value_lock, flags);
 
-	rc = pm8058_write(led->pm_chip,	SSBI_REG_ADDR_LED_CTRL(offset),
-			&tmp, 1);
+	rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset),
+								tmp);
 	if (rc) {
 		dev_err(led->cdev.dev, "can't set (%d) led value\n",
 				led->id);
@@ -159,7 +159,7 @@
 	}
 	spin_unlock_irqrestore(&led->value_lock, flags);
 
-	rc = pm8058_write(led->pm_chip, reg_addr, &reg_flash_led, 1);
+	rc = pm8xxx_writeb(led->dev->parent, reg_addr, reg_flash_led);
 	if (rc)
 		pr_err("%s: can't set flash led%d level %d\n", __func__,
 			led->id, rc);
@@ -294,46 +294,38 @@
 	struct pmic8058_led_data *led_dat;
 	struct pmic8058_led *curr_led;
 	int rc, i = 0;
-	struct pm8058_chip	*pm_chip;
 	u8			reg_kp;
 	u8			reg_led_ctrl[3];
 	u8			reg_flash_led0;
 	u8			reg_flash_led1;
 
-	pm_chip = dev_get_drvdata(pdev->dev.parent);
-	if (pm_chip == NULL) {
-		dev_err(&pdev->dev, "no parent data passed in\n");
-		return -EFAULT;
-	}
-
 	if (pdata == NULL) {
 		dev_err(&pdev->dev, "platform data not supplied\n");
 		return -EINVAL;
 	}
 
-	rc = pm8058_read(pm_chip, SSBI_REG_ADDR_DRV_KEYPAD, &reg_kp,
-				1);
+	rc = pm8xxx_readb(pdev->dev.parent, SSBI_REG_ADDR_DRV_KEYPAD, &reg_kp);
 	if (rc) {
 		dev_err(&pdev->dev, "can't get keypad backlight level\n");
 		goto err_reg_read;
 	}
 
-	rc = pm8058_read(pm_chip, SSBI_REG_ADDR_LED_CTRL_BASE,
-			reg_led_ctrl, 3);
+	rc = pm8xxx_read_buf(pdev->dev.parent, SSBI_REG_ADDR_LED_CTRL_BASE,
+							reg_led_ctrl, 3);
 	if (rc) {
 		dev_err(&pdev->dev, "can't get led levels\n");
 		goto err_reg_read;
 	}
 
-	rc = pm8058_read(pm_chip, SSBI_REG_ADDR_FLASH_DRV0,
-			&reg_flash_led0, 1);
+	rc = pm8xxx_readb(pdev->dev.parent, SSBI_REG_ADDR_FLASH_DRV0,
+						&reg_flash_led0);
 	if (rc) {
 		dev_err(&pdev->dev, "can't read flash led0\n");
 		goto err_reg_read;
 	}
 
-	rc = pm8058_read(pm_chip, SSBI_REG_ADDR_FLASH_DRV1,
-			&reg_flash_led1, 1);
+	rc = pm8xxx_readb(pdev->dev.parent, SSBI_REG_ADDR_FLASH_DRV1,
+						&reg_flash_led1);
 	if (rc) {
 		dev_err(&pdev->dev, "can't get flash led1\n");
 		goto err_reg_read;
@@ -366,7 +358,7 @@
 			goto fail_id_check;
 		}
 
-		led_dat->pm_chip		= pm_chip;
+		led_dat->dev			= &pdev->dev;
 
 		mutex_init(&led_dat->lock);
 		spin_lock_init(&led_dat->value_lock);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index a256e51..2d42e17 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1661,7 +1661,7 @@
 	memcpy(data, &skb->data[PEEK_DATA_OFSET], len);
 	iris_q_evt_data(radio, data, len, IRIS_BUF_PEEK);
 	radio_hci_req_complete(hdev, status);
-
+	kfree(data);
 
 }
 
@@ -1872,9 +1872,13 @@
 	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);
-	memcpy(&radio->fm_st_rsp.station_rsp, skb_pull(skb, len), len);
+	rsp = (struct hci_fm_station_rsp *)skb_pull(skb, len);
+	if (rsp == NULL)
+		return;
+	memcpy(&radio->fm_st_rsp.station_rsp, rsp, len);
 
 	iris_q_event(radio, IRIS_EVT_TUNE_SUCC);
 
@@ -1927,7 +1931,8 @@
 	len = ev->num_stations_found * PARAMS_PER_STATION + STN_FREQ_OFFSET;
 
 	for (cnt = STN_FREQ_OFFSET, stn_num = 0;
-		(cnt < len) && (stn_num < ev->num_stations_found);
+		(cnt < len) && (stn_num < ev->num_stations_found)
+		&& (stn_num < ARRAY_SIZE(ev->rel_freq));
 		cnt += PARAMS_PER_STATION, stn_num++) {
 		abs_freq = *((int *)&skb->data[cnt]);
 		rel_freq = abs_freq - radio->recv_conf.band_low_limit;
@@ -2069,8 +2074,16 @@
 
 void radio_hci_event_packet(struct radio_hci_dev *hdev, struct sk_buff *skb)
 {
-	struct radio_hci_event_hdr *hdr = (void *) skb->data;
-	__u8 event = hdr->evt;
+	struct radio_hci_event_hdr *hdr;
+	u8 event;
+
+	if (skb == NULL) {
+		FMDERR("Socket buffer is NULL");
+		return;
+	}
+
+	hdr = (void *) skb->data;
+	event = hdr->evt;
 
 	skb_pull(skb, RADIO_HCI_EVENT_HDR_SIZE);
 
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 3f41d43..a6b7f48 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -4,8 +4,9 @@
 endif
 
 ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+  EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
   obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
-  obj-$(CONFIG_MSM_CAMERA) += io/ sensors/ actuators/
+  obj-$(CONFIG_MSM_CAMERA) += io/ sensors/ actuators/ csi/
 else
   obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
 endif
@@ -16,7 +17,7 @@
 obj-$(CONFIG_ARCH_MSM7X30) += msm_vfe31.o msm_io_vfe31.o msm_vpe1.o
 obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o msm_io8x.o
 obj-$(CONFIG_ARCH_MSM8X60) += msm_vfe31.o msm_io_8x60.o msm_vpe1.o
-obj-$(CONFIG_ARCH_MSM8960) += msm_io_8960.o msm_ispif.o msm_vfe32.o msm_vpe.o
+obj-$(CONFIG_ARCH_MSM8960) += msm_io_8960.o msm_vfe32.o msm_vpe.o
 obj-$(CONFIG_MT9T013) += mt9t013.o mt9t013_reg.o
 obj-$(CONFIG_SN12M0PZ) += sn12m0pz.o sn12m0pz_reg.o
 obj-$(CONFIG_MT9P012) += mt9p012_reg.o
@@ -44,3 +45,4 @@
 obj-$(CONFIG_MT9D112) += mt9d112.o mt9d112_reg.o
 
 obj-$(CONFIG_MT9D113) += mt9d113.o mt9d113_reg.o
+obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += wfd/
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
new file mode 100644
index 0000000..3ce81af
--- /dev/null
+++ b/drivers/media/video/msm/csi/Makefile
@@ -0,0 +1,3 @@
+GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o msm_csid.o msm_ispif.o
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
new file mode 100644
index 0000000..fb809c9
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -0,0 +1,306 @@
+/* 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <media/msm_isp.h>
+#include "msm_csid.h"
+#include "msm.h"
+
+#define V4L2_IDENT_CSID                            50002
+
+/* MIPI	CSID registers */
+#define CSID_HW_VERSION_ADDR                        0x0
+#define CSID_CORE_CTRL_ADDR                         0x4
+#define CSID_RST_CMD_ADDR                           0x8
+#define CSID_CID_LUT_VC_0_ADDR                      0xc
+#define CSID_CID_LUT_VC_1_ADDR                      0x10
+#define CSID_CID_LUT_VC_2_ADDR                      0x14
+#define CSID_CID_LUT_VC_3_ADDR                      0x18
+#define CSID_CID_n_CFG_ADDR                         0x1C
+#define CSID_IRQ_CLEAR_CMD_ADDR                     0x5c
+#define CSID_IRQ_MASK_ADDR                          0x60
+#define CSID_IRQ_STATUS_ADDR                        0x64
+#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR    0x68
+#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR     0x6c
+#define CSID_CAPTURED_SHORT_PKT_ADDR                0x70
+#define CSID_CAPTURED_LONG_PKT_HDR_ADDR             0x74
+#define CSID_CAPTURED_LONG_PKT_FTR_ADDR             0x78
+#define CSID_PIF_MISR_DL0_ADDR                      0x7C
+#define CSID_PIF_MISR_DL1_ADDR                      0x80
+#define CSID_PIF_MISR_DL2_ADDR                      0x84
+#define CSID_PIF_MISR_DL3_ADDR                      0x88
+#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR             0x8C
+#define CSID_STATS_ECC_ADDR                         0x90
+#define CSID_STATS_CRC_ADDR                         0x94
+#define CSID_TG_CTRL_ADDR                           0x9C
+#define CSID_TG_VC_CFG_ADDR                         0xA0
+#define CSID_TG_DT_n_CFG_0_ADDR                     0xA8
+#define CSID_TG_DT_n_CFG_1_ADDR                     0xAC
+#define CSID_TG_DT_n_CFG_2_ADDR                     0xB0
+#define CSID_TG_DT_n_CFG_3_ADDR                     0xD8
+
+#define DBG_CSID 0
+
+static int msm_csid_cid_lut(
+	struct msm_camera_csid_lut_params *csid_lut_params,
+	void __iomem *csidbase)
+{
+	int rc = 0, i = 0;
+	uint32_t val = 0;
+
+	for (i = 0; i < csid_lut_params->num_cid && i < 4; i++) {
+		if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
+			csid_lut_params->vc_cfg[i].dt > 0x37) {
+			CDBG("%s: unsupported data type 0x%x\n",
+				 __func__, csid_lut_params->vc_cfg[i].dt);
+			return rc;
+		}
+		val = msm_io_r(csidbase + CSID_CID_LUT_VC_0_ADDR +
+		(csid_lut_params->vc_cfg[i].cid >> 2) * 4)
+		& ~(0xFF << csid_lut_params->vc_cfg[i].cid * 8);
+		val |= csid_lut_params->vc_cfg[i].dt <<
+			csid_lut_params->vc_cfg[i].cid * 8;
+		msm_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
+			(csid_lut_params->vc_cfg[i].cid >> 2) * 4);
+		val = csid_lut_params->vc_cfg[i].decode_format << 4 | 0x3;
+		msm_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
+			(csid_lut_params->vc_cfg[i].cid * 4));
+	}
+	return rc;
+}
+
+static int msm_csid_config(struct csid_cfg_params *cfg_params)
+{
+	int rc = 0;
+	uint32_t val = 0;
+	struct csid_device *csid_dev;
+	struct msm_camera_csid_params *csid_params;
+	void __iomem *csidbase;
+	csid_dev = v4l2_get_subdevdata(cfg_params->subdev);
+	csidbase = csid_dev->base;
+	csid_params = cfg_params->parms;
+	val = csid_params->lane_cnt - 1;
+	val |= csid_params->lane_assign << 2;
+	val |= 0x1 << 10;
+	val |= 0x1 << 11;
+	val |= 0x1 << 12;
+	val |= 0x1 << 28;
+	msm_io_w(val, csidbase + CSID_CORE_CTRL_ADDR);
+
+	rc = msm_csid_cid_lut(&csid_params->lut_params, csidbase);
+	if (rc < 0)
+		return rc;
+
+	msm_io_w(0x7fF10800, csidbase + CSID_IRQ_MASK_ADDR);
+	msm_io_w(0x7fF10800, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+
+	msleep(20);
+	return rc;
+}
+
+static irqreturn_t msm_csid_irq(int irq_num, void *data)
+{
+	uint32_t irq;
+	struct csid_device *csid_dev = data;
+	irq = msm_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
+	CDBG("%s CSID_IRQ_STATUS_ADDR = 0x%x\n", __func__, irq);
+	msm_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
+	return IRQ_HANDLED;
+}
+
+static int msm_csid_subdev_g_chip_ident(struct v4l2_subdev *sd,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_CSID;
+	chip->revision = 0;
+	return 0;
+}
+
+static struct msm_cam_clk_info csid_clk_info[] = {
+	{"csi_src_clk", 177780000},
+	{"csi_clk", -1},
+	{"csi_phy_clk", -1},
+	{"csi_pclk", -1},
+};
+
+static int msm_csid_init(struct v4l2_subdev *sd, uint32_t *csid_version)
+{
+	int rc = 0;
+	struct csid_device *csid_dev;
+	csid_dev = v4l2_get_subdevdata(sd);
+	if (csid_dev == NULL) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	csid_dev->base = ioremap(csid_dev->mem->start,
+		resource_size(csid_dev->mem));
+	if (!csid_dev->base) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
+		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
+	if (rc < 0) {
+		iounmap(csid_dev->base);
+		return rc;
+	}
+
+#if DBG_CSID
+	enable_irq(csid_dev->irq->start);
+#endif
+
+	*csid_version = csid_dev->hw_version;
+
+	return 0;
+}
+
+static int msm_csid_release(struct v4l2_subdev *sd)
+{
+	struct csid_device *csid_dev;
+	csid_dev = v4l2_get_subdevdata(sd);
+
+#if DBG_CSID
+	disable_irq(csid_dev->irq->start);
+#endif
+
+	msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
+		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
+
+	iounmap(csid_dev->base);
+	return 0;
+}
+
+static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct csid_cfg_params cfg_params;
+	switch (cmd) {
+	case VIDIOC_MSM_CSID_CFG:
+		cfg_params.subdev = sd;
+		cfg_params.parms = arg;
+		return msm_csid_config((struct csid_cfg_params *)&cfg_params);
+	case VIDIOC_MSM_CSID_INIT:
+		return msm_csid_init(sd, (uint32_t *)arg);
+	case VIDIOC_MSM_CSID_RELEASE:
+		return msm_csid_release(sd);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
+	.g_chip_ident = &msm_csid_subdev_g_chip_ident,
+	.ioctl = &msm_csid_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csid_subdev_ops = {
+	.core = &msm_csid_subdev_core_ops,
+};
+
+static int __devinit csid_probe(struct platform_device *pdev)
+{
+	struct csid_device *new_csid_dev;
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
+	if (!new_csid_dev) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&new_csid_dev->subdev, &msm_csid_subdev_ops);
+	v4l2_set_subdevdata(&new_csid_dev->subdev, new_csid_dev);
+	platform_set_drvdata(pdev, &new_csid_dev->subdev);
+	mutex_init(&new_csid_dev->mutex);
+
+	new_csid_dev->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "csid");
+	if (!new_csid_dev->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto csid_no_resource;
+	}
+	new_csid_dev->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "csid");
+	if (!new_csid_dev->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto csid_no_resource;
+	}
+	new_csid_dev->io = request_mem_region(new_csid_dev->mem->start,
+		resource_size(new_csid_dev->mem), pdev->name);
+	if (!new_csid_dev->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto csid_no_resource;
+	}
+
+	rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
+		IRQF_TRIGGER_RISING, "csid", new_csid_dev);
+	if (rc < 0) {
+		release_mem_region(new_csid_dev->mem->start,
+			resource_size(new_csid_dev->mem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto csid_no_resource;
+	}
+	disable_irq(new_csid_dev->irq->start);
+
+	new_csid_dev->base = ioremap(new_csid_dev->mem->start,
+		resource_size(new_csid_dev->mem));
+	if (!new_csid_dev->base) {
+		rc = -ENOMEM;
+		goto csid_no_resource;
+	}
+
+	new_csid_dev->hw_version =
+		msm_io_r(new_csid_dev->base + CSID_HW_VERSION_ADDR);
+	iounmap(new_csid_dev->base);
+
+	new_csid_dev->pdev = pdev;
+	return 0;
+
+csid_no_resource:
+	mutex_destroy(&new_csid_dev->mutex);
+	kfree(new_csid_dev);
+	return 0;
+}
+
+static struct platform_driver csid_driver = {
+	.probe = csid_probe,
+	.driver = {
+		.name = MSM_CSID_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_csid_init_module(void)
+{
+	return platform_driver_register(&csid_driver);
+}
+
+static void __exit msm_csid_exit_module(void)
+{
+	platform_driver_unregister(&csid_driver);
+}
+
+module_init(msm_csid_init_module);
+module_exit(msm_csid_exit_module);
+MODULE_DESCRIPTION("MSM CSID driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
new file mode 100644
index 0000000..f90abf2
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csid.h
@@ -0,0 +1,48 @@
+/* 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 MSM_CSID_H
+#define MSM_CSID_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csid_device {
+	struct platform_device *pdev;
+	struct v4l2_subdev subdev;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	void __iomem *base;
+	struct mutex mutex;
+	uint32_t hw_version;
+
+	struct clk *csid_clk[5];
+};
+
+struct csid_cfg_params {
+	struct v4l2_subdev *subdev;
+	void *parms;
+};
+
+#define VIDIOC_MSM_CSID_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csid_cfg_params)
+
+#define VIDIOC_MSM_CSID_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSID_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+
+#endif
+
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
new file mode 100644
index 0000000..b62ec84
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -0,0 +1,312 @@
+/* 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <mach/vreg.h>
+#include <media/msm_isp.h>
+#include "msm_csiphy.h"
+#include "msm.h"
+
+#define DBG_CSIPHY 0
+
+#define V4L2_IDENT_CSIPHY                        50003
+
+/*MIPI CSI PHY registers*/
+#define MIPI_CSIPHY_LNn_CFG1_ADDR                0x0
+#define MIPI_CSIPHY_LNn_CFG2_ADDR                0x4
+#define MIPI_CSIPHY_LNn_CFG3_ADDR                0x8
+#define MIPI_CSIPHY_LNn_CFG4_ADDR                0xC
+#define MIPI_CSIPHY_LNn_CFG5_ADDR                0x10
+#define MIPI_CSIPHY_LNCK_CFG1_ADDR               0x100
+#define MIPI_CSIPHY_LNCK_CFG2_ADDR               0x104
+#define MIPI_CSIPHY_LNCK_CFG3_ADDR               0x108
+#define MIPI_CSIPHY_LNCK_CFG4_ADDR               0x10C
+#define MIPI_CSIPHY_LNCK_CFG5_ADDR               0x110
+#define MIPI_CSIPHY_LNCK_MISC1_ADDR              0x128
+#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR        0x1E0
+#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR           0x1E8
+#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR           0x0144
+#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR      0x0180
+#define MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR      0x0184
+#define MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR      0x0188
+#define MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR      0x018C
+#define MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR      0x0190
+#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR        0x01A0
+#define MIPI_CSIPHY_INTERRUPT_MASK1_ADDR        0x01A4
+#define MIPI_CSIPHY_INTERRUPT_MASK2_ADDR        0x01A8
+#define MIPI_CSIPHY_INTERRUPT_MASK3_ADDR        0x01AC
+#define MIPI_CSIPHY_INTERRUPT_MASK4_ADDR        0x01B0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR       0x01C0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR       0x01C4
+#define MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR       0x01C8
+#define MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR       0x01CC
+#define MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR       0x01D0
+
+int msm_csiphy_config(struct csiphy_cfg_params *cfg_params)
+{
+	int rc = 0;
+	int i = 0;
+	uint32_t val = 0;
+	struct csiphy_device *csiphy_dev;
+	struct msm_camera_csiphy_params *csiphy_params;
+	void __iomem *csiphybase;
+	csiphy_dev = v4l2_get_subdevdata(cfg_params->subdev);
+	csiphybase = csiphy_dev->base;
+	csiphy_params = cfg_params->parms;
+	if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
+		CDBG("%s: unsupported lane cnt %d\n",
+			__func__, csiphy_params->lane_cnt);
+		return rc;
+	}
+
+	val = 0x3;
+	msm_io_w((((1 << csiphy_params->lane_cnt) - 1) << 2) | val,
+			 csiphybase + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+	msm_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
+	msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
+
+	for (i = 0; i < csiphy_params->lane_cnt; i++) {
+		msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
+		msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+		msm_io_w(csiphy_params->settle_cnt,
+			csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
+		msm_io_w(0x00000052,
+			csiphybase + MIPI_CSIPHY_LNn_CFG5_ADDR + 0x40*i);
+	}
+
+	msm_io_w(0x00000000, csiphybase + MIPI_CSIPHY_LNCK_CFG1_ADDR);
+	msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+	msm_io_w(csiphy_params->settle_cnt,
+			 csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
+	msm_io_w(0x5, csiphybase + MIPI_CSIPHY_LNCK_CFG4_ADDR);
+	msm_io_w(0x2, csiphybase + MIPI_CSIPHY_LNCK_CFG5_ADDR);
+	msm_io_w(0x0, csiphybase + 0x128);
+
+	msm_io_w(0x24,
+		csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
+	msm_io_w(0x24,
+		csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
+
+	for (i = 1; i <= csiphy_params->lane_cnt; i++) {
+		msm_io_w(0x6F,
+			csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR + 0x4*i);
+		msm_io_w(0x6F,
+			csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
+	}
+	return rc;
+}
+
+static irqreturn_t msm_csiphy_irq(int irq_num, void *data)
+{
+	uint32_t irq;
+	struct csiphy_device *csiphy_dev = data;
+	irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
+	msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
+	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
+	irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR);
+	msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR);
+	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS1 = 0x%x\n", __func__, irq);
+	irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR);
+	msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR);
+	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS2 = 0x%x\n", __func__, irq);
+	irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR);
+	msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR);
+	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS3 = 0x%x\n", __func__, irq);
+	irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR);
+	msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR);
+	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS4 = 0x%x\n", __func__, irq);
+	msm_io_w(0x1, csiphy_dev->base + 0x164);
+	msm_io_w(0x0, csiphy_dev->base + 0x164);
+	return IRQ_HANDLED;
+}
+
+static int msm_csiphy_subdev_g_chip_ident(struct v4l2_subdev *sd,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	BUG_ON(!chip);
+	chip->ident = V4L2_IDENT_CSIPHY;
+	chip->revision = 0;
+	return 0;
+}
+
+static struct msm_cam_clk_info csiphy_clk_info[] = {
+	{"csiphy_timer_src_clk", 177780000},
+	{"csiphy_timer_clk", -1},
+};
+
+static int msm_csiphy_init(struct v4l2_subdev *sd)
+{
+	int rc = 0;
+	struct csiphy_device *csiphy_dev;
+	csiphy_dev = v4l2_get_subdevdata(sd);
+	if (csiphy_dev == NULL) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	csiphy_dev->base = ioremap(csiphy_dev->mem->start,
+		resource_size(csiphy_dev->mem));
+	if (!csiphy_dev->base) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
+			csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 1);
+
+	if (rc < 0) {
+		iounmap(csiphy_dev->base);
+		return rc;
+	}
+
+#if DBG_CSIPHY
+	enable_irq(csiphy_dev->irq->start);
+#endif
+
+	return 0;
+}
+
+static int msm_csiphy_release(struct v4l2_subdev *sd)
+{
+	struct csiphy_device *csiphy_dev;
+	int i;
+	csiphy_dev = v4l2_get_subdevdata(sd);
+	for (i = 0; i < 4; i++)
+		msm_io_w(0x0, csiphy_dev->base +
+		MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+
+	msm_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+	msm_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+
+	msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
+		csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 0);
+
+#if DBG_CSIPHY
+	disable_irq(csiphy_dev->irq->start);
+#endif
+	iounmap(csiphy_dev->base);
+	return 0;
+}
+
+static long msm_csiphy_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct csiphy_cfg_params cfg_params;
+	switch (cmd) {
+	case VIDIOC_MSM_CSIPHY_CFG:
+		cfg_params.subdev = sd;
+		cfg_params.parms = arg;
+		return msm_csiphy_config(
+			(struct csiphy_cfg_params *)&cfg_params);
+	case VIDIOC_MSM_CSIPHY_INIT:
+		return msm_csiphy_init(sd);
+	case VIDIOC_MSM_CSIPHY_RELEASE:
+		return msm_csiphy_release(sd);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static struct v4l2_subdev_core_ops msm_csiphy_subdev_core_ops = {
+	.g_chip_ident = &msm_csiphy_subdev_g_chip_ident,
+	.ioctl = &msm_csiphy_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csiphy_subdev_ops = {
+	.core = &msm_csiphy_subdev_core_ops,
+};
+
+static int __devinit csiphy_probe(struct platform_device *pdev)
+{
+	struct csiphy_device *new_csiphy_dev;
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
+	if (!new_csiphy_dev) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&new_csiphy_dev->subdev, &msm_csiphy_subdev_ops);
+	v4l2_set_subdevdata(&new_csiphy_dev->subdev, new_csiphy_dev);
+	platform_set_drvdata(pdev, &new_csiphy_dev->subdev);
+
+	mutex_init(&new_csiphy_dev->mutex);
+
+	new_csiphy_dev->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "csiphy");
+	if (!new_csiphy_dev->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto csiphy_no_resource;
+	}
+	new_csiphy_dev->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "csiphy");
+	if (!new_csiphy_dev->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto csiphy_no_resource;
+	}
+	new_csiphy_dev->io = request_mem_region(new_csiphy_dev->mem->start,
+		resource_size(new_csiphy_dev->mem), pdev->name);
+	if (!new_csiphy_dev->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto csiphy_no_resource;
+	}
+
+	rc = request_irq(new_csiphy_dev->irq->start, msm_csiphy_irq,
+		IRQF_TRIGGER_RISING, "csiphy", new_csiphy_dev);
+	if (rc < 0) {
+		release_mem_region(new_csiphy_dev->mem->start,
+			resource_size(new_csiphy_dev->mem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto csiphy_no_resource;
+	}
+	disable_irq(new_csiphy_dev->irq->start);
+
+	new_csiphy_dev->pdev = pdev;
+	return 0;
+
+csiphy_no_resource:
+	mutex_destroy(&new_csiphy_dev->mutex);
+	kfree(new_csiphy_dev);
+	return 0;
+}
+
+static struct platform_driver csiphy_driver = {
+	.probe = csiphy_probe,
+	.driver = {
+		.name = MSM_CSIPHY_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_csiphy_init_module(void)
+{
+	return platform_driver_register(&csiphy_driver);
+}
+
+static void __exit msm_csiphy_exit_module(void)
+{
+	platform_driver_unregister(&csiphy_driver);
+}
+
+module_init(msm_csiphy_init_module);
+module_exit(msm_csiphy_exit_module);
+MODULE_DESCRIPTION("MSM CSIPHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csiphy.h b/drivers/media/video/msm/csi/msm_csiphy.h
new file mode 100644
index 0000000..522a1c1
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csiphy.h
@@ -0,0 +1,46 @@
+/* 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 MSM_CSIPHY_H
+#define MSM_CSIPHY_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csiphy_device {
+	struct platform_device *pdev;
+	struct v4l2_subdev subdev;
+	struct resource *mem;
+	struct resource *irq;
+	struct resource *io;
+	void __iomem *base;
+	struct mutex mutex;
+
+	struct clk *csiphy_clk[2];
+};
+
+struct csiphy_cfg_params {
+	struct v4l2_subdev *subdev;
+	void *parms;
+};
+
+#define VIDIOC_MSM_CSIPHY_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct csiphy_cfg_params)
+
+#define VIDIOC_MSM_CSIPHY_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSIPHY_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct v4l2_subdev*)
+
+#endif
diff --git a/drivers/media/video/msm/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
similarity index 86%
rename from drivers/media/video/msm/msm_ispif.c
rename to drivers/media/video/msm/csi/msm_ispif.c
index 8797d38..af61bd2 100644
--- a/drivers/media/video/msm/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -13,20 +13,13 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/regulator/consumer.h>
 #include <mach/gpio.h>
-#include <mach/board.h>
 #include <mach/camera.h>
-#include <mach/vreg.h>
-#include <mach/camera.h>
-#include <mach/clk.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
-#include <media/msm_isp.h>
 #include "msm_ispif.h"
 #include "msm.h"
 
 #define V4L2_IDENT_ISPIF			50001
+#define CSID_VERSION_V2                      0x2000011
 
 /* ISPIF registers */
 
@@ -147,7 +140,17 @@
 
 static void msm_ispif_sel_csid_core(uint8_t intftype, uint8_t csid)
 {
+	int rc = 0;
 	uint32_t data;
+	if (ispif->ispif_clk[intftype] == NULL) {
+		pr_err("%s: ispif NULL clk\n", __func__);
+		return;
+	}
+
+	rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
+	if (rc < 0)
+		pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
+
 	data = msm_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR);
 	data |= csid<<(intftype*4);
 	msm_io_w(data, ispif->base + ISPIF_INPUT_SEL_ADDR);
@@ -215,18 +218,6 @@
 	return rc;
 }
 
-static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd,
-								void *arg)
-{
-	switch (cmd) {
-	case VIDIOC_MSM_ISPSF_CFG:
-		return msm_ispif_config((struct msm_ispif_params_list *)arg);
-	default:
-		return -ENOIOCTLCMD;
-	}
-}
-
-
 static uint32_t msm_ispif_get_cid_mask(uint8_t intftype)
 {
 	uint32_t mask = 0;
@@ -373,20 +364,6 @@
 	return rc;
 }
 
-static struct v4l2_subdev_core_ops msm_ispif_subdev_core_ops = {
-	.g_chip_ident = &msm_ispif_subdev_g_chip_ident,
-	.ioctl = &msm_ispif_subdev_ioctl,
-};
-
-static struct v4l2_subdev_video_ops msm_ispif_subdev_video_ops = {
-	.s_stream = &msm_ispif_subdev_video_s_stream,
-};
-
-static const struct v4l2_subdev_ops msm_ispif_subdev_ops = {
-	.core = &msm_ispif_subdev_core_ops,
-	.video = &msm_ispif_subdev_video_ops,
-};
-
 static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out)
 {
 	out->ispifIrqStatus0 = msm_io_r(ispif->base +
@@ -426,84 +403,54 @@
 	return IRQ_HANDLED;
 }
 
-int msm_ispif_init(struct v4l2_subdev **sd, struct platform_device *pdev)
+static struct msm_cam_clk_info ispif_clk_info[] = {
+	{"csi_pix_clk", 0},
+	{"csi_rdi_clk", 0},
+	{"csi_pix1_clk", 0},
+	{"csi_rdi1_clk", 0},
+	{"csi_rdi2_clk", 0},
+};
+
+static int msm_ispif_init(const uint32_t *csid_version)
 {
 	int rc = 0;
-
-	ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
-	if (!ispif) {
-		pr_err("%s: no enough memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	v4l2_subdev_init(&ispif->subdev, &msm_ispif_subdev_ops);
-	v4l2_set_subdevdata(&ispif->subdev, ispif);
-	snprintf(ispif->subdev.name, sizeof(ispif->subdev.name),
-								"ispif");
-	mutex_init(&ispif->mutex);
-
-	ispif->mem = platform_get_resource_byname(pdev,
-					IORESOURCE_MEM, "ispif");
-	if (!ispif->mem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		rc = -ENODEV;
-		goto ispif_no_resource;
-	}
-	ispif->irq = platform_get_resource_byname(pdev,
-					IORESOURCE_IRQ, "ispif");
-	if (!ispif->irq) {
-		pr_err("%s: no irq resource?\n", __func__);
-		rc = -ENODEV;
-		goto ispif_no_resource;
-	}
-	ispif->io = request_mem_region(ispif->mem->start,
-		resource_size(ispif->mem), pdev->name);
-	if (!ispif->io) {
-		pr_err("%s: no valid mem region\n", __func__);
-		rc = -EBUSY;
-		goto ispif_no_resource;
-	}
-	ispif->base = ioremap(ispif->mem->start,
-		resource_size(ispif->mem));
-	if (!ispif->base) {
-		rc = -ENOMEM;
-		goto ispif_no_mem;
-	}
-
 	rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
 		IRQF_TRIGGER_RISING, "ispif", 0);
-	if (rc < 0)
-		goto ispif_irq_fail;
 
 	global_intf_cmd_mask = 0xFFFFFFFF;
 	init_completion(&ispif->reset_complete);
 
-	rc = msm_ispif_reset();
-	*sd = &(ispif->subdev);
-	return rc;
+	ispif->csid_version = *csid_version;
+	if (ispif->csid_version == CSID_VERSION_V2) {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 1);
+		if (rc < 0)
+			return rc;
+	} else {
+		rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+			ispif->ispif_clk, 2, 1);
+		if (rc < 0)
+			return rc;
+	}
 
-ispif_irq_fail:
-	iounmap(ispif->base);
-ispif_no_mem:
-	release_mem_region(ispif->mem->start,
-			resource_size(ispif->mem));
-ispif_no_resource:
-	mutex_destroy(&ispif->mutex);
-	kfree(ispif);
+	rc = msm_ispif_reset();
 	return rc;
 }
 
-void msm_ispif_release(struct v4l2_subdev *sd)
+static void msm_ispif_release(struct v4l2_subdev *sd)
 {
 	struct ispif_device *ispif =
 			(struct ispif_device *)v4l2_get_subdevdata(sd);
 
+	if (ispif->csid_version == CSID_VERSION_V2)
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+			ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 0);
+	else
+		msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+			ispif->ispif_clk, 2, 0);
+
 	CDBG("%s, free_irq\n", __func__);
 	free_irq(ispif->irq->start, 0);
-	iounmap(ispif->base);
-	release_mem_region(ispif->mem->start,
-		resource_size(ispif->mem));
-	kfree(ispif);
 }
 
 void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num)
@@ -537,3 +484,112 @@
 		data >>= 1;
 	}
 }
+
+static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd,
+								void *arg)
+{
+	switch (cmd) {
+	case VIDIOC_MSM_ISPIF_CFG:
+		return msm_ispif_config((struct msm_ispif_params_list *)arg);
+	case VIDIOC_MSM_ISPIF_INIT:
+		return msm_ispif_init((uint32_t *)arg);
+	case VIDIOC_MSM_ISPIF_RELEASE:
+		msm_ispif_release(sd);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static struct v4l2_subdev_core_ops msm_ispif_subdev_core_ops = {
+	.g_chip_ident = &msm_ispif_subdev_g_chip_ident,
+	.ioctl = &msm_ispif_subdev_ioctl,
+};
+
+static struct v4l2_subdev_video_ops msm_ispif_subdev_video_ops = {
+	.s_stream = &msm_ispif_subdev_video_s_stream,
+};
+
+static const struct v4l2_subdev_ops msm_ispif_subdev_ops = {
+	.core = &msm_ispif_subdev_core_ops,
+	.video = &msm_ispif_subdev_video_ops,
+};
+
+static int __devinit ispif_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	CDBG("%s\n", __func__);
+	ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
+	if (!ispif) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&ispif->subdev, &msm_ispif_subdev_ops);
+	v4l2_set_subdevdata(&ispif->subdev, ispif);
+	platform_set_drvdata(pdev, &ispif->subdev);
+	snprintf(ispif->subdev.name, sizeof(ispif->subdev.name),
+								"ispif");
+	mutex_init(&ispif->mutex);
+
+	ispif->mem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "ispif");
+	if (!ispif->mem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto ispif_no_resource;
+	}
+	ispif->irq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "ispif");
+	if (!ispif->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto ispif_no_resource;
+	}
+	ispif->io = request_mem_region(ispif->mem->start,
+		resource_size(ispif->mem), pdev->name);
+	if (!ispif->io) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto ispif_no_resource;
+	}
+	ispif->base = ioremap(ispif->mem->start,
+		resource_size(ispif->mem));
+	if (!ispif->base) {
+		rc = -ENOMEM;
+		goto ispif_no_mem;
+	}
+
+	ispif->pdev = pdev;
+	return 0;
+
+ispif_no_mem:
+	release_mem_region(ispif->mem->start,
+		resource_size(ispif->mem));
+ispif_no_resource:
+	mutex_destroy(&ispif->mutex);
+	kfree(ispif);
+	return rc;
+}
+
+static struct platform_driver ispif_driver = {
+	.probe = ispif_probe,
+	.driver = {
+		.name = MSM_ISPIF_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_ispif_init_module(void)
+{
+	return platform_driver_register(&ispif_driver);
+}
+
+static void __exit msm_ispif_exit_module(void)
+{
+	platform_driver_unregister(&ispif_driver);
+}
+
+module_init(msm_ispif_init_module);
+module_exit(msm_ispif_exit_module);
+MODULE_DESCRIPTION("MSM ISP Interface driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
similarity index 76%
rename from drivers/media/video/msm/msm_ispif.h
rename to drivers/media/video/msm/csi/msm_ispif.h
index 3b923ea..deadc28 100644
--- a/drivers/media/video/msm/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -13,27 +13,17 @@
 #ifndef MSM_ISPIF_H
 #define MSM_ISPIF_H
 
-#include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/regulator/consumer.h>
-#include <mach/gpio.h>
-#include <mach/board.h>
-#include <mach/camera.h>
-#include <mach/vreg.h>
-#include <mach/camera.h>
-#include <mach/clk.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
 #include <media/v4l2-subdev.h>
 
-
 struct ispif_irq_status {
 	uint32_t ispifIrqStatus0;
 	uint32_t ispifIrqStatus1;
 };
 
 struct ispif_device {
+	struct platform_device *pdev;
 	struct v4l2_subdev subdev;
 	struct resource *mem;
 	struct resource *irq;
@@ -42,19 +32,25 @@
 	struct mutex mutex;
 	uint8_t start_ack_pending;
 	struct completion reset_complete;
+	uint32_t csid_version;
+	struct clk *ispif_clk[5];
 };
 
-#define VIDIOC_MSM_ISPSF_CFG \
+#define VIDIOC_MSM_ISPIF_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_ispif_params)
 
+#define VIDIOC_MSM_ISPIF_INIT \
+	_IO('V', BASE_VIDIOC_PRIVATE + 2)
+
+#define VIDIOC_MSM_ISPIF_RELEASE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct v4l2_subdev*)
+
 #define ISPIF_STREAM(intf, action) (((intf)<<ISPIF_S_STREAM_SHIFT)+(action))
 #define ISPIF_ON_FRAME_BOUNDARY	(0x01 << 0)
 #define ISPIF_OFF_FRAME_BOUNDARY    (0x01 << 1)
 #define ISPIF_OFF_IMMEDIATELY       (0x01 << 2)
 #define ISPIF_S_STREAM_SHIFT	4
 
-int msm_ispif_init(struct v4l2_subdev **sd, struct platform_device *pdev);
-void msm_ispif_release(struct v4l2_subdev *sd);
 void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num);
 
 #endif
diff --git a/drivers/media/video/msm/io/Makefile b/drivers/media/video/msm/io/Makefile
index dc8708c..584738d 100644
--- a/drivers/media/video/msm/io/Makefile
+++ b/drivers/media/video/msm/io/Makefile
@@ -1,2 +1,3 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_eeprom.o
+obj-$(CONFIG_MSM_CAMERA) += msm_io_util.o
diff --git a/drivers/media/video/msm/io/msm_io_util.c b/drivers/media/video/msm/io/msm_io_util.c
new file mode 100644
index 0000000..9f58d6e
--- /dev/null
+++ b/drivers/media/video/msm/io/msm_io_util.c
@@ -0,0 +1,68 @@
+/* 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+
+int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct clk **clk_ptr, int num_clk, int enable)
+{
+	int i;
+	int rc = 0;
+	if (enable) {
+		for (i = 0; i < num_clk; i++) {
+			clk_ptr[i] = clk_get(dev, clk_info[i].clk_name);
+			if (IS_ERR(clk_ptr[i])) {
+				pr_err("%s get failed\n", clk_info[i].clk_name);
+				rc = PTR_ERR(clk_ptr[i]);
+				goto cam_clk_get_err;
+			}
+			if (clk_info[i].clk_rate >= 0) {
+				rc = clk_set_rate(clk_ptr[i],
+							clk_info[i].clk_rate);
+				if (rc < 0) {
+					pr_err("%s set failed\n",
+						   clk_info[i].clk_name);
+					goto cam_clk_set_err;
+				}
+			}
+			rc = clk_enable(clk_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s enable failed\n",
+					   clk_info[i].clk_name);
+				goto cam_clk_set_err;
+			}
+		}
+	} else {
+		for (i = num_clk - 1; i >= 0; i--) {
+			if (clk_ptr[i] != NULL)
+				clk_disable(clk_ptr[i]);
+				clk_put(clk_ptr[i]);
+		}
+	}
+	return rc;
+
+
+cam_clk_set_err:
+	clk_put(clk_ptr[i]);
+cam_clk_get_err:
+	for (i--; i >= 0; i--) {
+		if (clk_ptr[i] != NULL) {
+			clk_disable(clk_ptr[i]);
+			clk_put(clk_ptr[i]);
+		}
+	}
+	return rc;
+}
+
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 4b4d235..251f12d 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -774,11 +774,21 @@
 	}
 	if (!pb->count) {
 		/* Deallocation. free buf_offset array */
-		D("%s freeing buffer offsets array ", __func__);
+		D("%s Inst %p freeing buffer offsets array",
+			__func__, pcam_inst);
 		for (j = 0 ; j < pcam_inst->buf_count ; j++)
 			kfree(pcam_inst->buf_offset[j]);
 		kfree(pcam_inst->buf_offset);
+		pcam_inst->buf_offset = NULL;
+		/* If the userspace has deallocated all the
+		 * buffers, then release the vb2 queue */
+		if (pcam_inst->vbqueue_initialized) {
+			vb2_queue_release(&pcam_inst->vid_bufq);
+			pcam_inst->vbqueue_initialized = 0;
+		}
 	} else {
+		D("%s Inst %p Allocating buf_offset array",
+			__func__, pcam_inst);
 		/* Allocation. allocate buf_offset array */
 		pcam_inst->buf_offset = (struct msm_cam_buf_offset **)
 			kzalloc(pb->count * sizeof(struct msm_cam_buf_offset *),
@@ -796,6 +806,7 @@
 				for (j = i-1 ; j >= 0; j--)
 					kfree(pcam_inst->buf_offset[j]);
 				kfree(pcam_inst->buf_offset);
+				pcam_inst->buf_offset = NULL;
 				return -ENOMEM;
 			}
 		}
@@ -828,7 +839,18 @@
 
 	D("%s Inst = %p\n", __func__, pcam_inst);
 	WARN_ON(pctx != f->private_data);
+
+	if (!pcam_inst->buf_offset) {
+		pr_err("%s Buffer is already released. Returning. ", __func__);
+		return -EINVAL;
+	}
+
 	if (pb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		/* Reject the buffer if planes array was not allocated */
+		if (pb->m.planes == NULL) {
+			pr_err("%s Planes array is null ", __func__);
+			return -EINVAL;
+		}
 		for (i = 0; i < pcam_inst->plane_info.num_planes; i++) {
 			D("%s stored offsets for plane %d as"
 				"addr offset %d, data offset %d",
@@ -1093,7 +1115,7 @@
 	pcam_inst = container_of(f->private_data,
 			struct msm_cam_v4l2_dev_inst, eventHandle);
 
-	D("%s\n", __func__);
+	D("%s Inst %p\n", __func__, pcam_inst);
 	WARN_ON(pctx != f->private_data);
 
 	if (!pcam_inst->vbqueue_initialized) {
@@ -1451,7 +1473,7 @@
 
 		/* Register isp subdev */
 		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
-					&pcam->mctl.isp_sdev->sd);
+					pcam->mctl.isp_sdev->sd);
 		if (rc < 0) {
 			mutex_unlock(&pcam->vid_lock);
 			pr_err("%s: v4l2_device_register_subdev failed rc = %d\n",
@@ -1459,7 +1481,7 @@
 			return rc;
 		}
 		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
-					&pcam->mctl.isp_sdev->sd_vpe);
+					pcam->mctl.isp_sdev->sd_vpe);
 		if (rc < 0) {
 			mutex_unlock(&pcam->vid_lock);
 			pr_err("%s: vpe v4l2_device_register_subdev failed rc = %d\n",
@@ -1475,12 +1497,7 @@
 		}
 	}
 	pcam_inst->vbqueue_initialized = 0;
-	/* Initialize the video queue */
-	rc = pcam->mctl.mctl_buf_init(pcam_inst);
-	if (rc < 0) {
-		mutex_unlock(&pcam->vid_lock);
-		return rc;
-	}
+	rc = 0;
 
 	f->private_data = &pcam_inst->eventHandle;
 
@@ -1591,8 +1608,8 @@
 	f->private_data = NULL;
 
 	if (pcam->use_count == 0) {
-		v4l2_device_unregister_subdev(&pcam->mctl.isp_sdev->sd);
-		v4l2_device_unregister_subdev(&pcam->mctl.isp_sdev->sd_vpe);
+		v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd);
+		v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd_vpe);
 		rc = msm_cam_server_close_session(&g_server_dev, pcam);
 		if (rc < 0)
 			pr_err("msm_cam_server_close_session fails %d\n", rc);
@@ -1608,7 +1625,6 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		ion_client_destroy(pcam->mctl.client);
 #endif
-		dma_release_declared_memory(&pcam->pdev->dev);
 	}
 	mutex_unlock(&pcam->vid_lock);
 	return rc;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index f9cf5de..f11e43f 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -41,6 +41,12 @@
 #define ERR_COPY_FROM_USER() ERR_USER_COPY(0)
 #define ERR_COPY_TO_USER() ERR_USER_COPY(1)
 
+#define MSM_CSIPHY_DRV_NAME "msm_csiphy"
+#define MSM_CSID_DRV_NAME "msm_csid"
+#define MSM_ISPIF_DRV_NAME "msm_ispif"
+#define MSM_VFE_DRV_NAME "msm_vfe"
+#define MSM_VPE_DRV_NAME "msm_vpe"
+
 /* msm queue management APIs*/
 
 #define msm_dequeue(queue, member) ({	   \
@@ -113,6 +119,8 @@
 	NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
 	NOTIFY_VPE_MSG_EVT,
 	NOTIFY_PCLK_CHANGE, /* arg = pclk */
+	NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
+	NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
 	NOTIFY_INVALID
 };
 
@@ -215,6 +223,8 @@
 	struct v4l2_subdev *vpe_sdev;    /* vpe sub device : VPE */
 	struct v4l2_subdev *flash_sdev;    /* vpe sub device : VPE */
 	struct msm_cam_config_dev *config_device;
+	struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
+	struct v4l2_subdev *csid_sdev; /*csid sub device*/
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
 	struct v4l2_subdev *act_sdev; /* actuator sub device */
 
@@ -239,8 +249,8 @@
 		 struct msm_mctl_pp_cmd, void *data);
 
 	/* vfe subdevice */
-	struct v4l2_subdev sd;
-	struct v4l2_subdev sd_vpe;
+	struct v4l2_subdev *sd;
+	struct v4l2_subdev *sd_vpe;
 };
 
 struct msm_isp_buf_info {
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c
index 565c724..e401a7a 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -34,6 +34,7 @@
 #include <mach/camera.h>
 #include <linux/syscalls.h>
 #include <linux/hrtimer.h>
+#include <linux/ion.h>
 DEFINE_MUTEX(ctrl_cmd_lock);
 
 #define CAMERA_STOP_VIDEO 58
@@ -56,6 +57,8 @@
 static enum msm_camera_type camera_type[MSM_MAX_CAMERA_SENSORS];
 static uint32_t sensor_mount_angle[MSM_MAX_CAMERA_SENSORS];
 
+struct ion_client *client_for_ion;
+
 static const char *vfe_config_cmd[] = {
 	"CMD_GENERAL",  /* 0 */
 	"CMD_AXI_CFG_OUT1",
@@ -293,29 +296,41 @@
 	struct msm_pmem_info *info, spinlock_t* pmem_spinlock,
 	struct msm_sync *sync)
 {
-	struct file *file;
 	unsigned long paddr;
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+	struct file *file;
 	unsigned long kvstart;
+#endif
 	unsigned long len;
-	int rc;
+	int rc = -ENOMEM;
 	struct msm_pmem_region *region;
 	unsigned long flags;
 
-
+	region = kmalloc(sizeof(struct msm_pmem_region), GFP_KERNEL);
+	if (!region)
+		goto out;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		region->handle = ion_import_fd(client_for_ion, info->fd);
+		if (IS_ERR_OR_NULL(region->handle))
+			goto out1;
+		ion_phys(client_for_ion, region->handle,
+			&paddr, (size_t *)&len);
+#else
 	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
 	if (rc < 0) {
 		pr_err("%s: get_pmem_file fd %d error %d\n",
 			__func__,
 			info->fd, rc);
-		return rc;
+		goto out1;
 	}
-
+	region->file = file;
+#endif
 	if (!info->len)
 		info->len = len;
 
 	rc = check_pmem_info(info, len);
 	if (rc < 0)
-		return rc;
+		goto out2;
 
 	paddr += info->offset;
 	len = info->len;
@@ -323,29 +338,33 @@
 	spin_lock_irqsave(pmem_spinlock, flags);
 	if (check_overlap(ptype, paddr, len) < 0) {
 		spin_unlock_irqrestore(pmem_spinlock, flags);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out2;
 	}
 	spin_unlock_irqrestore(pmem_spinlock, flags);
 
-
-	region = kmalloc(sizeof(struct msm_pmem_region), GFP_KERNEL);
-	if (!region)
-		return -ENOMEM;
-
 	spin_lock_irqsave(pmem_spinlock, flags);
 	INIT_HLIST_NODE(&region->list);
 
 	region->paddr = paddr;
 	region->len = len;
-	region->file = file;
 	memcpy(&region->info, info, sizeof(region->info));
 
 	hlist_add_head(&(region->list), ptype);
 	spin_unlock_irqrestore(pmem_spinlock, flags);
 	CDBG("%s: type %d, paddr 0x%lx, vaddr 0x%lx\n",
 		__func__, info->type, paddr, (unsigned long)info->vaddr);
-
 	return 0;
+out2:
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	ion_free(client_for_ion, region->handle);
+#else
+	put_pmem_file(region->file);
+#endif
+out1:
+	kfree(region);
+out:
+	return rc;
 }
 
 /* return of 0 means failure */
@@ -616,7 +635,11 @@
 					pinfo->vaddr == region->info.vaddr &&
 					pinfo->fd == region->info.fd) {
 				hlist_del(node);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+				ion_free(client_for_ion, region->handle);
+#else
 				put_pmem_file(region->file);
+#endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
 					__func__, pinfo->type, pinfo->vaddr);
@@ -636,7 +659,11 @@
 				pinfo->vaddr == region->info.vaddr &&
 				pinfo->fd == region->info.fd) {
 				hlist_del(node);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+				ion_free(client_for_ion, region->handle);
+#else
 				put_pmem_file(region->file);
+#endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
 					__func__, pinfo->type, pinfo->vaddr);
@@ -655,7 +682,11 @@
 					pinfo->vaddr == region->info.vaddr &&
 					pinfo->fd == region->info.fd) {
 				hlist_del(node);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+				ion_free(client_for_ion, region->handle);
+#else
 				put_pmem_file(region->file);
+#endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
 					__func__, pinfo->type, pinfo->vaddr);
@@ -3013,14 +3044,22 @@
 		hlist_for_each_entry_safe(region, hnode, n,
 				&sync->pmem_frames, list) {
 			hlist_del(hnode);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+				ion_free(client_for_ion, region->handle);
+#else
 			put_pmem_file(region->file);
+#endif
 			kfree(region);
 		}
 		CDBG("%s, free stats pmem region\n", __func__);
 		hlist_for_each_entry_safe(region, hnode, n,
 				&sync->pmem_stats, list) {
 			hlist_del(hnode);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+				ion_free(client_for_ion, region->handle);
+#else
 			put_pmem_file(region->file);
+#endif
 			kfree(region);
 		}
 		msm_queue_drain(&sync->pict_q, list_pict);
@@ -3031,6 +3070,7 @@
 		sync->core_powered_on = 0;
 	}
 	mutex_unlock(&sync->lock);
+	ion_client_destroy(client_for_ion);
 
 	return 0;
 }
@@ -3733,6 +3773,7 @@
 		sync->core_powered_on = 1;
 	}
 	sync->opencnt++;
+	client_for_ion = msm_ion_client_create(-1, "camera");
 
 msm_open_done:
 	mutex_unlock(&sync->lock);
@@ -3774,6 +3815,14 @@
 	return rc;
 }
 
+static int msm_open_frame(struct inode *inode, struct file *filep)
+{
+	struct msm_cam_device *pmsm =
+		container_of(inode->i_cdev, struct msm_cam_device, cdev);
+	msm_queue_drain(&pmsm->sync->frame_q, list_frame);
+	return msm_open_common(inode, filep, 1, 0);
+}
+
 static int msm_open(struct inode *inode, struct file *filep)
 {
 	return msm_open_common(inode, filep, 1, 0);
@@ -3822,7 +3871,7 @@
 
 static const struct file_operations msm_fops_frame = {
 	.owner = THIS_MODULE,
-	.open = msm_open,
+	.open = msm_open_frame,
 	.unlocked_ioctl = msm_ioctl_frame,
 	.release = msm_release_frame,
 	.poll = msm_poll_frame,
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 0e4429e..1293c7b 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -25,74 +25,8 @@
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
 
-#define DBG_CSID 0
-#define DBG_CSIPHY 0
 #define BUFF_SIZE_128 128
 
-/* MIPI	CSI	PHY registers */
-#define MIPI_CSIPHY_LNn_CFG1_ADDR                0x0
-#define MIPI_CSIPHY_LNn_CFG2_ADDR                0x4
-#define MIPI_CSIPHY_LNn_CFG3_ADDR                0x8
-#define MIPI_CSIPHY_LNn_CFG4_ADDR                0xC
-#define MIPI_CSIPHY_LNn_CFG5_ADDR                0x10
-#define MIPI_CSIPHY_LNCK_CFG1_ADDR               0x100
-#define MIPI_CSIPHY_LNCK_CFG2_ADDR               0x104
-#define MIPI_CSIPHY_LNCK_CFG3_ADDR               0x108
-#define MIPI_CSIPHY_LNCK_CFG4_ADDR               0x10C
-#define MIPI_CSIPHY_LNCK_CFG5_ADDR               0x110
-#define MIPI_CSIPHY_LNCK_MISC1_ADDR              0x128
-#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR        0x1E0
-#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR           0x1E8
-#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR           0x0144
-#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR      0x0180
-#define MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR      0x0184
-#define MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR      0x0188
-#define MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR      0x018C
-#define MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR      0x0190
-#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR        0x01A0
-#define MIPI_CSIPHY_INTERRUPT_MASK1_ADDR        0x01A4
-#define MIPI_CSIPHY_INTERRUPT_MASK2_ADDR        0x01A8
-#define MIPI_CSIPHY_INTERRUPT_MASK3_ADDR        0x01AC
-#define MIPI_CSIPHY_INTERRUPT_MASK4_ADDR        0x01B0
-#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR       0x01C0
-#define MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR       0x01C4
-#define MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR       0x01C8
-#define MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR       0x01CC
-#define MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR       0x01D0
-
-/* MIPI	CSID registers */
-#define CSID_HW_VERSION_ADDR                    0x0
-#define CSID_CORE_CTRL_ADDR                     0x4
-#define CSID_RST_CMD_ADDR                       0x8
-#define CSID_CID_LUT_VC_0_ADDR                  0xc
-#define CSID_CID_LUT_VC_1_ADDR                  0x10
-#define CSID_CID_LUT_VC_2_ADDR                  0x14
-#define CSID_CID_LUT_VC_3_ADDR                  0x18
-#define CSID_CID_n_CFG_ADDR                     0x1C
-#define CSID_IRQ_CLEAR_CMD_ADDR                 0x5c
-#define CSID_IRQ_MASK_ADDR                      0x60
-#define CSID_IRQ_STATUS_ADDR                    0x64
-#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR    0x68
-#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR     0x6c
-#define CSID_CAPTURED_SHORT_PKT_ADDR                0x70
-#define CSID_CAPTURED_LONG_PKT_HDR_ADDR             0x74
-#define CSID_CAPTURED_LONG_PKT_FTR_ADDR             0x78
-#define CSID_PIF_MISR_DL0_ADDR                      0x7C
-#define CSID_PIF_MISR_DL1_ADDR                      0x80
-#define CSID_PIF_MISR_DL2_ADDR                      0x84
-#define CSID_PIF_MISR_DL3_ADDR                      0x88
-#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR             0x8C
-#define CSID_STATS_ECC_ADDR                         0x90
-#define CSID_STATS_CRC_ADDR                         0x94
-#define CSID_TG_CTRL_ADDR                           0x9C
-#define CSID_TG_VC_CFG_ADDR                         0xA0
-#define CSID_TG_DT_n_CFG_0_ADDR                     0xA8
-#define CSID_TG_DT_n_CFG_1_ADDR                     0xAC
-#define CSID_TG_DT_n_CFG_2_ADDR                     0xB0
-#define CSID_TG_DT_n_CFG_3_ADDR                     0xD8
-
-/* Regulator Voltage and Current */
-
 #define CAM_VAF_MINUV                 2800000
 #define CAM_VAF_MAXUV                 2800000
 #define CAM_VDIG_MINUV                    1200000
@@ -107,35 +41,11 @@
 #define CAM_VANA_LOAD_UA                  85600
 #define CAM_CSI_LOAD_UA                    20000
 
-#define CSID_VERSION_V2              0x2000011
-
-static uint32_t csid_hw_version;
 static struct clk *camio_cam_clk;
-static struct clk *camio_vfe_clk;
-static struct clk *camio_csi_src_clk;
-static struct clk *camio_csi1_src_clk;
-static struct clk *camio_csi0_vfe_clk;
-static struct clk *camio_csi0_clk;
-static struct clk *camio_csi0_pclk;
-static struct clk *camio_csi_pix_clk;
-static struct clk *camio_csi_pix1_clk;
-static struct clk *camio_csi_rdi_clk;
-static struct clk *camio_csi_rdi1_clk;
-static struct clk *camio_csi_rdi2_clk;
-static struct clk *camio_csiphy0_timer_clk;
-static struct clk *camio_csiphy1_timer_clk;
-static struct clk *camio_vfe_pclk;
-static struct clk *camio_csi0_phy_clk;
-static struct clk *camio_csiphy_timer_src_clk;
 
-/*static struct clk *camio_vfe_pclk;*/
 static struct clk *camio_jpeg_clk;
 static struct clk *camio_jpeg_pclk;
-static struct clk *camio_vpe_clk;
-static struct clk *camio_vpe_pclk;
-static struct regulator *fs_vfe;
 static struct regulator *fs_ijpeg;
-static struct regulator *fs_vpe;
 static struct regulator *cam_vana;
 static struct regulator *cam_vio;
 static struct regulator *cam_vdig;
@@ -144,10 +54,9 @@
 
 static struct msm_camera_io_clk camio_clk;
 static struct platform_device *camio_dev;
-static struct resource *csidio, *csiphyio, *s3drw_io, *s3dctl_io;
-static struct resource *csid_mem, *csiphy_mem, *s3drw_mem, *s3dctl_mem;
-static struct resource *csid_irq, *csiphy_irq;
-void __iomem *csidbase, *csiphybase, *s3d_rw, *s3d_ctl;
+static struct resource *s3drw_io, *s3dctl_io;
+static struct resource *s3drw_mem, *s3dctl_mem;
+void __iomem *s3d_rw, *s3d_ctl;
 struct msm_bus_scale_pdata *cam_bus_scale_table;
 
 
@@ -338,18 +247,6 @@
 			goto cam_vaf_disable;
 		}
 	}
-	if (fs_vfe == NULL) {
-		fs_vfe = regulator_get(&pdev->dev, "fs_vfe");
-		if (IS_ERR(fs_vfe)) {
-			pr_err("%s: Regulator FS_VFE get failed %ld\n",
-				__func__, PTR_ERR(fs_vfe));
-			fs_vfe = NULL;
-		} else if (regulator_enable(fs_vfe)) {
-			pr_err("%s: Regulator FS_VFE enable failed\n",
-							__func__);
-			regulator_put(fs_vfe);
-		}
-	}
 	return 0;
 
 cam_vaf_disable:
@@ -432,21 +329,12 @@
 		regulator_put(cam_vaf);
 		cam_vaf = NULL;
 	}
-
-	if (fs_vfe) {
-		regulator_disable(fs_vfe);
-		regulator_put(fs_vfe);
-		fs_vfe = NULL;
-	}
 }
 
 int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
 {
 	int rc = 0;
 	struct clk *clk = NULL;
-	struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
-	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-	uint8_t csid_core = camdev->csid_core;
 
 	switch (clktype) {
 	case CAMIO_CAM_MCLK_CLK:
@@ -455,105 +343,6 @@
 		msm_camio_clk_rate_set_2(clk, camio_clk.mclk_clk_rate);
 		break;
 
-	case CAMIO_VFE_CLK:
-		camio_vfe_clk =
-		clk = clk_get(NULL, "vfe_clk");
-		msm_camio_clk_rate_set_2(clk, camio_clk.vfe_clk_rate);
-		break;
-
-	case CAMIO_VFE_PCLK:
-		camio_vfe_pclk =
-		clk = clk_get(NULL, "vfe_pclk");
-		break;
-
-	case CAMIO_CSI0_VFE_CLK:
-		camio_csi0_vfe_clk =
-		clk = clk_get(NULL, "csi_vfe_clk");
-		break;
-/*
-	case CAMIO_CSI1_VFE_CLK:
-		camio_csi1_vfe_clk =
-		clk = clk_get(&camio_dev->dev, "csi_vfe_clk");
-		break;
-*/
-	case CAMIO_CSI_SRC_CLK:
-		camio_csi_src_clk =
-		clk = clk_get(NULL, "csi_src_clk");
-		msm_camio_clk_rate_set_2(clk, 177780000);
-		break;
-
-	case CAMIO_CSI1_SRC_CLK:
-		camio_csi1_src_clk =
-		clk = clk_get(&camio_dev->dev, "csi_src_clk");
-		msm_camio_clk_rate_set_2(clk, 177780000);
-		break;
-
-	case CAMIO_CSI0_CLK:
-		camio_csi0_clk =
-		clk = clk_get(&camio_dev->dev, "csi_clk");
-		break;
-
-	case CAMIO_CSI0_PHY_CLK:
-		camio_csi0_phy_clk =
-		clk = clk_get(&camio_dev->dev, "csi_phy_clk");
-		break;
-
-	case CAMIO_CSI_PIX_CLK:
-		camio_csi_pix_clk =
-		clk = clk_get(NULL, "csi_pix_clk");
-		/* mux to select between csid0 and csid1 */
-		msm_camio_clk_rate_set_2(clk, csid_core);
-		break;
-
-	case CAMIO_CSI_PIX1_CLK:
-		camio_csi_pix1_clk =
-		clk = clk_get(NULL, "csi_pix1_clk");
-		/* mux to select between csid0 and csid1 */
-		msm_camio_clk_rate_set_2(clk, csid_core);
-		break;
-
-	case CAMIO_CSI_RDI_CLK:
-		camio_csi_rdi_clk =
-		clk = clk_get(NULL, "csi_rdi_clk");
-		/* mux to select between csid0 and csid1 */
-		msm_camio_clk_rate_set_2(clk, csid_core);
-		break;
-
-	case CAMIO_CSI_RDI1_CLK:
-		camio_csi_rdi1_clk =
-		clk = clk_get(NULL, "csi_rdi1_clk");
-		/* mux to select between csid0 and csid1 */
-		msm_camio_clk_rate_set_2(clk, csid_core);
-		break;
-
-	case CAMIO_CSI_RDI2_CLK:
-		camio_csi_rdi2_clk =
-		clk = clk_get(NULL, "csi_rdi2_clk");
-		/* mux to select between csid0 and csid1 */
-		msm_camio_clk_rate_set_2(clk, csid_core);
-		break;
-
-	case CAMIO_CSIPHY0_TIMER_CLK:
-		camio_csiphy0_timer_clk =
-		clk = clk_get(NULL, "csi0phy_timer_clk");
-		break;
-
-	case CAMIO_CSIPHY1_TIMER_CLK:
-		camio_csiphy1_timer_clk =
-		clk = clk_get(NULL, "csi1phy_timer_clk");
-		break;
-
-	case CAMIO_CSIPHY_TIMER_SRC_CLK:
-		camio_csiphy_timer_src_clk =
-		clk = clk_get(NULL, "csiphy_timer_src_clk");
-		msm_camio_clk_rate_set_2(clk, 177780000);
-		break;
-
-	case CAMIO_CSI0_PCLK:
-		camio_csi0_pclk =
-		clk = clk_get(NULL, "csi_pclk");
-		break;
-
 	case CAMIO_JPEG_CLK:
 		camio_jpeg_clk =
 		clk = clk_get(NULL, "ijpeg_clk");
@@ -565,17 +354,6 @@
 		clk = clk_get(NULL, "ijpeg_pclk");
 		break;
 
-	case CAMIO_VPE_CLK:
-		camio_vpe_clk =
-		clk = clk_get(NULL, "vpe_clk");
-		msm_camio_clk_set_min_rate(clk, 150000000);
-		break;
-
-	case CAMIO_VPE_PCLK:
-		camio_vpe_pclk =
-		clk = clk_get(NULL, "vpe_pclk");
-		break;
-
 	default:
 		break;
 	}
@@ -601,62 +379,6 @@
 		clk = camio_cam_clk;
 		break;
 
-	case CAMIO_VFE_CLK:
-		clk = camio_vfe_clk;
-		break;
-
-	case CAMIO_VFE_PCLK:
-		clk = camio_vfe_pclk;
-		break;
-
-	case CAMIO_CSI0_VFE_CLK:
-		clk = camio_csi0_vfe_clk;
-		break;
-
-	case CAMIO_CSI_SRC_CLK:
-		clk = camio_csi_src_clk;
-		break;
-
-	case CAMIO_CSI0_CLK:
-		clk = camio_csi0_clk;
-		break;
-
-	case CAMIO_CSI0_PHY_CLK:
-		clk = camio_csi0_phy_clk;
-		break;
-
-	case CAMIO_CSI_PIX1_CLK:
-		clk = camio_csi_pix1_clk;
-		break;
-
-	case CAMIO_CSI_PIX_CLK:
-		clk = camio_csi_pix_clk;
-		break;
-
-	case CAMIO_CSI_RDI1_CLK:
-		clk = camio_csi_rdi1_clk;
-		break;
-
-	case CAMIO_CSI_RDI2_CLK:
-		clk = camio_csi_rdi2_clk;
-		break;
-
-	case CAMIO_CSI_RDI_CLK:
-		clk = camio_csi_rdi_clk;
-		break;
-
-	case CAMIO_CSIPHY0_TIMER_CLK:
-		clk = camio_csiphy0_timer_clk;
-		break;
-
-	case CAMIO_CSIPHY_TIMER_SRC_CLK:
-		clk = camio_csiphy_timer_src_clk;
-		break;
-
-	case CAMIO_CSI0_PCLK:
-		clk = camio_csi0_pclk;
-		break;
-
 	case CAMIO_JPEG_CLK:
 		clk = camio_jpeg_clk;
 		break;
@@ -665,14 +387,6 @@
 		clk = camio_jpeg_pclk;
 		break;
 
-	case CAMIO_VPE_CLK:
-		clk = camio_vpe_clk;
-		break;
-
-	case CAMIO_VPE_PCLK:
-		clk = camio_vpe_pclk;
-		break;
-
 	default:
 		break;
 	}
@@ -689,26 +403,6 @@
 	return rc;
 }
 
-int msm_camio_vfe_clk_rate_set(int rate)
-{
-	int rc = 0;
-	int round_rate;
-	struct clk *clk = camio_vfe_clk;
-	round_rate = clk_round_rate(clk, rate);
-	if (rc < 0) {
-		pr_err("%s: clk_round_rate failed %d\n",
-					__func__, rc);
-		return rc;
-	}
-
-	rc = clk_set_rate(clk, round_rate);
-	if (rc < 0)
-		pr_err("%s: clk_set_rate failed %d\n",
-					__func__, rc);
-
-	return rc;
-}
-
 void msm_camio_clk_rate_set(int rate)
 {
 	struct clk *clk = camio_cam_clk;
@@ -725,210 +419,6 @@
 	clk_set_min_rate(clk, rate);
 }
 
-#if DBG_CSID
-static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
-{
-	uint32_t irq;
-	irq = msm_io_r(csidbase + CSID_IRQ_STATUS_ADDR);
-	CDBG("%s CSID_IRQ_STATUS_ADDR = 0x%x\n", __func__, irq);
-	msm_io_w(irq, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
-	return IRQ_HANDLED;
-}
-#endif
-/*
-void msm_io_read_interrupt(void)
-{
-	uint32_t irq;
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS1 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS2 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS3 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS4 = 0x%x\n", __func__, irq);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR);
-	msm_io_w(0x1, csiphybase + 0x164);
-	msm_io_w(0x0, csiphybase + 0x164);
-	return;
-}
-*/
-#if DBG_CSIPHY
-static irqreturn_t msm_io_csiphy_irq(int irq_num, void *data)
-{
-	uint32_t irq;
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS1 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS2 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS3 = 0x%x\n", __func__, irq);
-	irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR);
-	msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR);
-	CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS4 = 0x%x\n", __func__, irq);
-	msm_io_w(0x1, csiphybase + 0x164);
-	msm_io_w(0x0, csiphybase + 0x164);
-	return IRQ_HANDLED;
-}
-#endif
-
-static int msm_camio_enable_v2_clks(void)
-{
-	int rc = 0;
-	csid_hw_version = msm_io_r(csidbase +
-				CSID_HW_VERSION_ADDR);
-	CDBG("%s csid_hw_version %d\n",
-		__func__,
-		csid_hw_version);
-
-	if (csid_hw_version == CSID_VERSION_V2) {
-		rc = msm_camio_clk_enable(CAMIO_CSI_PIX1_CLK);
-		if (rc < 0)
-			goto csi_pix1_fail;
-
-		rc = msm_camio_clk_enable(CAMIO_CSI_RDI1_CLK);
-		if (rc < 0)
-			goto csi_rdi1_fail;
-
-		rc = msm_camio_clk_enable(CAMIO_CSI_RDI2_CLK);
-		if (rc < 0)
-			goto csi_rdi2_fail;
-	}
-
-	return rc;
-
-csi_rdi2_fail:
-	msm_camio_clk_disable(CAMIO_CSI_RDI1_CLK);
-csi_rdi1_fail:
-	msm_camio_clk_disable(CAMIO_CSI_PIX1_CLK);
-csi_pix1_fail:
-	return rc;
-}
-
-static int msm_camio_enable_all_clks(uint8_t csid_core)
-{
-	int rc = 0;
-
-	rc = msm_camio_clk_enable(CAMIO_CSI_SRC_CLK);
-	if (rc < 0)
-		goto csi_src_fail;
-	if (csid_core == 1) {
-		rc = msm_camio_clk_enable(CAMIO_CSI1_SRC_CLK);
-		if (rc < 0)
-			goto csi1_src_fail;
-	}
-	rc = msm_camio_clk_enable(CAMIO_CSI0_CLK);
-	if (rc < 0)
-		goto csi0_fail;
-	rc = msm_camio_clk_enable(CAMIO_CSI0_PHY_CLK);
-	if (rc < 0)
-		goto csi0_phy_fail;
-	rc = msm_camio_clk_enable(CAMIO_CSIPHY_TIMER_SRC_CLK);
-	if (rc < 0)
-		goto csiphy_timer_src_fail;
-	if (csid_core == 0) {
-		rc = msm_camio_clk_enable(CAMIO_CSIPHY0_TIMER_CLK);
-		if (rc < 0)
-			goto csiphy0_timer_fail;
-	} else if (csid_core == 1) {
-		rc = msm_camio_clk_enable(CAMIO_CSIPHY1_TIMER_CLK);
-		if (rc < 0)
-			goto csiphy1_timer_fail;
-	}
-	rc = msm_camio_clk_enable(CAMIO_CSI0_PCLK);
-	if (rc < 0)
-		goto csi0p_fail;
-
-	rc = msm_camio_clk_enable(CAMIO_VFE_CLK);
-	if (rc < 0)
-		goto vfe_fail;
-	rc = msm_camio_clk_enable(CAMIO_VFE_PCLK);
-	if (rc < 0)
-		goto vfep_fail;
-
-	rc = msm_camio_clk_enable(CAMIO_CSI0_VFE_CLK);
-	if (rc < 0)
-		goto csi0_vfe_fail;
-	rc = msm_camio_clk_enable(CAMIO_CSI_PIX_CLK);
-	if (rc < 0)
-		goto csi_pix_fail;
-	rc = msm_camio_clk_enable(CAMIO_CSI_RDI_CLK);
-	if (rc < 0)
-		goto csi_rdi_fail;
-	return rc;
-
-csi_rdi_fail:
-	msm_camio_clk_disable(CAMIO_CSI_PIX_CLK);
-csi_pix_fail:
-	msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
-csi0_vfe_fail:
-	msm_camio_clk_disable(CAMIO_VFE_PCLK);
-vfep_fail:
-	msm_camio_clk_disable(CAMIO_VFE_CLK);
-vfe_fail:
-	msm_camio_clk_disable(CAMIO_CSI0_PCLK);
-csi0p_fail:
-	msm_camio_clk_disable(CAMIO_CSIPHY0_TIMER_CLK);
-csiphy1_timer_fail:
-	msm_camio_clk_disable(CAMIO_CSIPHY1_TIMER_CLK);
-csiphy0_timer_fail:
-	msm_camio_clk_disable(CAMIO_CSIPHY_TIMER_SRC_CLK);
-csiphy_timer_src_fail:
-	msm_camio_clk_disable(CAMIO_CSI0_PHY_CLK);
-csi0_phy_fail:
-	msm_camio_clk_disable(CAMIO_CSI0_CLK);
-csi0_fail:
-	msm_camio_clk_disable(CAMIO_CSI1_SRC_CLK);
-csi1_src_fail:
-	msm_camio_clk_disable(CAMIO_CSI_SRC_CLK);
-csi_src_fail:
-	return rc;
-}
-
-static void msm_camio_disable_v2_clks(void)
-{
-	if (csid_hw_version == CSID_VERSION_V2) {
-		msm_camio_clk_disable(CAMIO_CSI_RDI2_CLK);
-		msm_camio_clk_disable(CAMIO_CSI_RDI1_CLK);
-		msm_camio_clk_disable(CAMIO_CSI_PIX1_CLK);
-	}
-}
-
-static void msm_camio_disable_all_clks(uint8_t csid_core)
-{
-	msm_camio_disable_v2_clks();
-	msm_camio_clk_disable(CAMIO_CSI_RDI_CLK);
-	msm_camio_clk_disable(CAMIO_CSI_PIX_CLK);
-	msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
-	msm_camio_clk_disable(CAMIO_VFE_PCLK);
-	msm_camio_clk_disable(CAMIO_VFE_CLK);
-	msm_camio_clk_disable(CAMIO_CSI0_PCLK);
-	if (csid_core == 0)
-		msm_camio_clk_disable(CAMIO_CSIPHY0_TIMER_CLK);
-	else if (csid_core == 1)
-		msm_camio_clk_disable(CAMIO_CSIPHY1_TIMER_CLK);
-	msm_camio_clk_disable(CAMIO_CSIPHY_TIMER_SRC_CLK);
-	msm_camio_clk_disable(CAMIO_CSI0_PHY_CLK);
-	msm_camio_clk_disable(CAMIO_CSI0_CLK);
-	if (csid_core == 1)
-		msm_camio_clk_disable(CAMIO_CSI1_SRC_CLK);
-	msm_camio_clk_disable(CAMIO_CSI_SRC_CLK);
-}
-
 int msm_camio_jpeg_clk_disable(void)
 {
 	int rc = 0;
@@ -971,42 +461,6 @@
 	return rc;
 }
 
-int msm_camio_vpe_clk_disable(void)
-{
-	int rc = 0;
-	if (fs_vpe) {
-		regulator_disable(fs_vpe);
-		regulator_put(fs_vpe);
-	}
-
-	rc = msm_camio_clk_disable(CAMIO_VPE_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_disable(CAMIO_VPE_PCLK);
-	return rc;
-}
-
-int msm_camio_vpe_clk_enable(uint32_t clk_rate)
-{
-	int rc = 0;
-	(void)clk_rate;
-	fs_vpe = regulator_get(NULL, "fs_vpe");
-	if (IS_ERR(fs_vpe)) {
-		pr_err("%s: Regulator FS_VPE get failed %ld\n", __func__,
-			PTR_ERR(fs_vpe));
-		fs_vpe = NULL;
-	} else if (regulator_enable(fs_vpe)) {
-		pr_err("%s: Regulator FS_VPE enable failed\n", __func__);
-		regulator_put(fs_vpe);
-	}
-
-	rc = msm_camio_clk_enable(CAMIO_VPE_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_enable(CAMIO_VPE_PCLK);
-	return rc;
-}
-
 static int config_gpio_table(int gpio_en)
 {
 	struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
@@ -1040,125 +494,6 @@
 	return rc;
 }
 
-int msm_camio_enable(struct platform_device *pdev)
-{
-	int rc = 0;
-	struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
-	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-	uint8_t csid_core = camdev->csid_core;
-	char csid[] = "csid0";
-	char csiphy[] = "csiphy0";
-	if (csid_core < 0 || csid_core > 2)
-		return -ENODEV;
-
-	csid[4] = '0' + csid_core;
-	csiphy[6] = '0' + csid_core;
-
-	camio_dev = pdev;
-	camio_clk = camdev->ioclk;
-	cam_bus_scale_table = camdev->cam_bus_scale_table;
-
-	rc = msm_camio_enable_all_clks(csid_core);
-	if (rc < 0)
-		return rc;
-
-	csid_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, csid);
-	if (!csid_mem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		return -ENODEV;
-	}
-	csid_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, csid);
-	if (!csid_irq) {
-		pr_err("%s: no irq resource?\n", __func__);
-		return -ENODEV;
-	}
-	csiphy_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, csiphy);
-	if (!csiphy_mem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		return -ENODEV;
-	}
-	csiphy_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, csiphy);
-	if (!csiphy_irq) {
-		pr_err("%s: no irq resource?\n", __func__);
-		return -ENODEV;
-	}
-
-	csidio = request_mem_region(csid_mem->start,
-		resource_size(csid_mem), pdev->name);
-	if (!csidio) {
-		rc = -EBUSY;
-		goto common_fail;
-	}
-	csidbase = ioremap(csid_mem->start,
-		resource_size(csid_mem));
-	if (!csidbase) {
-		rc = -ENOMEM;
-		goto csi_busy;
-	}
-#if DBG_CSID
-	rc = request_irq(csid_irq->start, msm_io_csi_irq,
-		IRQF_TRIGGER_RISING, "csid", 0);
-	if (rc < 0)
-		goto csi_irq_fail;
-#endif
-	csiphyio = request_mem_region(csiphy_mem->start,
-		resource_size(csiphy_mem), pdev->name);
-	if (!csidio) {
-		rc = -EBUSY;
-		goto csi_irq_fail;
-	}
-	csiphybase = ioremap(csiphy_mem->start,
-		resource_size(csiphy_mem));
-	if (!csiphybase) {
-		rc = -ENOMEM;
-		goto csiphy_busy;
-	}
-#if DBG_CSIPHY
-	rc = request_irq(csiphy_irq->start, msm_io_csiphy_irq,
-		IRQF_TRIGGER_RISING, "csiphy", 0);
-	if (rc < 0)
-		goto csiphy_irq_fail;
-#endif
-	msm_camio_enable_v2_clks();
-	CDBG("camio enable done\n");
-	return 0;
-#if DBG_CSIPHY
-csiphy_irq_fail:
-	iounmap(csiphybase);
-#endif
-csiphy_busy:
-	release_mem_region(csiphy_mem->start, resource_size(csiphy_mem));
-csi_irq_fail:
-	iounmap(csidbase);
-csi_busy:
-	release_mem_region(csid_mem->start, resource_size(csid_mem));
-common_fail:
-	msm_camio_disable_all_clks(csid_core);
-	msm_camera_vreg_disable();
-	config_gpio_table(0);
-	return rc;
-}
-
-void msm_camio_disable(struct platform_device *pdev)
-{
-	struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
-	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-	uint8_t csid_core = camdev->csid_core;
-#if DBG_CSIPHY
-	free_irq(csiphy_irq->start, 0);
-#endif
-	iounmap(csiphybase);
-	release_mem_region(csiphy_mem->start, resource_size(csiphy_mem));
-
-#if DBG_CSID
-	free_irq(csid_irq->start, 0);
-#endif
-	iounmap(csidbase);
-	release_mem_region(csid_mem->start, resource_size(csid_mem));
-
-	msm_camio_disable_all_clks(csid_core);
-}
-
 int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *s_info)
 {
 	int32_t val = 0, rc = 0;
@@ -1306,103 +641,6 @@
 	return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
 }
 
-int msm_camio_csid_cid_lut(struct msm_camera_csid_lut_params *csid_lut_params)
-{
-	int rc = 0, i = 0;
-	uint32_t val = 0;
-
-	for (i = 0; i < csid_lut_params->num_cid && i < 4; i++)	{
-		if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
-			csid_lut_params->vc_cfg[i].dt > 0x37) {
-			CDBG("%s: unsupported data type 0x%x\n",
-				 __func__, csid_lut_params->vc_cfg[i].dt);
-			return rc;
-		}
-		val = msm_io_r(csidbase + CSID_CID_LUT_VC_0_ADDR +
-		(csid_lut_params->vc_cfg[i].cid >> 2) * 4)
-		& ~(0xFF << csid_lut_params->vc_cfg[i].cid * 8);
-		val |= csid_lut_params->vc_cfg[i].dt <<
-			csid_lut_params->vc_cfg[i].cid * 8;
-		msm_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
-			(csid_lut_params->vc_cfg[i].cid >> 2) * 4);
-		val = csid_lut_params->vc_cfg[i].decode_format << 4 | 0x3;
-		msm_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
-			(csid_lut_params->vc_cfg[i].cid * 4));
-	}
-	return rc;
-}
-
-int msm_camio_csid_config(struct msm_camera_csid_params *csid_params)
-{
-	int rc = 0;
-	uint32_t val = 0;
-	val = csid_params->lane_cnt - 1;
-	val |= csid_params->lane_assign << 2;
-	val |= 0x1 << 10;
-	val |= 0x1 << 11;
-	val |= 0x1 << 12;
-	val |= 0x1 << 28;
-	msm_io_w(val, csidbase + CSID_CORE_CTRL_ADDR);
-
-	rc = msm_camio_csid_cid_lut(&csid_params->lut_params);
-	if (rc < 0)
-		return rc;
-
-	msm_io_w(0x7fF10800, csidbase + CSID_IRQ_MASK_ADDR);
-	msm_io_w(0x7fF10800, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
-
-	msleep(20);
-	return rc;
-}
-
-int msm_camio_csiphy_config(struct msm_camera_csiphy_params *csiphy_params)
-{
-	int rc = 0;
-	int i = 0;
-	uint32_t val = 0;
-	if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
-		CDBG("%s: unsupported lane cnt %d\n",
-			__func__, csiphy_params->lane_cnt);
-		return rc;
-	}
-
-	val = 0x3;
-	msm_io_w((((1 << csiphy_params->lane_cnt) - 1) << 2) | val,
-			 csiphybase + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
-	msm_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
-	msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
-
-	for (i = 0; i < csiphy_params->lane_cnt; i++) {
-		msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
-		msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
-		msm_io_w(csiphy_params->settle_cnt,
-			csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
-		msm_io_w(0x00000052,
-			csiphybase + MIPI_CSIPHY_LNn_CFG5_ADDR + 0x40*i);
-	}
-
-	msm_io_w(0x00000000, csiphybase + MIPI_CSIPHY_LNCK_CFG1_ADDR);
-	msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
-	msm_io_w(csiphy_params->settle_cnt,
-			 csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
-	msm_io_w(0x5, csiphybase + MIPI_CSIPHY_LNCK_CFG4_ADDR);
-	msm_io_w(0x2, csiphybase + MIPI_CSIPHY_LNCK_CFG5_ADDR);
-	msm_io_w(0x0, csiphybase + 0x128);
-
-	msm_io_w(0x24,
-		csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
-	msm_io_w(0x24,
-		csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
-
-	for (i = 1; i <= csiphy_params->lane_cnt; i++) {
-		msm_io_w(0x6F,
-			csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR + 0x4*i);
-		msm_io_w(0x6F,
-			csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
-	}
-	return rc;
-}
-
 void msm_camio_mode_config(enum msm_cam_mode mode)
 {
 	uint32_t val;
@@ -1423,9 +661,13 @@
 void msm_camio_set_perf_lvl(enum msm_bus_perf_setting perf_setting)
 {
 	static uint32_t bus_perf_client;
+	struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
+	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
 	int rc = 0;
 	switch (perf_setting) {
 	case S_INIT:
+		cam_bus_scale_table = camdev->cam_bus_scale_table;
 		bus_perf_client =
 			msm_bus_scale_register_client(cam_bus_scale_table);
 		if (!bus_perf_client) {
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index e12d6b1..e4d4f27 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -638,7 +638,7 @@
 
 	int rc = -EINVAL;
 	void __user *argp = (void __user *)arg;
-	struct v4l2_subdev *sd = &pmctl->isp_sdev->sd;
+	struct v4l2_subdev *sd = pmctl->isp_sdev->sd;
 
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 	switch (cmd) {
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index a7fe8a2..a3cf004 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -28,6 +28,8 @@
 #include <linux/android_pmem.h>
 
 #include "msm.h"
+#include "msm_csid.h"
+#include "msm_csiphy.h"
 #include "msm_ispif.h"
 
 #ifdef CONFIG_MSM_CAMERA_DEBUG
@@ -188,7 +190,7 @@
 			ispif_params.params[0].csid = csid_core;
 
 			rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
-				VIDIOC_MSM_ISPSF_CFG, &ispif_params);
+				VIDIOC_MSM_ISPIF_CFG, &ispif_params);
 			if (rc < 0)
 				return rc;
 		}
@@ -207,17 +209,26 @@
 	case NOTIFY_VFE_BUF_EVT:
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
 			rc = p_mctl->isp_sdev->isp_notify(
-				&p_mctl->isp_sdev->sd, notification, arg);
+				p_mctl->isp_sdev->sd, notification, arg);
 		}
 		break;
 	case NOTIFY_VPE_MSG_EVT:
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
 			rc = p_mctl->isp_sdev->isp_notify(
-				&p_mctl->isp_sdev->sd_vpe, notification, arg);
+				p_mctl->isp_sdev->sd_vpe, notification, arg);
 		}
 		break;
 	case NOTIFY_PCLK_CHANGE:
-		rc = msm_camio_vfe_clk_rate_set(*(uint32_t *)arg);
+		rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
+			s_crystal_freq, *(uint32_t *)arg, 0);
+		break;
+	case NOTIFY_CSIPHY_CFG:
+		rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
+			core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
+		break;
+	case NOTIFY_CSID_CFG:
+		rc = v4l2_subdev_call(p_mctl->csid_sdev,
+			core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
 		break;
 	default:
 		break;
@@ -313,11 +324,105 @@
 	return rc;
 }
 
+static int msm_mctl_subdev_match_core(struct device *dev, void *data)
+{
+	int core_index = (int)data;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	if (pdev->id == core_index)
+		return 1;
+	else
+		return 0;
+}
+
+static int msm_mctl_register_subdevs(struct msm_cam_media_controller *p_mctl,
+	int core_index)
+{
+	struct device_driver *driver;
+	struct device *dev;
+	int rc = -ENODEV;
+
+	/* register csiphy subdev */
+	driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
+	if (!driver)
+		goto out;
+
+	dev = driver_find_device(driver, NULL, (void *)core_index,
+				msm_mctl_subdev_match_core);
+	if (!dev)
+		goto out_put_driver;
+
+	p_mctl->csiphy_sdev = dev_get_drvdata(dev);
+	put_driver(driver);
+
+	/* register csid subdev */
+	driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
+	if (!driver)
+		goto out;
+
+	dev = driver_find_device(driver, NULL, (void *)core_index,
+				msm_mctl_subdev_match_core);
+	if (!dev)
+		goto out_put_driver;
+
+	p_mctl->csid_sdev = dev_get_drvdata(dev);
+	put_driver(driver);
+
+	/* register ispif subdev */
+	driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
+	if (!driver)
+		goto out;
+
+	dev = driver_find_device(driver, NULL, 0,
+				msm_mctl_subdev_match_core);
+	if (!dev)
+		goto out_put_driver;
+
+	p_mctl->ispif_sdev = dev_get_drvdata(dev);
+	put_driver(driver);
+
+	/* register vfe subdev */
+	driver = driver_find(MSM_VFE_DRV_NAME, &platform_bus_type);
+	if (!driver)
+		goto out;
+
+	dev = driver_find_device(driver, NULL, 0,
+				msm_mctl_subdev_match_core);
+	if (!dev)
+		goto out_put_driver;
+
+	p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
+	put_driver(driver);
+
+	/* register vfe subdev */
+	driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
+	if (!driver)
+		goto out;
+
+	dev = driver_find_device(driver, NULL, 0,
+				msm_mctl_subdev_match_core);
+	if (!dev)
+		goto out_put_driver;
+
+	p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
+	put_driver(driver);
+
+	rc = 0;
+	return rc;
+out_put_driver:
+	put_driver(driver);
+out:
+	return rc;
+}
+
 static int msm_mctl_open(struct msm_cam_media_controller *p_mctl,
 				 const char *const apps_id)
 {
 	int rc = 0;
 	struct msm_sync *sync = NULL;
+	struct msm_camera_sensor_info *sinfo;
+	struct msm_camera_device_platform_data *camdev;
+	uint8_t csid_core;
 	D("%s\n", __func__);
 	if (!p_mctl) {
 		pr_err("%s: param is NULL", __func__);
@@ -330,8 +435,21 @@
 	mutex_lock(&sync->lock);
 	/* open sub devices - once only*/
 	if (!sync->opencnt) {
+		uint32_t csid_version;
 		wake_lock(&sync->wake_lock);
 
+		sinfo = sync->pdev->dev.platform_data;
+		sync->pdev->resource = sinfo->resource;
+		sync->pdev->num_resources = sinfo->num_resources;
+		camdev = sinfo->pdata;
+		csid_core = camdev->csid_core;
+		rc = msm_mctl_register_subdevs(p_mctl, csid_core);
+		if (rc < 0) {
+			pr_err("%s: msm_mctl_register_subdevs failed:%d\n",
+				__func__, rc);
+			goto msm_open_done;
+		}
+
 		/* turn on clock */
 		rc = msm_camio_sensor_clk_on(sync->pdev);
 		if (rc < 0) {
@@ -340,19 +458,34 @@
 			goto msm_open_done;
 		}
 
+		rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+			VIDIOC_MSM_CSIPHY_INIT, NULL);
+		if (rc < 0) {
+			pr_err("%s: csiphy initialization failed %d\n",
+				__func__, rc);
+			goto msm_open_done;
+		}
+
+		rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+			VIDIOC_MSM_CSID_INIT, &csid_version);
+		if (rc < 0) {
+			pr_err("%s: csid initialization failed %d\n",
+				__func__, rc);
+			goto msm_open_done;
+		}
+
 		/* ISP first*/
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_open)
 			rc = p_mctl->isp_sdev->isp_open(
-				&p_mctl->isp_sdev->sd,
-				&p_mctl->isp_sdev->sd_vpe, sync);
+				p_mctl->isp_sdev->sd,
+				p_mctl->isp_sdev->sd_vpe, sync);
 		if (rc < 0) {
 			pr_err("%s: isp init failed: %d\n", __func__, rc);
 			goto msm_open_done;
 		}
 
-		/*This has to be after isp_open, because isp_open initialize
-		 *platform resource. This dependency needs to be removed. */
-		rc = msm_ispif_init(&p_mctl->ispif_sdev, sync->pdev);
+		rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+			VIDIOC_MSM_ISPIF_INIT, &csid_version);
 		if (rc < 0) {
 			pr_err("%s: ispif initialization failed %d\n",
 				__func__, rc);
@@ -385,16 +518,21 @@
 
 static int msm_mctl_release(struct msm_cam_media_controller *p_mctl)
 {
-	struct msm_sync *sync = NULL;
 	int rc = 0;
+	struct msm_sync *sync = &(p_mctl->sync);
 
-	sync = &(p_mctl->sync);
-
-	msm_ispif_release(p_mctl->ispif_sdev);
+	v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+		VIDIOC_MSM_ISPIF_RELEASE, NULL);
 
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
 		p_mctl->isp_sdev->isp_release(&p_mctl->sync);
 
+	v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+		VIDIOC_MSM_CSID_RELEASE, NULL);
+
+	v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+		VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+
 	if (p_mctl->sync.actctrl.a_power_down)
 		p_mctl->sync.actctrl.a_power_down();
 
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index f7e5479..c7c7cf6 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -100,7 +100,7 @@
 	buf_type = (vb->num_planes == 1) ? VIDEOBUF2_SINGLE_PLANE
 					: VIDEOBUF2_MULTIPLE_PLANES;
 	if (buf_type == VIDEOBUF2_SINGLE_PLANE) {
-		offset.sp_off.y_off = 0;
+		offset.sp_off.y_off = pcam_inst->plane_info.sp_y_offset;
 		offset.sp_off.cbcr_off =
 			pcam_inst->plane_info.plane[0].offset;
 	}
@@ -319,52 +319,6 @@
 	return 0;
 }
 
-static int msm_buf_init(struct msm_cam_v4l2_dev_inst *pcam_inst)
-{
-	int rc = 0;
-	struct resource *res;
-	struct platform_device *pdev = NULL;
-	struct msm_cam_v4l2_device *pcam = NULL;
-
-	D("%s\n", __func__);
-	pcam = pcam_inst->pcam;
-	if (!pcam) {
-		pr_err("%s error : input is NULL\n", __func__);
-		return -EINVAL;
-	} else
-		pdev = pcam->mctl.sync.pdev;
-
-	if (!pdev) {
-		pr_err("%s error : pdev is NULL\n", __func__);
-		return -EINVAL;
-	}
-	if (pcam->use_count == 1) {
-		/* first check if we have resources */
-		res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-		if (res) {
-			D("res->start = 0x%x\n", (u32)res->start);
-			D("res->size = 0x%x\n", (u32)resource_size(res));
-			D("res->end = 0x%x\n", (u32)res->end);
-			rc = dma_declare_coherent_memory(&pdev->dev, res->start,
-					res->start,
-					resource_size(res),
-					DMA_MEMORY_MAP |
-					DMA_MEMORY_EXCLUSIVE);
-			if (!rc) {
-				pr_err("%s: Unable to declare coherent memory.\n",
-				__func__);
-				rc = -ENXIO;
-				return rc;
-			}
-			D("%s: found DMA capable resource\n", __func__);
-		} else {
-			pr_err("%s: no DMA capable resource\n", __func__);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
 int msm_mctl_out_type_to_inst_index(struct msm_cam_v4l2_device *pcam,
 					int out_type)
 {
@@ -502,7 +456,6 @@
 
 int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam)
 {
-	pcam->mctl.mctl_buf_init = msm_buf_init;
 	pcam->mctl.mctl_vbqueue_init = msm_vbqueue_init;
 	return 0;
 }
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 2bf95a0..8236dae 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -300,12 +300,12 @@
 	case VPE_CMD_INIT:
 	case VPE_CMD_DEINIT:
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	case VPE_CMD_DISABLE:
 	case VPE_CMD_RESET:
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	case VPE_CMD_ENABLE: {
 		struct msm_vpe_clock_rate clk_rate;
@@ -325,7 +325,7 @@
 		}
 		pp_cmd->value = (void *)&clk_rate;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		pp_cmd->value = argp;
 		break;
 	}
@@ -344,7 +344,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&flush_buf;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		if (rc == 0) {
 			if (copy_to_user((void *)argp,
 						&flush_buf,
@@ -372,7 +372,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&op_mode_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_INPUT_PLANE_CFG: {
@@ -390,7 +390,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&input_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_OUTPUT_PLANE_CFG: {
@@ -411,7 +411,7 @@
 		}
 		pp_cmd->value = (void *)&output_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_INPUT_PLANE_UPDATE: {
@@ -429,7 +429,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&input_update_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_SCALE_CFG_TYPE: {
@@ -447,7 +447,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&scaler_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_ZOOM: {
@@ -512,7 +512,7 @@
 			break;
 		}
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, (void *)zoom);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, (void *)zoom);
 		if (rc) {
 			kfree(zoom);
 			break;
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index b6dbe87..c13e7e5 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -143,7 +143,7 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	region->handle = ion_import_fd(client, info->fd);
 	if (IS_ERR_OR_NULL(region->handle))
-		goto OUT1;
+		goto out1;
 	ion_phys(client, region->handle, &paddr, (size_t *)&len);
 #elif CONFIG_ANDROID_PMEM
 	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 5c02f85..c5cc55c 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -15,6 +15,8 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/atomic.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
 #include <mach/irqs.h>
 #include <mach/camera.h>
 #include <media/v4l2-device.h>
@@ -23,7 +25,6 @@
 
 #include "msm.h"
 #include "msm_vfe32.h"
-#include "msm_ispif.h"
 
 atomic_t irq_cnt;
 
@@ -54,8 +55,8 @@
 	vfe32_put_ch_ping_addr((chn), (addr)))
 
 static struct vfe32_ctrl_type *vfe32_ctrl;
-static struct msm_camera_io_clk camio_clk;
 static void  *vfe_syncdata;
+static uint32_t vfe_clk_rate;
 
 struct vfe32_isr_queue_cmd {
 	struct list_head list;
@@ -210,6 +211,15 @@
 			V32_CLF_LUMA_UPDATE_OFF},
 		{VFE_CMD_CLF_CHROMA_UPDATE, V32_CLF_CHROMA_UPDATE_LEN,
 			V32_CLF_CHROMA_UPDATE_OFF},
+/*120*/ {VFE_CMD_PCA_ROLL_OFF_CFG},
+		{VFE_CMD_PCA_ROLL_OFF_UPDATE},
+		{VFE_CMD_GET_REG_DUMP},
+		{VFE_CMD_GET_LINEARIZATON_TABLE},
+		{VFE_CMD_GET_MESH_ROLLOFF_TABLE},
+/*125*/ {VFE_CMD_GET_PCA_ROLLOFF_TABLE},
+		{VFE_CMD_GET_RGB_G_TABLE},
+		{VFE_CMD_GET_LA_TABLE},
+		{VFE_CMD_DEMOSAICV3_UPDATE},
 };
 
 uint32_t vfe32_AXI_WM_CFG[] = {
@@ -343,6 +353,15 @@
 	"CLF_CFG",
 	"CLF_LUMA_UPDATE",
 	"CLF_CHROMA_UPDATE",
+	"PCA_ROLL_OFF_CFG", /*120*/
+	"PCA_ROLL_OFF_UPDATE",
+	"GET_REG_DUMP",
+	"GET_LINEARIZATON_TABLE",
+	"GET_MESH_ROLLOFF_TABLE",
+	"GET_PCA_ROLLOFF_TABLE", /*125*/
+	"GET_RGB_G_TABLE",
+	"GET_LA_TABLE",
+	"DEMOSAICV3_UPDATE",
 };
 
 static void vfe32_stop(void)
@@ -419,7 +438,7 @@
 	rp->evt_msg.type   = MSM_CAMERA_MSG;
 	rp->evt_msg.msg_id = path;
 	rp->type	   = id;
-	v4l2_subdev_notify(vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
+	v4l2_subdev_notify(&vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
 	spin_unlock_irqrestore(&vfe32_ctrl->sd_notify_lock, flags);
 }
 
@@ -1001,7 +1020,7 @@
 			 8 + ((vfe32_ctrl->sync_timer_number) * 12));
 	/* Sync Timer Pixel Duration */
 	value = *tbl++;
-	val = camio_clk.vfe_clk_rate / 10000;
+	val = vfe_clk_rate / 10000;
 	val = 10000000 / val;
 	val = value * 10000 / val;
 	CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
@@ -1020,6 +1039,7 @@
 	/* set bit 8 for auto increment. */
 	uint32_t value = VFE_DMI_CFG_DEFAULT;
 	value += (uint32_t)bankSel;
+	CDBG("%s: banksel = %d\n", __func__, bankSel);
 
 	msm_io_w(value, vfe32_ctrl->vfebase + VFE_DMI_CFG);
 	/* by default, always starts with offset 0.*/
@@ -1186,7 +1206,7 @@
 
 	isp_msg_evt.msg_id = isp_msg_id;
 	isp_msg_evt.sof_count = vfe32_ctrl->vfeFrameId;
-	v4l2_subdev_notify(vctrl->subdev,
+	v4l2_subdev_notify(&vctrl->subdev,
 			NOTIFY_ISP_MSG_EVT,
 			(void *)&isp_msg_evt);
 }
@@ -2072,6 +2092,9 @@
 		}
 		msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
+		cmdp_local = cmdp + V32_ASF_LEN/4;
+		msm_io_memcpy(vfe32_ctrl->vfebase + V32_ASF_SPECIAL_EFX_CFG_OFF,
+			cmdp_local, V32_ASF_SPECIAL_EFX_CFG_LEN);
 		break;
 
 	case VFE_CMD_PCA_ROLL_OFF_CFG:
@@ -2146,9 +2169,9 @@
 
 		CDBG("%s: start writing RollOff Ram0 table\n", __func__);
 		if (temp2)
-			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1);
-		else
 			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+		else
+			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1);
 
 		msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
 		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
@@ -2162,9 +2185,9 @@
 
 		CDBG("%s: start writing RollOff Ram1 table\n", __func__);
 		if (temp2)
-			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
-		else
 			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+		else
+			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
 
 		msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
 		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
@@ -2618,7 +2641,7 @@
 	msg.buf.ch_paddr[2]	= ch2_paddr;
 	msg.frameCounter = vfe32_ctrl->vfeFrameId;
 
-	v4l2_subdev_notify(vfe32_ctrl->subdev,
+	v4l2_subdev_notify(&vfe32_ctrl->subdev,
 			NOTIFY_VFE_MSG_OUT,
 			&msg);
 	return;
@@ -2684,13 +2707,13 @@
 			VFE_MODE_OF_OPERATION_SNAPSHOT) {
 			/* will add message for multi-shot. */
 			vfe32_ctrl->outpath.out0.capture_cnt--;
-			vfe_send_outmsg(vfe32_ctrl->subdev,
+			vfe_send_outmsg(&vfe32_ctrl->subdev,
 				MSG_ID_OUTPUT_T, ch0_paddr,
 				ch1_paddr, ch2_paddr);
 		} else {
 			/* always send message for continous mode. */
 			/* if continuous mode, for display. (preview) */
-			vfe_send_outmsg(vfe32_ctrl->subdev,
+			vfe_send_outmsg(&vfe32_ctrl->subdev,
 				MSG_ID_OUTPUT_P, ch0_paddr,
 				ch1_paddr, ch2_paddr);
 		}
@@ -2730,7 +2753,7 @@
 			vfe32_put_ch_addr(ping_pong,
 				vfe32_ctrl->outpath.out1.ch2,
 				free_buf->ch_paddr[2]);
-		vfe_send_outmsg(vfe32_ctrl->subdev,
+		vfe_send_outmsg(&vfe32_ctrl->subdev,
 			MSG_ID_OUTPUT_T, ch0_paddr,
 			ch1_paddr, ch2_paddr);
 	}
@@ -2756,7 +2779,7 @@
 		vfe32_put_ch_addr(ping_pong,
 			vfe32_ctrl->outpath.out2.ch1,
 			free_buf->ch_paddr[1]);
-		vfe_send_outmsg(vfe32_ctrl->subdev,
+		vfe_send_outmsg(&vfe32_ctrl->subdev,
 			MSG_ID_OUTPUT_S, ch0_paddr,
 			ch1_paddr, ch2_paddr);
 	}
@@ -2825,7 +2848,7 @@
 			vfe32_ctrl->operation_mode ==
 			VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
 			vfe32_ctrl->outpath.out1.capture_cnt--;
-			vfe_send_outmsg(vfe32_ctrl->subdev,
+			vfe_send_outmsg(&vfe32_ctrl->subdev,
 				MSG_ID_OUTPUT_S, ch0_paddr,
 				ch1_paddr, ch2_paddr);
 		}
@@ -2888,7 +2911,7 @@
 				vfe32_ctrl->outpath.out2.ch2,
 				free_buf->ch_paddr[2]);
 
-		vfe_send_outmsg(vfe32_ctrl->subdev,
+		vfe_send_outmsg(&vfe32_ctrl->subdev,
 			MSG_ID_OUTPUT_V, ch0_paddr,
 			ch1_paddr, ch2_paddr);
 
@@ -2980,7 +3003,7 @@
 		goto stats_done;
 	}
 
-	v4l2_subdev_notify(vfe32_ctrl->subdev,
+	v4l2_subdev_notify(&vfe32_ctrl->subdev,
 				NOTIFY_VFE_MSG_STATS,
 				&msgStats);
 stats_done:
@@ -3276,91 +3299,6 @@
 	return IRQ_HANDLED;
 }
 
-static int vfe32_resource_init(struct platform_device *pdev, void *sdata)
-{
-	struct resource	*vfemem, *vfeirq, *vfeio;
-	int rc;
-	struct msm_camera_sensor_info *s_info;
-	s_info = pdev->dev.platform_data;
-
-	pdev->resource = s_info->resource;
-	pdev->num_resources = s_info->num_resources;
-
-	vfemem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!vfemem) {
-		pr_err("%s: no mem resource?\n", __func__);
-		return -ENODEV;
-	}
-
-	vfeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!vfeirq) {
-		pr_err("%s: no irq resource?\n", __func__);
-		return -ENODEV;
-	}
-
-	vfeio = request_mem_region(vfemem->start,
-		resource_size(vfemem), pdev->name);
-	if (!vfeio) {
-		pr_err("%s: VFE region already claimed\n", __func__);
-		return -EBUSY;
-	}
-
-	vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
-	if (!vfe32_ctrl) {
-		rc = -ENOMEM;
-		goto cmd_init_failed1;
-	}
-
-	vfe32_ctrl->vfeirq = vfeirq->start;
-
-	vfe32_ctrl->vfebase =
-		ioremap(vfemem->start, (vfemem->end - vfemem->start) + 1);
-	if (!vfe32_ctrl->vfebase) {
-		rc = -ENOMEM;
-		pr_err("%s: vfe ioremap failed\n", __func__);
-		goto cmd_init_failed2;
-	}
-
-	vfe32_ctrl->extdata =
-		kmalloc(sizeof(struct vfe32_frame_extra), GFP_KERNEL);
-	if (!vfe32_ctrl->extdata) {
-		rc = -ENOMEM;
-		goto cmd_init_failed3;
-	}
-
-	vfe32_ctrl->extlen = sizeof(struct vfe32_frame_extra);
-
-	spin_lock_init(&vfe32_ctrl->stop_flag_lock);
-	spin_lock_init(&vfe32_ctrl->state_lock);
-	spin_lock_init(&vfe32_ctrl->io_lock);
-	spin_lock_init(&vfe32_ctrl->update_ack_lock);
-	spin_lock_init(&vfe32_ctrl->tasklet_lock);
-
-	spin_lock_init(&vfe32_ctrl->aec_ack_lock);
-	spin_lock_init(&vfe32_ctrl->awb_ack_lock);
-	spin_lock_init(&vfe32_ctrl->af_ack_lock);
-	spin_lock_init(&vfe32_ctrl->sd_notify_lock);
-	INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
-
-	vfe32_ctrl->syncdata = sdata;
-	vfe32_ctrl->vfemem = vfemem;
-	vfe32_ctrl->vfeio  = vfeio;
-	vfe32_ctrl->update_linear = false;
-	vfe32_ctrl->update_rolloff = false;
-	vfe32_ctrl->update_la = false;
-	vfe32_ctrl->update_gamma = false;
-	return 0;
-
-cmd_init_failed3:
-	free_irq(vfe32_ctrl->vfeirq, 0);
-	iounmap(vfe32_ctrl->vfebase);
-cmd_init_failed2:
-	kfree(vfe32_ctrl);
-cmd_init_failed1:
-	release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
-	return rc;
-}
-
 static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int subdev_cmd, void *arg)
 {
@@ -3659,36 +3597,103 @@
 	return rc;
 }
 
+static struct msm_cam_clk_info vfe32_clk_info[] = {
+	{"vfe_clk", 228570000},
+	{"vfe_pclk", -1},
+	{"csi_vfe_clk", -1},
+};
+
+static int msm_vfe_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+						u32 freq, u32 flags)
+{
+	int rc = 0;
+	int round_rate;
+
+	round_rate = clk_round_rate(vfe32_ctrl->vfe_clk[0], freq);
+	if (rc < 0) {
+		pr_err("%s: clk_round_rate failed %d\n",
+					__func__, rc);
+		return rc;
+	}
+
+	vfe_clk_rate = round_rate;
+	rc = clk_set_rate(vfe32_ctrl->vfe_clk[0], round_rate);
+	if (rc < 0)
+		pr_err("%s: clk_set_rate failed %d\n",
+					__func__, rc);
+
+	return rc;
+}
+
+static const struct v4l2_subdev_video_ops msm_vfe_subdev_video_ops = {
+	.s_crystal_freq = msm_vfe_subdev_s_crystal_freq,
+};
+
 static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
 	.ioctl = msm_vfe_subdev_ioctl,
 };
 
 static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
 	.core = &msm_vfe_subdev_core_ops,
+	.video = &msm_vfe_subdev_video_ops,
 };
 
 int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
 	struct platform_device *pdev)
 {
 	int rc = 0;
-	struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
-	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-
-	v4l2_subdev_init(sd, &msm_vfe_subdev_ops);
 	v4l2_set_subdev_hostdata(sd, data);
-	snprintf(sd->name, sizeof(sd->name), "vfe3.2");
-
 	vfe_syncdata = data;
 
-	camio_clk = camdev->ioclk;
+	spin_lock_init(&vfe32_ctrl->stop_flag_lock);
+	spin_lock_init(&vfe32_ctrl->state_lock);
+	spin_lock_init(&vfe32_ctrl->io_lock);
+	spin_lock_init(&vfe32_ctrl->update_ack_lock);
+	spin_lock_init(&vfe32_ctrl->tasklet_lock);
 
-	rc = vfe32_resource_init(pdev, vfe_syncdata);
+	spin_lock_init(&vfe32_ctrl->aec_ack_lock);
+	spin_lock_init(&vfe32_ctrl->awb_ack_lock);
+	spin_lock_init(&vfe32_ctrl->af_ack_lock);
+	spin_lock_init(&vfe32_ctrl->sd_notify_lock);
+	INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
+
+	vfe32_ctrl->update_linear = false;
+	vfe32_ctrl->update_rolloff = false;
+	vfe32_ctrl->update_la = false;
+	vfe32_ctrl->update_gamma = false;
+
+	enable_irq(vfe32_ctrl->vfeirq->start);
+
+	vfe32_ctrl->vfebase = ioremap(vfe32_ctrl->vfemem->start,
+		resource_size(vfe32_ctrl->vfemem));
+	if (!vfe32_ctrl->vfebase) {
+		rc = -ENOMEM;
+		pr_err("%s: vfe ioremap failed\n", __func__);
+		goto vfe_remap_failed;
+	}
+
+	if (vfe32_ctrl->fs_vfe == NULL) {
+		vfe32_ctrl->fs_vfe =
+			regulator_get(&vfe32_ctrl->pdev->dev, "fs_vfe");
+		if (IS_ERR(vfe32_ctrl->fs_vfe)) {
+			pr_err("%s: Regulator FS_VFE get failed %ld\n",
+				__func__, PTR_ERR(vfe32_ctrl->fs_vfe));
+			vfe32_ctrl->fs_vfe = NULL;
+			goto vfe_fs_failed;
+		} else if (regulator_enable(vfe32_ctrl->fs_vfe)) {
+			pr_err("%s: Regulator FS_VFE enable failed\n",
+							__func__);
+			regulator_put(vfe32_ctrl->fs_vfe);
+			vfe32_ctrl->fs_vfe = NULL;
+			goto vfe_fs_failed;
+		}
+	}
+
+	rc = msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
+			vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 1);
 	if (rc < 0)
-		return rc;
+		goto vfe_clk_enable_failed;
 
-	vfe32_ctrl->subdev = sd;
-	/* Bring up all the required GPIOs and Clocks */
-	rc = msm_camio_enable(pdev);
 	msm_camio_set_perf_lvl(S_INIT);
 	msm_camio_set_perf_lvl(S_PREVIEW);
 
@@ -3698,38 +3703,118 @@
 	else
 		vfe32_ctrl->register_total = VFE33_REGISTER_TOTAL;
 
-	/* TO DO: Need to release the VFE resources */
-	rc = request_irq(vfe32_ctrl->vfeirq, vfe32_parse_irq,
-			IRQF_TRIGGER_RISING, "vfe", 0);
+	return rc;
 
+vfe_clk_enable_failed:
+	regulator_disable(vfe32_ctrl->fs_vfe);
+	regulator_put(vfe32_ctrl->fs_vfe);
+	vfe32_ctrl->fs_vfe = NULL;
+vfe_fs_failed:
+	iounmap(vfe32_ctrl->vfebase);
+vfe_remap_failed:
+	disable_irq(vfe32_ctrl->vfeirq->start);
 	return rc;
 }
 
 void msm_vfe_subdev_release(struct platform_device *pdev)
 {
-	struct resource	*vfemem, *vfeio;
-
+	msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
+			vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
+	if (vfe32_ctrl->fs_vfe) {
+		regulator_disable(vfe32_ctrl->fs_vfe);
+		regulator_put(vfe32_ctrl->fs_vfe);
+		vfe32_ctrl->fs_vfe = NULL;
+	}
 	CDBG("%s, free_irq\n", __func__);
-	free_irq(vfe32_ctrl->vfeirq, 0);
+	disable_irq(vfe32_ctrl->vfeirq->start);
 	tasklet_kill(&vfe32_tasklet);
+	iounmap(vfe32_ctrl->vfebase);
 
 	if (atomic_read(&irq_cnt))
 		pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
 
-	vfemem = vfe32_ctrl->vfemem;
-	vfeio  = vfe32_ctrl->vfeio;
-
-	kfree(vfe32_ctrl->extdata);
-	iounmap(vfe32_ctrl->vfebase);
-	kfree(vfe32_ctrl);
-	vfe32_ctrl = NULL;
-	release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
-
-	CDBG("%s, msm_camio_disable\n", __func__);
-	msm_camio_disable(pdev);
 	msm_camio_set_perf_lvl(S_EXIT);
-
 	vfe_syncdata = NULL;
 }
 
+static int __devinit vfe32_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
+	if (!vfe32_ctrl) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
 
+	v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
+	snprintf(vfe32_ctrl->subdev.name,
+			 sizeof(vfe32_ctrl->subdev.name), "vfe3.2");
+	v4l2_set_subdevdata(&vfe32_ctrl->subdev, vfe32_ctrl);
+	platform_set_drvdata(pdev, &vfe32_ctrl->subdev);
+
+	vfe32_ctrl->vfemem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "vfe32");
+	if (!vfe32_ctrl->vfemem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe32_no_resource;
+	}
+	vfe32_ctrl->vfeirq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "vfe32");
+	if (!vfe32_ctrl->vfeirq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto vfe32_no_resource;
+	}
+
+	vfe32_ctrl->vfeio = request_mem_region(vfe32_ctrl->vfemem->start,
+		resource_size(vfe32_ctrl->vfemem), pdev->name);
+	if (!vfe32_ctrl->vfeio) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto vfe32_no_resource;
+	}
+
+	rc = request_irq(vfe32_ctrl->vfeirq->start, vfe32_parse_irq,
+		IRQF_TRIGGER_RISING, "vfe", 0);
+	if (rc < 0) {
+		release_mem_region(vfe32_ctrl->vfemem->start,
+			resource_size(vfe32_ctrl->vfemem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto vfe32_no_resource;
+	}
+
+	disable_irq(vfe32_ctrl->vfeirq->start);
+
+	vfe32_ctrl->pdev = pdev;
+	return 0;
+
+vfe32_no_resource:
+	kfree(vfe32_ctrl);
+	return 0;
+}
+
+static struct platform_driver vfe32_driver = {
+	.probe = vfe32_probe,
+	.driver = {
+		.name = MSM_VFE_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_vfe32_init_module(void)
+{
+	return platform_driver_register(&vfe32_driver);
+}
+
+static void __exit msm_vfe32_exit_module(void)
+{
+	platform_driver_unregister(&vfe32_driver);
+}
+
+module_init(msm_vfe32_init_module);
+module_exit(msm_vfe32_exit_module);
+MODULE_DESCRIPTION("VFE 3.2 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index a01d910..ecb8608 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -349,6 +349,9 @@
 #define V32_MODULE_CFG_OFF 0x00000010
 #define V32_MODULE_CFG_LEN 4
 
+#define V32_ASF_SPECIAL_EFX_CFG_OFF 0x000005FC
+#define V32_ASF_SPECIAL_EFX_CFG_LEN 4
+
 #define V32_CLF_CFG_OFF 0x000006B0
 #define V32_CLF_CFG_LEN 72
 
@@ -915,13 +918,14 @@
 
 	spinlock_t  tasklet_lock;
 	struct list_head tasklet_q;
-	int vfeirq;
 	void __iomem *vfebase;
 	void *syncdata;
 	uint32_t register_total;
 
 	struct resource	*vfemem;
 	struct resource *vfeio;
+	struct resource *vfeirq;
+	struct regulator *fs_vfe;
 
 	uint32_t stats_comp;
 	atomic_t vstate;
@@ -945,7 +949,9 @@
 	struct vfe_stats_control csStatsControl;
 
 	/* v4l2 subdev */
-	struct v4l2_subdev *subdev;
+	struct v4l2_subdev subdev;
+	struct platform_device *pdev;
+	struct clk *vfe_clk[3];
 	spinlock_t  sd_notify_lock;
 };
 
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index c59918d..658f911 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/pm_qos_params.h>
+#include <linux/regulator/consumer.h>
 #include <linux/clk.h>
 #include <mach/clk.h>
 #include <asm/div64.h>
@@ -32,9 +33,7 @@
 static int vpe_enable(uint32_t);
 static int vpe_disable(void);
 static int vpe_update_scaler(struct msm_pp_crop *pcrop);
-static struct vpe_device_type *vpe_device;
 struct vpe_ctrl_type *vpe_ctrl;
-static void *vpe_syncdata;
 static atomic_t vpe_init_done = ATOMIC_INIT(0);
 
 static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd,
@@ -49,14 +48,14 @@
 static int vpe_start(void)
 {
 	/*  enable the frame irq, bit 0 = Display list 0 ROI done */
-	msm_io_w_mb(1, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
-	msm_io_dump(vpe_device->vpebase, 0x120);
-	msm_io_dump(vpe_device->vpebase + 0x10000, 0x250);
-	msm_io_dump(vpe_device->vpebase + 0x30000, 0x20);
-	msm_io_dump(vpe_device->vpebase + 0x50000, 0x30);
-	msm_io_dump(vpe_device->vpebase + 0x50400, 0x10);
+	msm_io_w_mb(1, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
+	msm_io_dump(vpe_ctrl->vpebase, 0x120);
+	msm_io_dump(vpe_ctrl->vpebase + 0x10000, 0x250);
+	msm_io_dump(vpe_ctrl->vpebase + 0x30000, 0x20);
+	msm_io_dump(vpe_ctrl->vpebase + 0x50000, 0x30);
+	msm_io_dump(vpe_ctrl->vpebase + 0x50400, 0x10);
 	/* this triggers the operation. */
-	msm_io_w(1, vpe_device->vpebase + VPE_DL0_START_OFFSET);
+	msm_io_w(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET);
 	wmb();
 	return 0;
 }
@@ -70,16 +69,16 @@
 
 static void vpe_config_axi_default(void)
 {
-	msm_io_w(0x25, vpe_device->vpebase + VPE_AXI_ARB_2_OFFSET);
+	msm_io_w(0x25, vpe_ctrl->vpebase + VPE_AXI_ARB_2_OFFSET);
 	CDBG("%s: yaddr %ld cbcraddr %ld", __func__,
 		 vpe_ctrl->out_y_addr, vpe_ctrl->out_cbcr_addr);
 	if (!vpe_ctrl->out_y_addr || !vpe_ctrl->out_cbcr_addr)
 		return;
 	msm_io_w(vpe_ctrl->out_y_addr,
-		vpe_device->vpebase + VPE_OUTP0_ADDR_OFFSET);
+		vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
 	/* for video  CbCr address */
 	msm_io_w(vpe_ctrl->out_cbcr_addr,
-		vpe_device->vpebase + VPE_OUTP1_ADDR_OFFSET);
+		vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
 
 }
 
@@ -89,33 +88,33 @@
 	uint32_t rc = 0;
 
 	vpe_reset_state_variables();
-	vpe_version = msm_io_r(vpe_device->vpebase + VPE_HW_VERSION_OFFSET);
+	vpe_version = msm_io_r(vpe_ctrl->vpebase + VPE_HW_VERSION_OFFSET);
 	CDBG("vpe_version = 0x%x\n", vpe_version);
 	/* disable all interrupts.*/
-	msm_io_w(0, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
+	msm_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
 	/* clear all pending interrupts*/
-	msm_io_w(0x1fffff, vpe_device->vpebase + VPE_INTR_CLEAR_OFFSET);
+	msm_io_w(0x1fffff, vpe_ctrl->vpebase + VPE_INTR_CLEAR_OFFSET);
 	/* write sw_reset to reset the core. */
-	msm_io_w(0x10, vpe_device->vpebase + VPE_SW_RESET_OFFSET);
+	msm_io_w(0x10, vpe_ctrl->vpebase + VPE_SW_RESET_OFFSET);
 	/* then poll the reset bit, it should be self-cleared. */
 	while (1) {
 		rc =
-		msm_io_r(vpe_device->vpebase + VPE_SW_RESET_OFFSET) & 0x10;
+		msm_io_r(vpe_ctrl->vpebase + VPE_SW_RESET_OFFSET) & 0x10;
 		if (rc == 0)
 			break;
 	}
 	/*  at this point, hardware is reset. Then pogram to default
 		values. */
 	msm_io_w(VPE_AXI_RD_ARB_CONFIG_VALUE,
-			vpe_device->vpebase + VPE_AXI_RD_ARB_CONFIG_OFFSET);
+			vpe_ctrl->vpebase + VPE_AXI_RD_ARB_CONFIG_OFFSET);
 
 	msm_io_w(VPE_CGC_ENABLE_VALUE,
-			vpe_device->vpebase + VPE_CGC_EN_OFFSET);
-	msm_io_w(1, vpe_device->vpebase + VPE_CMD_MODE_OFFSET);
+			vpe_ctrl->vpebase + VPE_CGC_EN_OFFSET);
+	msm_io_w(1, vpe_ctrl->vpebase + VPE_CMD_MODE_OFFSET);
 	msm_io_w(VPE_DEFAULT_OP_MODE_VALUE,
-			vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+			vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 	msm_io_w(VPE_DEFAULT_SCALE_CONFIG,
-			vpe_device->vpebase + VPE_SCALE_CONFIG_OFFSET);
+			vpe_ctrl->vpebase + VPE_SCALE_CONFIG_OFFSET);
 	vpe_config_axi_default();
 	return rc;
 }
@@ -125,7 +124,7 @@
 	uint32_t  rot_flag, rc = 0;
 	struct msm_pp_crop *pcrop = (struct msm_pp_crop *)pinfo;
 
-	rot_flag = msm_io_r(vpe_device->vpebase +
+	rot_flag = msm_io_r(vpe_ctrl->vpebase +
 						VPE_OP_MODE_OFFSET) & 0xE00;
 	if (pinfo != NULL) {
 		pr_err("%s: Crop info in2_w = %d, in2_h = %d "
@@ -145,39 +144,39 @@
 	uint32_t i, offset;
 	offset = *p;
 	for (i = offset; i < (VPE_SCALE_COEFF_NUM + offset); i++) {
-		msm_io_w(*(++p), vpe_device->vpebase + VPE_SCALE_COEFF_LSBn(i));
-		msm_io_w(*(++p), vpe_device->vpebase + VPE_SCALE_COEFF_MSBn(i));
+		msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SCALE_COEFF_LSBn(i));
+		msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SCALE_COEFF_MSBn(i));
 	}
 }
 
 void vpe_input_plane_config(uint32_t *p)
 {
-	msm_io_w(*p, vpe_device->vpebase + VPE_SRC_FORMAT_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_UNPACK_PATTERN1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_IMAGE_SIZE_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_SIZE_OFFSET);
+	msm_io_w(*p, vpe_ctrl->vpebase + VPE_SRC_FORMAT_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_UNPACK_PATTERN1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_IMAGE_SIZE_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_SIZE_OFFSET);
 	vpe_ctrl->in_h_w = *p;
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_XY_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
 	CDBG("%s: in_h_w=0x%x", __func__, vpe_ctrl->in_h_w);
 }
 
 void vpe_output_plane_config(uint32_t *p)
 {
-	msm_io_w(*p, vpe_device->vpebase + VPE_OUT_FORMAT_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_PACK_PATTERN1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_YSTRIDE1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_SIZE_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_XY_OFFSET);
+	msm_io_w(*p, vpe_ctrl->vpebase + VPE_OUT_FORMAT_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_PACK_PATTERN1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_YSTRIDE1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_SIZE_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_XY_OFFSET);
 	vpe_ctrl->pcbcr_dis_offset = *(++p);
 }
 
 static int vpe_operation_config(uint32_t *p)
 {
 	uint32_t w, h, temp;
-	msm_io_w(*p, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+	msm_io_w(*p, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 
-	temp = msm_io_r(vpe_device->vpebase + VPE_OUT_SIZE_OFFSET);
+	temp = msm_io_r(vpe_ctrl->vpebase + VPE_OUT_SIZE_OFFSET);
 	w = temp & 0xFFF;
 	h = (temp & 0xFFF0000) >> 16;
 	if (*p++ & 0xE00) {
@@ -221,15 +220,15 @@
 		(pcrop->src_h >= pcrop->dst_h)) {
 		CDBG(" =======VPE no zoom needed.\n");
 
-		temp = msm_io_r(vpe_device->vpebase + VPE_OP_MODE_OFFSET)
+		temp = msm_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET)
 		& 0xfffffffc;
-		msm_io_w(temp, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+		msm_io_w(temp, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 
 
-		msm_io_w(0, vpe_device->vpebase + VPE_SRC_XY_OFFSET);
+		msm_io_w(0, vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
 
 		CDBG("vpe_ctrl->in_h_w = %d\n", vpe_ctrl->in_h_w);
-		msm_io_w(vpe_ctrl->in_h_w , vpe_device->vpebase +
+		msm_io_w(vpe_ctrl->in_h_w , vpe_ctrl->vpebase +
 				VPE_SRC_SIZE_OFFSET);
 
 		return rc;
@@ -240,8 +239,8 @@
 	/* assumption is both direction need zoom. this can be
 	improved. */
 	temp =
-		msm_io_r(vpe_device->vpebase + VPE_OP_MODE_OFFSET) | 0x3;
-	msm_io_w(temp, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+		msm_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET) | 0x3;
+	msm_io_w(temp, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 
 	src_ROI_width = pcrop->src_w;
 	src_ROI_height = pcrop->src_h;
@@ -253,7 +252,7 @@
 		out_ROI_height);
 	src_roi = (src_ROI_height << 16) + src_ROI_width;
 
-	msm_io_w(src_roi, vpe_device->vpebase + VPE_SRC_SIZE_OFFSET);
+	msm_io_w(src_roi, vpe_ctrl->vpebase + VPE_SRC_SIZE_OFFSET);
 
 	src_x = pcrop->src_x;
 	src_y = pcrop->src_y;
@@ -261,7 +260,7 @@
 	CDBG("src_x = %d, src_y=%d.\n", src_x, src_y);
 
 	src_xy = src_y*(1<<16) + src_x;
-	msm_io_w(src_xy, vpe_device->vpebase +
+	msm_io_w(src_xy, vpe_ctrl->vpebase +
 			VPE_SRC_XY_OFFSET);
 	CDBG("src_xy = %d, src_roi=%d.\n", src_xy, src_roi);
 
@@ -401,15 +400,15 @@
 	CDBG("phase init x = %d, init y = %d.\n",
 		 phase_init_x, phase_init_y);
 
-	msm_io_w(phase_step_x, vpe_device->vpebase +
+	msm_io_w(phase_step_x, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEX_STEP_OFFSET);
-	msm_io_w(phase_step_y, vpe_device->vpebase +
+	msm_io_w(phase_step_y, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEY_STEP_OFFSET);
 
-	msm_io_w(phase_init_x, vpe_device->vpebase +
+	msm_io_w(phase_init_x, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEX_INIT_OFFSET);
 
-	msm_io_w(phase_init_y, vpe_device->vpebase +
+	msm_io_w(phase_init_y, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEY_INIT_OFFSET);
 
 	return 1;
@@ -445,16 +444,16 @@
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
 	msm_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->src_frame.sp.y_off),
-			vpe_device->vpebase + VPE_SRCP0_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
 	msm_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off),
-			vpe_device->vpebase + VPE_SRCP1_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
 	msm_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->dest_frame.sp.y_off),
-			vpe_device->vpebase + VPE_OUTP0_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
 	msm_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off),
-			vpe_device->vpebase + VPE_OUTP1_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
 	vpe_ctrl->state = VPE_STATE_ACTIVE;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 	vpe_start();
@@ -473,7 +472,7 @@
 	vpe_ctrl->state = VPE_STATE_INIT;   /* put it back to idle. */
 	vpe_ctrl->pp_frame_info = NULL;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-	v4l2_subdev_notify(vpe_ctrl->subdev,
+	v4l2_subdev_notify(&vpe_ctrl->subdev,
 		NOTIFY_VPE_MSG_EVT, (void *)&rp);
 }
 
@@ -489,22 +488,20 @@
 
 static irqreturn_t vpe_parse_irq(int irq_num, void *data)
 {
-	vpe_ctrl->irq_status = msm_io_r_mb(vpe_device->vpebase +
+	vpe_ctrl->irq_status = msm_io_r_mb(vpe_ctrl->vpebase +
 							VPE_INTR_STATUS_OFFSET);
-	msm_io_w_mb(vpe_ctrl->irq_status, vpe_device->vpebase +
+	msm_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase +
 				VPE_INTR_CLEAR_OFFSET);
-	msm_io_w(0, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
+	msm_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
 	CDBG("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status);
 	tasklet_schedule(&vpe_tasklet);
 	return IRQ_HANDLED;
 }
 
-static int vpe_enable_irq(void)
-{
-	uint32_t rc = 0;
-	enable_irq(vpe_device->vpeirq);
-	return rc;
-}
+static struct msm_cam_clk_info vpe_clk_info[] = {
+	{"vpe_clk", 160000000},
+	{"vpe_pclk", -1},
+};
 
 int vpe_enable(uint32_t clk_rate)
 {
@@ -520,13 +517,32 @@
 	}
 	vpe_ctrl->state = VPE_STATE_INIT;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-	rc = msm_camio_vpe_clk_enable(clk_rate);
-	if (rc < 0) {
-		pr_err("%s: msm_camio_vpe_clk_enable failed", __func__);
-		vpe_ctrl->state = VPE_STATE_IDLE;
-		return rc;
+	enable_irq(vpe_ctrl->vpeirq->start);
+	vpe_ctrl->fs_vpe = regulator_get(NULL, "fs_vpe");
+	if (IS_ERR(vpe_ctrl->fs_vpe)) {
+		pr_err("%s: Regulator FS_VPE get failed %ld\n", __func__,
+			PTR_ERR(vpe_ctrl->fs_vpe));
+		vpe_ctrl->fs_vpe = NULL;
+		goto vpe_fs_failed;
+	} else if (regulator_enable(vpe_ctrl->fs_vpe)) {
+		pr_err("%s: Regulator FS_VPE enable failed\n", __func__);
+		regulator_put(vpe_ctrl->fs_vpe);
+		goto vpe_fs_failed;
 	}
-	vpe_enable_irq();
+
+	rc = msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+			vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 1);
+	if (rc < 0)
+		goto vpe_clk_failed;
+
+	return rc;
+
+vpe_clk_failed:
+	regulator_disable(vpe_ctrl->fs_vpe);
+	regulator_put(vpe_ctrl->fs_vpe);
+	vpe_ctrl->fs_vpe = NULL;
+vpe_fs_failed:
+	disable_irq(vpe_ctrl->vpeirq->start);
 	return rc;
 }
 
@@ -543,9 +559,15 @@
 	}
 	vpe_ctrl->state = VPE_STATE_IDLE;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-	disable_irq(vpe_device->vpeirq);
+
+	msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+			vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
+
+	regulator_disable(vpe_ctrl->fs_vpe);
+	regulator_put(vpe_ctrl->fs_vpe);
+	vpe_ctrl->fs_vpe = NULL;
+	disable_irq(vpe_ctrl->vpeirq->start);
 	tasklet_kill(&vpe_tasklet);
-	rc = msm_camio_vpe_clk_disable();
 	return rc;
 }
 
@@ -628,7 +650,7 @@
 	.core = &msm_vpe_subdev_core_ops,
 };
 
-static int msm_vpe_resource_init(struct platform_device *pdev, void *sdata);
+static int msm_vpe_resource_init(struct platform_device *pdev);
 
 int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
 	struct platform_device *pdev)
@@ -640,108 +662,122 @@
 		return -EBUSY;
 	}
 	atomic_set(&vpe_init_done, 1);
-	vpe_syncdata = data;
-	rc = msm_vpe_resource_init(pdev, vpe_syncdata);
+
+	rc = msm_vpe_resource_init(pdev);
 	if (rc < 0) {
 		atomic_set(&vpe_init_done, 0);
 		return rc;
 	}
-	vpe_ctrl->subdev = sd;
-	v4l2_subdev_init(sd, &msm_vpe_subdev_ops);
-	v4l2_set_subdev_hostdata(sd, data);
-	snprintf(sd->name, sizeof(sd->name), "vpe");
 	spin_lock_init(&vpe_ctrl->lock);
 	CDBG("%s:end", __func__);
 	return rc;
 }
 EXPORT_SYMBOL(msm_vpe_subdev_init);
 
-static int msm_vpe_resource_init(struct platform_device *pdev,
-				void *sdata)
+static int msm_vpe_resource_init(struct platform_device *pdev)
 {
 	int rc = 0;
-	struct resource   *vpemem, *vpeirq, *vpeio;
-	void __iomem      *vpebase;
-	/* first allocate */
-	vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
-	if (!vpe_ctrl) {
+
+	vpe_ctrl->vpebase = ioremap(vpe_ctrl->vpemem->start,
+		resource_size(vpe_ctrl->vpemem));
+
+	if (!vpe_ctrl->vpebase) {
 		rc = -ENOMEM;
-		goto vpe_free_device;
-	}
-	vpe_device = &vpe_ctrl->device_data;
-	/* does the device exist? */
-	vpeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-	if (!vpeirq) {
-		pr_err("%s: no vpe irq resource.\n", __func__);
-		rc = -ENODEV;
-		goto vpe_free_device;
-	}
-	vpemem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!vpemem) {
-		pr_err("%s: no vpe mem resource!\n", __func__);
-		rc = -ENODEV;
-		goto vpe_free_device;
-	}
-	vpeio = request_mem_region(vpemem->start,
-			resource_size(vpemem), pdev->name);
-	if (!vpeio) {
-		pr_err("%s: VPE region already claimed.\n", __func__);
-		rc = -EBUSY;
-		goto vpe_release_mem_region;
-	}
-	vpebase =
-		ioremap(vpemem->start,
-				(vpemem->end - vpemem->start) + 1);
-	if (!vpebase) {
-		pr_err("%s: vpe ioremap failed.\n", __func__);
-		rc = -ENOMEM;
-		goto vpe_release_mem_region;
+		pr_err("%s: vpe ioremap failed\n", __func__);
+		goto vpe_unmap_mem_region;
 	}
 
-	/* Fall through, _probe is successful. */
-	vpe_device->vpeirq = vpeirq->start;
-	vpe_device->vpemem = vpemem;
-	vpe_device->vpeio = vpeio;
-	vpe_device->vpebase = vpebase;
-	rc = request_irq(vpe_device->vpeirq,
-				vpe_parse_irq,
-				IRQF_TRIGGER_HIGH, "vpe", 0);
-	disable_irq(vpe_device->vpeirq);
-	CDBG("%s:end: vpebase=0x%p", __func__, vpebase);
-	return rc;  /* this rc should be zero.*/
-
-	iounmap(vpe_device->vpebase);  /* this path should never occur */
-
+	return rc;
 /* from this part it is error handling. */
-vpe_release_mem_region:
-	release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
-vpe_free_device:
-	kfree(vpe_ctrl);
+vpe_unmap_mem_region:
+	iounmap(vpe_ctrl->vpebase);
 	return rc;  /* this rc should have error code. */
 }
 
 void msm_vpe_subdev_release(struct platform_device *pdev)
 {
-	struct resource	*vpemem, *vpeio;
 	if (!atomic_read(&vpe_init_done)) {
 		/* no VPE object created */
 		pr_err("%s: no VPE object to release", __func__);
 		return;
 	}
-	CDBG("%s, free_irq\n", __func__);
-	free_irq(vpe_ctrl->device_data.vpeirq, 0);
 
-	vpemem = vpe_ctrl->device_data.vpemem;
-	vpeio  = vpe_ctrl->device_data.vpeio;
-
-	kfree(vpe_ctrl->extdata);
-	iounmap(vpe_ctrl->device_data.vpebase);
-	kfree(vpe_ctrl);
-	vpe_ctrl = NULL;
-	release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
-	CDBG("%s, end\n", __func__);
-	vpe_syncdata = NULL;
+	iounmap(vpe_ctrl->vpebase);
 	atomic_set(&vpe_init_done, 0);
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
 
+static int __devinit vpe_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
+	if (!vpe_ctrl) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&vpe_ctrl->subdev, &msm_vpe_subdev_ops);
+	v4l2_set_subdevdata(&vpe_ctrl->subdev, vpe_ctrl);
+	snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe");
+	platform_set_drvdata(pdev, &vpe_ctrl->subdev);
+
+	vpe_ctrl->vpemem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "vpe");
+	if (!vpe_ctrl->vpemem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto vpe_no_resource;
+	}
+	vpe_ctrl->vpeirq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "vpe");
+	if (!vpe_ctrl->vpeirq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto vpe_no_resource;
+	}
+
+	vpe_ctrl->vpeio = request_mem_region(vpe_ctrl->vpemem->start,
+		resource_size(vpe_ctrl->vpemem), pdev->name);
+	if (!vpe_ctrl->vpeio) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto vpe_no_resource;
+	}
+
+	rc = request_irq(vpe_ctrl->vpeirq->start, vpe_parse_irq,
+		IRQF_TRIGGER_RISING, "vfe", 0);
+	if (rc < 0) {
+		release_mem_region(vpe_ctrl->vpemem->start,
+			resource_size(vpe_ctrl->vpemem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto vpe_no_resource;
+	}
+
+	disable_irq(vpe_ctrl->vpeirq->start);
+
+	vpe_ctrl->pdev = pdev;
+	return 0;
+
+vpe_no_resource:
+	kfree(vpe_ctrl);
+	return 0;
+}
+
+struct platform_driver vpe_driver = {
+	.probe = vpe_probe,
+	.driver = {
+		.name = MSM_VPE_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_vpe_init_module(void)
+{
+	return platform_driver_register(&vpe_driver);
+}
+
+module_init(msm_vpe_init_module);
+MODULE_DESCRIPTION("VPE driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 40df0b0..6d84f4e 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -91,15 +91,6 @@
 	VPE_STATE_ACTIVE,
 };
 
-struct vpe_device_type {
-	/* device related. */
-	int   vpeirq;
-	void __iomem      *vpebase;
-	struct resource	  *vpemem;
-	struct resource   *vpeio;
-	void        *device_extdata;
-};
-
 struct dis_offset_type {
 	int32_t dis_offset_x;
 	int32_t dis_offset_y;
@@ -128,8 +119,15 @@
 	enum vpe_state    state;
 	unsigned long     out_y_addr;
 	unsigned long     out_cbcr_addr;
-	struct v4l2_subdev *subdev;
-	struct vpe_device_type device_data;
+	struct v4l2_subdev subdev;
+	struct platform_device *pdev;
+	struct resource   *vpeirq;
+	void __iomem      *vpebase;
+	struct resource	  *vpemem;
+	struct resource   *vpeio;
+	void        *device_extdata;
+	struct regulator *fs_vpe;
+	struct clk	*vpe_clk[2];
 	struct msm_mctl_pp_frame_info *pp_frame_info;
 };
 
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 6d697df..3e42126 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -1,6 +1,7 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 EXTRA_CFLAGS += -Idrivers/media/video/msm
 EXTRA_CFLAGS += -Idrivers/media/video/msm/io
+EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
 obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
 obj-$(CONFIG_IMX074) += imx074_v4l2.o
 obj-$(CONFIG_OV2720) += ov2720.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 19cf8c7..76ade6c 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -238,12 +238,14 @@
 		msm_sensor_write_res_settings(s_ctrl, res);
 		if (s_ctrl->curr_csi_params != s_ctrl->csi_params[res]) {
 			s_ctrl->curr_csi_params = s_ctrl->csi_params[res];
-			rc = msm_camio_csid_config(
+			v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
+				NOTIFY_CSID_CFG,
 				&s_ctrl->curr_csi_params->csid_params);
 			v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
 						NOTIFY_CID_CHANGE, NULL);
 			mb();
-			rc = msm_camio_csiphy_config(
+			v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
+				NOTIFY_CSIPHY_CFG,
 				&s_ctrl->curr_csi_params->csiphy_params);
 			mb();
 			msleep(20);
diff --git a/drivers/media/video/msm/wfd/Makefile b/drivers/media/video/msm/wfd/Makefile
new file mode 100644
index 0000000..e1484aa
--- /dev/null
+++ b/drivers/media/video/msm/wfd/Makefile
@@ -0,0 +1,4 @@
+#obj-$(CONFIG_MSM_WFD_V4L2) += wfd-ioctl.o
+#obj-$(CONFIG_MSM_WFD_V4L2) += enc-subdev.o
+obj-y += mdp-subdev.o
+obj-y += wfd-ioctl.o
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.c b/drivers/media/video/msm/wfd/mdp-subdev.c
new file mode 100644
index 0000000..ed72ca8
--- /dev/null
+++ b/drivers/media/video/msm/wfd/mdp-subdev.c
@@ -0,0 +1,275 @@
+/* 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.
+*
+*/
+#include "mdp-subdev.h"
+#include "wfd-util.h"
+#include <media/videobuf2-core.h>
+#include <linux/msm_mdp.h>
+
+struct mdp_instance {
+	struct fb_info *mdp;
+	u32 height;
+	u32 width;
+};
+
+int mdp_init(struct v4l2_subdev *sd, u32 val)
+{
+	return 0;
+}
+int mdp_open(struct v4l2_subdev *sd, void *arg)
+{
+	struct mdp_instance *inst = kzalloc(sizeof(struct mdp_instance),
+					GFP_KERNEL);
+	void **cookie = (void **)arg;
+	int rc = 0;
+	struct fb_info *fbi = NULL;
+
+	if (!inst) {
+		WFD_MSG_ERR("Out of memory\n");
+		return -ENOMEM;
+	}
+
+	fbi = msm_fb_get_writeback_fb();
+	if (!fbi) {
+		WFD_MSG_ERR("Failed to acquire mdp instance\n");
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	/*Tell HDMI daemon to open fb1*/
+	rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ADD);
+	if (rc) {
+		WFD_MSG_ERR("Failed add to kobj");
+		goto exit;
+	}
+
+	msm_fb_writeback_init(fbi);
+	inst->mdp = fbi;
+	*cookie = inst;
+	return rc;
+exit:
+	kfree(inst);
+	return rc;
+}
+
+int mdp_start(struct v4l2_subdev *sd, void *arg)
+{
+	struct mdp_instance *inst = arg;
+	int rc = 0;
+	struct fb_info *fbi = NULL;
+	if (inst) {
+		fbi = msm_fb_get_writeback_fb();
+		if (!fbi) {
+			WFD_MSG_ERR("Failed to acquire mdp instance\n");
+			rc = -ENODEV;
+			goto exit;
+		}
+		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ONLINE);
+		if (rc)
+			WFD_MSG_ERR("Failed to send ONLINE event\n");
+	}
+exit:
+	return rc;
+}
+int mdp_stop(struct v4l2_subdev *sd, void *arg)
+{
+	struct mdp_instance *inst = arg;
+	int rc = 0;
+	struct fb_info *fbi = NULL;
+	if (inst) {
+		fbi = (struct fb_info *)inst->mdp;
+		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_OFFLINE);
+		if (rc) {
+			WFD_MSG_ERR("Failed to send offline event\n");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+int mdp_close(struct v4l2_subdev *sd, void *arg)
+{
+	struct mdp_instance *inst = arg;
+	struct fb_info *fbi = NULL;
+	if (inst) {
+		fbi = (struct fb_info *)inst->mdp;
+		msm_fb_writeback_terminate(fbi);
+		kfree(inst);
+	}
+	return 0;
+}
+int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
+{
+	int rc = 0;
+	struct mdp_buf_info *binfo = arg;
+	struct msmfb_data fbdata;
+	struct mdp_instance *inst;
+	if (!binfo || !binfo->inst || !binfo->b) {
+		WFD_MSG_ERR("Invalid argument\n");
+		return -EINVAL;
+	}
+	inst = binfo->inst;
+	fbdata.offset = binfo->offset;
+	fbdata.memory_id = binfo->fd;
+	fbdata.id = 0;
+	fbdata.flags = 0;
+	fbdata.priv = (uint32_t)binfo->b;
+
+	WFD_MSG_INFO("queue buffer to mdp with offset = %u,"
+			"fd = %u, priv = %u\n",
+			fbdata.offset, fbdata.memory_id, fbdata.priv);
+	rc = msm_fb_writeback_queue_buffer(inst->mdp, &fbdata);
+
+	if (rc)
+		WFD_MSG_ERR("Failed to queue buffer\n");
+	return rc;
+}
+int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
+{
+	int rc = 0;
+	struct mdp_buf_info *obuf = arg;
+	struct msmfb_data fbdata;
+	struct mdp_instance *inst;
+	if (!arg) {
+		WFD_MSG_ERR("Invalid argument\n");
+		return -EINVAL;
+	}
+
+	inst = obuf->inst;
+	fbdata.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING;
+	rc = msm_fb_writeback_dequeue_buffer(inst->mdp, &fbdata);
+	if (rc) {
+		WFD_MSG_ERR("Failed to dequeue buffer\n");
+		return rc;
+	}
+	WFD_MSG_INFO("dequeue buffer from mdp with offset = %u,"
+			"fd = %u, priv = %u\n",
+			fbdata.offset, fbdata.memory_id, fbdata.priv);
+	obuf->b = (struct vb2_buffer *)fbdata.priv;
+	return rc;
+}
+int mdp_prepare_buffer(struct v4l2_subdev *sd, void *arg)
+{
+	int rc = 0;
+	struct mdp_buf_info *binfo = arg;
+	struct msmfb_writeback_data wbdata;
+	struct mdp_instance *inst;
+
+	if (!binfo || !binfo->inst || !binfo->b) {
+		WFD_MSG_ERR("Invalid argument\n");
+		return -EINVAL;
+	}
+
+	inst = binfo->inst;
+	wbdata.buf_info.offset = binfo->offset;
+	wbdata.buf_info.memory_id = binfo->fd;
+	wbdata.buf_info.id = 0;
+	wbdata.buf_info.flags = 0;
+	wbdata.buf_info.priv = (uint32_t)binfo->b;
+
+	wbdata.img.width = inst->width;
+	wbdata.img.height = inst->height;
+	wbdata.img.format = MDP_RGB_565;
+	WFD_MSG_DBG("offset = %u, fd = %u, width = %u, height = %u,"
+			"uaddr = %u\n", wbdata.buf_info.offset,
+			wbdata.buf_info.memory_id,
+			wbdata.img.width, wbdata.img.height,
+			wbdata.buf_info.priv);
+
+	rc = msm_fb_writeback_register_buffer(inst->mdp, &wbdata);
+	if (rc) {
+		WFD_MSG_ERR("Failed to register buffer\n");
+		return -EIO;
+	}
+	return rc;
+}
+int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
+{
+	struct mdp_prop *prop = (struct mdp_prop *)arg;
+	struct mdp_instance *inst = prop->inst;
+	if (!prop || !inst) {
+		WFD_MSG_ERR("Invalid arguments\n");
+		return -EINVAL;
+	}
+	inst->height = prop->height;
+	inst->width = prop->width;
+	return 0;
+}
+int mdp_release_buffer(struct v4l2_subdev *sd, void *arg)
+{
+	int rc = 0;
+	struct mdp_buf_info *binfo = arg;
+	struct msmfb_writeback_data wbdata;
+	struct mdp_instance *inst;
+	if (!binfo || !binfo->inst || !binfo->b) {
+		WFD_MSG_ERR("Invalid argument\n");
+		return -EINVAL;
+	}
+	inst = binfo->inst;
+
+	wbdata.buf_info.offset = binfo->offset;
+	wbdata.buf_info.memory_id = binfo->fd;
+	wbdata.buf_info.id = 0;
+	wbdata.buf_info.flags = 0;
+	wbdata.buf_info.priv = (uint32_t)binfo->b;
+
+	wbdata.img.width = inst->width;
+	wbdata.img.height = inst->height;
+	wbdata.img.format = MDP_RGB_565;
+
+	rc = msm_fb_writeback_unregister_buffer(inst->mdp, &wbdata);
+
+	if (rc)
+		WFD_MSG_ERR("Failed to unregister buffer\n");
+	return rc;
+}
+long mdp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	int rc = 0;
+	if (!sd) {
+		WFD_MSG_ERR("Invalid arguments\n");
+		return -EINVAL;
+	}
+	switch (cmd) {
+	case MDP_Q_BUFFER:
+		rc = mdp_q_buffer(sd, arg);
+		break;
+	case MDP_DQ_BUFFER:
+		rc = mdp_dq_buffer(sd, arg);
+		break;
+	case MDP_PREPARE_BUF:
+		rc = mdp_prepare_buffer(sd, arg);
+		break;
+	case MDP_OPEN:
+		rc = mdp_open(sd, arg);
+		break;
+	case MDP_START:
+		rc = mdp_start(sd, arg);
+		break;
+	case MDP_STOP:
+		rc = mdp_stop(sd, arg);
+		break;
+	case MDP_SET_PROP:
+		rc = mdp_set_prop(sd, arg);
+		break;
+	case MDP_RELEASE_BUF:
+		rc = mdp_release_buffer(sd, arg);
+		break;
+	case MDP_CLOSE:
+		rc = mdp_close(sd, arg);
+		break;
+	default:
+		WFD_MSG_ERR("IOCTL: %u not supported\n", cmd);
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.h b/drivers/media/video/msm/wfd/mdp-subdev.h
new file mode 100644
index 0000000..fe8963a
--- /dev/null
+++ b/drivers/media/video/msm/wfd/mdp-subdev.h
@@ -0,0 +1,41 @@
+/* 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.
+*
+*/
+
+#include <linux/videodev2.h>
+#include <media/v4l2-subdev.h>
+
+#define MDP_MAGIC_IOCTL 'M'
+
+struct mdp_buf_info {
+	void *inst;
+	struct vb2_buffer *b;
+	u32 fd;
+	u32 offset;
+};
+
+struct mdp_prop {
+	void *inst;
+	u32 height;
+	u32 width;
+};
+#define MDP_Q_BUFFER  _IOW(MDP_MAGIC_IOCTL, 1, struct mdp_buf_info *)
+#define MDP_DQ_BUFFER  _IOR(MDP_MAGIC_IOCTL, 2, struct mdp_out_buf *)
+#define MDP_PREPARE_BUF  _IOW(MDP_MAGIC_IOCTL, 3, struct  mdp_buf_info *)
+#define MDP_OPEN  _IOR(MDP_MAGIC_IOCTL, 4, void **)
+#define MDP_SET_PROP  _IOW(MDP_MAGIC_IOCTL, 5, struct mdp_prop *)
+#define MDP_RELEASE_BUF  _IOW(MDP_MAGIC_IOCTL, 6, struct mdp_buf_info *)
+#define MDP_CLOSE  _IOR(MDP_MAGIC_IOCTL, 7, void *)
+#define MDP_START  _IOR(MDP_MAGIC_IOCTL, 8, void *)
+#define MDP_STOP  _IOR(MDP_MAGIC_IOCTL, 9, void *)
+extern int mdp_init(struct v4l2_subdev *sd, u32 val);
+extern long mdp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
new file mode 100644
index 0000000..9db5b54
--- /dev/null
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -0,0 +1,655 @@
+/* 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.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+#include <linux/android_pmem.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-msm-mem.h>
+#include "wfd-util.h"
+#include "mdp-subdev.h"
+
+#define WFD_VERSION KERNEL_VERSION(0, 0, 1)
+#define DEFAULT_WFD_WIDTH 640
+#define DEFAULT_WFD_HEIGHT 480
+#define MIN_BUF_COUNT 2
+
+struct wfd_device {
+	struct platform_device *pdev;
+	struct v4l2_device v4l2_dev;
+	struct video_device *pvdev;
+	struct v4l2_subdev mdp_sdev;
+};
+
+struct mem_info {
+	u32 fd;
+	u32 offset;
+};
+
+struct wfd_inst {
+	struct vb2_queue vid_bufq;
+	spinlock_t buflock;
+	spinlock_t inst_lock;
+	u32 buf_count;
+	struct task_struct *mdp_task;
+	void *mdp_inst;
+	u32 height;
+	u32 width;
+	u32 pixelformat;
+	struct mem_info **minfo;
+	bool streamoff;
+};
+
+struct wfd_vid_buffer {
+	struct vb2_buffer    vidbuf;
+};
+
+static int wfd_vidbuf_queue_setup(struct vb2_queue *q,
+		unsigned int *num_buffers, unsigned int *num_planes,
+		unsigned long sizes[], void *alloc_ctxs[])
+{
+	WFD_MSG_DBG("In %s\n", __func__);
+
+	if (num_buffers == NULL || num_planes == NULL)
+		return -EINVAL;
+
+	*num_planes = 1;
+	/*MDP outputs in RGB for now;i
+	 * make sure it's smaller than VIDEO_MAX_PLANES*/
+	sizes[0] = 800*480*2;
+
+	return 0;
+}
+
+void wfd_vidbuf_wait_prepare(struct vb2_queue *q)
+{
+}
+void wfd_vidbuf_wait_finish(struct vb2_queue *q)
+{
+}
+
+int wfd_vidbuf_buf_init(struct vb2_buffer *vb)
+{
+	int rc = 0;
+	struct vb2_queue *q = vb->vb2_queue;
+	struct file *priv_data = (struct file *)(q->drv_priv);
+	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(priv_data);
+	struct mdp_buf_info buf = {
+					inst->mdp_inst,
+					vb,
+					inst->minfo[vb->v4l2_buf.index]->fd,
+					inst->minfo[vb->v4l2_buf.index]->offset
+					};
+
+	if (inst && !inst->vid_bufq.streaming) {
+		rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core,
+				ioctl, MDP_PREPARE_BUF, (void *)&buf);
+		if (rc)
+			WFD_MSG_ERR("Unable to prepare/register the buffer\n");
+	}
+	return rc;
+}
+
+int wfd_vidbuf_buf_prepare(struct vb2_buffer *vb)
+{
+	return 0;
+}
+
+int wfd_vidbuf_buf_finish(struct vb2_buffer *vb)
+{
+	return 0;
+}
+
+void wfd_vidbuf_buf_cleanup(struct vb2_buffer *vb)
+{
+	int rc = 0;
+	struct vb2_queue *q = vb->vb2_queue;
+	struct file *priv_data = (struct file *)(q->drv_priv);
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(priv_data);
+	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct mdp_buf_info buf = {
+					inst->mdp_inst,
+					vb,
+					inst->minfo[vb->v4l2_buf.index]->fd,
+					inst->minfo[vb->v4l2_buf.index]->offset
+					};
+	WFD_MSG_DBG("Releasing buffer\n");
+	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
+			 MDP_RELEASE_BUF, (void *)&buf);
+	if (rc)
+		WFD_MSG_ERR("Failed to release the buffer\n");
+}
+
+int wfd_vidbuf_start_streaming(struct vb2_queue *q)
+{
+	struct file *priv_data = (struct file *)(q->drv_priv);
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(priv_data);
+	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	int rc = 0;
+	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
+			 MDP_START, (void *)inst->mdp_inst);
+	if (rc)
+		WFD_MSG_ERR("Failed to start MDP\n");
+
+	return rc;
+}
+
+int wfd_vidbuf_stop_streaming(struct vb2_queue *q)
+{
+	struct file *priv_data = (struct file *)(q->drv_priv);
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(priv_data);
+	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	int rc = 0;
+	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
+			 MDP_STOP, (void *)inst->mdp_inst);
+	if (rc)
+		WFD_MSG_ERR("Failed to stop MDP\n");
+
+	return rc;
+}
+
+void wfd_vidbuf_buf_queue(struct vb2_buffer *vb)
+{
+	int rc = 0;
+	struct vb2_queue *q = vb->vb2_queue;
+	struct file *priv_data = (struct file *)(q->drv_priv);
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(priv_data);
+	struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+	struct mdp_buf_info buf = {
+					inst->mdp_inst,
+					vb,
+					inst->minfo[vb->v4l2_buf.index]->fd,
+					inst->minfo[vb->v4l2_buf.index]->offset
+					};
+
+	WFD_MSG_DBG("Inside wfd_vidbuf_queue\n");
+	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
+			MDP_Q_BUFFER, (void *)&buf);
+	if (rc)
+		WFD_MSG_ERR("Failed to call fill this buffer\n");
+}
+
+static struct vb2_ops wfd_vidbuf_ops = {
+	.queue_setup = wfd_vidbuf_queue_setup,
+
+	.wait_prepare = wfd_vidbuf_wait_prepare,
+	.wait_finish = wfd_vidbuf_wait_finish,
+
+	.buf_init = wfd_vidbuf_buf_init,
+	.buf_prepare = wfd_vidbuf_buf_prepare,
+	.buf_finish = wfd_vidbuf_buf_finish,
+	.buf_cleanup = wfd_vidbuf_buf_cleanup,
+
+	.start_streaming = wfd_vidbuf_start_streaming,
+	.stop_streaming = wfd_vidbuf_stop_streaming,
+
+	.buf_queue = wfd_vidbuf_buf_queue,
+
+};
+
+static const struct v4l2_subdev_core_ops mdp_subdev_core_ops = {
+	.init = mdp_init,
+	.ioctl = mdp_ioctl,
+};
+static const struct v4l2_subdev_ops mdp_subdev_ops = {
+	.core = &mdp_subdev_core_ops,
+};
+static int wfdioc_querycap(struct file *filp, void *fh,
+		struct v4l2_capability *cap) {
+	WFD_MSG_DBG("wfdioc_querycap: E\n");
+	memset(cap, 0, sizeof(struct v4l2_capability));
+	strlcpy(cap->driver, "wifi-display", sizeof(cap->driver));
+	strlcpy(cap->card, "msm", sizeof(cap->card));
+	cap->version = WFD_VERSION;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	WFD_MSG_DBG("wfdioc_querycap: X\n");
+	return 0;
+}
+static int wfdioc_g_fmt(struct file *filp, void *fh,
+			struct v4l2_format *fmt)
+{
+	struct wfd_inst *inst = filp->private_data;
+	unsigned long flags;
+	if (!fmt) {
+		WFD_MSG_ERR("Invalid argument\n");
+		return -EINVAL;
+	}
+	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		WFD_MSG_ERR("Only V4L2_BUF_TYPE_VIDEO_CAPTURE is supported\n");
+		return -EINVAL;
+	}
+	spin_lock_irqsave(&inst->inst_lock, flags);
+	fmt->fmt.pix.width = inst->width;
+	fmt->fmt.pix.height = inst->height;
+	fmt->fmt.pix.pixelformat = inst->pixelformat;
+	fmt->fmt.pix.sizeimage = inst->width * inst->height * 2;
+	fmt->fmt.pix.bytesperline = inst->width * 2; /*TODO: Needs
+							discussion */
+	fmt->fmt.pix.field = V4L2_FIELD_NONE;
+	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; /*TODO: Needs
+							discussion*/
+	fmt->fmt.pix.priv = 0;
+	spin_unlock_irqrestore(&inst->inst_lock, flags);
+	return 0;
+}
+static int wfdioc_s_fmt(struct file *filp, void *fh,
+			struct v4l2_format *fmt)
+{
+	int rc = 0;
+	struct wfd_inst *inst = filp->private_data;
+	struct wfd_device *wfd_dev = video_drvdata(filp);
+	struct mdp_prop prop;
+	unsigned long flags;
+	if (!fmt) {
+		WFD_MSG_ERR("Invalid argument\n");
+		return -EINVAL;
+	}
+
+	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+		fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_RGB565) {
+		WFD_MSG_ERR("Only V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+				"V4L2_PIX_FMT_RGB565 are supported\n");
+		return -EINVAL;
+	}
+	spin_lock_irqsave(&inst->inst_lock, flags);
+	prop.height = inst->height = fmt->fmt.pix.height;
+	prop.width = inst->width = fmt->fmt.pix.width;
+	prop.inst = inst->mdp_inst;
+	fmt->fmt.pix.sizeimage = inst->height * inst->width * 2;
+	fmt->fmt.pix.field = V4L2_FIELD_NONE;
+	fmt->fmt.pix.bytesperline = inst->width * 2; /*TODO: Needs
+							 discussion */
+	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; /*TODO: Needs
+						      discussion*/
+	spin_unlock_irqrestore(&inst->inst_lock, flags);
+	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl, MDP_SET_PROP,
+				(void *)&prop);
+	if (rc)
+		WFD_MSG_ERR("Failed to set height/width property on mdp\n");
+	return rc;
+}
+static int wfdioc_reqbufs(struct file *filp, void *fh,
+		struct v4l2_requestbuffers *b)
+{
+	int rc = 0;
+	struct wfd_inst *inst = filp->private_data;
+	unsigned long flags;
+	int i;
+	if (b->type != V4L2_CAP_VIDEO_CAPTURE ||
+		b->memory != V4L2_MEMORY_USERPTR) {
+		WFD_MSG_ERR("Only V4L2_CAP_VIDEO_CAPTURE and "
+		"V4L2_CAP_VIDEO_CAPTURE are supported\n");
+		return -EINVAL;
+	}
+	if (b->count < MIN_BUF_COUNT)
+		b->count = MIN_BUF_COUNT;
+	spin_lock_irqsave(&inst->inst_lock, flags);
+	if (inst->minfo) {
+		for (i = 0; i < inst->buf_count; ++i)
+			kfree(inst->minfo[i]);
+	}
+	kfree(inst->minfo);
+	inst->buf_count = b->count;
+	inst->minfo = kzalloc(sizeof(struct mem_info *) * inst->buf_count,
+						GFP_KERNEL);
+	for (i = 0; i < inst->buf_count; ++i)
+		inst->minfo[i] = kzalloc(sizeof(struct mem_info), GFP_KERNEL);
+	spin_unlock_irqrestore(&inst->inst_lock, flags);
+	rc = vb2_reqbufs(&inst->vid_bufq, b);
+	if (rc) {
+		WFD_MSG_ERR("Failed in videobuf_reqbufs, rc = %d\n", rc);
+		spin_lock_irqsave(&inst->inst_lock, flags);
+		if (inst->minfo) {
+			for (i = 0; i < inst->buf_count; ++i)
+				kfree(inst->minfo[i]);
+		}
+		kfree(inst->minfo);
+		inst->minfo = NULL;
+		spin_unlock_irqrestore(&inst->inst_lock, flags);
+	}
+	return rc;
+}
+static int wfdioc_qbuf(struct file *filp, void *fh,
+		struct v4l2_buffer *b)
+{
+	int rc = 0;
+	struct wfd_inst *inst = filp->private_data;
+
+	if (!inst || !b || !b->reserved ||
+			(b->index < 0 || b->index >= inst->buf_count)) {
+		WFD_MSG_ERR("Invalid input parameters to QBUF IOCTL\n");
+		return -EINVAL;
+	}
+	if (!inst->vid_bufq.streaming) {
+		if (copy_from_user(inst->minfo[b->index], (void *)b->reserved,
+				sizeof(struct mem_info))) {
+			WFD_MSG_ERR(" copy_from_user failed. Populate"
+						" v4l2_buffer->reserved with meminfo\n");
+			return -EINVAL;
+		}
+	}
+	rc = vb2_qbuf(&inst->vid_bufq, b);
+	if (rc)
+		WFD_MSG_ERR("Failed to queue buffer\n");
+	return rc;
+}
+static int mdp_output_thread(void *data)
+{
+	int rc = 0;
+	struct file *filp = (struct file *)data;
+	struct wfd_inst *inst = filp->private_data;
+	struct wfd_device *wfd_dev =
+		(struct wfd_device *)video_drvdata(filp);
+	struct vb2_buffer *vbuf = NULL;
+	struct mdp_buf_info obuf = {inst->mdp_inst, vbuf, 0, 0};
+	while (!kthread_should_stop()) {
+		rc = v4l2_subdev_call(&wfd_dev->mdp_sdev,
+			core, ioctl, MDP_DQ_BUFFER, (void *)&obuf);
+
+		if (rc) {
+			WFD_MSG_ERR("Either streamoff called or"
+						" MDP REPORTED ERROR\n");
+			break;
+		} else
+			WFD_MSG_DBG("Dequeued buffer successfully\n");
+
+		vbuf = obuf.b;
+		vb2_buffer_done(vbuf,
+			rc ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+	}
+	WFD_MSG_DBG("Exiting the thread\n");
+	return rc;
+}
+static int wfdioc_streamon(struct file *filp, void *fh,
+		enum v4l2_buf_type i)
+{
+	int rc = 0;
+	struct wfd_inst *inst = filp->private_data;
+	unsigned long flags;
+	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		WFD_MSG_ERR("stream on for buffer type = %d is not "
+			"supported.\n", i);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&inst->inst_lock, flags);
+	inst->streamoff = false;
+	spin_unlock_irqrestore(&inst->inst_lock, flags);
+	/*TODO: Do we need to lock the instance here*/
+	rc = vb2_streamon(&inst->vid_bufq, i);
+	if (rc) {
+		WFD_MSG_ERR("videobuf_streamon failed with err = %d\n", rc);
+		goto vidbuf_streamon_failed;
+	}
+	inst->mdp_task = kthread_run(mdp_output_thread, filp,
+				"mdp_output_thread");
+	if (IS_ERR(inst->mdp_task)) {
+		rc = PTR_ERR(inst->mdp_task);
+		goto mdp_task_failed;
+	}
+	return rc;
+mdp_task_failed:
+	vb2_streamoff(&inst->vid_bufq, i);
+vidbuf_streamon_failed:
+	return rc;
+}
+static int wfdioc_streamoff(struct file *filp, void *fh,
+		enum v4l2_buf_type i)
+{
+	struct wfd_inst *inst = filp->private_data;
+	unsigned long flags;
+	spin_lock_irqsave(&inst->inst_lock, flags);
+	if (inst->streamoff) {
+		WFD_MSG_ERR("Module is already in streamoff state\n");
+		spin_unlock_irqrestore(&inst->inst_lock, flags);
+		return -EINVAL;
+	}
+	inst->streamoff = true;
+	spin_unlock_irqrestore(&inst->inst_lock, flags);
+	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		WFD_MSG_ERR("stream off for buffer type = %d is not "
+			"supported.\n", i);
+		return -EINVAL;
+	}
+	WFD_MSG_DBG("Calling videobuf_streamoff\n");
+	vb2_streamoff(&inst->vid_bufq, i);
+	vb2_queue_release(&inst->vid_bufq);
+	kthread_stop(inst->mdp_task);
+	return 0;
+}
+static int wfdioc_dqbuf(struct file *filp, void *fh,
+		struct v4l2_buffer *b)
+{
+	struct wfd_inst *inst = filp->private_data;
+	WFD_MSG_INFO("Waiting to dequeue buffer\n");
+	return vb2_dqbuf(&inst->vid_bufq, b, 0);
+}
+static const struct v4l2_ioctl_ops g_wfd_ioctl_ops = {
+	.vidioc_querycap = wfdioc_querycap,
+	.vidioc_s_fmt_vid_cap = wfdioc_s_fmt,
+	.vidioc_g_fmt_vid_cap = wfdioc_g_fmt,
+	.vidioc_reqbufs = wfdioc_reqbufs,
+	.vidioc_qbuf = wfdioc_qbuf,
+	.vidioc_streamon = wfdioc_streamon,
+	.vidioc_streamoff = wfdioc_streamoff,
+	.vidioc_dqbuf = wfdioc_dqbuf,
+};
+static int wfd_set_default_properties(struct wfd_inst *inst)
+{
+	unsigned long flags;
+	if (!inst) {
+		WFD_MSG_ERR("Invalid argument\n");
+		return -EINVAL;
+	}
+	spin_lock_irqsave(&inst->inst_lock, flags);
+	inst->height = DEFAULT_WFD_HEIGHT;
+	inst->width = DEFAULT_WFD_WIDTH;
+	inst->pixelformat = V4L2_PIX_FMT_RGB565;
+	spin_unlock_irqrestore(&inst->inst_lock, flags);
+	return 0;
+}
+static int wfd_open(struct file *filp)
+{
+	int rc = 0;
+	struct wfd_inst *inst;
+	struct wfd_device *wfd_dev;
+	WFD_MSG_DBG("wfd_open: E\n");
+	inst = kzalloc(sizeof(struct wfd_inst), GFP_KERNEL);
+	if (!inst) {
+		WFD_MSG_ERR("Could not allocate memory for "
+			"wfd instance\n");
+		return -ENOMEM;
+	}
+	spin_lock_init(&inst->inst_lock);
+	spin_lock_init(&inst->buflock);
+	wfd_dev = video_drvdata(filp);
+	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl, MDP_OPEN,
+				(void *)&inst->mdp_inst);
+	if (rc) {
+		WFD_MSG_ERR("Failed to open mdp subdevice: %d\n", rc);
+		goto err_mdp_open;
+	}
+
+	videobuf2_queue_pmem_contig_init(&inst->vid_bufq,
+				V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				&wfd_vidbuf_ops,
+				sizeof(struct wfd_vid_buffer),
+				filp);  /*TODO: Check if it needs to be freed*/
+	wfd_set_default_properties(inst);
+	filp->private_data = inst;
+	WFD_MSG_DBG("wfd_open: X\n");
+	return rc;
+err_mdp_open:
+	kfree(inst);
+	return rc;
+}
+static int wfd_close(struct file *filp)
+{
+	struct wfd_inst *inst;
+	struct wfd_device *wfd_dev;
+	int rc = 0;
+	int k;
+	unsigned long flags;
+	wfd_dev = video_drvdata(filp);
+	WFD_MSG_DBG("wfd_close: E\n");
+	inst = filp->private_data;
+	if (inst) {
+		wfdioc_streamoff(filp, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
+				MDP_CLOSE, (void *)inst->mdp_inst);
+		if (rc)
+			WFD_MSG_ERR("Failed to CLOSE mdp subdevice: %d\n", rc);
+		spin_lock_irqsave(&inst->inst_lock, flags);
+		if (inst->minfo) {
+			for (k = 0; k < inst->buf_count; ++k)
+				kfree(inst->minfo[k]);
+		}
+		kfree(inst->minfo);
+		inst->minfo = NULL;
+		spin_unlock_irqrestore(&inst->inst_lock, flags);
+		kfree(inst);
+	}
+	WFD_MSG_DBG("wfd_close: X\n");
+	return 0;
+}
+static const struct v4l2_file_operations g_wfd_fops = {
+	.owner = THIS_MODULE,
+	.open = wfd_open,
+	.release = wfd_close,
+	.ioctl = video_ioctl2
+};
+void release_video_device(struct video_device *pvdev)
+{
+
+}
+static int __devinit __wfd_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct wfd_device *wfd_dev;
+	WFD_MSG_DBG("__wfd_probe: E\n");
+	wfd_dev = kzalloc(sizeof(*wfd_dev), GFP_KERNEL);  /*TODO: Free it*/
+	if (!wfd_dev) {
+		WFD_MSG_ERR("Could not allocate memory for "
+				"wfd device\n");
+		return -ENOMEM;
+	}
+	pdev->dev.platform_data = (void *) wfd_dev;
+	rc = v4l2_device_register(&pdev->dev, &wfd_dev->v4l2_dev);
+	if (rc) {
+		WFD_MSG_ERR("Failed to register the video device\n");
+		goto err_v4l2_registration;
+	}
+	wfd_dev->pvdev = video_device_alloc();
+	if (!wfd_dev->pvdev) {
+		WFD_MSG_ERR("Failed to allocate video device\n");
+		goto err_video_device_alloc;
+	}
+
+	wfd_dev->pvdev->release = release_video_device;
+	wfd_dev->pvdev->fops = &g_wfd_fops;
+	wfd_dev->pvdev->ioctl_ops = &g_wfd_ioctl_ops;
+
+	rc = video_register_device(wfd_dev->pvdev, VFL_TYPE_GRABBER, -1);
+	if (rc) {
+		WFD_MSG_ERR("Failed to register the device\n");
+		goto err_video_register_device;
+	}
+	video_set_drvdata(wfd_dev->pvdev, wfd_dev);
+
+	v4l2_subdev_init(&wfd_dev->mdp_sdev, &mdp_subdev_ops);
+	strncpy(wfd_dev->mdp_sdev.name, "wfd-mdp", V4L2_SUBDEV_NAME_SIZE);
+	rc = v4l2_device_register_subdev(&wfd_dev->v4l2_dev,
+						&wfd_dev->mdp_sdev);
+	if (rc) {
+		WFD_MSG_ERR("Failed to register mdp subdevice: %d\n", rc);
+		goto err_mdp_register_subdev;
+	}
+	WFD_MSG_DBG("__wfd_probe: X\n");
+	return rc;
+err_mdp_register_subdev:
+	video_unregister_device(wfd_dev->pvdev);
+err_video_register_device:
+	video_device_release(wfd_dev->pvdev);
+err_video_device_alloc:
+	v4l2_device_unregister(&wfd_dev->v4l2_dev);
+err_v4l2_registration:
+	kfree(wfd_dev);
+	return rc;
+}
+
+static int __devexit __wfd_remove(struct platform_device *pdev)
+{
+	struct wfd_device *wfd_dev;
+	wfd_dev = (struct wfd_device *)pdev->dev.platform_data;
+
+	WFD_MSG_DBG("Inside wfd_remove\n");
+	if (!wfd_dev) {
+		WFD_MSG_ERR("Error removing WFD device");
+		return -ENODEV;
+	}
+
+	v4l2_device_unregister_subdev(&wfd_dev->mdp_sdev);
+	video_unregister_device(wfd_dev->pvdev);
+	video_device_release(wfd_dev->pvdev);
+	v4l2_device_unregister(&wfd_dev->v4l2_dev);
+	kfree(wfd_dev);
+	return 0;
+}
+static struct platform_driver wfd_driver = {
+	.probe =  __wfd_probe,
+	.remove = __wfd_remove,
+	.driver = {
+		.name = "msm_wfd",
+		.owner = THIS_MODULE,
+	}
+};
+
+static int __init wfd_init(void)
+{
+	int rc = 0;
+	WFD_MSG_DBG("Calling init function of wfd driver\n");
+	rc = platform_driver_register(&wfd_driver);
+	if (rc) {
+		WFD_MSG_ERR("failed to load the driver\n");
+		goto err_platform_registration;
+	}
+err_platform_registration:
+	return rc;
+}
+
+static void __exit wfd_exit(void)
+{
+	WFD_MSG_DBG("wfd_exit: X\n");
+	platform_driver_unregister(&wfd_driver);
+}
+
+module_init(wfd_init);
+module_exit(wfd_exit);
diff --git a/drivers/media/video/msm/wfd/wfd-util.h b/drivers/media/video/msm/wfd/wfd-util.h
new file mode 100644
index 0000000..038a2cb
--- /dev/null
+++ b/drivers/media/video/msm/wfd/wfd-util.h
@@ -0,0 +1,30 @@
+/* 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 _WFD_UTIL_H_
+#define _WFD_UTIL_H_
+
+/*#define DEBUG_WFD*/
+
+#ifdef DEBUG_WFD
+	#define WFD_MSG_INFO(fmt...) pr_info(fmt)
+	#define WFD_MSG_WARN(fmt...) pr_warning(fmt)
+	#define WFD_MSG_DBG(fmt...) pr_debug(fmt)
+#else
+	#define WFD_MSG_INFO(fmt...)
+	#define WFD_MSG_WARN(fmt...)
+	#define WFD_MSG_DBG(fmt...)
+#endif
+	#define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR fmt)
+	#define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT fmt)
+#endif
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index a4feb838..c27fea6 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -157,6 +157,7 @@
 	tristate "PMIC8058 Power Management chip"
 	depends on MSM_SSBI
 	select MFD_CORE
+	select MFD_PM8XXX
 	select MSM_SHOW_RESUME_IRQ
 	help
 	  Say yes here for Qualcomm PM8058 chip.
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index 7367e66..a73a695 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -16,14 +16,13 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pm8xxx/misc.h>
 
 /* PON CTRL 1 register */
-#define REG_PM8058_PON_CTRL_1			0x01C
-#define REG_PM8921_PON_CTRL_1			0x01C
-#define REG_PM8018_PON_CTRL_1			0x01C
+#define REG_PM8XXX_PON_CTRL_1			0x01C
 
 #define PON_CTRL_1_PULL_UP_MASK			0xE0
 #define PON_CTRL_1_USB_PWR_EN			0x10
@@ -32,9 +31,65 @@
 #define PON_CTRL_1_WD_EN_RESET			0x08
 #define PON_CTRL_1_WD_EN_PWR_OFF		0x00
 
-/* Regulator L22 control register */
+/* PON CNTL registers */
+#define REG_PM8058_PON_CNTL_4			0x098
+#define REG_PM8901_PON_CNTL_4			0x099
+#define REG_PM8018_PON_CNTL_4			0x01E
+#define REG_PM8921_PON_CNTL_4			0x01E
+#define REG_PM8058_PON_CNTL_5			0x07B
+#define REG_PM8901_PON_CNTL_5			0x09A
+#define REG_PM8018_PON_CNTL_5			0x01F
+#define REG_PM8921_PON_CNTL_5			0x01F
+
+#define PON_CTRL_4_RESET_EN_MASK		0x01
+#define PON_CTRL_4_SHUTDOWN_ON_RESET		0x0
+#define PON_CTRL_4_RESTART_ON_RESET		0x1
+#define PON_CTRL_5_HARD_RESET_EN_MASK		0x08
+#define PON_CTRL_5_HARD_RESET_EN		0x08
+#define PON_CTRL_5_HARD_RESET_DIS		0x00
+
+/* Regulator master enable addresses */
+#define REG_PM8058_VREG_EN_MSM			0x018
+#define REG_PM8058_VREG_EN_GRP_5_4		0x1C8
+
+/* Regulator control registers for shutdown/reset */
+#define REG_PM8058_S0_CTRL			0x004
+#define REG_PM8058_S1_CTRL			0x005
+#define REG_PM8058_S3_CTRL			0x111
+#define REG_PM8058_L21_CTRL			0x120
 #define REG_PM8058_L22_CTRL			0x121
 
+#define PM8058_REGULATOR_ENABLE_MASK		0x80
+#define PM8058_REGULATOR_ENABLE			0x80
+#define PM8058_REGULATOR_DISABLE		0x00
+#define PM8058_REGULATOR_PULL_DOWN_MASK		0x40
+#define PM8058_REGULATOR_PULL_DOWN_EN		0x40
+
+/* Buck CTRL register */
+#define PM8058_SMPS_LEGACY_VREF_SEL		0x20
+#define PM8058_SMPS_LEGACY_VPROG_MASK		0x1F
+#define PM8058_SMPS_ADVANCED_BAND_MASK		0xC0
+#define PM8058_SMPS_ADVANCED_BAND_SHIFT		6
+#define PM8058_SMPS_ADVANCED_VPROG_MASK		0x3F
+
+/* Buck TEST2 registers for shutdown/reset */
+#define REG_PM8058_S0_TEST2			0x084
+#define REG_PM8058_S1_TEST2			0x085
+#define REG_PM8058_S3_TEST2			0x11A
+
+#define PM8058_REGULATOR_BANK_WRITE		0x80
+#define PM8058_REGULATOR_BANK_MASK		0x70
+#define PM8058_REGULATOR_BANK_SHIFT		4
+#define PM8058_REGULATOR_BANK_SEL(n)	((n) << PM8058_REGULATOR_BANK_SHIFT)
+
+/* Buck TEST2 register bank 1 */
+#define PM8058_SMPS_LEGACY_VLOW_SEL		0x01
+
+/* Buck TEST2 register bank 7 */
+#define PM8058_SMPS_ADVANCED_MODE_MASK		0x02
+#define PM8058_SMPS_ADVANCED_MODE		0x02
+#define PM8058_SMPS_LEGACY_MODE			0x00
+
 /* SLEEP CTRL register */
 #define REG_PM8058_SLEEP_CTRL			0x02B
 #define REG_PM8921_SLEEP_CTRL			0x10A
@@ -44,6 +99,10 @@
 #define SLEEP_CTRL_SMPL_EN_RESET		0x04
 #define SLEEP_CTRL_SMPL_EN_PWR_OFF		0x00
 
+#define SLEEP_CTRL_SMPL_SEL_MASK		0x03
+#define SLEEP_CTRL_SMPL_SEL_MIN			0
+#define SLEEP_CTRL_SMPL_SEL_MAX			3
+
 /* FTS regulator PMR registers */
 #define REG_PM8901_REGULATOR_S1_PMR		0xA7
 #define REG_PM8901_REGULATOR_S2_PMR		0xA8
@@ -53,6 +112,19 @@
 #define PM8901_REGULATOR_PMR_STATE_MASK		0x60
 #define PM8901_REGULATOR_PMR_STATE_OFF		0x20
 
+/* COINCELL CHG registers */
+#define REG_PM8058_COIN_CHG			0x02F
+#define REG_PM8921_COIN_CHG			0x09C
+#define REG_PM8018_COIN_CHG			0x09C
+
+#define COINCELL_RESISTOR_SHIFT			0x2
+
+/* GP TEST register */
+#define REG_PM8XXX_GP_TEST_1			0x07A
+
+/* Stay on configuration */
+#define PM8XXX_STAY_ON_CFG			0x92
+
 /* GPIO UART MUX CTRL registers */
 #define REG_PM8XXX_GPIO_MUX_CTRL		0x1CC
 
@@ -64,6 +136,7 @@
 	struct pm8xxx_misc_platform_data	pdata;
 	struct device				*dev;
 	enum pm8xxx_version			version;
+	u64					osc_halt_count;
 };
 
 static LIST_HEAD(pm8xxx_misc_chips);
@@ -89,6 +162,154 @@
 	return rc;
 }
 
+/*
+ * Set an SMPS regulator to be disabled in its CTRL register, but enabled
+ * in the master enable register.  Also set it's pull down enable bit.
+ * Take care to make sure that the output voltage doesn't change if switching
+ * from advanced mode to legacy mode.
+ */
+static int
+__pm8058_disable_smps_locally_set_pull_down(struct pm8xxx_misc_chip *chip,
+	u16 ctrl_addr, u16 test2_addr, u16 master_enable_addr,
+	u8 master_enable_bit)
+{
+	int rc = 0;
+	u8 vref_sel, vlow_sel, band, vprog, bank, reg;
+
+	bank = PM8058_REGULATOR_BANK_SEL(7);
+	rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
+	if (rc) {
+		pr_err("%s: pm8xxx_writeb(0x%03X) failed: rc=%d\n", __func__,
+			test2_addr, rc);
+		goto done;
+	}
+
+	rc = pm8xxx_readb(chip->dev->parent, test2_addr, &reg);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n",
+		       __func__, test2_addr, rc);
+		goto done;
+	}
+
+	/* Check if in advanced mode. */
+	if ((reg & PM8058_SMPS_ADVANCED_MODE_MASK) ==
+					PM8058_SMPS_ADVANCED_MODE) {
+		/* Determine current output voltage. */
+		rc = pm8xxx_readb(chip->dev->parent, ctrl_addr, &reg);
+		if (rc) {
+			pr_err("%s: FAIL pm8xxx_readb(0x%03X): rc=%d\n",
+			       __func__, ctrl_addr, rc);
+			goto done;
+		}
+
+		band = (reg & PM8058_SMPS_ADVANCED_BAND_MASK)
+			>> PM8058_SMPS_ADVANCED_BAND_SHIFT;
+		switch (band) {
+		case 3:
+			vref_sel = 0;
+			vlow_sel = 0;
+			break;
+		case 2:
+			vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
+			vlow_sel = 0;
+			break;
+		case 1:
+			vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
+			vlow_sel = PM8058_SMPS_LEGACY_VLOW_SEL;
+			break;
+		default:
+			pr_err("%s: regulator already disabled\n", __func__);
+			return -EPERM;
+		}
+		vprog = (reg & PM8058_SMPS_ADVANCED_VPROG_MASK);
+		/* Round up if fine step is in use. */
+		vprog = (vprog + 1) >> 1;
+		if (vprog > PM8058_SMPS_LEGACY_VPROG_MASK)
+			vprog = PM8058_SMPS_LEGACY_VPROG_MASK;
+
+		/* Set VLOW_SEL bit. */
+		bank = PM8058_REGULATOR_BANK_SEL(1);
+		rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
+		if (rc) {
+			pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n",
+			       __func__, test2_addr, rc);
+			goto done;
+		}
+
+		rc = pm8xxx_misc_masked_write(chip, test2_addr,
+			PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK
+				| PM8058_SMPS_LEGACY_VLOW_SEL,
+			PM8058_REGULATOR_BANK_WRITE |
+			PM8058_REGULATOR_BANK_SEL(1) | vlow_sel);
+		if (rc)
+			goto done;
+
+		/* Switch to legacy mode */
+		bank = PM8058_REGULATOR_BANK_SEL(7);
+		rc = pm8xxx_writeb(chip->dev->parent, test2_addr, bank);
+		if (rc) {
+			pr_err("%s: FAIL pm8xxx_writeb(0x%03X): rc=%d\n",
+					__func__, test2_addr, rc);
+			goto done;
+		}
+		rc = pm8xxx_misc_masked_write(chip, test2_addr,
+				PM8058_REGULATOR_BANK_WRITE |
+				PM8058_REGULATOR_BANK_MASK |
+				PM8058_SMPS_ADVANCED_MODE_MASK,
+				PM8058_REGULATOR_BANK_WRITE |
+				PM8058_REGULATOR_BANK_SEL(7) |
+				PM8058_SMPS_LEGACY_MODE);
+		if (rc)
+			goto done;
+
+		/* Enable locally, enable pull down, keep voltage the same. */
+		rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
+			PM8058_REGULATOR_ENABLE_MASK |
+			PM8058_REGULATOR_PULL_DOWN_MASK |
+			PM8058_SMPS_LEGACY_VREF_SEL |
+			PM8058_SMPS_LEGACY_VPROG_MASK,
+			PM8058_REGULATOR_ENABLE | PM8058_REGULATOR_PULL_DOWN_EN
+				| vref_sel | vprog);
+		if (rc)
+			goto done;
+	}
+
+	/* Enable in master control register. */
+	rc = pm8xxx_misc_masked_write(chip, master_enable_addr,
+			master_enable_bit, master_enable_bit);
+	if (rc)
+		goto done;
+
+	/* Disable locally and enable pull down. */
+	rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
+		PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
+		PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
+
+done:
+	return rc;
+}
+
+static int
+__pm8058_disable_ldo_locally_set_pull_down(struct pm8xxx_misc_chip *chip,
+		u16 ctrl_addr, u16 master_enable_addr, u8 master_enable_bit)
+{
+	int rc;
+
+	/* Enable LDO in master control register. */
+	rc = pm8xxx_misc_masked_write(chip, master_enable_addr,
+			master_enable_bit, master_enable_bit);
+	if (rc)
+		goto done;
+
+	/* Disable LDO in CTRL register and set pull down */
+	rc = pm8xxx_misc_masked_write(chip, ctrl_addr,
+		PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
+		PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
+
+done:
+	return rc;
+}
+
 static int __pm8018_reset_pwr_off(struct pm8xxx_misc_chip *chip, int reset)
 {
 	int rc;
@@ -107,7 +328,7 @@
 	 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
 	 * USB charging is enabled.
 	 */
-	rc = pm8xxx_misc_masked_write(chip, REG_PM8018_PON_CTRL_1,
+	rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
 		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
 		| PON_CTRL_1_WD_EN_MASK,
 		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
@@ -122,6 +343,24 @@
 {
 	int rc;
 
+	/* When shutting down, enable active pulldowns on important rails. */
+	if (!reset) {
+		/* Disable SMPS's 0,1,3 locally and set pulldown enable bits. */
+		__pm8058_disable_smps_locally_set_pull_down(chip,
+			REG_PM8058_S0_CTRL, REG_PM8058_S0_TEST2,
+			REG_PM8058_VREG_EN_MSM, BIT(7));
+		__pm8058_disable_smps_locally_set_pull_down(chip,
+			REG_PM8058_S1_CTRL, REG_PM8058_S1_TEST2,
+			REG_PM8058_VREG_EN_MSM, BIT(6));
+		__pm8058_disable_smps_locally_set_pull_down(chip,
+			REG_PM8058_S3_CTRL, REG_PM8058_S3_TEST2,
+			REG_PM8058_VREG_EN_GRP_5_4, BIT(7) | BIT(4));
+		/* Disable LDO 21 locally and set pulldown enable bit. */
+		__pm8058_disable_ldo_locally_set_pull_down(chip,
+			REG_PM8058_L21_CTRL, REG_PM8058_VREG_EN_GRP_5_4,
+			BIT(1));
+	}
+
 	/*
 	 * Fix-up: Set regulator LDO22 to 1.225 V in high power mode. Leave its
 	 * pull-down state intact. This ensures a safe shutdown.
@@ -146,7 +385,7 @@
 	 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
 	 * USB charging is enabled.
 	 */
-	rc = pm8xxx_misc_masked_write(chip, REG_PM8058_PON_CTRL_1,
+	rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
 		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
 		| PON_CTRL_1_WD_EN_MASK,
 		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
@@ -206,7 +445,7 @@
 	 * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
 	 * USB charging is enabled.
 	 */
-	rc = pm8xxx_misc_masked_write(chip, REG_PM8921_PON_CTRL_1,
+	rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
 		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
 		| PON_CTRL_1_WD_EN_MASK,
 		PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
@@ -267,6 +506,397 @@
 EXPORT_SYMBOL_GPL(pm8xxx_reset_pwr_off);
 
 /**
+ * pm8xxx_smpl_control - enables/disables SMPL detection
+ * @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
+ *
+ * This function enables or disables the Sudden Momentary Power Loss detection
+ * module.  If SMPL detection is enabled, then when a sufficiently long power
+ * loss event occurs, the PMIC will automatically reset itself.  If SMPL
+ * detection is disabled, then the PMIC will shutdown when power loss occurs.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_control(int enable)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8018:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
+				(enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+					   : SLEEP_CTRL_SMPL_EN_PWR_OFF));
+			break;
+		case PM8XXX_VERSION_8058:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
+				(enable ? SLEEP_CTRL_SMPL_EN_RESET
+					   : SLEEP_CTRL_SMPL_EN_PWR_OFF));
+			break;
+		case PM8XXX_VERSION_8921:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
+				(enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+					   : SLEEP_CTRL_SMPL_EN_PWR_OFF));
+			break;
+		default:
+			/* PMIC doesn't have reset_pwr_off; do nothing. */
+			break;
+		}
+		if (rc) {
+			pr_err("setting smpl control failed, rc=%d\n", rc);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_smpl_control);
+
+
+/**
+ * pm8xxx_smpl_set_delay - sets the SMPL detection time delay
+ * @delay: enum value corresponding to delay time
+ *
+ * This function sets the time delay of the SMPL detection module.  If power
+ * is reapplied within this interval, then the PMIC reset automatically.  The
+ * SMPL detection module must be enabled for this delay time to take effect.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+
+	if (delay < SLEEP_CTRL_SMPL_SEL_MIN
+	    || delay > SLEEP_CTRL_SMPL_SEL_MAX) {
+		pr_err("%s: invalid delay specified: %d\n", __func__, delay);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8018:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
+				delay);
+			break;
+		case PM8XXX_VERSION_8058:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
+				delay);
+			break;
+		case PM8XXX_VERSION_8921:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
+				delay);
+			break;
+		default:
+			/* PMIC doesn't have reset_pwr_off; do nothing. */
+			break;
+		}
+		if (rc) {
+			pr_err("setting smpl delay failed, rc=%d\n", rc);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_smpl_set_delay);
+
+/**
+ * pm8xxx_coincell_chg_config - Disables or enables the coincell charger, and
+ *				configures its voltage and resistor settings.
+ * @chg_config:			Holds both voltage and resistor values, and a
+ *				switch to change the state of charger.
+ *				If state is to disable the charger then
+ *				both voltage and resistor are disregarded.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	u8 reg = 0, voltage, resistor;
+	int rc = 0;
+
+	if (chg_config == NULL) {
+		pr_err("chg_config is NULL\n");
+		return -EINVAL;
+	}
+
+	voltage = chg_config->voltage;
+	resistor = chg_config->resistor;
+
+	if (resistor < PM8XXX_COINCELL_RESISTOR_2100_OHMS ||
+			resistor > PM8XXX_COINCELL_RESISTOR_800_OHMS) {
+		pr_err("Invalid resistor value provided\n");
+		return -EINVAL;
+	}
+
+	if (voltage < PM8XXX_COINCELL_VOLTAGE_3p2V ||
+		(voltage > PM8XXX_COINCELL_VOLTAGE_3p0V &&
+			voltage != PM8XXX_COINCELL_VOLTAGE_2p5V)) {
+		pr_err("Invalid voltage value provided\n");
+		return -EINVAL;
+	}
+
+	if (chg_config->state == PM8XXX_COINCELL_CHG_DISABLE) {
+		reg = 0;
+	} else {
+		reg |= voltage;
+		reg |= (resistor << COINCELL_RESISTOR_SHIFT);
+	}
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8018:
+			rc = pm8xxx_writeb(chip->dev->parent,
+					REG_PM8018_COIN_CHG, reg);
+			break;
+		case PM8XXX_VERSION_8058:
+			rc = pm8xxx_writeb(chip->dev->parent,
+					REG_PM8058_COIN_CHG, reg);
+			break;
+		case PM8XXX_VERSION_8921:
+			rc = pm8xxx_writeb(chip->dev->parent,
+					REG_PM8921_COIN_CHG, reg);
+			break;
+		default:
+			/* PMIC doesn't have reset_pwr_off; do nothing. */
+			break;
+		}
+		if (rc) {
+			pr_err("coincell chg. config failed, rc=%d\n", rc);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_coincell_chg_config);
+
+/**
+ * pm8xxx_watchdog_reset_control - enables/disables watchdog reset detection
+ * @enable: 0 = shutdown when PS_HOLD goes low, 1 = reset when PS_HOLD goes low
+ *
+ * This function enables or disables the PMIC watchdog reset detection feature.
+ * If watchdog reset detection is enabled, then the PMIC will reset itself
+ * when PS_HOLD goes low.  If it is not enabled, then the PMIC will shutdown
+ * when PS_HOLD goes low.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_watchdog_reset_control(int enable)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8018:
+		case PM8XXX_VERSION_8058:
+		case PM8XXX_VERSION_8921:
+			rc = pm8xxx_misc_masked_write(chip,
+				REG_PM8XXX_PON_CTRL_1, PON_CTRL_1_WD_EN_MASK,
+				(enable ? PON_CTRL_1_WD_EN_RESET
+					   : PON_CTRL_1_WD_EN_PWR_OFF));
+			break;
+		default:
+			/* WD reset control not supported */
+			break;
+		}
+		if (rc) {
+			pr_err("setting WD reset control failed, rc=%d\n", rc);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_watchdog_reset_control);
+
+/**
+ * pm8xxx_stay_on - enables stay_on feature
+ *
+ * PMIC stay-on feature allows PMIC to ignore MSM PS_HOLD=low
+ * signal so that some special functions like debugging could be
+ * performed.
+ *
+ * This feature should not be used in any product release.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_stay_on(void)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8018:
+		case PM8XXX_VERSION_8058:
+		case PM8XXX_VERSION_8921:
+			rc = pm8xxx_writeb(chip->dev->parent,
+				REG_PM8XXX_GP_TEST_1, PM8XXX_STAY_ON_CFG);
+			break;
+		default:
+			/* stay on not supported */
+			break;
+		}
+		if (rc) {
+			pr_err("stay_on failed failed, rc=%d\n", rc);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_stay_on);
+
+static int
+__pm8xxx_hard_reset_config(struct pm8xxx_misc_chip *chip,
+		enum pm8xxx_pon_config config, u16 pon4_addr, u16 pon5_addr)
+{
+	int rc = 0;
+
+	switch (config) {
+	case PM8XXX_DISABLE_HARD_RESET:
+		rc = pm8xxx_misc_masked_write(chip, pon5_addr,
+				PON_CTRL_5_HARD_RESET_EN_MASK,
+				PON_CTRL_5_HARD_RESET_DIS);
+		break;
+	case PM8XXX_SHUTDOWN_ON_HARD_RESET:
+		rc = pm8xxx_misc_masked_write(chip, pon5_addr,
+				PON_CTRL_5_HARD_RESET_EN_MASK,
+				PON_CTRL_5_HARD_RESET_EN);
+		if (!rc) {
+			rc = pm8xxx_misc_masked_write(chip, pon4_addr,
+					PON_CTRL_4_RESET_EN_MASK,
+					PON_CTRL_4_SHUTDOWN_ON_RESET);
+		}
+		break;
+	case PM8XXX_RESTART_ON_HARD_RESET:
+		rc = pm8xxx_misc_masked_write(chip, pon5_addr,
+				PON_CTRL_5_HARD_RESET_EN_MASK,
+				PON_CTRL_5_HARD_RESET_EN);
+		if (!rc) {
+			rc = pm8xxx_misc_masked_write(chip, pon4_addr,
+					PON_CTRL_4_RESET_EN_MASK,
+					PON_CTRL_4_RESTART_ON_RESET);
+		}
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+/**
+ * pm8xxx_hard_reset_config - Allows different reset configurations
+ *
+ * config = PM8XXX_DISABLE_HARD_RESET to disable hard reset
+ *	  = PM8XXX_SHUTDOWN_ON_HARD_RESET to turn off the system on hard reset
+ *	  = PM8XXX_RESTART_ON_HARD_RESET to restart the system on hard reset
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_hard_reset_config(enum pm8xxx_pon_config config)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8018:
+			__pm8xxx_hard_reset_config(chip, config,
+				REG_PM8018_PON_CNTL_4, REG_PM8018_PON_CNTL_5);
+			break;
+		case PM8XXX_VERSION_8058:
+			__pm8xxx_hard_reset_config(chip, config,
+				REG_PM8058_PON_CNTL_4, REG_PM8058_PON_CNTL_5);
+			break;
+		case PM8XXX_VERSION_8901:
+			__pm8xxx_hard_reset_config(chip, config,
+				REG_PM8901_PON_CNTL_4, REG_PM8901_PON_CNTL_5);
+			break;
+		case PM8XXX_VERSION_8921:
+			__pm8xxx_hard_reset_config(chip, config,
+				REG_PM8921_PON_CNTL_4, REG_PM8921_PON_CNTL_5);
+			break;
+		default:
+			/* hard reset config. no supported */
+			break;
+		}
+		if (rc) {
+			pr_err("hard reset config. failed, rc=%d\n", rc);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_hard_reset_config);
+
+/* Handle the OSC_HALT interrupt: 32 kHz XTAL oscillator has stopped. */
+static irqreturn_t pm8xxx_osc_halt_isr(int irq, void *data)
+{
+	struct pm8xxx_misc_chip *chip = data;
+	u64 count = 0;
+
+	if (chip) {
+		chip->osc_halt_count++;
+		count = chip->osc_halt_count;
+	}
+
+	pr_crit("%s: OSC_HALT interrupt has triggered, 32 kHz XTAL oscillator"
+				" has halted (%llu)!\n", __func__, count);
+
+	return IRQ_HANDLED;
+}
+
+/**
  * pm8xxx_uart_gpio_mux_ctrl - Mux configuration to select the UART
  *
  * @uart_path_sel: Input argument to select either UART1/2/3
@@ -314,7 +944,7 @@
 	struct pm8xxx_misc_chip *sibling;
 	struct list_head *prev;
 	unsigned long flags;
-	int rc = 0;
+	int rc = 0, irq;
 
 	if (!pdata) {
 		pr_err("missing platform data\n");
@@ -332,6 +962,18 @@
 	chip->version = pm8xxx_get_version(chip->dev->parent);
 	memcpy(&(chip->pdata), pdata, sizeof(struct pm8xxx_misc_platform_data));
 
+	irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
+	if (irq > 0) {
+		rc = request_any_context_irq(irq, pm8xxx_osc_halt_isr,
+				 IRQF_TRIGGER_RISING | IRQF_DISABLED,
+				 "pm8xxx_osc_halt_irq", chip);
+		if (rc < 0) {
+			pr_err("%s: request_any_context_irq(%d) FAIL: %d\n",
+							 __func__, irq, rc);
+			goto fail_irq;
+		}
+	}
+
 	/* Insert PMICs in priority order (lowest value first). */
 	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
 	prev = &pm8xxx_misc_chips;
@@ -347,12 +989,20 @@
 	platform_set_drvdata(pdev, chip);
 
 	return rc;
+
+fail_irq:
+	platform_set_drvdata(pdev, NULL);
+	kfree(chip);
+	return rc;
 }
 
 static int __devexit pm8xxx_misc_remove(struct platform_device *pdev)
 {
 	struct pm8xxx_misc_chip *chip = platform_get_drvdata(pdev);
 	unsigned long flags;
+	int irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
+	if (irq > 0)
+		free_irq(irq, chip);
 
 	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
 	list_del(&chip->link);
diff --git a/drivers/mfd/pmic8058.c b/drivers/mfd/pmic8058.c
index 85c8a9d..77e393e 100644
--- a/drivers/mfd/pmic8058.c
+++ b/drivers/mfd/pmic8058.c
@@ -14,55 +14,32 @@
  * Qualcomm PMIC8058 driver
  *
  */
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/ratelimit.h>
-#include <linux/kthread.h>
+#include <linux/irq.h>
 #include <linux/msm_ssbi.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/pmic8058.h>
-#include <linux/platform_device.h>
-#include <linux/ratelimit.h>
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-#include <linux/irq.h>
-#include <linux/syscore_ops.h>
-#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/msm_adc.h>
+
+#define REG_MPP_BASE			0x50
 
 /* PMIC8058 Revision */
-#define SSBI_REG_REV			0x002  /* PMIC4 revision */
+#define PM8058_REG_REV			0x002  /* PMIC4 revision */
+#define PM8058_VERSION_MASK		0xF0
+#define PM8058_REVISION_MASK		0x0F
+#define PM8058_VERSION_VALUE		0xE0
 
-/* PMIC8058 IRQ */
-#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
+/* PMIC 8058 Battery Alarm SSBI registers */
+#define REG_BATT_ALARM_THRESH		0x023
+#define REG_BATT_ALARM_CTRL1		0x024
+#define REG_BATT_ALARM_CTRL2		0x0AA
+#define REG_BATT_ALARM_PWM_CTRL		0x0A3
 
-#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	PM8058_IRQF_LVL_SEL		0x01	/* level select */
-#define	PM8058_IRQF_MASK_FE		0x02	/* mask falling edge */
-#define	PM8058_IRQF_MASK_RE		0x04	/* mask rising edge */
-#define	PM8058_IRQF_CLR			0x08	/* clear interrupt */
-#define	PM8058_IRQF_BITS_MASK		0x70
-#define	PM8058_IRQF_BITS_SHIFT		4
-#define	PM8058_IRQF_WRITE		0x80
-
-#define	PM8058_IRQF_MASK_ALL		(PM8058_IRQF_MASK_FE | \
-					PM8058_IRQF_MASK_RE)
-#define PM8058_IRQF_W_C_M		(PM8058_IRQF_WRITE |	\
-					PM8058_IRQF_CLR |	\
-					PM8058_IRQF_MASK_ALL)
-
-/* MISC register */
-#define	SSBI_REG_ADDR_MISC		0x1CC
+#define REG_TEMP_ALRM_CTRL		0x1B
+#define REG_TEMP_ALRM_PWM		0x9B
 
 /* PON CNTL 1 register */
 #define SSBI_REG_ADDR_PON_CNTL_1	0x01C
@@ -138,53 +115,32 @@
 /* GP_TEST1 register */
 #define SSBI_REG_ADDR_GP_TEST_1		0x07A
 
-/* IRQ */
-#define	MAX_PM_IRQ		256
-#define	MAX_PM_BLOCKS		(MAX_PM_IRQ / 8 + 1)
-#define	MAX_PM_MASTERS		(MAX_PM_BLOCKS / 8 + 1)
+#define PM8058_RTC_BASE			0x1E8
+#define PM8058_OTHC_CNTR_BASE0		0xA0
+#define PM8058_OTHC_CNTR_BASE1		0x134
+#define PM8058_OTHC_CNTR_BASE2		0x137
+
+#define SINGLE_IRQ_RESOURCE(_name, _irq) \
+{ \
+	.name	= _name, \
+	.start	= _irq, \
+	.end	= _irq, \
+	.flags	= IORESOURCE_IRQ, \
+}
 
 struct pm8058_chip {
 	struct pm8058_platform_data	pdata;
 	struct device		*dev;
+	struct pm_irq_chip	*irq_chip;
+	struct mfd_cell         *mfd_regulators, *mfd_xo_buffers;
 
-	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	bus_unlock_config[MAX_PM_IRQ];
-	u8	wake_enable[MAX_PM_IRQ];
-	u16	count_wakeable;
-
-	u8	revision;
+	u8		revision;
 
 	struct mutex	pm_lock;
 };
 
-#if defined(CONFIG_DEBUG_FS)
-struct pm8058_dbg_device {
-	struct mutex		dbg_mutex;
-	struct pm8058_chip	*pm_chip;
-	struct dentry		*dent;
-	int			addr;
-};
-
-static struct pm8058_dbg_device *pmic_dbg_device;
-#endif
-
 static struct pm8058_chip *pmic_chip;
 
-/* Helper Functions */
-DEFINE_RATELIMIT_STATE(pm8058_msg_ratelimit, 60 * HZ, 10);
-
-static inline int pm8058_can_print(void)
-{
-	return __ratelimit(&pm8058_msg_ratelimit);
-}
-
 static inline int
 ssbi_read(struct device *dev, u16 addr, u8 *buf, size_t len)
 {
@@ -223,111 +179,6 @@
 	return rc;
 }
 
-/* External APIs */
-int pm8058_rev(struct pm8058_chip *chip)
-{
-	if (chip == NULL)
-		return -EINVAL;
-
-	return chip->revision;
-}
-EXPORT_SYMBOL(pm8058_rev);
-
-int pm8058_irq_get_rt_status(struct pm8058_chip *chip, int irq)
-{
-	int     rc;
-	u8      block, bits, bit;
-
-	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;
-
-	mutex_lock(&chip->pm_lock);
-
-	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:
-	mutex_unlock(&chip->pm_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL(pm8058_irq_get_rt_status);
-
-int pm8058_read(struct pm8058_chip *chip, u16 addr, u8 *values,
-		unsigned int len)
-{
-	if (chip == NULL)
-		return -EINVAL;
-
-	return ssbi_read(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8058_read);
-
-int pm8058_write(struct pm8058_chip *chip, u16 addr, u8 *values,
-		 unsigned int len)
-{
-	if (chip == NULL)
-		return -EINVAL;
-
-	return ssbi_write(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8058_write);
-
-int pm8058_misc_control(struct pm8058_chip *chip, int mask, int flag)
-{
-	int		rc;
-	u8		misc;
-
-	if (chip == NULL)
-		chip = pmic_chip;	/* for calls from non child */
-	if (chip == NULL)
-		return -ENODEV;
-
-	mutex_lock(&chip->pm_lock);
-
-	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
-		       __func__, SSBI_REG_ADDR_MISC, rc);
-		goto get_out;
-	}
-
-	misc &= ~mask;
-	misc |= flag;
-
-	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
-	if (rc) {
-		pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
-		       __func__, SSBI_REG_ADDR_MISC, misc, rc);
-		goto get_out;
-	}
-
-get_out:
-	mutex_unlock(&chip->pm_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL(pm8058_misc_control);
-
 /**
  * pm8058_smpl_control - enables/disables SMPL detection
  * @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
@@ -713,765 +564,694 @@
 }
 EXPORT_SYMBOL(pm8058_hard_reset_config);
 
-/* Internal functions */
-static inline int
-pm8058_config_irq(struct pm8058_chip *chip, u8 *bp, u8 *cp)
+static int pm8058_readb(const struct device *dev, u16 addr, u8 *val)
 {
-	int	rc;
+	const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+	const struct pm8058_chip *pmic = pm8058_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 pm8058_irq_mask(struct irq_data *data)
+static int pm8058_writeb(const struct device *dev, u16 addr, u8 val)
 {
-	int	master, irq_bit;
-	struct	pm8058_chip *chip = irq_data_get_irq_chip_data(data);
-	u8	block, config;
-	unsigned int irq = data->irq;
+	const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+	const struct pm8058_chip *pmic = pm8058_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 = PM8058_IRQF_WRITE | chip->config[irq] |
-		PM8058_IRQF_MASK_FE | PM8058_IRQF_MASK_RE;
-	chip->bus_unlock_config[irq] = config;
+	return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
 }
 
-static void pm8058_irq_unmask(struct irq_data *data)
+static int pm8058_read_buf(const struct device *dev, u16 addr, u8 *buf,
+								int cnt)
 {
-	int	master, irq_bit;
-	struct	pm8058_chip *chip = irq_data_get_irq_chip_data(data);
-	u8	block, config, old_irqs_allowed, old_blocks_allowed;
-	unsigned int irq = data->irq;
+	const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+	const struct pm8058_chip *pmic = pm8058_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];
-	if (old_irqs_allowed & (1 << irq_bit)) {
-		pr_debug("%s: no need to enable an already enabled irq=%d\n",
-					__func__, irq + chip->pdata.irq_base);
-		return;
-	}
-
-	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 = PM8058_IRQF_WRITE | chip->config[irq];
-	chip->bus_unlock_config[irq] = config;
+	return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
 }
 
-static void pm8058_irq_ack(struct irq_data *data)
+static int pm8058_write_buf(const struct device *dev, u16 addr, u8 *buf,
+								int cnt)
 {
-	struct	pm8058_chip *chip = irq_data_get_irq_chip_data(data);
-	u8	block, config;
-	unsigned int irq = data->irq;
+	const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+	const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-
-	config = PM8058_IRQF_WRITE | chip->config[irq] | PM8058_IRQF_CLR;
-	/* Keep the mask */
-	if (!(chip->irqs_allowed[block] & (1 << (irq % 8))))
-		config |= PM8058_IRQF_MASK_FE | PM8058_IRQF_MASK_RE;
-	chip->bus_unlock_config[irq] = config;
+	return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
 }
 
-static int pm8058_irq_set_type(struct irq_data *data, unsigned int flow_type)
+static int pm8058_read_irq_stat(const struct device *dev, int irq)
 {
-	int	master, irq_bit;
-	struct	pm8058_chip *chip = irq_data_get_irq_chip_data(data);
-	u8	block, config;
-	unsigned int irq = data->irq;
+	const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+	const struct pm8058_chip *pmic = pm8058_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 << PM8058_IRQF_BITS_SHIFT) |
-			PM8058_IRQF_MASK_RE | PM8058_IRQF_MASK_FE;
-	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		if (flow_type & IRQF_TRIGGER_RISING)
-			chip->config[irq] &= ~PM8058_IRQF_MASK_RE;
-		if (flow_type & IRQF_TRIGGER_FALLING)
-			chip->config[irq] &= ~PM8058_IRQF_MASK_FE;
-	} else {
-		chip->config[irq] |= PM8058_IRQF_LVL_SEL;
-
-		if (flow_type & IRQF_TRIGGER_HIGH)
-			chip->config[irq] &= ~PM8058_IRQF_MASK_RE;
-		else
-			chip->config[irq] &= ~PM8058_IRQF_MASK_FE;
-	}
-
-	config = PM8058_IRQF_WRITE | chip->config[irq] | PM8058_IRQF_CLR;
-	chip->bus_unlock_config[irq] = config;
-	return 0;
-}
-
-static int pm8058_irq_set_wake(struct irq_data *data, unsigned int on)
-{
-	struct	pm8058_chip *chip = irq_data_get_irq_chip_data(data);
-	unsigned int irq = data->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 void pm8058_irq_bus_lock(struct irq_data *data)
+static enum pm8xxx_version pm8058_get_version(const struct device *dev)
 {
-	u8	block;
-	struct	pm8058_chip *chip = irq_data_get_irq_chip_data(data);
-	unsigned int irq = data->irq;
+	const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+	const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
+	enum pm8xxx_version version = -ENODEV;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-	chip->bus_unlock_config[irq] = 0;
+	if ((pmic->revision & PM8058_VERSION_MASK) == PM8058_VERSION_VALUE)
+		version = PM8XXX_VERSION_8058;
 
-	mutex_lock(&chip->pm_lock);
+	return version;
 }
 
-static void pm8058_irq_bus_sync_unlock(struct irq_data *data)
+static int pm8058_get_revision(const struct device *dev)
 {
-	u8	block, config;
-	struct	pm8058_chip *chip = irq_data_get_irq_chip_data(data);
-	unsigned int irq = data->irq;
+	const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+	const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
 
-	irq -= chip->pdata.irq_base;
-	block = irq / 8;
-	config = chip->bus_unlock_config[irq];
-	/* dont waste cpu cycles if we dont have data to write */
-	if (config)
-		pm8058_config_irq(chip, &block, &config);
-	mutex_unlock(&chip->pm_lock);
+	return pmic->revision & PM8058_REVISION_MASK;
 }
 
-static inline int
-pm8058_read_root(struct pm8058_chip *chip, u8 *rp)
-{
-	int	rc;
-
-	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;
-	}
-
-	return rc;
-}
-
-static inline int
-pm8058_read_master(struct pm8058_chip *chip, u8 m, u8 *bp)
-{
-	int	rc;
-
-	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;
-}
-
-static inline int
-pm8058_read_block(struct pm8058_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 pm8058_isr_thread(int irq_requested, void *data)
-{
-	struct pm8058_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];
-
-	mutex_lock(&chip->pm_lock);
-
-	/* Read root for masters */
-	if (pm8058_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 (pm8058_read_master(chip, i, &blocks[i]))
-				goto bail_out;
-
-			if (!blocks[i]) {
-				if (pm8058_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 (pm8058_read_block(chip, &block, &bits))
-				goto bail_out;
-
-			if (!bits) {
-				if (pm8058_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 = PM8058_IRQF_W_C_M |
-						(k << PM8058_IRQF_BITS_SHIFT);
-
-					pm8058_config_irq(chip,
-							  &block, &config);
-
-					if (pm8058_can_print())
-						pr_err("%s: Spurious IRQ: "
-						       "[master, block, bit]="
-						       "[%d, %d (%d), %d]\n",
-							__func__,
-						       i, j, block, k);
-					spurious++;
-				}
-			}
-		}
-
-	}
-
-bail_out:
-
-	mutex_unlock(&chip->pm_lock);
-
-	for (i = 0; i < handled; i++) {
-		int pmic_irq = irqs_to_handle[i] - chip->pdata.irq_base;
-
-		/* ack the interrupt first */
-		block  = pmic_irq / 8 ;
-		config = PM8058_IRQF_WRITE | chip->config[pmic_irq]
-				| PM8058_IRQF_CLR;
-		pm8058_config_irq(chip, &block, &config);
-
-		/* calle the action handler */
-		handle_nested_irq(irqs_to_handle[i]);
-	}
-
-	if (spurious) {
-		if (!pm8058_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 8058 register address is invalid: %d\n",
-			func_name, addr);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int data_set(void *data, u64 val)
-{
-	struct pm8058_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 = pm8058_write(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
-
-	if (rc)
-		pr_err("%s: FAIL pm8058_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 pm8058_dbg_device *dbgdev = data;
-	int rc;
-	u8 reg;
-
-	mutex_lock(&dbgdev->dbg_mutex);
-
-	rc = check_addr(dbgdev->addr, __func__);
-	if (rc)
-		goto done;
-
-	rc = pm8058_read(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
-
-	if (rc) {
-		pr_err("%s: FAIL pm8058_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 pm8058_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 pm8058_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 pmic8058_dbg_probe(struct pm8058_chip *chip)
-{
-	struct pm8058_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("pm8058-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 pmic8058_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 pmic8058_dbg_probe(struct pm8058_chip *chip)
-{
-	return 0;
-}
-
-static int __devexit pmic8058_dbg_remove(void)
-{
-	return 0;
-}
-
-#endif
-
-static struct irq_chip pm8058_irq_chip = {
-	.name      = "pm8058",
-	.irq_ack	= pm8058_irq_ack,
-	.irq_mask	= pm8058_irq_mask,
-	.irq_unmask	= pm8058_irq_unmask,
-	.irq_set_type	= pm8058_irq_set_type,
-	.irq_set_wake	= pm8058_irq_set_wake,
-	.irq_bus_lock	= pm8058_irq_bus_lock,
-	.irq_bus_sync_unlock	= pm8058_irq_bus_sync_unlock,
+static struct pm8xxx_drvdata pm8058_drvdata = {
+	.pmic_readb		= pm8058_readb,
+	.pmic_writeb		= pm8058_writeb,
+	.pmic_read_buf		= pm8058_read_buf,
+	.pmic_write_buf		= pm8058_write_buf,
+	.pmic_read_irq_stat	= pm8058_read_irq_stat,
+	.pmic_get_version	= pm8058_get_version,
+	.pmic_get_revision	= pm8058_get_revision,
 };
 
-static int pm8058_suspend(void)
-{
-	struct	pm8058_chip *chip = pmic_chip;
-	struct irq_data *data;
-	int	i;
-
-	for (i = 0; i < MAX_PM_IRQ; i++) {
-		if (chip->config[i] && !chip->wake_enable[i]) {
-			if (!((chip->config[i] & PM8058_IRQF_MASK_ALL)
-			      == PM8058_IRQF_MASK_ALL)) {
-				data = irq_get_irq_data(i +
-						chip->pdata.irq_base);
-				pm8058_irq_bus_lock(data);
-				pm8058_irq_mask(data);
-				pm8058_irq_bus_sync_unlock(data);
-			}
-		}
-	}
-
-	if (!chip->count_wakeable)
-		disable_irq(chip->pdata.irq);
-
-	return 0;
-}
-
-extern int msm_show_resume_irq_mask;
-
-static void pm8058_show_resume_irq(void)
-{
-	u8	block, bits;
-	int i;
-	struct pm8058_chip *chip = pmic_chip;
-
-	if (!msm_show_resume_irq_mask)
-		return;
-
-	for (i = 0; i < MAX_PM_IRQ; i++) {
-		if (chip->wake_enable[i]) {
-			block = i / 8;
-			if (!pm8058_read_block(chip, &block, &bits)) {
-				if (bits & (1 << (i & 0x7)))
-					pr_warning("%s:%d triggered\n",
-					__func__, i + chip->pdata.irq_base);
-			}
-		}
-	}
-}
-
-static void pm8058_resume(void)
-{
-	struct	pm8058_chip *chip = pmic_chip;
-	struct irq_data *data;
-	int	i;
-
-	pm8058_show_resume_irq();
-
-	for (i = 0; i < MAX_PM_IRQ; i++) {
-		if (chip->config[i] && !chip->wake_enable[i]) {
-			if (!((chip->config[i] & PM8058_IRQF_MASK_ALL)
-			      == PM8058_IRQF_MASK_ALL)) {
-				data = irq_get_irq_data(i +
-						chip->pdata.irq_base);
-				pm8058_irq_bus_lock(data);
-				pm8058_irq_unmask(data);
-				pm8058_irq_bus_sync_unlock(data);
-			}
-		}
-	}
-
-	if (!chip->count_wakeable)
-		enable_irq(chip->pdata.irq);
-}
-
-static struct syscore_ops pm8058_pm = {
-	.suspend = pm8058_suspend,
-	.resume = pm8058_resume,
+static const struct resource pm8058_charger_resources[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE("CHGVAL",		PM8058_CHGVAL_IRQ),
+	SINGLE_IRQ_RESOURCE("CHGINVAL",		PM8058_CHGINVAL_IRQ),
+	SINGLE_IRQ_RESOURCE("CHGILIM",		PM8058_CHGILIM_IRQ),
+	SINGLE_IRQ_RESOURCE("VCP",		PM8058_VCP_IRQ),
+	SINGLE_IRQ_RESOURCE("ATC_DONE",		PM8058_ATC_DONE_IRQ),
+	SINGLE_IRQ_RESOURCE("ATCFAIL",		PM8058_ATCFAIL_IRQ),
+	SINGLE_IRQ_RESOURCE("AUTO_CHGDONE",	PM8058_AUTO_CHGDONE_IRQ),
+	SINGLE_IRQ_RESOURCE("AUTO_CHGFAIL",	PM8058_AUTO_CHGFAIL_IRQ),
+	SINGLE_IRQ_RESOURCE("CHGSTATE",		PM8058_CHGSTATE_IRQ),
+	SINGLE_IRQ_RESOURCE("FASTCHG",		PM8058_FASTCHG_IRQ),
+	SINGLE_IRQ_RESOURCE("CHG_END",		PM8058_CHG_END_IRQ),
+	SINGLE_IRQ_RESOURCE("BATTTEMP",		PM8058_BATTTEMP_IRQ),
+	SINGLE_IRQ_RESOURCE("CHGHOT",		PM8058_CHGHOT_IRQ),
+	SINGLE_IRQ_RESOURCE("CHGTLIMIT",	PM8058_CHGTLIMIT_IRQ),
+	SINGLE_IRQ_RESOURCE("CHG_GONE",		PM8058_CHG_GONE_IRQ),
+	SINGLE_IRQ_RESOURCE("VCPMAJOR",		PM8058_VCPMAJOR_IRQ),
+	SINGLE_IRQ_RESOURCE("VBATDET",		PM8058_VBATDET_IRQ),
+	SINGLE_IRQ_RESOURCE("BATFET",		PM8058_BATFET_IRQ),
+	SINGLE_IRQ_RESOURCE("BATT_REPLACE",	PM8058_BATT_REPLACE_IRQ),
+	SINGLE_IRQ_RESOURCE("BATTCONNECT",	PM8058_BATTCONNECT_IRQ),
+	SINGLE_IRQ_RESOURCE("VBATDET_LOW",	PM8058_VBATDET_LOW_IRQ),
 };
 
+static struct mfd_cell pm8058_charger_cell __devinitdata = {
+	.name		= "pm8058-charger",
+	.id		= -1,
+	.resources	= pm8058_charger_resources,
+	.num_resources	= ARRAY_SIZE(pm8058_charger_resources),
+};
+
+static const struct resource misc_cell_resources[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE("pm8xxx_osc_halt_irq", PM8058_OSCHALT_IRQ),
+};
+
+static struct mfd_cell misc_cell __devinitdata = {
+	.name		= PM8XXX_MISC_DEV_NAME,
+	.id		= -1,
+	.resources	= misc_cell_resources,
+	.num_resources	= ARRAY_SIZE(misc_cell_resources),
+};
+
+static struct mfd_cell pm8058_pwm_cell __devinitdata = {
+	.name		= "pm8058-pwm",
+	.id		= -1,
+};
+
+static struct resource xoadc_resources[] = {
+	SINGLE_IRQ_RESOURCE(NULL, PM8058_ADC_IRQ),
+};
+
+static struct mfd_cell xoadc_cell __devinitdata = {
+	.name		= "pm8058-xoadc",
+	.id		= -1,
+	.resources	= xoadc_resources,
+	.num_resources	= ARRAY_SIZE(xoadc_resources),
+};
+
+static const struct resource thermal_alarm_cell_resources[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE("pm8058_tempstat_irq", PM8058_TEMPSTAT_IRQ),
+	SINGLE_IRQ_RESOURCE("pm8058_overtemp_irq", PM8058_OVERTEMP_IRQ),
+};
+
+static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
+	.adc_channel			= CHANNEL_ADC_DIE_TEMP,
+	.adc_type			= PM8XXX_TM_ADC_PM8058_ADC,
+	.reg_addr_temp_alarm_ctrl	= REG_TEMP_ALRM_CTRL,
+	.reg_addr_temp_alarm_pwm	= REG_TEMP_ALRM_PWM,
+	.tm_name			= "pm8058_tz",
+	.irq_name_temp_stat		= "pm8058_tempstat_irq",
+	.irq_name_over_temp		= "pm8058_overtemp_irq",
+};
+
+static struct mfd_cell thermal_alarm_cell __devinitdata = {
+	.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 struct mfd_cell debugfs_cell __devinitdata = {
+	.name		= "pm8xxx-debug",
+	.id		= -1,
+	.platform_data	= "pm8058-dbg",
+	.pdata_size	= sizeof("pm8058-dbg"),
+};
+
+static const struct resource othc0_cell_resources[] __devinitconst = {
+	{
+		.name	= "othc_base",
+		.start	= PM8058_OTHC_CNTR_BASE0,
+		.end	= PM8058_OTHC_CNTR_BASE0,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static const struct resource othc1_cell_resources[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE(NULL, PM8058_SW_1_IRQ),
+	SINGLE_IRQ_RESOURCE(NULL, PM8058_IR_1_IRQ),
+	{
+		.name	= "othc_base",
+		.start	= PM8058_OTHC_CNTR_BASE1,
+		.end	= PM8058_OTHC_CNTR_BASE1,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static const struct resource othc2_cell_resources[] __devinitconst = {
+	{
+		.name	= "othc_base",
+		.start	= PM8058_OTHC_CNTR_BASE2,
+		.end	= PM8058_OTHC_CNTR_BASE2,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static const struct resource batt_alarm_cell_resources[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE("pm8058_batt_alarm_irq", PM8058_BATT_ALARM_IRQ),
+};
+
+static struct mfd_cell leds_cell __devinitdata = {
+	.name		= "pm8058-led",
+	.id		= -1,
+};
+
+static struct mfd_cell othc0_cell __devinitdata = {
+	.name		= "pm8058-othc",
+	.id		= 0,
+	.resources	= othc0_cell_resources,
+	.num_resources  = ARRAY_SIZE(othc0_cell_resources),
+};
+
+static struct mfd_cell othc1_cell __devinitdata = {
+	.name		= "pm8058-othc",
+	.id		= 1,
+	.resources	= othc1_cell_resources,
+	.num_resources  = ARRAY_SIZE(othc1_cell_resources),
+};
+
+static struct mfd_cell othc2_cell __devinitdata = {
+	.name		= "pm8058-othc",
+	.id		= 2,
+	.resources	= othc2_cell_resources,
+	.num_resources  = ARRAY_SIZE(othc2_cell_resources),
+};
+
+static struct pm8xxx_batt_alarm_core_data batt_alarm_cdata = {
+	.irq_name		= "pm8058_batt_alarm_irq",
+	.reg_addr_threshold	= REG_BATT_ALARM_THRESH,
+	.reg_addr_ctrl1		= REG_BATT_ALARM_CTRL1,
+	.reg_addr_ctrl2		= REG_BATT_ALARM_CTRL2,
+	.reg_addr_pwm_ctrl	= REG_BATT_ALARM_PWM_CTRL,
+};
+
+static struct mfd_cell batt_alarm_cell __devinitdata = {
+	.name		= PM8XXX_BATT_ALARM_DEV_NAME,
+	.id		= -1,
+	.resources	= batt_alarm_cell_resources,
+	.num_resources	= ARRAY_SIZE(batt_alarm_cell_resources),
+	.platform_data	= &batt_alarm_cdata,
+	.pdata_size	= sizeof(struct pm8xxx_batt_alarm_core_data),
+};
+
+static struct mfd_cell upl_cell __devinitdata = {
+	.name		= PM8XXX_UPL_DEV_NAME,
+	.id		= -1,
+};
+
+static struct mfd_cell nfc_cell __devinitdata = {
+	.name		= PM8XXX_NFC_DEV_NAME,
+	.id		= -1,
+};
+
+static const struct resource rtc_cell_resources[] __devinitconst = {
+	[0] = SINGLE_IRQ_RESOURCE(NULL, PM8058_RTC_ALARM_IRQ),
+	[1] = {
+		.name   = "pmic_rtc_base",
+		.start  = PM8058_RTC_BASE,
+		.end    = PM8058_RTC_BASE,
+		.flags  = IORESOURCE_IO,
+	},
+};
+
+static struct mfd_cell rtc_cell __devinitdata = {
+	.name		= PM8XXX_RTC_DEV_NAME,
+	.id		= -1,
+	.resources	= rtc_cell_resources,
+	.num_resources  = ARRAY_SIZE(rtc_cell_resources),
+};
+
+static const struct resource resources_pwrkey[] __devinitconst = {
+	SINGLE_IRQ_RESOURCE(NULL, PM8058_PWRKEY_REL_IRQ),
+	SINGLE_IRQ_RESOURCE(NULL, PM8058_PWRKEY_PRESS_IRQ),
+};
+
+static struct mfd_cell vibrator_cell __devinitdata = {
+	.name		= PM8XXX_VIBRATOR_DEV_NAME,
+	.id		= -1,
+};
+
+static struct mfd_cell pwrkey_cell __devinitdata = {
+	.name		= PM8XXX_PWRKEY_DEV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(resources_pwrkey),
+	.resources	= resources_pwrkey,
+};
+
+static const struct resource resources_keypad[] = {
+	SINGLE_IRQ_RESOURCE(NULL, PM8058_KEYPAD_IRQ),
+	SINGLE_IRQ_RESOURCE(NULL, PM8058_KEYSTUCK_IRQ),
+};
+
+static struct mfd_cell keypad_cell __devinitdata = {
+	.name		= PM8XXX_KEYPAD_DEV_NAME,
+	.id		= -1,
+	.num_resources  = ARRAY_SIZE(resources_keypad),
+	.resources	= resources_keypad,
+};
+
+static const struct resource mpp_cell_resources[] __devinitconst = {
+	{
+		.start	= PM8058_IRQ_BLOCK_BIT(PM8058_MPP_BLOCK_START, 0),
+		.end	= PM8058_IRQ_BLOCK_BIT(PM8058_MPP_BLOCK_START, 0)
+			  + PM8058_MPPS - 1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell mpp_cell __devinitdata = {
+	.name		= PM8XXX_MPP_DEV_NAME,
+	.id		= 0,
+	.resources	= mpp_cell_resources,
+	.num_resources	= ARRAY_SIZE(mpp_cell_resources),
+};
+
+static const struct resource gpio_cell_resources[] __devinitconst = {
+	[0] = {
+		.start = PM8058_IRQ_BLOCK_BIT(PM8058_GPIO_BLOCK_START, 0),
+		.end   = PM8058_IRQ_BLOCK_BIT(PM8058_GPIO_BLOCK_START, 0)
+			+ PM8058_GPIOS - 1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell gpio_cell __devinitdata = {
+	.name		= PM8XXX_GPIO_DEV_NAME,
+	.id		= -1,
+	.resources	= gpio_cell_resources,
+	.num_resources	= ARRAY_SIZE(gpio_cell_resources),
+};
+
+static int __devinit
+pm8058_add_subdevices(const struct pm8058_platform_data *pdata,
+				struct pm8058_chip *pmic)
+{
+	int rc = 0, irq_base = 0, i;
+	struct pm_irq_chip *irq_chip;
+	static struct mfd_cell *mfd_regulators, *mfd_xo_buffers;
+
+	if (pdata->irq_pdata) {
+		pdata->irq_pdata->irq_cdata.nirqs = PM8058_NR_IRQS;
+		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->gpio_pdata) {
+		pdata->gpio_pdata->gpio_cdata.ngpios = PM8058_GPIOS;
+		gpio_cell.platform_data = pdata->gpio_pdata;
+		gpio_cell.pdata_size = sizeof(struct pm8xxx_gpio_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &gpio_cell, 1,
+					NULL, irq_base);
+		if (rc) {
+			pr_err("Failed to add  gpio subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->mpp_pdata) {
+		pdata->mpp_pdata->core_data.nmpps = PM8058_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 pm8058 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 = "pm8058-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 pm8058_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;
+	}
+
+	if (pdata->num_xo_buffers > 0 && pdata->xo_buffer_pdata) {
+		mfd_xo_buffers = kzalloc(sizeof(struct mfd_cell)
+					 * (pdata->num_xo_buffers), GFP_KERNEL);
+		if (!mfd_xo_buffers) {
+			pr_err("Cannot allocate %d bytes for pm8058 XO buffer "
+				"mfd cells\n", sizeof(struct mfd_cell)
+						* (pdata->num_xo_buffers));
+			rc = -ENOMEM;
+			goto bail;
+		}
+		for (i = 0; i < pdata->num_xo_buffers; i++) {
+			mfd_xo_buffers[i].name = PM8058_XO_BUFFER_DEV_NAME;
+			mfd_xo_buffers[i].id = pdata->xo_buffer_pdata[i].id;
+			mfd_xo_buffers[i].platform_data =
+				&(pdata->xo_buffer_pdata[i]);
+			mfd_xo_buffers[i].pdata_size =
+					sizeof(struct pm8058_xo_pdata);
+		}
+		rc = mfd_add_devices(pmic->dev, 0, mfd_xo_buffers,
+				pdata->num_xo_buffers, NULL, irq_base);
+		if (rc) {
+			pr_err("Failed to add XO buffer subdevices ret=%d\n",
+				rc);
+			kfree(mfd_xo_buffers);
+			goto bail;
+		}
+		pmic->mfd_xo_buffers = mfd_xo_buffers;
+	}
+
+	if (pdata->keypad_pdata) {
+		keypad_cell.platform_data = pdata->keypad_pdata;
+		keypad_cell.pdata_size =
+			sizeof(struct pm8xxx_keypad_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &keypad_cell, 1, NULL,
+					irq_base);
+		if (rc) {
+			pr_err("Failed to add keypad subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->rtc_pdata) {
+		rtc_cell.platform_data = pdata->rtc_pdata;
+		rtc_cell.pdata_size = sizeof(struct pm8xxx_rtc_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &rtc_cell, 1, NULL,
+						irq_base);
+		if (rc) {
+			pr_err("Failed to add rtc subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->pwrkey_pdata) {
+		pwrkey_cell.platform_data = pdata->pwrkey_pdata;
+		pwrkey_cell.pdata_size =
+			sizeof(struct pm8xxx_pwrkey_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &pwrkey_cell, 1, NULL,
+							irq_base);
+		if (rc) {
+			pr_err("Failed to add pwrkey subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->vibrator_pdata) {
+		vibrator_cell.platform_data = pdata->vibrator_pdata;
+		vibrator_cell.pdata_size =
+				sizeof(struct pm8xxx_vibrator_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &vibrator_cell, 1, NULL,
+								irq_base);
+		if (rc) {
+			pr_err("Failed to add vibrator subdevice ret=%d\n",
+									rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->leds_pdata) {
+		leds_cell.platform_data = pdata->leds_pdata;
+		leds_cell.pdata_size =
+			sizeof(struct pmic8058_leds_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &leds_cell, 1, NULL,
+								irq_base);
+		if (rc) {
+			pr_err("Failed to add leds subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->xoadc_pdata) {
+		xoadc_cell.platform_data = pdata->xoadc_pdata;
+		xoadc_cell.pdata_size =
+			sizeof(struct xoadc_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &xoadc_cell, 1, NULL,
+								irq_base);
+		if (rc) {
+			pr_err("Failed to add leds subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->othc0_pdata) {
+		othc0_cell.platform_data = pdata->othc0_pdata;
+		othc0_cell.pdata_size =
+			sizeof(struct pmic8058_othc_config_pdata);
+		rc = mfd_add_devices(pmic->dev, 0, &othc0_cell, 1, NULL, 0);
+		if (rc) {
+			pr_err("Failed to add othc0 subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->othc1_pdata) {
+		othc1_cell.platform_data = pdata->othc1_pdata;
+		othc1_cell.pdata_size =
+			sizeof(struct pmic8058_othc_config_pdata);
+		rc = mfd_add_devices(pmic->dev, 0, &othc1_cell, 1, NULL,
+								irq_base);
+		if (rc) {
+			pr_err("Failed to add othc1 subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->othc2_pdata) {
+		othc2_cell.platform_data = pdata->othc2_pdata;
+		othc2_cell.pdata_size =
+			sizeof(struct pmic8058_othc_config_pdata);
+		rc = mfd_add_devices(pmic->dev, 0, &othc2_cell, 1, NULL, 0);
+		if (rc) {
+			pr_err("Failed to add othc2 subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->pwm_pdata) {
+		pm8058_pwm_cell.platform_data = pdata->pwm_pdata;
+		pm8058_pwm_cell.pdata_size = sizeof(struct pm8058_pwm_pdata);
+		rc = mfd_add_devices(pmic->dev, 0, &pm8058_pwm_cell, 1, NULL,
+								irq_base);
+		if (rc) {
+			pr_err("Failed to add pwm subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	if (pdata->misc_pdata) {
+		misc_cell.platform_data = pdata->misc_pdata;
+		misc_cell.pdata_size = sizeof(struct pm8xxx_misc_platform_data);
+		rc = mfd_add_devices(pmic->dev, 0, &misc_cell, 1, NULL,
+				      irq_base);
+		if (rc) {
+			pr_err("Failed to add  misc subdevice ret=%d\n", rc);
+			goto bail;
+		}
+	}
+
+	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, &batt_alarm_cell, 1, NULL,
+				irq_base);
+	if (rc) {
+		pr_err("Failed to add battery alarm subdevice ret=%d\n",
+			rc);
+		goto bail;
+	}
+
+	rc = mfd_add_devices(pmic->dev, 0, &upl_cell, 1, NULL, 0);
+	if (rc) {
+		pr_err("Failed to add upl subdevice ret=%d\n", rc);
+		goto bail;
+	}
+
+	rc = mfd_add_devices(pmic->dev, 0, &nfc_cell, 1, NULL, 0);
+	if (rc) {
+		pr_err("Failed to add upl subdevice ret=%d\n", rc);
+		goto bail;
+	}
+
+	if (pdata->charger_pdata) {
+		pm8058_charger_cell.platform_data = pdata->charger_pdata;
+		pm8058_charger_cell.pdata_size = sizeof(struct
+						pmic8058_charger_data);
+		rc = mfd_add_devices(pmic->dev, 0, &pm8058_charger_cell,
+						1, NULL, irq_base);
+		if (rc) {
+			pr_err("Failed to add charger 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 __devinit pm8058_probe(struct platform_device *pdev)
 {
-	int	i, rc;
-	struct	pm8058_platform_data *pdata = pdev->dev.platform_data;
-	struct	pm8058_chip *chip;
+	int rc;
+	struct pm8058_platform_data *pdata = pdev->dev.platform_data;
+	struct pm8058_chip *pmic;
 
-	if (pdata == NULL || !gpio_is_valid(pdata->irq)) {
+	if (pdata == NULL) {
 		pr_err("%s: No platform_data or IRQ.\n", __func__);
 		return -ENODEV;
 	}
 
-	if (pdata->num_subdevs == 0) {
-		pr_err("%s: No sub devices to support.\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;
+
+	pm8058_drvdata.pm_chip_data = pmic;
+	platform_set_drvdata(pdev, &pm8058_drvdata);
+
+	mutex_init(&pmic->pm_lock);
+	pmic_chip = pmic;
 
 	/* Read PMIC chip revision */
-	rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
+	rc = pm8058_readb(pmic->dev, PM8058_REG_REV, &pmic->revision);
 	if (rc)
-		pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
+		pr_err("%s: Failed on pm8058_readb for revision: 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);
 
-	mutex_init(&chip->pm_lock);
-	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;
-
-	/* Register for all reserved IRQs */
-	for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
-		irq_set_chip(i, &pm8058_irq_chip);
-		irq_set_chip_data(i, (void *)chip);
-		irq_set_handler(i, handle_edge_irq);
-		set_irq_flags(i, IRQF_VALID);
-		irq_set_nested_thread(i, 1);
+	rc = pm8058_add_subdevices(pdata, pmic);
+	if (rc) {
+		pr_err("Cannot add subdevices rc=%d\n", rc);
+		goto err;
 	}
 
-	rc = mfd_add_devices(chip->dev, 0, pdata->sub_devices,
-			     pdata->num_subdevs, NULL, 0);
-
-	/* Add charger sub device with the chip parameter as driver data */
-	if (pdata->charger_sub_device) {
-		rc = mfd_add_devices(chip->dev, 0,
-					pdata->charger_sub_device,
-					1, NULL, 0);
-	}
-
-	if (pdata->init) {
-		rc = pdata->init(chip);
-		if (rc != 0) {
-			pr_err("%s: board init failed\n", __func__);
-			chip->dev = NULL;
-			kfree(chip);
-			return -ENODEV;
-		}
-	}
-
-	rc = request_threaded_irq(pdata->irq, NULL, pm8058_isr_thread,
-			IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
-			"pm8058-irq", chip);
-	if (rc < 0)
-		pr_err("%s: could not request irq %d: %d\n", __func__,
-				pdata->irq, rc);
-
-	rc = pmic8058_dbg_probe(chip);
-	if (rc < 0)
-		pr_err("%s: could not set up debugfs: %d\n", __func__, rc);
-
 	rc = pm8058_hard_reset_config(SHUTDOWN_ON_HARD_RESET);
 	if (rc < 0)
 		pr_err("%s: failed to config shutdown on hard reset: %d\n",
 								__func__, rc);
 
-	register_syscore_ops(&pm8058_pm);
-
 	return 0;
+
+err:
+	mfd_remove_devices(pmic->dev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(pmic);
+	return rc;
 }
 
 static int __devexit pm8058_remove(struct platform_device *pdev)
 {
-	struct	pm8058_chip *chip;
+	struct pm8xxx_drvdata *drvdata;
+	struct pm8058_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);
-		}
-		mutex_destroy(&chip->pm_lock);
-		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);
+		mutex_destroy(&pmic->pm_lock);
+		kfree(pmic->mfd_regulators);
+		kfree(pmic);
 	}
-
-	pmic8058_dbg_remove();
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
@@ -1489,7 +1269,7 @@
 {
 	return platform_driver_register(&pm8058_driver);
 }
-arch_initcall(pm8058_init);
+postcore_initcall(pm8058_init);
 
 static void __exit pm8058_exit(void)
 {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index dfbf345..3d7738e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -601,21 +601,19 @@
 	  on the PM8XXX chips. The vibrator is controlled using the
 	  timed output class.
 
-config PMIC8058_NFC
-	tristate "Qualcomm PM8058 support for Near Field Communication"
-	depends on PMIC8058
-	default y
+config PMIC8XXX_NFC
+	tristate "Qualcomm PM8XXX support for Near Field Communication"
+	depends on MFD_PM8XXX
 	help
-	  Qualcomm PM8058 chip has a module to support NFC (Near Field
+	  Qualcomm PM8XXX chips have a module to support NFC (Near Field
 	  Communication). This option enables the driver to support it.
 
-config PMIC8058_UPL
-	tristate "Qualcomm PM8058 support for User Programmable Logic"
-	depends on PMIC8058
-	default n
+config PMIC8XXX_UPL
+	tristate "Qualcomm PM8XXX support for User Programmable Logic"
+	depends on MFD_PM8XXX
 	help
 	  This option enables device driver support for User Programmable Logic
-	  on Qualcomm PM8058 chip.  The UPL module provides a means to implement
+	  on Qualcomm PM8XXX chips. The UPL module provides a means to implement
 	  simple truth table based logic via a set of control registers. I/O may
 	  be routed in and out of the UPL module via GPIO or DTEST pins.
 
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a38ccfd..b7f23c8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -59,8 +59,8 @@
 obj-$(CONFIG_PMIC8058_PWM) += pmic8058-pwm.o
 obj-$(CONFIG_PMIC8058_VIBRATOR) += pmic8058-vibrator.o
 obj-$(CONFIG_PMIC8XXX_VIBRATOR) += pm8xxx-vibrator.o
-obj-$(CONFIG_PMIC8058_NFC) += pmic8058-nfc.o
-obj-$(CONFIG_PMIC8058_UPL) += pmic8058-upl.o
+obj-$(CONFIG_PMIC8XXX_NFC) += pm8xxx-nfc.o
+obj-$(CONFIG_PMIC8XXX_UPL) += pm8xxx-upl.o
 obj-$(CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN) \
 	+= msm_migrate_pages.o
 obj-$(CONFIG_PMIC8058_XOADC) += pmic8058-xoadc.o
diff --git a/drivers/misc/pm8xxx-nfc.c b/drivers/misc/pm8xxx-nfc.c
new file mode 100644
index 0000000..1aaa3e3
--- /dev/null
+++ b/drivers/misc/pm8xxx-nfc.c
@@ -0,0 +1,311 @@
+/* Copyright (c) 2010,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.
+ *
+ */
+/*
+ * Qualcomm PMIC8XXX NFC driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/nfc.h>
+
+/* PM8XXX NFC */
+#define SSBI_REG_NFC_CTRL	0x14D
+#define SSBI_REG_NFC_TEST	0x14E
+
+/* NFC_CTRL */
+#define PM8XXX_NFC_SUPPORT_EN		0x80
+#define PM8XXX_NFC_LDO_EN		0x40
+#define PM8XXX_NFC_EN			0x20
+#define PM8XXX_NFC_EXT_VDDLDO_EN	0x10
+#define PM8XXX_NFC_VPH_PWR_EN		0x08
+#define PM8XXX_NFC_RESERVED		0x04
+#define PM8XXX_NFC_VDDLDO_LEVEL		0x03
+
+/* NFC_TEST */
+#define PM8XXX_NFC_VDDLDO_MON_EN	0x80
+#define PM8XXX_NFC_ATEST_EN		0x40
+#define PM8XXX_NFC_DTEST1_EN		0x20
+#define PM8XXX_NFC_RESERVED2		0x18
+#define PM8XXX_NFC_VDDLDO_OK_S		0x04
+#define PM8XXX_NFC_MBG_EN_S		0x02
+#define PM8XXX_NFC_EXT_EN_S		0x01
+
+struct pm8xxx_nfc_device {
+	struct device *dev;
+	struct mutex		nfc_mutex;
+#if defined(CONFIG_DEBUG_FS)
+	struct dentry		*dent;
+#endif
+};
+static struct pm8xxx_nfc_device	*nfc_dev;
+
+/* APIs */
+/*
+ * pm8xxx_nfc_request - request a handle to access NFC device
+ */
+struct pm8xxx_nfc_device *pm8xxx_nfc_request(void)
+{
+	return nfc_dev;
+}
+EXPORT_SYMBOL(pm8xxx_nfc_request);
+
+/*
+ * pm8xxx_nfc_config - configure NFC signals
+ *
+ * @nfcdev: the NFC device
+ * @mask: signal mask to configure
+ * @flags: control flags
+ */
+int pm8xxx_nfc_config(struct pm8xxx_nfc_device *nfcdev, u32 mask, u32 flags)
+{
+	u8	nfc_ctrl, nfc_test, m, f;
+	int	rc;
+
+	if (nfcdev == NULL || IS_ERR(nfcdev) || !mask)
+		return -EINVAL;
+
+	mutex_lock(&nfcdev->nfc_mutex);
+
+	if (!(mask & PM_NFC_CTRL_REQ))
+		goto config_test;
+
+	rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_CTRL, &nfc_ctrl);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_ctrl=0x%x)\n",
+		       __func__, rc, nfc_ctrl);
+		goto config_done;
+	}
+
+	m = mask & 0x00ff;
+	f = flags & 0x00ff;
+	nfc_ctrl &= ~m;
+	nfc_ctrl |= m & f;
+
+	rc = pm8xxx_writeb(nfcdev->dev->parent, SSBI_REG_NFC_CTRL, nfc_ctrl);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_writeb(): rc=%d (nfc_ctrl=0x%x)\n",
+		       __func__, rc, nfc_ctrl);
+		goto config_done;
+	}
+
+config_test:
+	if (!(mask & PM_NFC_TEST_REQ))
+		goto config_done;
+
+	rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_TEST, &nfc_test);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_test=0x%x)\n",
+		       __func__, rc, nfc_test);
+		goto config_done;
+	}
+
+	m = (mask >> 8) & 0x00ff;
+	f = (flags >> 8) & 0x00ff;
+	nfc_test &= ~m;
+	nfc_test |= m & f;
+
+	rc = pm8xxx_writeb(nfcdev->dev->parent, SSBI_REG_NFC_TEST, nfc_test);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_writeb(): rc=%d (nfc_test=0x%x)\n",
+		       __func__, rc, nfc_test);
+		goto config_done;
+	}
+
+config_done:
+	mutex_unlock(&nfcdev->nfc_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(pm8xxx_nfc_config);
+
+/*
+ * pm8xxx_nfc_get_status - get NFC status
+ *
+ * @nfcdev: the NFC device
+ * @mask: of status mask to read
+ * @status: pointer to the status variable
+ */
+int pm8xxx_nfc_get_status(struct pm8xxx_nfc_device *nfcdev,
+			  u32 mask, u32 *status)
+{
+	u8	nfc_ctrl, nfc_test;
+	u32	st;
+	int	rc;
+
+	if (nfcdev == NULL || IS_ERR(nfcdev) || status == NULL)
+		return -EINVAL;
+
+	st = 0;
+	mutex_lock(&nfcdev->nfc_mutex);
+
+	if (!(mask & PM_NFC_CTRL_REQ))
+		goto read_test;
+
+	rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_CTRL, &nfc_ctrl);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_ctrl=0x%x)\n",
+		       __func__, rc, nfc_ctrl);
+		goto get_status_done;
+	}
+
+read_test:
+	if (!(mask & (PM_NFC_TEST_REQ | PM_NFC_TEST_STATUS)))
+		goto get_status_done;
+
+	rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_TEST, &nfc_test);
+	if (rc)
+		pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_test=0x%x)\n",
+		       __func__, rc, nfc_test);
+
+get_status_done:
+	st = nfc_ctrl;
+	st |= nfc_test << 8;
+	*status = st;
+
+	mutex_unlock(&nfcdev->nfc_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(pm8xxx_nfc_get_status);
+
+/*
+ * pm8xxx_nfc_free - free the NFC device
+ */
+void pm8xxx_nfc_free(struct pm8xxx_nfc_device *nfcdev)
+{
+	/* Disable all signals */
+	pm8xxx_nfc_config(nfcdev, PM_NFC_CTRL_REQ, 0);
+}
+EXPORT_SYMBOL(pm8xxx_nfc_free);
+
+#if defined(CONFIG_DEBUG_FS)
+static int pm8xxx_nfc_debug_set(void *data, u64 val)
+{
+	struct pm8xxx_nfc_device *nfcdev;
+	u32	mask, control;
+	int	rc;
+
+	nfcdev = (struct pm8xxx_nfc_device *)data;
+	control = (u32)val & 0xffff;
+	mask = ((u32)val >> 16) & 0xffff;
+	rc = pm8xxx_nfc_config(nfcdev, mask, control);
+	if (rc)
+		pr_err("%s: ERR pm8xxx_nfc_config: rc=%d, "
+		       "[mask, control]=[0x%x, 0x%x]\n",
+		       __func__, rc, mask, control);
+
+	return 0;
+}
+
+static int pm8xxx_nfc_debug_get(void *data, u64 *val)
+{
+	struct pm8xxx_nfc_device *nfcdev;
+	u32	status;
+	int	rc;
+
+	nfcdev = (struct pm8xxx_nfc_device *)data;
+	rc = pm8xxx_nfc_get_status(nfcdev, (u32)-1, &status);
+	if (rc)
+		pr_err("%s: ERR pm8xxx_nfc_get_status: rc=%d, status=0x%x\n",
+		       __func__, rc, status);
+
+	if (val)
+		*val = (u64)status;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm8xxx_nfc_fops, pm8xxx_nfc_debug_get,
+			pm8xxx_nfc_debug_set, "%llu\n");
+
+static int pm8xxx_nfc_debug_init(struct pm8xxx_nfc_device *nfcdev)
+{
+	struct dentry *dent;
+
+	dent = debugfs_create_file("pm8xxx-nfc", 0644, NULL,
+				   (void *)nfcdev, &pm8xxx_nfc_fops);
+
+	if (dent == NULL || IS_ERR(dent))
+		pr_err("%s: ERR debugfs_create_file: dent=0x%x\n",
+		       __func__, (unsigned)dent);
+
+	nfcdev->dent = dent;
+	return 0;
+}
+#endif
+
+static int __devinit pm8xxx_nfc_probe(struct platform_device *pdev)
+{
+	struct pm8xxx_nfc_device	*nfcdev;
+
+	nfcdev = kzalloc(sizeof *nfcdev, GFP_KERNEL);
+	if (nfcdev == NULL) {
+		pr_err("%s: kzalloc() failed.\n", __func__);
+		return -ENOMEM;
+	}
+
+	mutex_init(&nfcdev->nfc_mutex);
+
+	nfcdev->dev = &pdev->dev;
+	nfc_dev = nfcdev;
+	platform_set_drvdata(pdev, nfcdev);
+
+#if defined(CONFIG_DEBUG_FS)
+	pm8xxx_nfc_debug_init(nfc_dev);
+#endif
+
+	pr_notice("%s: OK\n", __func__);
+	return 0;
+}
+
+static int __devexit pm8xxx_nfc_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_nfc_device *nfcdev = platform_get_drvdata(pdev);
+
+#if defined(CONFIG_DEBUG_FS)
+	debugfs_remove(nfcdev->dent);
+#endif
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(nfcdev);
+	return 0;
+}
+
+static struct platform_driver pm8xxx_nfc_driver = {
+	.probe		= pm8xxx_nfc_probe,
+	.remove		= __devexit_p(pm8xxx_nfc_remove),
+	.driver		= {
+		.name = PM8XXX_NFC_DEV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pm8xxx_nfc_init(void)
+{
+	return platform_driver_register(&pm8xxx_nfc_driver);
+}
+
+static void __exit pm8xxx_nfc_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_nfc_driver);
+}
+
+module_init(pm8xxx_nfc_init);
+module_exit(pm8xxx_nfc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PM8XXX NFC driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:" PM8XXX_NFC_DEV_NAME);
diff --git a/drivers/misc/pm8xxx-upl.c b/drivers/misc/pm8xxx-upl.c
new file mode 100644
index 0000000..d3d9746f
--- /dev/null
+++ b/drivers/misc/pm8xxx-upl.c
@@ -0,0 +1,350 @@
+/* Copyright (c) 2010,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.
+ *
+ */
+/*
+ * Qualcomm PM8XXX UPL driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/upl.h>
+
+/* PMIC8XXX UPL registers */
+#define SSBI_REG_UPL_CTRL		0x17B
+#define SSBI_REG_UPL_TRUTHTABLE1	0x17C
+#define SSBI_REG_UPL_TRUTHTABLE2	0x17D
+
+struct pm8xxx_upl_device {
+	struct device		*dev;
+	struct mutex		upl_mutex;
+#if defined(CONFIG_DEBUG_FS)
+	struct dentry		*dent;
+#endif
+};
+static struct pm8xxx_upl_device *upl_dev;
+
+/* APIs */
+
+/*
+ * pm8xxx_upl_request - request a handle to access UPL device
+ */
+struct pm8xxx_upl_device *pm8xxx_upl_request(void)
+{
+	return upl_dev;
+}
+EXPORT_SYMBOL(pm8xxx_upl_request);
+
+/*
+ * pm8xxx_upl_read_truthtable - read value currently stored in UPL truth table
+ *
+ * @upldev: the UPL device
+ * @truthtable: value read from UPL truth table
+ */
+int pm8xxx_upl_read_truthtable(struct pm8xxx_upl_device *upldev,
+				u16 *truthtable)
+{
+	int rc = 0;
+	u8 table[2];
+
+	if (upldev == NULL || IS_ERR(upldev))
+		return -EINVAL;
+
+	mutex_lock(&upldev->upl_mutex);
+
+	rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE1,
+							&(table[0]));
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_readb(0x%X)=0x%02X: rc=%d\n",
+			__func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
+		goto upl_read_done;
+	}
+
+	rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE2,
+							&(table[1]));
+	if (rc)
+		pr_err("%s: FAIL pm8xxx_readb(0x%X)=0x%02X: rc=%d\n",
+			__func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
+upl_read_done:
+	mutex_unlock(&upldev->upl_mutex);
+	*truthtable = (((u16)table[1]) << 8) | table[0];
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_upl_read_truthtable);
+
+/*
+ * pm8xxx_upl_writes_truthtable - write value into UPL truth table
+ *
+ * @upldev: the UPL device
+ * @truthtable: value written to UPL truth table
+ *
+ * Each bit in parameter "truthtable" corresponds to the UPL output for a given
+ * set of input pin values. For example, if the input pins have the following
+ * values: A=1, B=1, C=1, D=0, then the UPL would output the value of bit 14
+ * (0b1110) in parameter "truthtable".
+ */
+int pm8xxx_upl_write_truthtable(struct pm8xxx_upl_device *upldev,
+				u16 truthtable)
+{
+	int rc = 0;
+	u8 table[2];
+
+	if (upldev == NULL || IS_ERR(upldev))
+		return -EINVAL;
+
+	table[0] = truthtable & 0xFF;
+	table[1] = (truthtable >> 8) & 0xFF;
+
+	mutex_lock(&upldev->upl_mutex);
+
+	rc = pm8xxx_writeb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE1,
+								table[0]);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_writeb(0x%X)=0x%04X: rc=%d\n",
+			__func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
+		goto upl_write_done;
+	}
+
+	rc = pm8xxx_writeb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE2,
+								table[1]);
+	if (rc)
+		pr_err("%s: FAIL pm8xxx_writeb(0x%X)=0x%04X: rc=%d\n",
+			__func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
+upl_write_done:
+	mutex_unlock(&upldev->upl_mutex);
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_upl_write_truthtable);
+
+/*
+ * pm8xxx_upl_config - configure UPL I/O settings and UPL enable/disable
+ *
+ * @upldev: the UPL device
+ * @mask: setting mask to configure
+ * @flags: setting flags
+ */
+int pm8xxx_upl_config(struct pm8xxx_upl_device *upldev, u32 mask, u32 flags)
+{
+	int rc;
+	u8 upl_ctrl, m, f;
+
+	if (upldev == NULL || IS_ERR(upldev))
+		return -EINVAL;
+
+	mutex_lock(&upldev->upl_mutex);
+
+	rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_CTRL, &upl_ctrl);
+	if (rc) {
+		pr_err("%s: FAIL pm8xxx_readb(0x%X)=0x%02X: rc=%d\n",
+			__func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
+		goto upl_config_done;
+	}
+
+	m = mask & 0x00ff;
+	f = flags & 0x00ff;
+	upl_ctrl &= ~m;
+	upl_ctrl |= m & f;
+
+	rc = pm8xxx_writeb(upldev->dev->parent, SSBI_REG_UPL_CTRL, upl_ctrl);
+	if (rc)
+		pr_err("%s: FAIL pm8xxx_writeb(0x%X)=0x%02X: rc=%d\n",
+			__func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
+upl_config_done:
+	mutex_unlock(&upldev->upl_mutex);
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_upl_config);
+
+#if defined(CONFIG_DEBUG_FS)
+
+static int truthtable_set(void *data, u64 val)
+{
+	int rc;
+
+	rc = pm8xxx_upl_write_truthtable(data, val);
+	if (rc)
+		pr_err("%s: pm8xxx_upl_write_truthtable: rc=%d, "
+			"truthtable=0x%llX\n", __func__, rc, val);
+	return rc;
+}
+
+static int truthtable_get(void *data, u64 *val)
+{
+	int rc;
+	u16 truthtable;
+
+	rc = pm8xxx_upl_read_truthtable(data, &truthtable);
+	if (rc)
+		pr_err("%s: pm8xxx_upl_read_truthtable: rc=%d, "
+			"truthtable=0x%X\n", __func__, rc, truthtable);
+	if (val)
+		*val = truthtable;
+
+	return rc;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(upl_truthtable_fops, truthtable_get,
+			truthtable_set, "0x%04llX\n");
+
+/* enter values as 0xMMMMFFFF where MMMM is the mask and FFFF is the flags */
+static int control_set(void *data, u64 val)
+{
+	u8 mask, flags;
+	int rc;
+
+	flags = val & 0xFFFF;
+	mask = (val >> 16) & 0xFFFF;
+
+	rc = pm8xxx_upl_config(data, mask, flags);
+	if (rc)
+		pr_err("%s: pm8xxx_upl_config: rc=%d, mask = 0x%X, "
+			"flags = 0x%X\n", __func__, rc, mask, flags);
+	return rc;
+}
+
+static int control_get(void *data, u64 *val)
+{
+	struct pm8xxx_upl_device *upldev;
+	int rc = 0;
+	u8 ctrl;
+
+	upldev = data;
+
+	mutex_lock(&upldev->upl_mutex);
+
+	rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_CTRL, &ctrl);
+	if (rc)
+		pr_err("%s: FAIL pm8xxx_readb(): rc=%d (ctrl=0x%02X)\n",
+		       __func__, rc, ctrl);
+
+	mutex_unlock(&upldev->upl_mutex);
+
+	*val = ctrl;
+
+	return rc;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(upl_control_fops, control_get,
+			control_set, "0x%02llX\n");
+
+static int pm8xxx_upl_debug_init(struct pm8xxx_upl_device *upldev)
+{
+	struct dentry *dent;
+	struct dentry *temp;
+
+	dent = debugfs_create_dir("pm8xxx-upl", NULL);
+	if (dent == NULL || IS_ERR(dent)) {
+		pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
+					__func__, (unsigned)dent);
+		return -ENOMEM;
+	}
+
+	temp = debugfs_create_file("truthtable", S_IRUSR | S_IWUSR, dent,
+					upldev, &upl_truthtable_fops);
+	if (temp == NULL || IS_ERR(temp)) {
+		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
+					__func__, (unsigned)dent);
+		goto debug_error;
+	}
+
+	temp = debugfs_create_file("control", S_IRUSR | S_IWUSR, dent,
+					upldev, &upl_control_fops);
+	if (temp == NULL || IS_ERR(temp)) {
+		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
+					__func__, (unsigned)dent);
+		goto debug_error;
+	}
+
+	upldev->dent = dent;
+	return 0;
+
+debug_error:
+	debugfs_remove_recursive(dent);
+	return -ENOMEM;
+}
+
+static int __devexit pm8xxx_upl_debug_remove(struct pm8xxx_upl_device *upldev)
+{
+	debugfs_remove_recursive(upldev->dent);
+	return 0;
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
+static int __devinit pm8xxx_upl_probe(struct platform_device *pdev)
+{
+	struct pm8xxx_upl_device	*upldev;
+
+	upldev = kzalloc(sizeof *upldev, GFP_KERNEL);
+	if (upldev == NULL) {
+		pr_err("%s: kzalloc() failed.\n", __func__);
+		return -ENOMEM;
+	}
+
+	mutex_init(&upldev->upl_mutex);
+
+	upl_dev = upldev;
+	upldev->dev = &pdev->dev;
+	platform_set_drvdata(pdev, upldev);
+
+#if defined(CONFIG_DEBUG_FS)
+	pm8xxx_upl_debug_init(upl_dev);
+#endif
+	pr_notice("%s: OK\n", __func__);
+	return 0;
+}
+
+static int __devexit pm8xxx_upl_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_upl_device *upldev = platform_get_drvdata(pdev);
+
+#if defined(CONFIG_DEBUG_FS)
+	pm8xxx_upl_debug_remove(upldev);
+#endif
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(upldev);
+	pr_notice("%s: OK\n", __func__);
+
+	return 0;
+}
+
+static struct platform_driver pm8xxx_upl_driver = {
+	.probe		= pm8xxx_upl_probe,
+	.remove		= __devexit_p(pm8xxx_upl_remove),
+	.driver		= {
+		.name = PM8XXX_UPL_DEV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pm8xxx_upl_init(void)
+{
+	return platform_driver_register(&pm8xxx_upl_driver);
+}
+
+static void __exit pm8xxx_upl_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_upl_driver);
+}
+
+module_init(pm8xxx_upl_init);
+module_exit(pm8xxx_upl_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PM8XXX UPL driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:" PM8XXX_UPL_DEV_NAME);
diff --git a/drivers/misc/pm8xxx-vibrator.c b/drivers/misc/pm8xxx-vibrator.c
index 8aa7f72..4f22efe 100644
--- a/drivers/misc/pm8xxx-vibrator.c
+++ b/drivers/misc/pm8xxx-vibrator.c
@@ -27,6 +27,7 @@
 #define VIB_DRV_SEL_MASK	0xf8
 #define VIB_DRV_SEL_SHIFT	0x03
 #define VIB_DRV_EN_MANUAL_MASK	0xfc
+#define VIB_DRV_LOGIC_SHIFT	0x2
 
 #define VIB_MAX_LEVEL_mV	3100
 #define VIB_MIN_LEVEL_mV	1200
@@ -43,6 +44,40 @@
 	u8  reg_vib_drv;
 };
 
+static struct pm8xxx_vib *vib_dev;
+
+int pm8xxx_vibrator_config(struct pm8xxx_vib_config *vib_config)
+{
+	u8 reg = 0;
+	int rc;
+
+	if (vib_dev == NULL) {
+		pr_err("%s: vib_dev is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (vib_config->drive_mV) {
+		if ((vib_config->drive_mV < VIB_MIN_LEVEL_mV) ||
+			(vib_config->drive_mV > VIB_MAX_LEVEL_mV)) {
+			pr_err("Invalid vibrator drive strength\n");
+			return -EINVAL;
+		}
+	}
+
+	reg = (vib_config->drive_mV / 100) << VIB_DRV_SEL_SHIFT;
+
+	reg |= (!!vib_config->active_low) << VIB_DRV_LOGIC_SHIFT;
+
+	reg |= vib_config->enable_mode;
+
+	rc = pm8xxx_writeb(vib_dev->dev->parent, VIB_DRV, reg);
+	if (rc)
+		pr_err("%s: pm8xxx write failed: rc=%d\n", __func__, rc);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_vibrator_config);
+
 /* REVISIT: just for debugging, will be removed in final working version */
 static void __dump_vib_regs(struct pm8xxx_vib *vib, char *msg)
 {
@@ -240,6 +275,8 @@
 
 	platform_set_drvdata(pdev, vib);
 
+	vib_dev = vib;
+
 	return 0;
 
 err_read_vib:
diff --git a/drivers/misc/pmic8058-nfc.c b/drivers/misc/pmic8058-nfc.c
deleted file mode 100644
index 76a19f4..0000000
--- a/drivers/misc/pmic8058-nfc.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/* Copyright (c) 2010, 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.
- *
- */
-/*
- * Qualcomm PMIC8058 NFC driver
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/mfd/pmic8058.h>
-#include <linux/pmic8058-nfc.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-
-/* PMIC8058 NFC */
-#define	SSBI_REG_NFC_CTRL	0x14D
-#define	SSBI_REG_NFC_TEST	0x14E
-
-/* NFC_CTRL */
-#define	PM8058_NFC_SUPPORT_EN		0x80
-#define	PM8058_NFC_LDO_EN		0x40
-#define	PM8058_NFC_EN			0x20
-#define	PM8058_NFC_EXT_VDDLDO_EN	0x10
-#define	PM8058_NFC_VPH_PWR_EN		0x08
-#define	PM8058_NFC_RESERVED		0x04
-#define	PM8058_NFC_VDDLDO_LEVEL		0x03
-
-/* NFC_TEST */
-#define	PM8058_NFC_VDDLDO_MON_EN	0x80
-#define	PM8058_NFC_ATEST_EN		0x40
-#define	PM8058_NFC_DTEST1_EN		0x20
-#define	PM8058_NFC_RESERVED2		0x18
-#define	PM8058_NFC_VDDLDO_OK_S		0x04
-#define	PM8058_NFC_MBG_EN_S		0x02
-#define	PM8058_NFC_EXT_EN_S		0x01
-
-struct pm8058_nfc_device {
-	struct mutex		nfc_mutex;
-	struct pm8058_chip	*pm_chip;
-#if defined(CONFIG_DEBUG_FS)
-	struct dentry 		*dent;
-#endif
-};
-static struct pm8058_nfc_device	*nfc_dev;
-
-/* APIs */
-/*
- * pm8058_nfc_request - request a handle to access NFC device
- */
-struct pm8058_nfc_device *pm8058_nfc_request(void)
-{
-	return nfc_dev;
-}
-EXPORT_SYMBOL(pm8058_nfc_request);
-
-/*
- * pm8058_nfc_config - configure NFC signals
- *
- * @nfcdev: the NFC device
- * @mask: signal mask to configure
- * @flags: control flags
- */
-int pm8058_nfc_config(struct pm8058_nfc_device *nfcdev, u32 mask, u32 flags)
-{
-	u8	nfc_ctrl, nfc_test, m, f;
-	int	rc;
-
-	if (nfcdev == NULL || IS_ERR(nfcdev) || !mask)
-		return -EINVAL;
-	if (nfcdev->pm_chip == NULL)
-		return -ENODEV;
-
-	mutex_lock(&nfcdev->nfc_mutex);
-
-	if (!(mask & PM_NFC_CTRL_REQ))
-		goto config_test;
-
-	rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_CTRL, &nfc_ctrl, 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_ctrl=0x%x)\n",
-		       __func__, rc, nfc_ctrl);
-		goto config_done;
-	}
-
-	m = mask & 0x00ff;
-	f = flags & 0x00ff;
-	nfc_ctrl &= ~m;
-	nfc_ctrl |= m & f;
-
-	rc = pm8058_write(nfcdev->pm_chip, SSBI_REG_NFC_CTRL, &nfc_ctrl, 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_write(): rc=%d (nfc_ctrl=0x%x)\n",
-		       __func__, rc, nfc_ctrl);
-		goto config_done;
-	}
-
-config_test:
-	if (!(mask & PM_NFC_TEST_REQ))
-		goto config_done;
-
-	rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_TEST, &nfc_test, 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_test=0x%x)\n",
-		       __func__, rc, nfc_test);
-		goto config_done;
-	}
-
-	m = (mask >> 8) & 0x00ff;
-	f = (flags >> 8) & 0x00ff;
-	nfc_test &= ~m;
-	nfc_test |= m & f;
-
-	rc = pm8058_write(nfcdev->pm_chip, SSBI_REG_NFC_TEST, &nfc_test, 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_write(): rc=%d (nfc_test=0x%x)\n",
-		       __func__, rc, nfc_test);
-		goto config_done;
-	}
-
-config_done:
-	mutex_unlock(&nfcdev->nfc_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(pm8058_nfc_config);
-
-/*
- * pm8058_nfc_get_status - get NFC status
- *
- * @nfcdev: the NFC device
- * @mask: of status mask to read
- * @status: pointer to the status variable
- */
-int pm8058_nfc_get_status(struct pm8058_nfc_device *nfcdev,
-			  u32 mask, u32 *status)
-{
-	u8	nfc_ctrl, nfc_test;
-	u32	st;
-	int	rc;
-
-	if (nfcdev == NULL || IS_ERR(nfcdev) || status == NULL)
-		return -EINVAL;
-	if (nfcdev->pm_chip == NULL)
-		return -ENODEV;
-
-	st = 0;
-	mutex_lock(&nfcdev->nfc_mutex);
-
-	if (!(mask & PM_NFC_CTRL_REQ))
-		goto read_test;
-
-	rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_CTRL, &nfc_ctrl, 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_ctrl=0x%x)\n",
-		       __func__, rc, nfc_ctrl);
-		goto get_status_done;
-	}
-
-read_test:
-	if (!(mask & (PM_NFC_TEST_REQ | PM_NFC_TEST_STATUS)))
-		goto get_status_done;
-
-	rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_TEST, &nfc_test, 1);
-	if (rc)
-		pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_test=0x%x)\n",
-		       __func__, rc, nfc_test);
-
-get_status_done:
-	st = nfc_ctrl;
-	st |= nfc_test << 8;
-	*status = st;
-
-	mutex_unlock(&nfcdev->nfc_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(pm8058_nfc_get_status);
-
-/*
- * pm8058_nfc_free - free the NFC device
- */
-void pm8058_nfc_free(struct pm8058_nfc_device *nfcdev)
-{
-	/* Disable all signals */
-	pm8058_nfc_config(nfcdev, PM_NFC_CTRL_REQ, 0);
-}
-EXPORT_SYMBOL(pm8058_nfc_free);
-
-#if defined(CONFIG_DEBUG_FS)
-static int pm8058_nfc_debug_set(void *data, u64 val)
-{
-	struct pm8058_nfc_device *nfcdev;
-	u32	mask, control;
-	int	rc;
-
-	nfcdev = (struct pm8058_nfc_device *)data;
-	control = (u32)val & 0xffff;
-	mask = ((u32)val >> 16) & 0xffff;
-	rc = pm8058_nfc_config(nfcdev, mask, control);
-	if (rc)
-		pr_err("%s: ERR pm8058_nfc_config: rc=%d, "
-		       "[mask, control]=[0x%x, 0x%x]\n",
-		       __func__, rc, mask, control);
-
-	return 0;
-}
-
-static int pm8058_nfc_debug_get(void *data, u64 *val)
-{
-	struct pm8058_nfc_device *nfcdev;
-	u32	status;
-	int	rc;
-
-	nfcdev = (struct pm8058_nfc_device *)data;
-	rc = pm8058_nfc_get_status(nfcdev, (u32)-1, &status);
-	if (rc)
-		pr_err("%s: ERR pm8058_nfc_get_status: rc=%d, status=0x%x\n",
-		       __func__, rc, status);
-
-	if (val)
-		*val = (u64)status;
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(pm8058_nfc_fops, pm8058_nfc_debug_get,
-			pm8058_nfc_debug_set, "%llu\n");
-
-static int pm8058_nfc_debug_init(struct pm8058_nfc_device *nfcdev)
-{
-	struct dentry *dent;
-
-	dent = debugfs_create_file("pm8058-nfc", 0644, NULL,
-				   (void *)nfcdev, &pm8058_nfc_fops);
-
-	if (dent == NULL || IS_ERR(dent))
-		pr_err("%s: ERR debugfs_create_file: dent=0x%x\n",
-		       __func__, (unsigned)dent);
-
-	nfcdev->dent = dent;
-	return 0;
-}
-#endif
-
-static int __devinit pmic8058_nfc_probe(struct platform_device *pdev)
-{
-	struct pm8058_chip		*pm_chip;
-	struct pm8058_nfc_device	*nfcdev;
-
-	pm_chip = dev_get_drvdata(pdev->dev.parent);
-	if (pm_chip == NULL) {
-		pr_err("%s: no parent data passed in.\n", __func__);
-		return -EFAULT;
-	}
-
-	nfcdev = kzalloc(sizeof *nfcdev, GFP_KERNEL);
-	if (nfcdev == NULL) {
-		pr_err("%s: kzalloc() failed.\n", __func__);
-		return -ENOMEM;
-	}
-
-	mutex_init(&nfcdev->nfc_mutex);
-
-	nfcdev->pm_chip = pm_chip;
-	nfc_dev = nfcdev;
-	platform_set_drvdata(pdev, nfcdev);
-
-#if defined(CONFIG_DEBUG_FS)
-	pm8058_nfc_debug_init(nfc_dev);
-#endif
-
-	pr_notice("%s: OK\n", __func__);
-	return 0;
-}
-
-static int __devexit pmic8058_nfc_remove(struct platform_device *pdev)
-{
-	struct pm8058_nfc_device *nfcdev = platform_get_drvdata(pdev);
-
-#if defined(CONFIG_DEBUG_FS)
-	debugfs_remove(nfcdev->dent);
-#endif
-
-	platform_set_drvdata(pdev, nfcdev->pm_chip);
-	kfree(nfcdev);
-	return 0;
-}
-
-static struct platform_driver pmic8058_nfc_driver = {
-	.probe		= pmic8058_nfc_probe,
-	.remove		= __devexit_p(pmic8058_nfc_remove),
-	.driver		= {
-		.name = "pm8058-nfc",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init pm8058_nfc_init(void)
-{
-	return platform_driver_register(&pmic8058_nfc_driver);
-}
-
-static void __exit pm8058_nfc_exit(void)
-{
-	platform_driver_unregister(&pmic8058_nfc_driver);
-}
-
-module_init(pm8058_nfc_init);
-module_exit(pm8058_nfc_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("PMIC8058 NFC driver");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:pmic8058-nfc");
diff --git a/drivers/misc/pmic8058-pwm.c b/drivers/misc/pmic8058-pwm.c
index ad03b88..33407b7 100644
--- a/drivers/misc/pmic8058-pwm.c
+++ b/drivers/misc/pmic8058-pwm.c
@@ -19,11 +19,11 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/pwm.h>
-#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/pmic8058-pwm.h>
-#include <linux/slab.h>
 
 #define	PM8058_LPG_BANKS		8
 #define	PM8058_PWM_CHANNELS		PM8058_LPG_BANKS	/* MAX=8 */
@@ -179,6 +179,7 @@
 struct pm8058_pwm_chip;
 
 struct pwm_device {
+	struct device		*dev;
 	int			pwm_id;		/* = bank/channel id */
 	int			in_use;
 	const char		*label;
@@ -188,14 +189,13 @@
 	int			use_lut;	/* Use LUT to output PWM */
 	u8			pwm_ctl[PM8058_LPG_CTL_REGS];
 	int			irq;
-	struct pm8058_pwm_chip	*chip;
+	struct pm8058_pwm_chip  *chip;
 };
 
 struct pm8058_pwm_chip {
 	struct pwm_device	pwm_dev[PM8058_PWM_CHANNELS];
 	u8			bank_mask;
 	struct mutex		pwm_mutex;
-	struct pm8058_chip	*pm_chip;
 	struct pm8058_pwm_pdata	*pdata;
 };
 
@@ -244,9 +244,10 @@
 	else
 		reg = chip->bank_mask & ~(1 << pwm->pwm_id);
 
-	rc = pm8058_write(chip->pm_chip, SSBI_REG_ADDR_LPG_BANK_EN, &reg, 1);
+	rc = pm8xxx_writeb(pwm->dev->parent,
+				SSBI_REG_ADDR_LPG_BANK_EN, reg);
 	if (rc) {
-		pr_err("pm8058_write(): rc=%d (Enable LPG Bank)\n", rc);
+		pr_err("pm8xxx_write(): rc=%d (Enable LPG Bank)\n", rc);
 		goto bail_out;
 	}
 	chip->bank_mask = reg;
@@ -261,10 +262,10 @@
 	u8	reg;
 
 	reg = pwm->pwm_id;
-	rc = pm8058_write(pwm->chip->pm_chip, SSBI_REG_ADDR_LPG_BANK_SEL,
-			     &reg, 1);
+	rc = pm8xxx_writeb(pwm->dev->parent,
+			SSBI_REG_ADDR_LPG_BANK_SEL, reg);
 	if (rc)
-		pr_err("pm8058_write(): rc=%d (Select PWM Bank)\n", rc);
+		pr_err("pm8xxx_write(): rc=%d (Select PWM Bank)\n", rc);
 	return rc;
 }
 
@@ -284,10 +285,10 @@
 		reg &= ~PM8058_PWM_RAMP_GEN_START;
 	}
 
-	rc = pm8058_write(pwm->chip->pm_chip, SSBI_REG_ADDR_LPG_CTL(0),
-			  &reg, 1);
+	rc = pm8xxx_writeb(pwm->dev->parent, SSBI_REG_ADDR_LPG_CTL(0),
+									reg);
 	if (rc)
-		pr_err("pm8058_write(): rc=%d (Enable PWM Ctl 0)\n", rc);
+		pr_err("pm8xxx_write(): rc=%d (Enable PWM Ctl 0)\n", rc);
 	else
 		pwm->pwm_ctl[0] = reg;
 	return rc;
@@ -415,15 +416,13 @@
 		cfg1 = (pwm_value >> 1) & 0x80;
 		cfg1 |= start_idx + i;
 
-		rc = pm8058_write(pwm->chip->pm_chip,
-			     SSBI_REG_ADDR_LPG_LUT_CFG0,
-			     &cfg0, 1);
+		rc = pm8xxx_writeb(pwm->dev->parent,
+			     SSBI_REG_ADDR_LPG_LUT_CFG0, cfg0);
 		if (rc)
 			break;
 
-		rc = pm8058_write(pwm->chip->pm_chip,
-			     SSBI_REG_ADDR_LPG_LUT_CFG1,
-			     &cfg1, 1);
+		rc = pm8xxx_writeb(pwm->dev->parent,
+			     SSBI_REG_ADDR_LPG_LUT_CFG1, cfg1);
 		if (rc)
 			break;
 	}
@@ -539,11 +538,11 @@
 
 	/* Write in reverse way so 0 would be the last */
 	for (i = end - 1; i >= start; i--) {
-		rc = pm8058_write(pwm->chip->pm_chip,
+		rc = pm8xxx_writeb(pwm->dev->parent,
 				  SSBI_REG_ADDR_LPG_CTL(i),
-				  &pwm->pwm_ctl[i], 1);
+				  pwm->pwm_ctl[i]);
 		if (rc) {
-			pr_err("pm8058_write(): rc=%d (PWM Ctl[%d])\n", rc, i);
+			pr_err("pm8xxx_write(): rc=%d (PWM Ctl[%d])\n", rc, i);
 			return rc;
 		}
 	}
@@ -957,8 +956,8 @@
 	case PM_PWM_LED_2:
 		conf = mode & PM8058_LED_MODE_MASK;
 		conf |= (max_current / 2) << PM8058_LED_CURRENT_SHIFT;
-		rc = pm8058_write(pwm->chip->pm_chip,
-				  SSBI_REG_ADDR_LED(id), &conf, 1);
+		rc = pm8xxx_writeb(pwm->dev->parent,
+				  SSBI_REG_ADDR_LED(id), conf);
 		break;
 
 	case PM_PWM_LED_KPD:
@@ -982,8 +981,8 @@
 		}
 		conf |= (max_current / 20) << PM8058_FLASH_CURRENT_SHIFT;
 		id -= PM_PWM_LED_KPD;
-		rc = pm8058_write(pwm->chip->pm_chip,
-				  SSBI_REG_ADDR_FLASH(id), &conf, 1);
+		rc = pm8xxx_writeb(pwm->dev->parent,
+				  SSBI_REG_ADDR_FLASH(id), conf);
 		break;
 	default:
 		rc = -EINVAL;
@@ -1012,10 +1011,10 @@
 			/* Only Test 1 available */
 			reg |= (1 << PM8058_PWM_DTEST_SHIFT) &
 				PM8058_PWM_DTEST_MASK;
-		rc = pm8058_write(pwm->chip->pm_chip, SSBI_REG_ADDR_LPG_TEST,
-				  &reg, 1);
+		rc = pm8xxx_writeb(pwm->dev->parent,
+			SSBI_REG_ADDR_LPG_TEST, reg);
 		if (rc)
-			pr_err("pm8058_write(DTEST=0x%x): rc=%d\n", reg, rc);
+			pr_err("pm8xxx_write(DTEST=0x%x): rc=%d\n", reg, rc);
 
 	}
 	return rc;
@@ -1024,16 +1023,9 @@
 
 static int __devinit pmic8058_pwm_probe(struct platform_device *pdev)
 {
-	struct pm8058_chip	*pm_chip;
 	struct pm8058_pwm_chip	*chip;
 	int	i;
 
-	pm_chip = dev_get_drvdata(pdev->dev.parent);
-	if (pm_chip == NULL) {
-		pr_err("no parent data passed in.\n");
-		return -EFAULT;
-	}
-
 	chip = kzalloc(sizeof *chip, GFP_KERNEL);
 	if (chip == NULL) {
 		pr_err("kzalloc() failed.\n");
@@ -1043,12 +1035,12 @@
 	for (i = 0; i < PM8058_PWM_CHANNELS; i++) {
 		chip->pwm_dev[i].pwm_id = i;
 		chip->pwm_dev[i].chip = chip;
+		chip->pwm_dev[i].dev = &pdev->dev;
 	}
 
 	mutex_init(&chip->pwm_mutex);
 
 	chip->pdata = pdev->dev.platform_data;
-	chip->pm_chip = pm_chip;
 	pwm_chip = chip;
 	platform_set_drvdata(pdev, chip);
 
diff --git a/drivers/misc/pmic8058-upl.c b/drivers/misc/pmic8058-upl.c
deleted file mode 100644
index ae0abd8..0000000
--- a/drivers/misc/pmic8058-upl.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/* Copyright (c) 2010, 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.
- *
- */
-/*
- * Qualcomm PMIC8058 UPL driver
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/mfd/pmic8058.h>
-#include <linux/pmic8058-upl.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-
-/* PMIC8058 UPL registers */
-#define	SSBI_REG_UPL_CTRL		0x17B
-#define	SSBI_REG_UPL_TRUTHTABLE1	0x17C
-#define	SSBI_REG_UPL_TRUTHTABLE2	0x17D
-
-struct pm8058_upl_device {
-	struct mutex		upl_mutex;
-	struct pm8058_chip	*pm_chip;
-#if defined(CONFIG_DEBUG_FS)
-	struct dentry		*dent;
-#endif
-};
-static struct pm8058_upl_device *upl_dev;
-
-/* APIs */
-
-/*
- * pm8058_upl_request - request a handle to access UPL device
- */
-struct pm8058_upl_device *pm8058_upl_request(void)
-{
-	return upl_dev;
-}
-EXPORT_SYMBOL(pm8058_upl_request);
-
-/*
- * pm8058_upl_read_truthtable - read value currently stored in UPL truth table
- *
- * @upldev: the UPL device
- * @truthtable: value read from UPL truth table
- */
-int pm8058_upl_read_truthtable(struct pm8058_upl_device *upldev,
-				u16 *truthtable)
-{
-	int rc = 0;
-	u8 table[2];
-
-	if (upldev == NULL || IS_ERR(upldev))
-		return -EINVAL;
-	if (upldev->pm_chip == NULL)
-		return -ENODEV;
-
-	mutex_lock(&upldev->upl_mutex);
-
-	rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE1,
-			&(table[0]), 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_read(0x%X)=0x%02X: rc=%d\n",
-			__func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
-		goto upl_read_done;
-	}
-
-	rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE2,
-			&(table[1]), 1);
-	if (rc)
-		pr_err("%s: FAIL pm8058_read(0x%X)=0x%02X: rc=%d\n",
-			__func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
-upl_read_done:
-	mutex_unlock(&upldev->upl_mutex);
-	*truthtable = (((u16)table[1]) << 8) | table[0];
-	return rc;
-}
-EXPORT_SYMBOL(pm8058_upl_read_truthtable);
-
-/*
- * pm8058_upl_writes_truthtable - write value into UPL truth table
- *
- * @upldev: the UPL device
- * @truthtable: value written to UPL truth table
- *
- * Each bit in parameter "truthtable" corresponds to the UPL output for a given
- * set of input pin values. For example, if the input pins have the following
- * values: A=1, B=1, C=1, D=0, then the UPL would output the value of bit 14
- * (0b1110) in parameter "truthtable".
- */
-int pm8058_upl_write_truthtable(struct pm8058_upl_device *upldev,
-				u16 truthtable)
-{
-	int rc = 0;
-	u8 table[2];
-
-	if (upldev == NULL || IS_ERR(upldev))
-		return -EINVAL;
-	if (upldev->pm_chip == NULL)
-		return -ENODEV;
-
-	table[0] = truthtable & 0xFF;
-	table[1] = (truthtable >> 8) & 0xFF;
-
-	mutex_lock(&upldev->upl_mutex);
-
-	rc = pm8058_write(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE1,
-				&(table[0]), 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_write(0x%X)=0x%04X: rc=%d\n",
-			__func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
-		goto upl_write_done;
-	}
-
-	rc = pm8058_write(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE2,
-				&(table[1]), 1);
-	if (rc)
-		pr_err("%s: FAIL pm8058_write(0x%X)=0x%04X: rc=%d\n",
-			__func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
-upl_write_done:
-	mutex_unlock(&upldev->upl_mutex);
-	return rc;
-}
-EXPORT_SYMBOL(pm8058_upl_write_truthtable);
-
-/*
- * pm8058_upl_config - configure UPL I/O settings and UPL enable/disable
- *
- * @upldev: the UPL device
- * @mask: setting mask to configure
- * @flags: setting flags
- */
-int pm8058_upl_config(struct pm8058_upl_device *upldev, u32 mask, u32 flags)
-{
-	int rc;
-	u8 upl_ctrl, m, f;
-
-	if (upldev == NULL || IS_ERR(upldev))
-		return -EINVAL;
-	if (upldev->pm_chip == NULL)
-		return -ENODEV;
-
-	mutex_lock(&upldev->upl_mutex);
-
-	rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_CTRL, &upl_ctrl, 1);
-	if (rc) {
-		pr_err("%s: FAIL pm8058_read(0x%X)=0x%02X: rc=%d\n",
-			__func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
-		goto upl_config_done;
-	}
-
-	m = mask & 0x00ff;
-	f = flags & 0x00ff;
-	upl_ctrl &= ~m;
-	upl_ctrl |= m & f;
-
-	rc = pm8058_write(upldev->pm_chip, SSBI_REG_UPL_CTRL, &upl_ctrl, 1);
-	if (rc)
-		pr_err("%s: FAIL pm8058_write(0x%X)=0x%02X: rc=%d\n",
-			__func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
-upl_config_done:
-	mutex_unlock(&upldev->upl_mutex);
-	return rc;
-}
-EXPORT_SYMBOL(pm8058_upl_config);
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int truthtable_set(void *data, u64 val)
-{
-	int rc;
-
-	rc = pm8058_upl_write_truthtable(data, val);
-	if (rc)
-		pr_err("%s: pm8058_upl_write_truthtable: rc=%d, "
-			"truthtable=0x%llX\n", __func__, rc, val);
-	return rc;
-}
-
-static int truthtable_get(void *data, u64 *val)
-{
-	int rc;
-	u16 truthtable;
-
-	rc = pm8058_upl_read_truthtable(data, &truthtable);
-	if (rc)
-		pr_err("%s: pm8058_upl_read_truthtable: rc=%d, "
-			"truthtable=0x%X\n", __func__, rc, truthtable);
-	if (val)
-		*val = truthtable;
-
-	return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(upl_truthtable_fops, truthtable_get,
-			truthtable_set, "0x%04llX\n");
-
-/* enter values as 0xMMMMFFFF where MMMM is the mask and FFFF is the flags */
-static int control_set(void *data, u64 val)
-{
-	u8 mask, flags;
-	int rc;
-
-	flags = val & 0xFFFF;
-	mask = (val >> 16) & 0xFFFF;
-
-	rc = pm8058_upl_config(data, mask, flags);
-	if (rc)
-		pr_err("%s: pm8058_upl_config: rc=%d, mask = 0x%X, "
-			"flags = 0x%X\n", __func__, rc, mask, flags);
-	return rc;
-}
-
-static int control_get(void *data, u64 *val)
-{
-	struct pm8058_upl_device *upldev;
-	int rc = 0;
-	u8 ctrl;
-
-	upldev = data;
-
-	mutex_lock(&upldev->upl_mutex);
-
-	rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_CTRL, &ctrl, 1);
-	if (rc)
-		pr_err("%s: FAIL pm8058_read(): rc=%d (ctrl=0x%02X)\n",
-		       __func__, rc, ctrl);
-
-	mutex_unlock(&upldev->upl_mutex);
-
-	*val = ctrl;
-
-	return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(upl_control_fops, control_get,
-			control_set, "0x%02llX\n");
-
-static int pm8058_upl_debug_init(struct pm8058_upl_device *upldev)
-{
-	struct dentry *dent;
-	struct dentry *temp;
-
-	dent = debugfs_create_dir("pm8058-upl", NULL);
-	if (dent == NULL || IS_ERR(dent)) {
-		pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
-					__func__, (unsigned)dent);
-		return -ENOMEM;
-	}
-
-	temp = debugfs_create_file("truthtable", S_IRUSR | S_IWUSR, dent,
-					upldev, &upl_truthtable_fops);
-	if (temp == NULL || IS_ERR(temp)) {
-		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
-					__func__, (unsigned)dent);
-		goto debug_error;
-	}
-
-	temp = debugfs_create_file("control", S_IRUSR | S_IWUSR, dent,
-					upldev, &upl_control_fops);
-	if (temp == NULL || IS_ERR(temp)) {
-		pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
-					__func__, (unsigned)dent);
-		goto debug_error;
-	}
-
-	upldev->dent = dent;
-	return 0;
-
-debug_error:
-	debugfs_remove_recursive(dent);
-	return -ENOMEM;
-}
-
-static int __devexit pm8058_upl_debug_remove(struct pm8058_upl_device *upldev)
-{
-	debugfs_remove_recursive(upldev->dent);
-	return 0;
-}
-
-#endif /* CONFIG_DEBUG_FS */
-
-static int __devinit pmic8058_upl_probe(struct platform_device *pdev)
-{
-	struct pm8058_chip		*pm_chip;
-	struct pm8058_upl_device	*upldev;
-
-	pm_chip = dev_get_drvdata(pdev->dev.parent);
-	if (pm_chip == NULL) {
-		pr_err("%s: no parent data passed in.\n", __func__);
-		return -EFAULT;
-	}
-
-	upldev = kzalloc(sizeof *upldev, GFP_KERNEL);
-	if (upldev == NULL) {
-		pr_err("%s: kzalloc() failed.\n", __func__);
-		return -ENOMEM;
-	}
-
-	mutex_init(&upldev->upl_mutex);
-
-	upldev->pm_chip = pm_chip;
-	upl_dev = upldev;
-	platform_set_drvdata(pdev, upldev);
-
-#if defined(CONFIG_DEBUG_FS)
-	pm8058_upl_debug_init(upl_dev);
-#endif
-	pr_notice("%s: OK\n", __func__);
-	return 0;
-}
-
-static int __devexit pmic8058_upl_remove(struct platform_device *pdev)
-{
-	struct pm8058_upl_device *upldev = platform_get_drvdata(pdev);
-
-#if defined(CONFIG_DEBUG_FS)
-	pm8058_upl_debug_remove(upldev);
-#endif
-
-	platform_set_drvdata(pdev, upldev->pm_chip);
-	kfree(upldev);
-	pr_notice("%s: OK\n", __func__);
-
-	return 0;
-}
-
-static struct platform_driver pmic8058_upl_driver = {
-	.probe		= pmic8058_upl_probe,
-	.remove		= __devexit_p(pmic8058_upl_remove),
-	.driver		= {
-		.name = "pm8058-upl",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init pm8058_upl_init(void)
-{
-	return platform_driver_register(&pmic8058_upl_driver);
-}
-
-static void __exit pm8058_upl_exit(void)
-{
-	platform_driver_unregister(&pmic8058_upl_driver);
-}
-
-module_init(pm8058_upl_init);
-module_exit(pm8058_upl_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("PMIC8058 UPL driver");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:pmic8058-upl");
diff --git a/drivers/misc/pmic8058-xoadc.c b/drivers/misc/pmic8058-xoadc.c
index b63800c..14b790f 100644
--- a/drivers/misc/pmic8058-xoadc.c
+++ b/drivers/misc/pmic8058-xoadc.c
@@ -17,7 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/msm_adc.h>
-#include <linux/pmic8058-xoadc.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pmic8058.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
@@ -54,8 +54,8 @@
 #define ADC_ARB_USRP_DATA1                      0x19C
 
 struct pmic8058_adc {
+	struct device *dev;
 	struct xoadc_platform_data *pdata;
-	struct pm8058_chip *pm_chip;
 	struct adc_properties *adc_prop;
 	struct xoadc_conv_state	conv[2];
 	int xoadc_queue_count;
@@ -144,8 +144,8 @@
 	/* Write twice to the CNTRL register for the arbiter settings
 	   to take into effect */
 	for (i = 0; i < 2; i++) {
-		rc = pm8058_write(adc_pmic->pm_chip, ADC_ARB_USRP_CNTRL,
-					&data_arb_cntrl, 1);
+		rc = pm8xxx_writeb(adc_pmic->dev->parent, ADC_ARB_USRP_CNTRL,
+							data_arb_cntrl);
 		if (rc < 0) {
 			pr_debug("%s: PM8058 write failed\n", __func__);
 			return rc;
@@ -165,8 +165,8 @@
 {
 
 	struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
-	u8 data_arb_cntrl, data_amux_chan, data_arb_rsv, data_ana_param;
-	u8 data_dig_param, data_ana_param2;
+	u8 data_arb_cntrl = 0, data_amux_chan = 0, data_arb_rsv = 0;
+	u8 data_dig_param = 0, data_ana_param2 = 0, data_ana_param = 0;
 	int rc;
 
 	rc = pm8058_xoadc_arb_cntrl(1, adc_instance, slot->chan_path);
@@ -307,15 +307,15 @@
 		break;
 	}
 
-	rc = pm8058_write(adc_pmic->pm_chip,
-			ADC_ARB_USRP_AMUX_CNTRL, &data_amux_chan, 1);
+	rc = pm8xxx_writeb(adc_pmic->dev->parent,
+			ADC_ARB_USRP_AMUX_CNTRL, data_amux_chan);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 write failed\n", __func__);
 		return rc;
 	}
 
-	rc = pm8058_write(adc_pmic->pm_chip,
-			ADC_ARB_USRP_RSV, &data_arb_rsv, 1);
+	rc = pm8xxx_writeb(adc_pmic->dev->parent,
+			ADC_ARB_USRP_RSV, data_arb_rsv);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 write failed\n", __func__);
 		return rc;
@@ -341,22 +341,22 @@
 		break;
 	}
 
-	rc = pm8058_write(adc_pmic->pm_chip,
-				ADC_ARB_USRP_ANA_PARAM, &data_ana_param, 1);
+	rc = pm8xxx_writeb(adc_pmic->dev->parent,
+				ADC_ARB_USRP_ANA_PARAM, data_ana_param);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 write failed\n", __func__);
 		return rc;
 	}
 
-	rc = pm8058_write(adc_pmic->pm_chip,
-				ADC_ARB_USRP_DIG_PARAM, &data_dig_param, 1);
+	rc = pm8xxx_writeb(adc_pmic->dev->parent,
+			ADC_ARB_USRP_DIG_PARAM, data_dig_param);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 write failed\n", __func__);
 		return rc;
 	}
 
-	rc = pm8058_write(adc_pmic->pm_chip,
-				ADC_ARB_USRP_ANA_PARAM, &data_ana_param2, 1);
+	rc = pm8xxx_writeb(adc_pmic->dev->parent,
+			ADC_ARB_USRP_ANA_PARAM, data_ana_param2);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 write failed\n", __func__);
 		return rc;
@@ -364,8 +364,8 @@
 
 	enable_irq(adc_pmic->adc_irq);
 
-	rc = pm8058_write(adc_pmic->pm_chip,
-				ADC_ARB_USRP_CNTRL, &data_arb_cntrl, 1);
+	rc = pm8xxx_writeb(adc_pmic->dev->parent,
+				ADC_ARB_USRP_CNTRL, data_arb_cntrl);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 write failed\n", __func__);
 		return rc;
@@ -434,13 +434,15 @@
 	if (!xoadc_initialized)
 		return -ENODEV;
 
-	rc = pm8058_read(adc_pmic->pm_chip, ADC_ARB_USRP_DATA0, &rslt_lsb, 1);
+	rc = pm8xxx_readb(adc_pmic->dev->parent, ADC_ARB_USRP_DATA0,
+							&rslt_lsb);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 read failed\n", __func__);
 		return rc;
 	}
 
-	rc = pm8058_read(adc_pmic->pm_chip, ADC_ARB_USRP_DATA1, &rslt_msb, 1);
+	rc = pm8xxx_readb(adc_pmic->dev->parent, ADC_ARB_USRP_DATA1,
+							&rslt_msb);
 	if (rc < 0) {
 		pr_debug("%s: PM8058 read failed\n", __func__);
 		return rc;
@@ -657,7 +659,7 @@
 
 	wake_lock_destroy(&adc_pmic->adc_wakelock);
 	msm_xo_put(adc_pmic->adc_voter);
-	platform_set_drvdata(pdev, adc_pmic->pm_chip);
+	platform_set_drvdata(pdev, NULL);
 	device_init_wakeup(&pdev->dev, 0);
 	kfree(adc_pmic);
 	xoadc_initialized = false;
@@ -668,16 +670,9 @@
 static int __devinit pm8058_xoadc_probe(struct platform_device *pdev)
 {
 	struct xoadc_platform_data *pdata = pdev->dev.platform_data;
-	struct pm8058_chip *pm_chip;
 	struct pmic8058_adc *adc_pmic;
 	int i, rc = 0;
 
-	pm_chip = dev_get_drvdata(pdev->dev.parent);
-	if (pm_chip == NULL) {
-		dev_err(&pdev->dev, "no parent data passed in\n");
-		return -EFAULT;
-	}
-
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform data?\n");
 		return -EINVAL;
@@ -689,7 +684,7 @@
 		return -ENOMEM;
 	}
 
-	adc_pmic->pm_chip = pm_chip;
+	adc_pmic->dev = &pdev->dev;
 	adc_pmic->adc_prop = pdata->xoadc_prop;
 	adc_pmic->xoadc_num = pdata->xoadc_num;
 	adc_pmic->xoadc_queue_count = 0;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index ce13d27..4a475c6 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -244,7 +244,7 @@
 
 static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
 {
-	if (host->plat->sdcc_v4_sup) {
+	if (host->sdcc_version) {
 		if (host->is_sps_mode) {
 			/* Reset DML first */
 			msmsdcc_dml_reset(host);
@@ -345,7 +345,7 @@
 	mb();
 	udelay(host->reg_write_delay);
 
-	if (host->plat->sdcc_v4_sup &&
+	if (host->sdcc_version &&
 		(readl_relaxed(host->base + MCI_STATUS2) &
 			MCI_MCLK_REG_WR_ACTIVE)) {
 		start = ktime_get();
@@ -966,6 +966,9 @@
 	void __iomem *base = host->base;
 	unsigned int pio_irqmask = 0;
 
+	BUG_ON(!data->sg);
+	BUG_ON(!data->sg_len);
+
 	host->curr.data = data;
 	host->curr.xfer_size = data->blksz * data->blocks;
 	host->curr.xfer_remain = host->curr.xfer_size;
@@ -1631,7 +1634,7 @@
 	if (mrq->data && (mrq->data->flags & MMC_DATA_WRITE)) {
 		if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
 			mrq->cmd->opcode == 54) {
-			if (!host->plat->sdcc_v4_sup)
+			if (!host->sdcc_version)
 				host->dummy_52_needed = 1;
 			else
 				/*
@@ -1716,7 +1719,12 @@
 		rc = PTR_ERR(vreg->reg);
 		pr_err("%s: regulator_get(%s) failed. rc=%d\n",
 			__func__, vreg->name, rc);
+		goto out;
 	}
+
+	if (regulator_count_voltages(vreg->reg) > 0)
+		vreg->set_voltage_sup = 1;
+
 out:
 	return rc;
 }
@@ -2490,7 +2498,7 @@
 	usleep_range(5000, 5500);
 
 	spin_lock_irqsave(&host->lock, flags);
-	/* Start SD CLK output. */
+	/* Disable PWRSAVE would make sure that SD CLK is always running */
 	writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
 			& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
 	msmsdcc_delay(host);
@@ -2514,6 +2522,9 @@
 	}
 
 out_unlock:
+	/* Enable PWRSAVE */
+	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
+			MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
 	spin_unlock_irqrestore(&host->lock, flags);
 out:
 	return rc;
@@ -3524,9 +3535,10 @@
 	if (pdev->id < 1 || pdev->id > 5)
 		return -EINVAL;
 
-	if (plat->is_sdio_al_client)
-		if (!plat->sdio_lpm_gpio_setup || !plat->sdiowakeup_irq)
-			return -EINVAL;
+	if (plat->is_sdio_al_client && !plat->sdiowakeup_irq) {
+		pr_err("%s: No wakeup IRQ for sdio_al client\n", __func__);
+		return -EINVAL;
+	}
 
 	if (pdev->resource == NULL || pdev->num_resources < 2) {
 		pr_err("%s: Invalid resource\n", __func__);
@@ -3692,6 +3704,14 @@
 	host->clk_rate = clk_get_rate(host->clk);
 	if (!host->clk_rate)
 		dev_err(&pdev->dev, "Failed to read MCLK\n");
+
+	/*
+	* Lookup the Controller Version, to identify the supported features
+	* Version number read as 0 would indicate SDCC3 or earlier versions
+	*/
+	host->sdcc_version = readl_relaxed(host->base + MCI_VERSION);
+	pr_info("%s: mci-version: %x\n", mmc_hostname(host->mmc),
+		host->sdcc_version);
 	/*
 	 * Set the register write delay according to min. clock frequency
 	 * supported and update later when the host->clk_rate changes.
@@ -3743,7 +3763,7 @@
 	 * status is to use the AUTO_PROG_DONE status provided by SDCC4
 	 * controller. So let's enable the CMD23 for SDCC4 only.
 	 */
-	if (!plat->disable_cmd23 && host->plat->sdcc_v4_sup)
+	if (!plat->disable_cmd23 && host->sdcc_version)
 		mmc->caps |= MMC_CAP_CMD23;
 
 	mmc->caps |= plat->uhs_caps;
@@ -4096,7 +4116,8 @@
 			host->clks_on = 0;
 		}
 
-		if (!host->sdio_gpio_lpm) {
+		if (host->plat->sdio_lpm_gpio_setup &&
+				!host->sdio_gpio_lpm) {
 			spin_unlock_irqrestore(&host->lock, flags);
 			host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 0);
 			spin_lock_irqsave(&host->lock, flags);
@@ -4115,7 +4136,8 @@
 			msmsdcc_disable_irq_wake(host);
 		}
 
-		if (host->sdio_gpio_lpm) {
+		if (host->plat->sdio_lpm_gpio_setup &&
+				host->sdio_gpio_lpm) {
 			spin_unlock_irqrestore(&host->lock, flags);
 			host->plat->sdio_lpm_gpio_setup(mmc_dev(mmc), 1);
 			spin_lock_irqsave(&host->lock, flags);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 12aa54b..2019913 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -168,6 +168,7 @@
 
 #define MMCIMASK1		0x040
 #define MMCIFIFOCNT		0x044
+#define MCI_VERSION		0x050
 #define MCICCSTIMER		0x058
 #define MCI_DLL_CONFIG		0x060
 #define MCI_DLL_EN		(1 << 16)
@@ -316,6 +317,7 @@
 
 	u32			pwr;
 	struct mmc_platform_data *plat;
+	u32			sdcc_version;
 
 	unsigned int		oldstat;
 
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index aeb85dc..3b3758e 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -374,8 +374,11 @@
 	if (!p->device_up) {
 		r = msm_bam_dmux_open(p->ch_id, dev, bam_notify);
 
-		if (r < 0)
+		if (r < 0) {
+			DBG0("%s: ch=%d failed with rc %d\n",
+					__func__, p->ch_id, r);
 			return -ENODEV;
+		}
 	}
 
 	p->device_up = DEVICE_ACTIVE;
@@ -688,8 +691,10 @@
 		dev = alloc_netdev(sizeof(struct rmnet_private),
 				   "rmnet%d", rmnet_setup);
 
-		if (!dev)
+		if (!dev) {
+			pr_err("%s: no memory for netdev %d\n", __func__, n);
 			return -ENOMEM;
+		}
 
 		netdevs[n] = dev;
 		d = &(dev->dev);
@@ -707,6 +712,8 @@
 
 		ret = register_netdev(dev);
 		if (ret) {
+			pr_err("%s: unable to register netdev"
+				   " %d rc=%d\n", __func__, n, ret);
 			free_netdev(dev);
 			return ret;
 		}
@@ -737,8 +744,11 @@
 		bam_rmnet_drivers[n].driver.name = tempname;
 		bam_rmnet_drivers[n].driver.owner = THIS_MODULE;
 		ret = platform_driver_register(&bam_rmnet_drivers[n]);
-		if (!ret)
+		if (ret) {
+			pr_err("%s: registration failed n=%d rc=%d\n",
+					__func__, n, ret);
 			return ret;
+		}
 	}
 	return 0;
 }
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index 1064aa0..a3c32b9 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -2192,7 +2192,7 @@
 
 	retval = request_any_context_irq(dev->irq, smsc911x_irqhandler,
 			     irq_flags | IRQF_SHARED, dev->name, dev);
-	if (retval) {
+	if (retval < 0) {
 		SMSC_WARN(pdata, probe,
 			  "Unable to claim requested irq: %d", dev->irq);
 		goto out_unmap_io_3;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index c16632e..1c56f34 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -27,7 +27,6 @@
 #define DEVICE "wcnss_wlan"
 #define VERSION "1.01"
 #define WCNSS_PIL_DEVICE "wcnss"
-#define WCNSS_NV_NAME "wlan/prima/WCNSS_qcom_cfg.ini"
 
 /* module params */
 #define WCNSS_CONFIG_UNSPECIFIED (-1)
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 8fb2a8d..e43166e 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -425,6 +425,85 @@
 }
 
 /**
+ * Find the handle of a BAM device based on the physical address
+ *
+ * This function finds a BAM device in the BAM registration list that
+ * matches the specified physical address, and returns its handle.
+ *
+ * @phys_addr - physical address of the BAM
+ *
+ * @h - device handle of the BAM
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_phy2h(u32 phys_addr, u32 *handle)
+{
+	struct sps_bam *bam;
+
+	list_for_each_entry(bam, &sps->bams_q, list) {
+		if (bam->props.phys_addr == phys_addr) {
+			*handle = (u32) bam;
+			return 0;
+		}
+	}
+
+	SPS_INFO("sps: BAM device 0x%x is not registered yet.\n", phys_addr);
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(sps_phy2h);
+
+/**
+ * Setup desc/data FIFO for bam-to-bam connection
+ *
+ * @mem_buffer - Pointer to struct for allocated memory properties.
+ *
+ * @addr - address of FIFO
+ *
+ * @size - FIFO size
+ *
+ * @use_offset - use address offset instead of absolute address
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
+		  u32 addr, u32 size, int use_offset)
+{
+	if ((mem_buffer == NULL) || (size == 0))
+		return SPS_ERROR;
+
+	if (use_offset) {
+		if ((addr + size) <= sps->pipemem_size)
+			mem_buffer->phys_base = sps->pipemem_phys_base + addr;
+		else {
+			SPS_ERR("sps: requested mem is out of "
+					"pipe mem range.\n");
+			return SPS_ERROR;
+		}
+	} else {
+		if (addr >= sps->pipemem_phys_base &&
+			(addr + size) <= (sps->pipemem_phys_base
+						+ sps->pipemem_size))
+			mem_buffer->phys_base = addr;
+		else {
+			SPS_ERR("sps: requested mem is out of "
+					"pipe mem range.\n");
+			return SPS_ERROR;
+		}
+	}
+
+	mem_buffer->base = spsi_get_mem_ptr(mem_buffer->phys_base);
+	mem_buffer->size = size;
+
+	memset(mem_buffer->base, 0, mem_buffer->size);
+
+	return 0;
+}
+EXPORT_SYMBOL(sps_setup_bam2bam_fifo);
+
+/**
  * Find the BAM device from the handle
  *
  * This function finds a BAM device in the BAM registration list that
@@ -597,7 +676,7 @@
 	if (pipe == NULL)
 		return SPS_ERROR;
 
-	bam = sps_bam_lock(pipe);
+	bam = pipe->bam;
 	if (bam == NULL)
 		return SPS_ERROR;
 
@@ -620,7 +699,9 @@
 	}
 
 	/* Disconnect the BAM pipe */
+	mutex_lock(&bam->lock);
 	result = sps_rm_state_change(pipe, SPS_STATE_DISCONNECT);
+	mutex_unlock(&bam->lock);
 	if (result)
 		goto exit_err;
 
@@ -628,7 +709,6 @@
 	result = 0;
 
 exit_err:
-	sps_bam_unlock(bam);
 
 	return result;
 }
@@ -725,7 +805,6 @@
 	struct sps_pipe *pipe = h;
 	struct sps_bam *bam;
 	int result;
-	int ret;
 
 	SPS_DBG("%s.", __func__);
 
@@ -733,17 +812,8 @@
 	if (bam == NULL)
 		return SPS_ERROR;
 
-	ret = clk_enable(sps->dfab_clk);
-	if (ret) {
-		SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
-		sps_bam_unlock(bam);
-		return SPS_ERROR;
-	}
-
 	result = sps_bam_pipe_transfer(bam, pipe->pipe_index, transfer);
 
-	clk_disable(sps->dfab_clk);
-
 	sps_bam_unlock(bam);
 
 	return result;
@@ -760,7 +830,6 @@
 	struct sps_pipe *pipe = h;
 	struct sps_bam *bam;
 	int result;
-	int ret;
 
 	SPS_DBG("%s.", __func__);
 
@@ -768,18 +837,9 @@
 	if (bam == NULL)
 		return SPS_ERROR;
 
-	ret = clk_enable(sps->dfab_clk);
-	if (ret) {
-		SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
-		sps_bam_unlock(bam);
-		return SPS_ERROR;
-	}
-
 	result = sps_bam_pipe_transfer_one(bam, pipe->pipe_index,
 					   addr, size, user, flags);
 
-	clk_disable(sps->dfab_clk);
-
 	sps_bam_unlock(bam);
 
 	return result;
@@ -1432,14 +1492,24 @@
 			goto clk_err;
 		}
 	}
-#endif
 
+	ret = clk_enable(sps->dfab_clk);
+	if (ret) {
+		SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
+		goto clk_err;
+	}
+#endif
 	ret = sps_device_init();
 	if (ret) {
 		SPS_ERR("sps:sps_device_init err.");
+#ifdef CONFIG_SPS_SUPPORT_BAMDMA
+		clk_disable(sps->dfab_clk);
+#endif
 		goto sps_device_init_err;
 	}
-
+#ifdef CONFIG_SPS_SUPPORT_BAMDMA
+	clk_disable(sps->dfab_clk);
+#endif
 	sps->is_ready = true;
 
 	SPS_INFO("sps is ready.");
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index ac6dc4f..edd789e 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -217,6 +217,18 @@
 		/* Enable the BAM interrupt */
 		irq_mask = BAM_IRQ_ALL;
 		dev->state |= BAM_STATE_IRQ;
+
+		/* Register BAM IRQ for apps wakeup */
+		if (dev->props.options & SPS_BAM_OPT_IRQ_WAKEUP) {
+			result = enable_irq_wake(dev->props.irq);
+
+			if (result) {
+				SPS_ERR("Failed to enable wakeup irq "
+					"BAM 0x%x IRQ %d",
+					BAM_ID(dev), dev->props.irq);
+				return SPS_ERROR;
+			}
+		}
 	}
 
 	/* Is global BAM control managed by the local processor? */
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index cca1035..3590e6d 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -244,7 +244,7 @@
 
 config BATTERY_MSM8X60
 	tristate "MSM8X60 battery"
-	select PMIC8058_BATTALARM
+	select PMIC8XXX_BATTALARM
 	help
 	  Some MSM boards have dual charging paths to charge the battery.
 	  Say Y to enable support for the battery charging in
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 2d0f7cd..d7cf3a8 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -89,6 +89,12 @@
 	DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
 	spinlock_t		bms_output_lock;
 	struct single_row_lut	*adjusted_fcc_temp_lut;
+	unsigned int		charging_began;
+	unsigned int		start_percent;
+	unsigned int		end_percent;
+
+	uint16_t		ocv_reading_at_100;
+	int			cc_reading_at_100;
 };
 
 static struct pm8921_bms_chip *the_chip;
@@ -484,6 +490,9 @@
 	}
 	*result = msw << 16 | lsw;
 	pr_debug("msw = %04x lsw = %04x cc = %d\n", msw, lsw, *result);
+	*result = *result - chip->cc_reading_at_100;
+	pr_debug("cc = %d after subtracting %d\n",
+					*result, chip->cc_reading_at_100);
 	return 0;
 }
 
@@ -497,12 +506,29 @@
 		pr_err("fail to read LAST_GOOD_OCV_VALUE rc = %d\n", rc);
 		return rc;
 	}
-	*result = xoadc_reading_to_microvolt(reading);
-	pr_debug("raw = %04x ocv_uV = %u\n", reading, *result);
-	*result = adjust_xo_vbatt_reading(chip, *result);
-	pr_debug("after adj ocv_uV = %u\n", *result);
-	if (*result != 0)
-		last_ocv_uv = *result;
+
+	if (chip->ocv_reading_at_100 != reading) {
+		chip->ocv_reading_at_100 = 0;
+		chip->cc_reading_at_100 = 0;
+		*result = xoadc_reading_to_microvolt(reading);
+		pr_debug("raw = %04x ocv_uV = %u\n", reading, *result);
+		*result = adjust_xo_vbatt_reading(chip, *result);
+		pr_debug("after adj ocv_uV = %u\n", *result);
+		if (*result != 0)
+			last_ocv_uv = *result;
+	} else {
+		/*
+		 * force 100% ocv by selecting the highest profiled ocv
+		 * This is the first row last column entry in the ocv
+		 * lookup table
+		 */
+		int cols = chip->pc_temp_ocv_lut->cols;
+
+		pr_debug("Forcing max voltage %d\n",
+				1000 * chip->pc_temp_ocv_lut->ocv[0][cols-1]);
+		*result = 1000 * chip->pc_temp_ocv_lut->ocv[0][cols-1];
+	}
+
 	return 0;
 }
 
@@ -628,18 +654,33 @@
 static int interpolate_scalingfactor_fcc(struct pm8921_bms_chip *chip,
 								int cycles)
 {
-	return interpolate_single_lut(chip->fcc_sf_lut, cycles);
+	/*
+	 * sf table could be null when no battery aging data is available, in
+	 * that case return 100%
+	 */
+	if (chip->fcc_sf_lut)
+		return interpolate_single_lut(chip->fcc_sf_lut, cycles);
+	else
+		return 100;
 }
 
 static int interpolate_scalingfactor_pc(struct pm8921_bms_chip *chip,
 				int cycles, int pc)
 {
 	int i, scalefactorrow1, scalefactorrow2, scalefactor;
+	int rows, cols;
 	int row1 = 0;
 	int row2 = 0;
-	int rows = chip->pc_sf_lut->rows;
-	int cols = chip->pc_sf_lut->cols;
 
+	/*
+	 * sf table could be null when no battery aging data is available, in
+	 * that case return 100%
+	 */
+	if (!chip->pc_sf_lut)
+		return 100;
+
+	rows = chip->pc_sf_lut->rows;
+	cols = chip->pc_sf_lut->cols;
 	if (pc > chip->pc_sf_lut->percent[0]) {
 		pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
 		row1 = 0;
@@ -1016,10 +1057,10 @@
 
 	/* calculate cc milli_volt_hour */
 	calculate_cc_mah(chip, cc_mah, &coulumb_counter);
+	pr_debug("cc_mah = %lldmAh cc = %d\n", *cc_mah, coulumb_counter);
 
 	pm_bms_unlock_output_data(chip);
 	spin_unlock_irqrestore(&chip->bms_output_lock, flags);
-	pr_debug("cc_mah = %lldmAh cc = %d\n", *cc_mah, coulumb_counter);
 }
 
 static int calculate_real_fcc(struct pm8921_bms_chip *chip,
@@ -1037,7 +1078,8 @@
 						&cc_mah);
 
 	real_fcc = remaining_charge - cc_mah;
-
+	pr_debug("real_fcc = %d, RC = %d CC = %lld\n",
+			real_fcc, remaining_charge, cc_mah);
 	return real_fcc;
 }
 /*
@@ -1102,9 +1144,23 @@
 		update_userspace = 0;
 	}
 
-	if (update_userspace) {
-		last_soc = soc;
+	if (last_soc == -EINVAL || soc <= last_soc) {
+		last_soc = update_userspace ? soc : last_soc;
+		return soc;
 	}
+
+	/*
+	 * soc > last_soc
+	 * the device must be charging for reporting a higher soc, if not ignore
+	 * this soc and continue reporting the last_soc
+	 */
+	if (the_chip->start_percent != 0) {
+		last_soc = soc;
+	} else {
+		pr_debug("soc = %d reporting last_soc = %d\n", soc, last_soc);
+		soc = last_soc;
+	}
+
 	return soc;
 }
 
@@ -1645,19 +1701,18 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_fcc);
 
-static int start_percent;
-static int end_percent;
 void pm8921_bms_charging_began(void)
 {
-	start_percent = pm8921_bms_get_percent_charge();
-	pr_debug("start_percent = %u%%\n", start_percent);
+	the_chip->start_percent = pm8921_bms_get_percent_charge();
+	pr_debug("start_percent = %u%%\n", the_chip->start_percent);
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
 
 void pm8921_bms_charging_end(int is_battery_full)
 {
 	if (is_battery_full && the_chip != NULL) {
-		int batt_temp, rc;
+		unsigned long flags;
+		int batt_temp, rc, cc_reading;
 		struct pm8921_adc_chan_result result;
 
 		rc = pm8921_adc_read(the_chip->batt_temp_channel, &result);
@@ -1673,12 +1728,25 @@
 						batt_temp, last_chargecycles);
 		last_real_fcc_batt_temp = batt_temp;
 		readjust_fcc_table();
+
+		spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+		pm_bms_lock_output_data(the_chip);
+		pm_bms_read_output_data(the_chip, LAST_GOOD_OCV_VALUE,
+						&the_chip->ocv_reading_at_100);
+		read_cc(the_chip, &cc_reading);
+		pm_bms_unlock_output_data(the_chip);
+		spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
+		the_chip->cc_reading_at_100 = cc_reading;
+		pr_debug("EOC ocv_reading = 0x%x cc_reading = %d\n",
+				the_chip->ocv_reading_at_100,
+				the_chip->cc_reading_at_100);
 	}
 
 charge_cycle_calculation:
-	end_percent = pm8921_bms_get_percent_charge();
-	if (end_percent > start_percent) {
-		last_charge_increase = end_percent - start_percent;
+	the_chip->end_percent = pm8921_bms_get_percent_charge();
+	if (the_chip->end_percent > the_chip->start_percent) {
+		last_charge_increase =
+			the_chip->end_percent - the_chip->start_percent;
 		if (last_charge_increase > 100) {
 			last_chargecycles++;
 			last_charge_increase = last_charge_increase % 100;
@@ -1686,9 +1754,11 @@
 	}
 	pr_debug("end_percent = %u%% last_charge_increase = %d"
 			"last_chargecycles = %d\n",
-			end_percent,
+			the_chip->end_percent,
 			last_charge_increase,
 			last_chargecycles);
+	the_chip->start_percent = 0;
+	the_chip->end_percent = 0;
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_charging_end);
 
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 303dd99..148a5e5 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -105,6 +105,39 @@
 	FSM_STATE_FLCB = 22,
 };
 
+struct fsm_state_to_batt_status {
+	enum chg_fsm_state	fsm_state;
+	int			batt_state;
+};
+
+static struct fsm_state_to_batt_status map[] = {
+	{FSM_STATE_OFF_0, POWER_SUPPLY_STATUS_UNKNOWN},
+	{FSM_STATE_BATFETDET_START_12, POWER_SUPPLY_STATUS_UNKNOWN},
+	{FSM_STATE_BATFETDET_END_16, POWER_SUPPLY_STATUS_UNKNOWN},
+	/*
+	 * for CHG_HIGHI_1 report NOT_CHARGING if battery missing,
+	 * too hot/cold, charger too hot
+	 */
+	{FSM_STATE_ON_CHG_HIGHI_1, POWER_SUPPLY_STATUS_FULL},
+	{FSM_STATE_ATC_2A, POWER_SUPPLY_STATUS_CHARGING},
+	{FSM_STATE_ATC_2B, POWER_SUPPLY_STATUS_CHARGING},
+	{FSM_STATE_ON_BAT_3, POWER_SUPPLY_STATUS_DISCHARGING},
+	{FSM_STATE_ATC_FAIL_4, POWER_SUPPLY_STATUS_DISCHARGING},
+	{FSM_STATE_DELAY_5, POWER_SUPPLY_STATUS_UNKNOWN },
+	{FSM_STATE_ON_CHG_AND_BAT_6, POWER_SUPPLY_STATUS_CHARGING},
+	{FSM_STATE_FAST_CHG_7, POWER_SUPPLY_STATUS_CHARGING},
+	{FSM_STATE_TRKL_CHG_8, POWER_SUPPLY_STATUS_CHARGING},
+	{FSM_STATE_CHG_FAIL_9, POWER_SUPPLY_STATUS_DISCHARGING},
+	{FSM_STATE_EOC_10, POWER_SUPPLY_STATUS_FULL},
+	{FSM_STATE_ON_CHG_VREGOK_11, POWER_SUPPLY_STATUS_NOT_CHARGING},
+	{FSM_STATE_ATC_PAUSE_13, POWER_SUPPLY_STATUS_NOT_CHARGING},
+	{FSM_STATE_FAST_CHG_PAUSE_14, POWER_SUPPLY_STATUS_NOT_CHARGING},
+	{FSM_STATE_TRKL_CHG_PAUSE_15, POWER_SUPPLY_STATUS_NOT_CHARGING},
+	{FSM_STATE_START_BOOT, POWER_SUPPLY_STATUS_NOT_CHARGING},
+	{FSM_STATE_FLCB_VREGOK, POWER_SUPPLY_STATUS_NOT_CHARGING},
+	{FSM_STATE_FLCB, POWER_SUPPLY_STATUS_NOT_CHARGING},
+};
+
 enum chg_regulation_loop {
 	VDD_LOOP = BIT(3),
 	BAT_CURRENT_LOOP = BIT(2),
@@ -335,6 +368,19 @@
 				enable ? CHG_EN_BIT : 0);
 }
 
+#define CHG_FAILED_CLEAR	BIT(0)
+#define ATC_FAILED_CLEAR	BIT(1)
+static int pm_chg_failed_clear(struct pm8921_chg_chip *chip, int clear)
+{
+	int rc;
+
+	rc = pm_chg_masked_write(chip, CHG_CNTRL_3, ATC_FAILED_CLEAR,
+				clear ? ATC_FAILED_CLEAR : 0);
+	rc |= pm_chg_masked_write(chip, CHG_CNTRL_3, CHG_FAILED_CLEAR,
+				clear ? CHG_FAILED_CLEAR : 0);
+	return rc;
+}
+
 #define CHG_CHARGE_DIS_BIT	BIT(1)
 static int pm_chg_charge_dis(struct pm8921_chg_chip *chip, int disable)
 {
@@ -523,7 +569,7 @@
 	return pm_chg_masked_write(chip, CHG_TWDOG, PM8921_CHG_WD_MASK, 0);
 }
 
-#define PM8921_CHG_TCHG_MASK	0x3F
+#define PM8921_CHG_TCHG_MASK	0x7F
 #define PM8921_CHG_TCHG_MIN	4
 #define PM8921_CHG_TCHG_MAX	512
 #define PM8921_CHG_TCHG_STEP	4
@@ -968,36 +1014,22 @@
 
 static int get_prop_batt_status(struct pm8921_chg_chip *chip)
 {
-	int temp = 0;
+	int batt_state = POWER_SUPPLY_STATUS_DISCHARGING;
+	int fsm_state = pm_chg_get_fsm_state(chip);
+	int i;
 
-	if (!get_prop_batt_present(chip))
-		return POWER_SUPPLY_STATUS_UNKNOWN;
+	for (i = 0; i < ARRAY_SIZE(map); i++)
+		if (map[i].fsm_state == fsm_state)
+			batt_state = map[i].batt_state;
 
-	if (chip->ext) {
-		if (chip->ext_charge_done)
-			return POWER_SUPPLY_STATUS_FULL;
+	if (fsm_state == FSM_STATE_ON_CHG_HIGHI_1) {
+		if (!pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ)
+			|| !pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ)
+			|| !pm_chg_get_rt_status(chip, CHGHOT_IRQ))
 
-		if (chip->ext_charging)
-			return POWER_SUPPLY_STATUS_CHARGING;
+			batt_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
 	}
-
-	/* TODO reading the FSM state is more reliable */
-	temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
-
-	temp |= pm_chg_get_rt_status(chip, FASTCHG_IRQ);
-	if (temp)
-		return POWER_SUPPLY_STATUS_CHARGING;
-	/*
-	 * The battery is not charging
-	 * check the FET - if on battery is discharging
-	 *		 - if off battery is isolated(full) and the system
-	 *		   is being driven from a charger
-	 */
-	temp = pm_chg_get_rt_status(chip, BATFET_IRQ);
-	if (temp)
-		return POWER_SUPPLY_STATUS_DISCHARGING;
-
-	return POWER_SUPPLY_STATUS_FULL;
+	return batt_state;
 }
 
 static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
@@ -1506,8 +1538,17 @@
 static irqreturn_t chgfail_irq_handler(int irq, void *data)
 {
 	struct pm8921_chg_chip *chip = data;
+	int ret;
 
-	pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
+	ret = pm_chg_failed_clear(chip, 1);
+	if (ret)
+		pr_err("Failed to write CHG_FAILED_CLEAR bit\n");
+
+	pr_err("batt_present = %d, batt_temp_ok = %d, state_changed_to=%d\n",
+			get_prop_batt_present(chip),
+			pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ),
+			pm_chg_get_fsm_state(data));
+
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
 	power_supply_changed(&chip->dc_psy);
@@ -2028,6 +2069,7 @@
 	pm8921_chg_enable_irq(chip, USBIN_UV_IRQ);
 	pm8921_chg_enable_irq(chip, DCIN_OV_IRQ);
 	pm8921_chg_enable_irq(chip, DCIN_UV_IRQ);
+	pm8921_chg_enable_irq(chip, CHGFAIL_IRQ);
 	pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
 	pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
 
@@ -2329,6 +2371,9 @@
 		pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0C);
 	}
 
+	/* Disable EOC FSM processing */
+	pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x91);
+
 	rc = pm_chg_charge_dis(chip, charging_disabled);
 	if (rc) {
 		pr_err("Failed to disable CHG_CHARGE_DIS bit rc=%d\n", rc);
diff --git a/drivers/power/pmic8058-charger.c b/drivers/power/pmic8058-charger.c
index a3ce54d..70b5d59 100644
--- a/drivers/power/pmic8058-charger.c
+++ b/drivers/power/pmic8058-charger.c
@@ -15,7 +15,6 @@
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 #include <linux/errno.h>
-#include <linux/mfd/pmic8058.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/bitops.h>
@@ -25,8 +24,10 @@
 #include <linux/slab.h>
 #include <linux/msm_adc.h>
 #include <linux/notifier.h>
-#include <linux/pmic8058-batt-alarm.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pmic8058.h>
 #include <linux/pmic8058-charger.h>
+#include <linux/mfd/pm8xxx/batt-alarm.h>
 
 #include <mach/msm_xo.h>
 #include <mach/msm_hsusb.h>
@@ -177,7 +178,6 @@
 
 struct pm8058_charger {
 	struct pmic_charger_pdata *pdata;
-	struct pm8058_chip *pm_chip;
 	struct device *dev;
 
 	int pmic_chg_irq[PMIC_CHG_MAX_INTS];
@@ -228,7 +228,11 @@
 	if (rc)
 		goto out;
 
-	rc = pm8058_batt_alarm_threshold_set(resume_mv, 4300);
+	rc = pm8xxx_batt_alarm_threshold_set(
+			PM8XXX_BATT_ALARM_LOWER_COMPARATOR, resume_mv);
+	if (!rc)
+		rc = pm8xxx_batt_alarm_threshold_set(
+			PM8XXX_BATT_ALARM_UPPER_COMPARATOR, 4300);
 
 out:
 	mutex_unlock(&batt_alarm_lock);
@@ -255,15 +259,9 @@
 
 static int pm_chg_get_rt_status(int irq)
 {
-	int count = 3;
 	int ret;
 
-	while ((ret =
-		pm8058_irq_get_rt_status(pm8058_chg.pm_chip, irq)) == -EAGAIN
-	       && count--) {
-		dev_info(pm8058_chg.dev, "%s trycount=%d\n", __func__, count);
-		cpu_relax();
-	}
+	ret = pm8xxx_read_irq_stat(pm8058_chg.dev->parent, irq);
 	if (ret == -EAGAIN)
 		return 0;
 	else
@@ -281,53 +279,53 @@
 	u8 temp;
 	int temp2;
 
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_CNTRL = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_CNTRL_2 = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_VMAX_SEL, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_VMAX_SEL, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_VMAX_SEL = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_VBAT_DET, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_VBAT_DET, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_VBAT_DET = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_IMAX, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_IMAX, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_IMAX = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TRICKLE, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TRICKLE, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_TRICKLE = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_ITERM, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_ITERM, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_ITERM = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TTRKL_MAX, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TTRKL_MAX, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_TTRKL_MAX = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TCHG_MAX, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TCHG_MAX, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_TCHG_MAX = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEMP_THRESH, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEMP_THRESH, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_TEMP_THRESH = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEMP_REG, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEMP_REG, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_TEMP_REG = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_PULSE, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_PULSE, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_PULSE = 0x%x\n", temp);
 
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_1,
-		    &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_1,
+		    &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_1 = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_3,
-		    &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_3,
+		    &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_3 = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_10,
-		    &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_10,
+		    &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_10 = 0x%x\n",
 		temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_11,
-		    &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_11,
+		    &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_11 = 0x%x\n",
 		temp);
 
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_1, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_1, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_1 = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_3, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_3, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_3 = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_10, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_10, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_10 = 0x%x\n", temp);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_11, &temp, 1);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_11, &temp);
 	dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_11 = 0x%x\n", temp);
 
 	temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGVAL_IRQ]);
@@ -405,7 +403,7 @@
 	u8 temp;
 	int ret;
 
-	ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
 	if (ret)
 		return ret;
 	if (value)
@@ -413,7 +411,7 @@
 	else
 		temp &= ~BIT(CHG_USB_SUSPEND);
 
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, temp);
 }
 
 static int pm_chg_auto_disable(int value)
@@ -421,7 +419,7 @@
 	u8 temp;
 	int ret;
 
-	ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
 	if (ret)
 		return ret;
 	if (value)
@@ -429,7 +427,7 @@
 	else
 		temp &= ~BIT(CHARGE_AUTO_DIS);
 
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
 }
 
 static int pm_chg_batt_temp_disable(int value)
@@ -437,7 +435,7 @@
 	u8 temp;
 	int ret;
 
-	ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
 	if (ret)
 		return ret;
 	if (value)
@@ -445,7 +443,7 @@
 	else
 		temp &= ~BIT(CHG_BATT_TEMP_DIS);
 
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
 }
 
 static int pm_chg_vbatdet_set(int voltage)
@@ -463,7 +461,7 @@
 	temp = diff / PM8058_CHG_V_STEP_MV;
 	dev_dbg(pm8058_chg.dev, "%s voltage=%d setting %02x\n", __func__,
 		voltage, temp);
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_VBAT_DET, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_VBAT_DET, temp);
 }
 
 static int pm_chg_imaxsel_set(int chg_current)
@@ -484,7 +482,7 @@
 			__func__, chg_current);
 		temp = 31;
 	}
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_IMAX, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_IMAX, temp);
 }
 
 #define PM8058_CHG_VMAX_MIN  3300
@@ -501,7 +499,7 @@
 	temp = (voltage - PM8058_CHG_V_MIN_MV) / PM8058_CHG_V_STEP_MV;
 	dev_dbg(pm8058_chg.dev, "%s mV=%d setting %02x\n", __func__, voltage,
 		temp);
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_VMAX_SEL, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_VMAX_SEL, temp);
 }
 
 static int pm_chg_failed_clear(int value)
@@ -509,14 +507,14 @@
 	u8 temp;
 	int ret;
 
-	ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
 	if (ret)
 		return ret;
 	if (value)
 		temp |= BIT(CHG_FAILED_CLEAR);
 	else
 		temp &= ~BIT(CHG_FAILED_CLEAR);
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
 }
 
 static int pm_chg_iterm_set(int chg_current)
@@ -524,7 +522,7 @@
 	u8 temp;
 
 	temp = (chg_current / PM8058_CHG_I_TERM_STEP_MA) - 1;
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_ITERM, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_ITERM, temp);
 }
 
 static int pm_chg_tchg_set(int minutes)
@@ -532,7 +530,7 @@
 	u8 temp;
 
 	temp = (minutes >> PM8058_CHG_T_TCHG_SHIFT) - 1;
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TCHG_MAX, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TCHG_MAX, temp);
 }
 
 static int pm_chg_ttrkl_set(int minutes)
@@ -540,7 +538,8 @@
 	u8 temp;
 
 	temp = minutes - 1;
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TTRKL_MAX, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TTRKL_MAX,
+									temp);
 }
 
 static int pm_chg_enum_done_enable(int value)
@@ -548,7 +547,7 @@
 	u8 temp;
 	int ret;
 
-	ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
 	if (ret)
 		return ret;
 	if (value)
@@ -556,7 +555,7 @@
 	else
 		temp &= ~BIT(ENUM_DONE);
 
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
 }
 
 static uint32_t get_fsm_state(void)
@@ -564,8 +563,8 @@
 	u8 temp;
 
 	temp = 0x00;
-	pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
-	pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
+	pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, temp);
+	pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, &temp);
 	return (uint32_t)temp;
 }
 
@@ -590,7 +589,7 @@
 	u8 temp;
 	int ret;
 
-	ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
 	if (ret)
 		return ret;
 	if (value)
@@ -598,7 +597,7 @@
 	else
 		temp &= ~BIT(CHG_CHARGE_DIS);
 
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, temp);
 }
 
 static void pm8058_start_system_current(struct msm_hardware_charger *hw_chg,
@@ -734,7 +733,11 @@
 	case PMIC8058_CHG_STATE_ATC:
 	case PMIC8058_CHG_STATE_FAST_CHG:
 	case PMIC8058_CHG_STATE_TRKL_CHG:
-		rc = pm8058_batt_alarm_state_set(0, 0);
+		rc = pm8xxx_batt_alarm_disable(
+				PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+		if (!rc)
+			rc = pm8xxx_batt_alarm_disable(
+				PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
 		if (rc)
 			dev_err(pm8058_chg.dev,
 				"%s: unable to set alarm state\n", __func__);
@@ -863,25 +866,25 @@
 		}
 	} else {
 		if (pm8058_chg.present) {
-			ret = pm8058_read(pm8058_chg.pm_chip,
+			ret = pm8xxx_readb(pm8058_chg.dev->parent,
 						PM8058_OVP_TEST_REG,
-						&old, 1);
+						&old);
 			temp = old | BIT(FORCE_OVP_OFF);
-			ret = pm8058_write(pm8058_chg.pm_chip,
+			ret = pm8xxx_writeb(pm8058_chg.dev->parent,
 						PM8058_OVP_TEST_REG,
-						&temp, 1);
+						temp);
 			temp = 0xFC;
-			ret = pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST,
-						&temp, 1);
+			ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+					PM8058_CHG_TEST, temp);
 			/* 10 ms sleep is for the VCHG to discharge */
 			msleep(10);
 			temp = 0xF0;
-			ret = pm8058_write(pm8058_chg.pm_chip,
+			ret = pm8xxx_writeb(pm8058_chg.dev->parent,
 						PM8058_CHG_TEST,
-						&temp, 1);
-			ret = pm8058_write(pm8058_chg.pm_chip,
+						temp);
+			ret = pm8xxx_writeb(pm8058_chg.dev->parent,
 						PM8058_OVP_TEST_REG,
-						&old, 1);
+						old);
 
 			pm_chg_enum_done_enable(0);
 			pm_chg_auto_disable(1);
@@ -904,21 +907,21 @@
 
 		pm_chg_enum_done_enable(0);
 		pm_chg_auto_disable(1);
-		ret = pm8058_read(pm8058_chg.pm_chip,
-				PM8058_OVP_TEST_REG, &old, 1);
+		ret = pm8xxx_readb(pm8058_chg.dev->parent,
+				PM8058_OVP_TEST_REG, &old);
 		temp = old | BIT(FORCE_OVP_OFF);
-		ret = pm8058_write(pm8058_chg.pm_chip,
-				PM8058_OVP_TEST_REG, &temp, 1);
+		ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+				PM8058_OVP_TEST_REG, temp);
 		temp = 0xFC;
-		ret = pm8058_write(pm8058_chg.pm_chip,
-				PM8058_CHG_TEST, &temp, 1);
+		ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+				PM8058_CHG_TEST, temp);
 		/* 10 ms sleep is for the VCHG to discharge */
 		msleep(10);
 		temp = 0xF0;
-		ret = pm8058_write(pm8058_chg.pm_chip,
-				PM8058_CHG_TEST, &temp, 1);
-		ret = pm8058_write(pm8058_chg.pm_chip,
-				PM8058_OVP_TEST_REG, &old, 1);
+		ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+				PM8058_CHG_TEST, temp);
+		ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+				PM8058_OVP_TEST_REG, old);
 
 		if (!is_chg_plugged_in()) {
 			msm_charger_notify_event(&usb_hw_chg,
@@ -983,8 +986,8 @@
 	u8 temp;
 
 	temp = 0x00;
-	if (!pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1)) {
-		pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
+	if (!pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, temp)) {
+		pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, &temp);
 		dev_dbg(pm8058_chg.dev, "%s state=%d\n", __func__, temp);
 	}
 	return IRQ_HANDLED;
@@ -1187,7 +1190,7 @@
 			"%s:couldnt find resource AUTO_CHGDONE\n", __func__);
 		goto err_out;
 	} else {
-		ret = request_threaded_irq(res->start, NULL,
+		ret = request_irq(res->start,
 				  pm8058_chg_auto_chgdone_handler,
 				  IRQF_TRIGGER_RISING,
 				  res->name, NULL);
@@ -1208,7 +1211,7 @@
 			"%s:couldnt find resource AUTO_CHGFAIL\n", __func__);
 		goto err_out;
 	} else {
-		ret = request_threaded_irq(res->start, NULL,
+		ret = request_irq(res->start,
 				  pm8058_chg_auto_chgfail_handler,
 				  IRQF_TRIGGER_RISING, res->name, NULL);
 		if (ret < 0) {
@@ -1227,7 +1230,7 @@
 			"%s:couldnt find resource CHGSTATE\n", __func__);
 		goto err_out;
 	} else {
-		ret = request_threaded_irq(res->start, NULL,
+		ret = request_irq(res->start,
 				  pm8058_chg_chgstate_handler,
 				  IRQF_TRIGGER_RISING, res->name, NULL);
 		if (ret < 0) {
@@ -1246,7 +1249,7 @@
 			"%s:couldnt find resource FASTCHG\n", __func__);
 		goto err_out;
 	} else {
-		ret = request_threaded_irq(res->start, NULL,
+		ret = request_irq(res->start,
 				  pm8058_chg_fastchg_handler,
 				  IRQF_TRIGGER_RISING, res->name, NULL);
 		if (ret < 0) {
@@ -1265,7 +1268,7 @@
 			"%s:couldnt find resource CHG_END\n", __func__);
 		goto err_out;
 	} else {
-		ret = request_threaded_irq(res->start, NULL,
+		ret = request_irq(res->start,
 				  pm8058_chg_batttemp_handler,
 				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				  res->name, NULL);
@@ -1286,7 +1289,7 @@
 			"%s:couldnt find resource BATT_REPLACE\n", __func__);
 		goto err_out;
 	} else {
-		ret = request_threaded_irq(res->start, NULL,
+		ret = request_irq(res->start,
 				  pm8058_chg_batt_replace_handler,
 				  IRQF_TRIGGER_RISING, res->name, NULL);
 		if (ret < 0) {
@@ -1305,7 +1308,7 @@
 			"%s:couldnt find resource BATTCONNECT\n", __func__);
 		goto err_out;
 	} else {
-		ret = request_threaded_irq(res->start, NULL,
+		ret = request_irq(res->start,
 				  pm8058_chg_battconnect_handler,
 				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				  res->name, NULL);
@@ -1351,7 +1354,7 @@
 	u8 temp;
 	int rc;
 
-	rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	rc = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
 	if (rc)
 		return rc;
 
@@ -1367,7 +1370,7 @@
 	u8 temp;
 	int rc;
 
-	rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	rc = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
 	if (rc)
 		return rc;
 	if (on)
@@ -1375,7 +1378,7 @@
 	else
 		temp &= ~BIT(CHG_CHARGE_BAT);
 
-	return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+	return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, temp);
 
 }
 EXPORT_SYMBOL(pm8058_set_charge_batt);
@@ -1496,12 +1499,12 @@
 	u8 temp;
 
 	temp = 0xA3;
-	pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
+	pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_2, temp);
 	temp = 0x84;
-	pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
+	pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_2, temp);
 	msleep(2);
 	temp = 0x80;
-	pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
+	pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_2, temp);
 	return 0;
 }
 
@@ -1511,7 +1514,7 @@
 	int ret;
 	u8 temp;
 
-	ret = pm8058_read(pm8058_chg.pm_chip, i, &temp, 1);
+	ret = pm8xxx_readb(pm8058_chg.dev->parent, i, &temp);
 	if (ret)
 		return -EAGAIN;
 	*val = temp;
@@ -1525,7 +1528,7 @@
 	u8 temp;
 
 	temp = (u8) val;
-	ret = pm8058_write(pm8058_chg.pm_chip, i, &temp, 1);
+	ret = pm8xxx_writeb(pm8058_chg.dev->parent, i, temp);
 	mb();
 	if (ret)
 		return -EAGAIN;
@@ -1821,7 +1824,11 @@
 		break;
 	/* expected case - trip of low threshold */
 	case 1:
-		rc = pm8058_batt_alarm_state_set(0, 0);
+		rc = pm8xxx_batt_alarm_disable(
+				PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+		if (!rc)
+			rc = pm8xxx_batt_alarm_disable(
+				PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
 		if (rc)
 			dev_err(pm8058_chg.dev,
 				"%s: unable to set alarm state\n", __func__);
@@ -1841,8 +1848,15 @@
 
 static int pm8058_monitor_for_recharging(void)
 {
+	int rc;
 	/* enable low comparator */
-	return pm8058_batt_alarm_state_set(1, 0);
+	rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+	if (!rc)
+		return pm8xxx_batt_alarm_enable(
+				PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
+
+	return rc;
+
 }
 
 static struct msm_battery_gauge pm8058_batt_gauge = {
@@ -1860,33 +1874,30 @@
 	int ret = 0;
 
 	temp = 0x10;
-	ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
-	ret |= pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST, &old, 1);
+	ret |= pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST, temp);
+	ret |= pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEST, &old);
 	old = old & ~BIT(IGNORE_LL);
 	temp = 0x90  | (0xF & old);
-	ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
+	ret |= pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST, temp);
 
 	return ret;
 }
 
 static int __devinit pm8058_charger_probe(struct platform_device *pdev)
 {
-	struct pm8058_chip *pm_chip;
 	struct pmic8058_charger_data *pdata;
 	int rc = 0;
 
-	pm_chip = dev_get_drvdata(pdev->dev.parent);
-	if (pm_chip == NULL) {
-		pr_err("%s:no parent data passed in.\n", __func__);
-		return -EFAULT;
-	}
-
-	pm8058_chg.pm_chip = pm_chip;
 	pm8058_chg.pdata = pdev->dev.platform_data;
 	pm8058_chg.dev = &pdev->dev;
 	pdata = (struct pmic8058_charger_data *) pm8058_chg.pdata;
 
-	if (pdata) {
+	if (pdata == NULL) {
+		pr_err("%s: pdata not present\n", __func__);
+		return -EINVAL;
+	}
+
+	if (pdata->charger_data_valid) {
 		usb_hw_chg.type = pdata->charger_type;
 		chg_data.charger_type = pdata->charger_type;
 		chg_data.max_source_current = pdata->max_source_current;
@@ -1928,7 +1939,10 @@
 	pm8058_chg_enable_irq(BATTTEMP_IRQ);
 	pm8058_chg_enable_irq(BATTCONNECT_IRQ);
 
-	rc = pm8058_batt_alarm_state_set(0, 0);
+	rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+	if (!rc)
+		rc = pm8xxx_batt_alarm_disable(
+			PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
 	if (rc) {
 		pr_err("%s: unable to set batt alarm state\n", __func__);
 		goto free_irq;
@@ -1938,26 +1952,31 @@
 	 * The batt-alarm driver requires sane values for both min / max,
 	 * regardless of whether they're both activated.
 	 */
-	rc = pm8058_batt_alarm_threshold_set(resume_mv, 4300);
+	rc = pm8xxx_batt_alarm_threshold_set(
+			PM8XXX_BATT_ALARM_LOWER_COMPARATOR, resume_mv);
+	if (!rc)
+		rc = pm8xxx_batt_alarm_threshold_set(
+			PM8XXX_BATT_ALARM_UPPER_COMPARATOR, 4300);
 	if (rc) {
 		pr_err("%s: unable to set batt alarm threshold\n", __func__);
 		goto free_irq;
 	}
 
-	rc = pm8058_batt_alarm_hold_time_set(PM8058_BATT_ALARM_HOLD_TIME_16_MS);
+	rc = pm8xxx_batt_alarm_hold_time_set(
+				PM8XXX_BATT_ALARM_HOLD_TIME_16_MS);
 	if (rc) {
 		pr_err("%s: unable to set batt alarm hold time\n", __func__);
 		goto free_irq;
 	}
 
 	/* PWM enabled at 2Hz */
-	rc = pm8058_batt_alarm_pwm_rate_set(1, 7, 4);
+	rc = pm8xxx_batt_alarm_pwm_rate_set(1, 7, 4);
 	if (rc) {
 		pr_err("%s: unable to set batt alarm pwm rate\n", __func__);
 		goto free_irq;
 	}
 
-	rc = pm8058_batt_alarm_register_notifier(&alarm_notifier);
+	rc = pm8xxx_batt_alarm_register_notifier(&alarm_notifier);
 	if (rc) {
 		pr_err("%s: unable to register alarm notifier\n", __func__);
 		goto free_irq;
@@ -1987,11 +2006,14 @@
 	remove_debugfs_entries();
 	kfree(chip);
 
-	rc = pm8058_batt_alarm_state_set(0, 0);
+	rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+	if (!rc)
+		rc = pm8xxx_batt_alarm_disable(
+			PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
 	if (rc)
 		pr_err("%s: unable to set batt alarm state\n", __func__);
 
-	rc |= pm8058_batt_alarm_unregister_notifier(&alarm_notifier);
+	rc |= pm8xxx_batt_alarm_unregister_notifier(&alarm_notifier);
 	if (rc)
 		pr_err("%s: unable to register alarm notifier\n", __func__);
 	return rc;
diff --git a/drivers/regulator/pm8058-xo.c b/drivers/regulator/pm8058-xo.c
index 581e228..b778660 100644
--- a/drivers/regulator/pm8058-xo.c
+++ b/drivers/regulator/pm8058-xo.c
@@ -19,6 +19,7 @@
 #include <linux/bitops.h>
 #include <linux/mfd/pmic8058.h>
 #include <linux/regulator/driver.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/regulator/pm8058-xo.h>
 
 /* XO buffer masks and values */
@@ -39,6 +40,7 @@
 #define XO_DISABLE		(XO_MODE_MANUAL | XO_BUFFER_DISABLE)
 
 struct pm8058_xo_buffer {
+	struct device			*dev;
 	struct pm8058_xo_pdata		*pdata;
 	struct regulator_dev		*rdev;
 	u16				ctrl_addr;
@@ -55,7 +57,7 @@
 	XO_BUFFER(A1, 0x186),
 };
 
-static int pm8058_xo_buffer_write(struct pm8058_chip *chip,
+static int pm8058_xo_buffer_write(struct pm8058_xo_buffer *xo,
 		u16 addr, u8 val, u8 mask, u8 *reg_save)
 {
 	u8	reg;
@@ -63,10 +65,10 @@
 
 	reg = (*reg_save & ~mask) | (val & mask);
 	if (reg != *reg_save)
-		rc = pm8058_write(chip, addr, &reg, 1);
+		rc = pm8xxx_writeb(xo->dev->parent, addr, reg);
 
 	if (rc)
-		pr_err("FAIL: pm8058_write: rc=%d\n", rc);
+		pr_err("FAIL: pm8xxx_write: rc=%d\n", rc);
 	else
 		*reg_save = reg;
 	return rc;
@@ -75,10 +77,9 @@
 static int pm8058_xo_buffer_enable(struct regulator_dev *dev)
 {
 	struct pm8058_xo_buffer *xo = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 	int rc;
 
-	rc = pm8058_xo_buffer_write(chip, xo->ctrl_addr, XO_ENABLE,
+	rc = pm8058_xo_buffer_write(xo, xo->ctrl_addr, XO_ENABLE,
 				    XO_ENABLE_MASK, &xo->ctrl_reg);
 	if (rc)
 		pr_err("FAIL: pm8058_xo_buffer_write: rc=%d\n", rc);
@@ -99,10 +100,9 @@
 static int pm8058_xo_buffer_disable(struct regulator_dev *dev)
 {
 	struct pm8058_xo_buffer *xo = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 	int rc;
 
-	rc = pm8058_xo_buffer_write(chip, xo->ctrl_addr, XO_DISABLE,
+	rc = pm8058_xo_buffer_write(xo, xo->ctrl_addr, XO_DISABLE,
 				    XO_ENABLE_MASK, &xo->ctrl_reg);
 	if (rc)
 		pr_err("FAIL: pm8058_xo_buffer_write: rc=%d\n", rc);
@@ -130,23 +130,21 @@
 	VREG_DESCRIP(PM8058_XO_ID_A1, "8058_xo_a1", &pm8058_xo_ops),
 };
 
-static int pm8058_init_xo_buffer(struct pm8058_chip *chip,
-				 struct pm8058_xo_buffer *xo)
+static int pm8058_init_xo_buffer(struct pm8058_xo_buffer *xo)
 {
 	int	rc;
 
 	/* Save the current control register state */
-	rc = pm8058_read(chip, xo->ctrl_addr, &xo->ctrl_reg, 1);
+	rc = pm8xxx_readb(xo->dev->parent, xo->ctrl_addr, &xo->ctrl_reg);
 
 	if (rc)
-		pr_err("FAIL: pm8058_read: rc=%d\n", rc);
+		pr_err("FAIL: pm8xxx_read: rc=%d\n", rc);
 	return rc;
 }
 
 static int __devinit pm8058_xo_buffer_probe(struct platform_device *pdev)
 {
 	struct regulator_desc *rdesc;
-	struct pm8058_chip *chip;
 	struct pm8058_xo_buffer *xo;
 	int rc = 0;
 
@@ -154,16 +152,15 @@
 		return -EINVAL;
 
 	if (pdev->id >= 0 && pdev->id < PM8058_XO_ID_MAX) {
-		chip = dev_get_drvdata(pdev->dev.parent);
 		rdesc = &pm8058_xo_buffer_desc[pdev->id];
 		xo = &pm8058_xo_buffer[pdev->id];
 		xo->pdata = pdev->dev.platform_data;
+		xo->dev  = &pdev->dev;
 
-		rc = pm8058_init_xo_buffer(chip, xo);
+		rc = pm8058_init_xo_buffer(xo);
 		if (rc)
 			goto bail;
 
-		platform_set_drvdata(pdev, chip);
 		xo->rdev = regulator_register(rdesc, &pdev->dev,
 					&xo->pdata->init_data, xo);
 		if (IS_ERR(xo->rdev)) {
diff --git a/drivers/regulator/pmic8058-regulator.c b/drivers/regulator/pmic8058-regulator.c
index c11f32b..e137b0f 100644
--- a/drivers/regulator/pmic8058-regulator.c
+++ b/drivers/regulator/pmic8058-regulator.c
@@ -18,6 +18,7 @@
 #include <linux/mfd/pmic8058.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/mfd/pm8xxx/core.h>
 #include <linux/regulator/pmic8058-regulator.h>
 
 /* Regulator types */
@@ -205,6 +206,7 @@
 };
 
 struct pm8058_vreg {
+	struct device			*dev;
 	struct pm8058_vreg_pdata	*pdata;
 	struct regulator_dev		*rdev;
 	struct pm8058_enable		*global_enable[GLOBAL_ENABLE_MAX];
@@ -375,11 +377,9 @@
 	NCP(NCP, 0x090, 0x0EC),
 };
 
-static int pm8058_smps_set_voltage_advanced(struct pm8058_vreg *vreg,
-					struct pm8058_chip *chip, int uV,
+static int pm8058_smps_set_voltage_advanced(struct pm8058_vreg *vreg, int uV,
 					int force_on);
-static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg,
-					struct pm8058_chip *chip, int uV);
+static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg, int uV);
 static int _pm8058_vreg_is_enabled(struct pm8058_vreg *vreg);
 
 static unsigned int pm8058_vreg_get_mode(struct regulator_dev *dev);
@@ -387,7 +387,7 @@
 static void print_write_error(struct pm8058_vreg *vreg, int rc,
 				const char *func);
 
-static int pm8058_vreg_write(struct pm8058_chip *chip,
+static int pm8058_vreg_write(struct pm8058_vreg *vreg,
 		u16 addr, u8 val, u8 mask, u8 *reg_save)
 {
 	int rc = 0;
@@ -395,9 +395,9 @@
 
 	reg = (*reg_save & ~mask) | (val & mask);
 	if (reg != *reg_save)
-		rc = pm8058_write(chip, addr, &reg, 1);
+		rc = pm8xxx_writeb(vreg->dev->parent, addr, reg);
 	if (rc)
-		pr_err("%s: pm8058_write failed, rc=%d\n", __func__, rc);
+		pr_err("%s: pm8xxx_write failed, rc=%d\n", __func__, rc);
 	else
 		*reg_save = reg;
 	return rc;
@@ -416,14 +416,13 @@
 }
 
 
-static int pm8058_vreg_set_global_enable(struct pm8058_vreg *vreg,
-					 struct pm8058_chip *chip, int on)
+static int pm8058_vreg_set_global_enable(struct pm8058_vreg *vreg, int on)
 {
 	int rc = 0, i;
 
 	for (i = 0;
 	     (i < GLOBAL_ENABLE_MAX) && !rc && vreg->global_enable[i]; i++)
-		rc = pm8058_vreg_write(chip, vreg->global_enable[i]->addr,
+		rc = pm8058_vreg_write(vreg, vreg->global_enable[i]->addr,
 					(on ? vreg->global_enable_mask[i] : 0),
 					vreg->global_enable_mask[i],
 					&vreg->global_enable[i]->reg);
@@ -452,8 +451,7 @@
 	return ret;
 }
 
-static int pm8058_vreg_set_pin_ctrl(struct pm8058_vreg *vreg,
-		struct pm8058_chip *chip, int on)
+static int pm8058_vreg_set_pin_ctrl(struct pm8058_vreg *vreg, int on)
 {
 	int rc = 0, bank;
 	u8 val = 0, mask;
@@ -473,7 +471,7 @@
 				val |= LDO_TEST_PIN_CTRL_EN3;
 
 			bank = (pf == PM8058_VREG_PIN_FN_ENABLE ? 5 : 6);
-			rc = pm8058_vreg_write(chip, vreg->test_addr,
+			rc = pm8058_vreg_write(vreg, vreg->test_addr,
 				val | REGULATOR_BANK_SEL(bank)
 				  | REGULATOR_BANK_WRITE,
 				LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK,
@@ -484,26 +482,25 @@
 			val = LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE
 				| REGULATOR_BANK_SEL(0);
 			mask = LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK;
-			rc = pm8058_vreg_write(chip, vreg->test_addr, val, mask,
+			rc = pm8058_vreg_write(vreg, vreg->test_addr, val, mask,
 						&vreg->test_reg[0]);
 			if (rc)
 				goto bail;
 
 			if (pf == PM8058_VREG_PIN_FN_ENABLE) {
 				/* Pin control ON/OFF */
-				rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+				rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
 					LDO_CTRL_PM_HPM,
 					LDO_ENABLE_MASK | LDO_CTRL_PM_MASK,
 					&vreg->ctrl_reg);
 				if (rc)
 					goto bail;
-				rc = pm8058_vreg_set_global_enable(vreg, chip,
-								   0);
+				rc = pm8058_vreg_set_global_enable(vreg, 0);
 				if (rc)
 					goto bail;
 			} else {
 				/* Pin control LPM/HPM */
-				rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+				rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
 					LDO_ENABLE | LDO_CTRL_PM_LPM,
 					LDO_ENABLE_MASK | LDO_CTRL_PM_MASK,
 					&vreg->ctrl_reg);
@@ -512,14 +509,14 @@
 			}
 		} else {
 			/* Pin control off */
-			rc = pm8058_vreg_write(chip, vreg->test_addr,
+			rc = pm8058_vreg_write(vreg, vreg->test_addr,
 				REGULATOR_BANK_SEL(5) | REGULATOR_BANK_WRITE,
 				LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK,
 				&vreg->test_reg[5]);
 			if (rc)
 				goto bail;
 
-			rc = pm8058_vreg_write(chip, vreg->test_addr,
+			rc = pm8058_vreg_write(vreg, vreg->test_addr,
 				REGULATOR_BANK_SEL(6) | REGULATOR_BANK_WRITE,
 				LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK,
 				&vreg->test_reg[6]);
@@ -551,29 +548,29 @@
 				if (pc & PM8058_VREG_PIN_CTRL_A1)
 					val |= SMPS_PIN_CTRL_LPM_A1;
 			}
-			rc = pm8058_vreg_set_global_enable(vreg, chip, 0);
+			rc = pm8058_vreg_set_global_enable(vreg, 0);
 			if (rc)
 				goto bail;
 
-			rc = pm8058_smps_set_voltage_legacy(vreg, chip,
+			rc = pm8058_smps_set_voltage_legacy(vreg,
 							vreg->save_uV);
 			if (rc)
 				goto bail;
 
-			rc = pm8058_vreg_write(chip, vreg->sleep_ctrl_addr, val,
+			rc = pm8058_vreg_write(vreg, vreg->sleep_ctrl_addr, val,
 				SMPS_PIN_CTRL_MASK | SMPS_PIN_CTRL_LPM_MASK,
 				&vreg->sleep_ctrl_reg);
 			if (rc)
 				goto bail;
 
-			rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+			rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
 				(pf == PM8058_VREG_PIN_FN_ENABLE
 				       ? 0 : SMPS_LEGACY_ENABLE),
 				SMPS_LEGACY_ENABLE, &vreg->ctrl_reg);
 			if (rc)
 				goto bail;
 
-			rc = pm8058_vreg_write(chip, vreg->clk_ctrl_addr,
+			rc = pm8058_vreg_write(vreg, vreg->clk_ctrl_addr,
 				(pf == PM8058_VREG_PIN_FN_ENABLE
 				       ? SMPS_CLK_CTRL_PWM : SMPS_CLK_CTRL_PFM),
 				SMPS_CLK_CTRL_MASK, &vreg->clk_ctrl_reg);
@@ -584,20 +581,20 @@
 			if (!SMPS_IN_ADVANCED_MODE(vreg)) {
 				if (_pm8058_vreg_is_enabled(vreg))
 					val = SMPS_LEGACY_ENABLE;
-				rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+				rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
 					val, SMPS_LEGACY_ENABLE,
 					&vreg->ctrl_reg);
 				if (rc)
 					goto bail;
 			}
 
-			rc = pm8058_vreg_write(chip, vreg->sleep_ctrl_addr, 0,
+			rc = pm8058_vreg_write(vreg, vreg->sleep_ctrl_addr, 0,
 				SMPS_PIN_CTRL_MASK | SMPS_PIN_CTRL_LPM_MASK,
 				&vreg->sleep_ctrl_reg);
 			if (rc)
 				goto bail;
 
-			rc = pm8058_smps_set_voltage_advanced(vreg, chip,
+			rc = pm8058_smps_set_voltage_advanced(vreg,
 							 vreg->save_uV, 0);
 			if (rc)
 				goto bail;
@@ -615,13 +612,13 @@
 			if (pc & PM8058_VREG_PIN_CTRL_A1)
 				val |= LVS_PIN_CTRL_EN3;
 
-			rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val,
+			rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val,
 					LVS_PIN_CTRL_MASK | LVS_ENABLE_MASK,
 					&vreg->ctrl_reg);
 			if (rc)
 				goto bail;
 
-			rc = pm8058_vreg_set_global_enable(vreg, chip, 0);
+			rc = pm8058_vreg_set_global_enable(vreg, 0);
 			if (rc)
 				goto bail;
 		} else {
@@ -629,7 +626,7 @@
 			if (_pm8058_vreg_is_enabled(vreg))
 				val = LVS_ENABLE;
 
-			rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val,
+			rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val,
 					LVS_ENABLE_MASK | LVS_PIN_CTRL_MASK,
 					&vreg->ctrl_reg);
 			if (rc)
@@ -649,7 +646,6 @@
 static int pm8058_vreg_enable(struct regulator_dev *dev)
 {
 	struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 	int mode;
 	int rc = 0;
 
@@ -657,16 +653,15 @@
 
 	if (mode == REGULATOR_MODE_IDLE) {
 		/* Turn on pin control. */
-		rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+		rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
 		if (rc)
 			goto bail;
 		return rc;
 	}
 	if (vreg->type == REGULATOR_TYPE_SMPS && SMPS_IN_ADVANCED_MODE(vreg))
-		rc = pm8058_smps_set_voltage_advanced(vreg, chip,
-							vreg->save_uV, 1);
+		rc = pm8058_smps_set_voltage_advanced(vreg, vreg->save_uV, 1);
 	else
-		rc = pm8058_vreg_write(chip, vreg->ctrl_addr, REGULATOR_EN_MASK,
+		rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, REGULATOR_EN_MASK,
 			REGULATOR_EN_MASK, &vreg->ctrl_reg);
 bail:
 	if (rc)
@@ -706,26 +701,25 @@
 static int pm8058_vreg_disable(struct regulator_dev *dev)
 {
 	struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 	int rc = 0;
 
 	/* Disable in global control register. */
-	rc = pm8058_vreg_set_global_enable(vreg, chip, 0);
+	rc = pm8058_vreg_set_global_enable(vreg, 0);
 	if (rc)
 		goto bail;
 
 	/* Turn off pin control. */
-	rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+	rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
 	if (rc)
 		goto bail;
 
 	/* Disable in local control register. */
 	if (vreg->type == REGULATOR_TYPE_SMPS && SMPS_IN_ADVANCED_MODE(vreg))
-		rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+		rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
 			SMPS_ADVANCED_BAND_OFF, SMPS_ADVANCED_BAND_MASK,
 			&vreg->ctrl_reg);
 	else
-		rc = pm8058_vreg_write(chip, vreg->ctrl_addr, 0,
+		rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, 0,
 			REGULATOR_EN_MASK, &vreg->ctrl_reg);
 
 bail:
@@ -735,8 +729,7 @@
 	return rc;
 }
 
-static int pm8058_pldo_set_voltage(struct pm8058_chip *chip,
-		struct pm8058_vreg *vreg, int uV)
+static int pm8058_pldo_set_voltage(struct pm8058_vreg *vreg, int uV)
 {
 	int vmin, rc = 0;
 	unsigned vprog, fine_step;
@@ -775,7 +768,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 = pm8058_vreg_write(chip, vreg->test_addr,
+		rc = pm8058_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]);
@@ -784,13 +777,13 @@
 	}
 
 	/* Write new voltage. */
-	rc = pm8058_vreg_write(chip, vreg->ctrl_addr, vprog,
+	rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, vprog,
 				LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
 	if (rc)
 		goto bail;
 
 	/* Write range extension. */
-	rc = pm8058_vreg_write(chip, vreg->test_addr,
+	rc = pm8058_vreg_write(vreg, vreg->test_addr,
 			range_ext | REGULATOR_BANK_SEL(4)
 			 | REGULATOR_BANK_WRITE,
 			LDO_TEST_RANGE_EXT_MASK | REGULATOR_BANK_MASK,
@@ -799,7 +792,7 @@
 		goto bail;
 
 	/* Write fine step, range select and program voltage update. */
-	rc = pm8058_vreg_write(chip, vreg->test_addr,
+	rc = pm8058_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
@@ -812,8 +805,7 @@
 	return rc;
 }
 
-static int pm8058_nldo_set_voltage(struct pm8058_chip *chip,
-		struct pm8058_vreg *vreg, int uV)
+static int pm8058_nldo_set_voltage(struct pm8058_vreg *vreg, int uV)
 {
 	unsigned vprog, fine_step_reg;
 	int rc;
@@ -826,13 +818,13 @@
 	vprog >>= 1;
 
 	/* Write new voltage. */
-	rc = pm8058_vreg_write(chip, vreg->ctrl_addr, vprog,
+	rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, vprog,
 				LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
 	if (rc)
 		goto bail;
 
 	/* Write fine step. */
-	rc = pm8058_vreg_write(chip, vreg->test_addr,
+	rc = pm8058_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
@@ -849,12 +841,11 @@
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 
 	if (vreg->is_nmos)
-		return pm8058_nldo_set_voltage(chip, vreg, min_uV);
+		return pm8058_nldo_set_voltage(vreg, min_uV);
 	else
-		return pm8058_pldo_set_voltage(chip, vreg, min_uV);
+		return pm8058_pldo_set_voltage(vreg, min_uV);
 }
 
 static int pm8058_pldo_get_voltage(struct pm8058_vreg *vreg)
@@ -967,8 +958,7 @@
 }
 
 static int pm8058_smps_set_voltage_advanced(struct pm8058_vreg *vreg,
-					struct pm8058_chip *chip, int uV,
-					int force_on)
+					int uV,	int force_on)
 {
 	u8 vprog, band;
 	int rc, new_uV;
@@ -992,7 +982,7 @@
 		band = SMPS_ADVANCED_BAND_OFF;
 
 	/* Set advanced mode bit to 1. */
-	rc = pm8058_vreg_write(chip, vreg->test_addr, SMPS_ADVANCED_MODE
+	rc = pm8058_vreg_write(vreg, vreg->test_addr, SMPS_ADVANCED_MODE
 		| REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(7),
 		SMPS_ADVANCED_MODE_MASK | REGULATOR_BANK_MASK,
 		&vreg->test_reg[7]);
@@ -1000,7 +990,7 @@
 		goto bail;
 
 	/* Set voltage and voltage band. */
-	rc = pm8058_vreg_write(chip, vreg->ctrl_addr, band | vprog,
+	rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, band | vprog,
 			SMPS_ADVANCED_BAND_MASK | SMPS_ADVANCED_VPROG_MASK,
 			&vreg->ctrl_reg);
 	if (rc)
@@ -1012,8 +1002,7 @@
 	return rc;
 }
 
-static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg,
-					struct pm8058_chip *chip, int uV)
+static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg, int uV)
 {
 	u8 vlow, vref, vprog, pd, en;
 	int rc;
@@ -1033,7 +1022,7 @@
 	}
 
 	/* set vlow bit for ultra low voltage mode */
-	rc = pm8058_vreg_write(chip, vreg->test_addr,
+	rc = pm8058_vreg_write(vreg, vreg->test_addr,
 		vlow | REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(1),
 		REGULATOR_BANK_MASK | SMPS_LEGACY_VLOW_SEL_MASK,
 		&vreg->test_reg[1]);
@@ -1041,7 +1030,7 @@
 		goto bail;
 
 	/* Set advanced mode bit to 0. */
-	rc = pm8058_vreg_write(chip, vreg->test_addr, SMPS_LEGACY_MODE
+	rc = pm8058_vreg_write(vreg, vreg->test_addr, SMPS_LEGACY_MODE
 		| REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(7),
 		SMPS_ADVANCED_MODE_MASK | REGULATOR_BANK_MASK,
 		&vreg->test_reg[7]);
@@ -1052,7 +1041,7 @@
 	pd = (vreg->pdata->pull_down_enable ? SMPS_LEGACY_PULL_DOWN_ENABLE : 0);
 
 	/* Set voltage (and the rest of the control register). */
-	rc = pm8058_vreg_write(chip, vreg->ctrl_addr, en | pd | vref | vprog,
+	rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, en | pd | vref | vprog,
 		SMPS_LEGACY_ENABLE | SMPS_LEGACY_PULL_DOWN_ENABLE
 		| SMPS_LEGACY_VREF_SEL_MASK | SMPS_LEGACY_VPROG_MASK,
 		&vreg->ctrl_reg);
@@ -1067,16 +1056,15 @@
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 	int rc = 0;
 
 	if (min_uV < SMPS_UV_MIN || min_uV > SMPS_UV_MAX)
 		return -EINVAL;
 
 	if (SMPS_IN_ADVANCED_MODE(vreg))
-		rc = pm8058_smps_set_voltage_advanced(vreg, chip, min_uV, 0);
+		rc = pm8058_smps_set_voltage_advanced(vreg, min_uV, 0);
 	else
-		rc = pm8058_smps_set_voltage_legacy(vreg, chip, min_uV);
+		rc = pm8058_smps_set_voltage_legacy(vreg, min_uV);
 
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -1088,7 +1076,6 @@
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 	int rc;
 	u8 val;
 
@@ -1098,7 +1085,7 @@
 	val = (min_uV - NCP_UV_MIN) / NCP_UV_STEP;
 
 	/* voltage setting */
-	rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val, NCP_VPROG_MASK,
+	rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val, NCP_VPROG_MASK,
 			&vreg->ctrl_reg);
 	if (rc)
 		print_write_error(vreg, rc, __func__);
@@ -1113,8 +1100,7 @@
 	return NCP_UV_MIN + vprog * NCP_UV_STEP;
 }
 
-static int pm8058_ldo_set_mode(struct pm8058_vreg *vreg,
-		struct pm8058_chip *chip, unsigned int mode)
+static int pm8058_ldo_set_mode(struct pm8058_vreg *vreg, unsigned int mode)
 {
 	int rc = 0;
 	u8 mask, val;
@@ -1125,13 +1111,13 @@
 		val = (_pm8058_vreg_is_enabled(vreg) ? LDO_ENABLE : 0)
 			| LDO_CTRL_PM_HPM;
 		mask = LDO_ENABLE_MASK | LDO_CTRL_PM_MASK;
-		rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val, mask,
+		rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val, mask,
 					&vreg->ctrl_reg);
 		if (rc)
 			goto bail;
 
 		if (pm8058_vreg_using_pin_ctrl(vreg))
-			rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+			rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
 		if (rc)
 			goto bail;
 		break;
@@ -1141,7 +1127,7 @@
 		val = (_pm8058_vreg_is_enabled(vreg) ? LDO_ENABLE : 0)
 			| LDO_CTRL_PM_LPM;
 		mask = LDO_ENABLE_MASK | LDO_CTRL_PM_MASK;
-		rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val, mask,
+		rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val, mask,
 					&vreg->ctrl_reg);
 		if (rc)
 			goto bail;
@@ -1149,13 +1135,13 @@
 		val = LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE
 			| REGULATOR_BANK_SEL(0);
 		mask = LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK;
-		rc = pm8058_vreg_write(chip, vreg->test_addr, val, mask,
+		rc = pm8058_vreg_write(vreg, vreg->test_addr, val, mask,
 					&vreg->test_reg[0]);
 		if (rc)
 			goto bail;
 
 		if (pm8058_vreg_using_pin_ctrl(vreg))
-			rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+			rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
 		if (rc)
 			goto bail;
 		break;
@@ -1163,7 +1149,7 @@
 	case REGULATOR_MODE_IDLE:
 		/* Pin Control */
 		if (_pm8058_vreg_is_enabled(vreg))
-			rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+			rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
 		if (rc)
 			goto bail;
 		break;
@@ -1180,8 +1166,7 @@
 	return rc;
 }
 
-static int pm8058_smps_set_mode(struct pm8058_vreg *vreg,
-		struct pm8058_chip *chip, unsigned int mode)
+static int pm8058_smps_set_mode(struct pm8058_vreg *vreg, unsigned int mode)
 {
 	int rc = 0;
 	u8 mask, val;
@@ -1191,13 +1176,13 @@
 		/* HPM */
 		val = SMPS_CLK_CTRL_PWM;
 		mask = SMPS_CLK_CTRL_MASK;
-		rc = pm8058_vreg_write(chip, vreg->clk_ctrl_addr, val, mask,
+		rc = pm8058_vreg_write(vreg, vreg->clk_ctrl_addr, val, mask,
 					&vreg->clk_ctrl_reg);
 		if (rc)
 			goto bail;
 
 		if (pm8058_vreg_using_pin_ctrl(vreg))
-			rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+			rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
 		if (rc)
 			goto bail;
 		break;
@@ -1206,13 +1191,13 @@
 		/* LPM */
 		val = SMPS_CLK_CTRL_PFM;
 		mask = SMPS_CLK_CTRL_MASK;
-		rc = pm8058_vreg_write(chip, vreg->clk_ctrl_addr, val, mask,
+		rc = pm8058_vreg_write(vreg, vreg->clk_ctrl_addr, val, mask,
 					&vreg->clk_ctrl_reg);
 		if (rc)
 			goto bail;
 
 		if (pm8058_vreg_using_pin_ctrl(vreg))
-			rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+			rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
 		if (rc)
 			goto bail;
 		break;
@@ -1220,7 +1205,7 @@
 	case REGULATOR_MODE_IDLE:
 		/* Pin Control */
 		if (_pm8058_vreg_is_enabled(vreg))
-			rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+			rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
 		if (rc)
 			goto bail;
 		break;
@@ -1237,18 +1222,17 @@
 	return rc;
 }
 
-static int pm8058_lvs_set_mode(struct pm8058_vreg *vreg,
-		struct pm8058_chip *chip, unsigned int mode)
+static int pm8058_lvs_set_mode(struct pm8058_vreg *vreg, unsigned int mode)
 {
 	int rc = 0;
 
 	if (mode == REGULATOR_MODE_IDLE) {
 		/* Use pin control. */
 		if (_pm8058_vreg_is_enabled(vreg))
-			rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+			rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
 	} else {
 		/* Turn off pin control. */
-		rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+		rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
 	}
 
 	return rc;
@@ -1268,7 +1252,6 @@
 static int pm8058_vreg_set_mode(struct regulator_dev *dev, unsigned int mode)
 {
 	struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
-	struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
 	unsigned prev_optimum = vreg->optimum;
 	unsigned prev_pc_vote = vreg->pc_vote;
 	unsigned prev_mode_initialized = vreg->mode_initialized;
@@ -1320,13 +1303,13 @@
 
 	switch (vreg->type) {
 	case REGULATOR_TYPE_LDO:
-		rc = pm8058_ldo_set_mode(vreg, chip, new_mode);
+		rc = pm8058_ldo_set_mode(vreg, new_mode);
 		break;
 	case REGULATOR_TYPE_SMPS:
-		rc = pm8058_smps_set_mode(vreg, chip, new_mode);
+		rc = pm8058_smps_set_mode(vreg, new_mode);
 		break;
 	case REGULATOR_TYPE_LVS:
-		rc = pm8058_lvs_set_mode(vreg, chip, new_mode);
+		rc = pm8058_lvs_set_mode(vreg, new_mode);
 		break;
 	}
 
@@ -1499,24 +1482,25 @@
 	VREG_DESCRIP(PM8058_VREG_ID_NCP, "8058_ncp", &pm8058_ncp_ops),
 };
 
-static int pm8058_master_enable_init(struct pm8058_chip *chip)
+static int pm8058_master_enable_init(struct pm8058_vreg *vreg)
 {
 	int rc = 0, i;
 
 	for (i = 0; i < MASTER_ENABLE_COUNT; i++) {
-		rc = pm8058_read(chip, m_en[i].addr, &(m_en[i].reg), 1);
+		rc = pm8xxx_readb(vreg->dev->parent, m_en[i].addr,
+							&(m_en[i].reg));
 		if (rc)
 			goto bail;
 	}
 
 bail:
 	if (rc)
-		pr_err("%s: pm8058_read failed, rc=%d\n", __func__, rc);
+		pr_err("%s: pm8xxx_read failed, rc=%d\n", __func__, rc);
 
 	return rc;
 }
 
-static int pm8058_init_ldo(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_ldo(struct pm8058_vreg *vreg)
 {
 	int rc = 0, i;
 	u8 bank;
@@ -1524,11 +1508,12 @@
 	/* Save the current test register state. */
 	for (i = 0; i < LDO_TEST_BANKS; i++) {
 		bank = REGULATOR_BANK_SEL(i);
-		rc = pm8058_write(chip, vreg->test_addr, &bank, 1);
+		rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank);
 		if (rc)
 			goto bail;
 
-		rc = pm8058_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;
 		vreg->test_reg[i] |= REGULATOR_BANK_WRITE;
@@ -1540,14 +1525,14 @@
 		vreg->optimum = REGULATOR_MODE_FAST;
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+	rc = pm8058_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 pm8058_init_smps(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_smps(struct pm8058_vreg *vreg)
 {
 	int rc = 0, i;
 	u8 bank;
@@ -1555,24 +1540,26 @@
 	/* Save the current test2 register state. */
 	for (i = 0; i < SMPS_TEST_BANKS; i++) {
 		bank = REGULATOR_BANK_SEL(i);
-		rc = pm8058_write(chip, vreg->test_addr, &bank, 1);
+		rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank);
 		if (rc)
 			goto bail;
 
-		rc = pm8058_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;
 		vreg->test_reg[i] |= REGULATOR_BANK_WRITE;
 	}
 
 	/* Save the current clock control register state. */
-	rc = pm8058_read(chip, vreg->clk_ctrl_addr, &vreg->clk_ctrl_reg, 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->clk_ctrl_addr,
+						&vreg->clk_ctrl_reg);
 	if (rc)
 		goto bail;
 
 	/* Save the current sleep control register state. */
-	rc = pm8058_read(chip, vreg->sleep_ctrl_addr, &vreg->sleep_ctrl_reg, 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->sleep_ctrl_addr,
+						&vreg->sleep_ctrl_reg);
 	if (rc)
 		goto bail;
 
@@ -1585,7 +1572,7 @@
 		vreg->optimum = REGULATOR_MODE_FAST;
 
 	/* Set advanced mode pull down enable based on platform data. */
-	rc = pm8058_vreg_write(chip, vreg->test_addr,
+	rc = pm8058_vreg_write(vreg, vreg->test_addr,
 		(vreg->pdata->pull_down_enable
 			? SMPS_ADVANCED_PULL_DOWN_ENABLE : 0)
 		| REGULATOR_BANK_SEL(6) | REGULATOR_BANK_WRITE,
@@ -1596,7 +1583,7 @@
 
 	if (!SMPS_IN_ADVANCED_MODE(vreg)) {
 		/* Set legacy mode pull down enable based on platform data. */
-		rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+		rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
 			(vreg->pdata->pull_down_enable
 				? SMPS_LEGACY_PULL_DOWN_ENABLE : 0),
 			SMPS_LEGACY_PULL_DOWN_ENABLE, &vreg->ctrl_reg);
@@ -1608,26 +1595,27 @@
 	return rc;
 }
 
-static int pm8058_init_lvs(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_lvs(struct pm8058_vreg *vreg)
 {
 	int rc = 0;
 
 	vreg->optimum = REGULATOR_MODE_FAST;
 
 	/* Set pull down enable based on platform data. */
-	rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+	rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
 		(vreg->pdata->pull_down_enable
 			? LVS_PULL_DOWN_ENABLE : LVS_PULL_DOWN_DISABLE),
 		LVS_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
 	return rc;
 }
 
-static int pm8058_init_ncp(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_ncp(struct pm8058_vreg *vreg)
 {
 	int rc = 0;
 
 	/* Save the current test1 register state. */
-	rc = pm8058_read(chip, vreg->test_addr, &vreg->test_reg[0], 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+					&vreg->test_reg[0]);
 	if (rc)
 		goto bail;
 
@@ -1637,8 +1625,7 @@
 	return rc;
 }
 
-static int pm8058_init_regulator(struct pm8058_chip *chip,
-		struct pm8058_vreg *vreg)
+static int pm8058_init_regulator(struct pm8058_vreg *vreg)
 {
 	static int master_enable_inited;
 	int rc = 0;
@@ -1646,28 +1633,28 @@
 	vreg->mode_initialized = 0;
 
 	if (!master_enable_inited) {
-		rc = pm8058_master_enable_init(chip);
+		rc = pm8058_master_enable_init(vreg);
 		if (!rc)
 			master_enable_inited = 1;
 	}
 
 	/* save the current control register state */
-	rc = pm8058_read(chip, vreg->ctrl_addr, &vreg->ctrl_reg, 1);
+	rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg);
 	if (rc)
 		goto bail;
 
 	switch (vreg->type) {
 	case REGULATOR_TYPE_LDO:
-		rc = pm8058_init_ldo(chip, vreg);
+		rc = pm8058_init_ldo(vreg);
 		break;
 	case REGULATOR_TYPE_SMPS:
-		rc = pm8058_init_smps(chip, vreg);
+		rc = pm8058_init_smps(vreg);
 		break;
 	case REGULATOR_TYPE_LVS:
-		rc = pm8058_init_lvs(chip, vreg);
+		rc = pm8058_init_lvs(vreg);
 		break;
 	case REGULATOR_TYPE_NCP:
-		rc = pm8058_init_ncp(chip, vreg);
+		rc = pm8058_init_ncp(vreg);
 		break;
 	}
 
@@ -1681,7 +1668,6 @@
 static int __devinit pm8058_vreg_probe(struct platform_device *pdev)
 {
 	struct regulator_desc *rdesc;
-	struct pm8058_chip *chip;
 	struct pm8058_vreg *vreg;
 	const char *reg_name = NULL;
 	int rc = 0;
@@ -1690,13 +1676,13 @@
 		return -EINVAL;
 
 	if (pdev->id >= 0 && pdev->id < PM8058_VREG_MAX) {
-		chip = dev_get_drvdata(pdev->dev.parent);
 		rdesc = &pm8058_vreg_descrip[pdev->id];
 		vreg = &pm8058_vreg[pdev->id];
 		vreg->pdata = pdev->dev.platform_data;
 		reg_name = pm8058_vreg_descrip[pdev->id].name;
+		vreg->dev = &pdev->dev;
 
-		rc = pm8058_init_regulator(chip, vreg);
+		rc = pm8058_init_regulator(vreg);
 		if (rc)
 			goto bail;
 
@@ -1705,7 +1691,6 @@
 			vreg->pdata->init_data.constraints.valid_modes_mask
 			      &= ~(REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE);
 
-		platform_set_drvdata(pdev, chip);
 		vreg->rdev = regulator_register(rdesc, &pdev->dev,
 				&vreg->pdata->init_data, vreg);
 		if (IS_ERR(vreg->rdev)) {
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 1e4302b..6aa111c 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -21,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/clk.h>
+#include <linux/pm_runtime.h>
 #include <mach/sps.h>
 
 /* Per spec.max 40 bytes per received message */
@@ -44,6 +45,7 @@
 #define MSM_SLIM_PERF_SUMM_THRESHOLD	0x8000
 #define MSM_SLIM_NCHANS			32
 #define MSM_SLIM_NPORTS			24
+#define MSM_SLIM_AUTOSUSPEND		MSEC_PER_SEC
 
 /*
  * Need enough descriptors to receive present messages from slaves
@@ -80,6 +82,7 @@
 #define QC_DEVID_SAT1	0x3
 #define QC_DEVID_SAT2	0x4
 #define QC_DEVID_PGD	0x5
+#define QC_MSM_DEVS	5
 
 /* Component registers */
 enum comp_reg {
@@ -184,6 +187,12 @@
 	REF_CLK_GEAR	= 15,
 };
 
+enum msm_ctrl_state {
+	MSM_CTRL_AWAKE,
+	MSM_CTRL_SLEEPING,
+	MSM_CTRL_ASLEEP,
+};
+
 struct msm_slim_sps_bam {
 	u32			hdl;
 	void __iomem		*base;
@@ -226,10 +235,11 @@
 	struct mutex		tx_lock;
 	u8			pgdla;
 	bool			use_rx_msgqs;
-	int			suspended;
 	int			pipe_b;
 	struct completion	reconf;
 	bool			reconf_busy;
+	bool			chan_active;
+	enum msm_ctrl_state	state;
 };
 
 struct msm_slim_sat {
@@ -241,6 +251,8 @@
 	u16			*satch;
 	u8			nsatch;
 	bool			sent_capability;
+	bool			pending_reconf;
+	bool			pending_capability;
 	int			shead;
 	int			stail;
 	spinlock_t lock;
@@ -322,6 +334,16 @@
 	return false;
 }
 
+static void msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
+{
+	pm_runtime_get_sync(dev->dev);
+}
+static void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
+{
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put(dev->dev);
+}
+
 static irqreturn_t msm_slim_interrupt(int irq, void *d)
 {
 	struct msm_slim_ctrl *dev = d;
@@ -450,6 +472,10 @@
 		 * before exiting ISR
 		 */
 		mb();
+		if (dev->ctrl.sched.usedslots == 0 && dev->chan_active) {
+			dev->chan_active = false;
+			msm_slim_put_ctrl(dev);
+		}
 		complete(&dev->reconf);
 	}
 	pstat = readl_relaxed(dev->base + PGD_PORT_INT_ST_EEn + (16 * dev->ee));
@@ -649,17 +675,37 @@
 	u8 *puc;
 	int timeout;
 	u8 la = txn->la;
+	u8 mc = (u8)(txn->mc & 0xFF);
+	/*
+	 * Voting for runtime PM: Slimbus has 2 possible use cases:
+	 * 1. messaging
+	 * 2. Data channels
+	 * Messaging case goes through messaging slots and data channels
+	 * use their own slots
+	 * This "get" votes for messaging bandwidth
+	 */
+	if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+		msm_slim_get_ctrl(dev);
 	mutex_lock(&dev->tx_lock);
+	if (dev->state == MSM_CTRL_ASLEEP) {
+		dev_err(dev->dev, "runtime or system PM suspended state");
+		mutex_unlock(&dev->tx_lock);
+		if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+			msm_slim_put_ctrl(dev);
+		return -EBUSY;
+	}
 	if (txn->mt == SLIM_MSG_MT_CORE &&
-		txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
-		dev->reconf_busy) {
+		mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION) {
+		if (dev->reconf_busy) {
 			wait_for_completion(&dev->reconf);
 			dev->reconf_busy = false;
-	}
-	if (dev->suspended) {
-		dev_err(dev->dev, "No transaction in suspended state");
-		mutex_unlock(&dev->tx_lock);
-		return -EBUSY;
+		}
+		/* This "get" votes for data channels */
+		if (dev->ctrl.sched.usedslots != 0 &&
+			!dev->chan_active) {
+			dev->chan_active = true;
+			msm_slim_get_ctrl(dev);
+		}
 	}
 	txn->rl--;
 	pbuf = msm_get_msg_buf(ctrl, txn->rl);
@@ -668,19 +714,19 @@
 
 	if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
 		mutex_unlock(&dev->tx_lock);
+		if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+			msm_slim_put_ctrl(dev);
 		return -EPROTONOSUPPORT;
 	}
 	if (txn->mt == SLIM_MSG_MT_CORE && txn->la == 0xFF &&
-		(txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
-		 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
-		 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT))
+		(mc == SLIM_MSG_MC_CONNECT_SOURCE ||
+		 mc == SLIM_MSG_MC_CONNECT_SINK ||
+		 mc == SLIM_MSG_MC_DISCONNECT_PORT))
 		la = dev->pgdla;
 	if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
-		*pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc,
-					0, la);
+		*pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, mc, 0, la);
 	else
-		*pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc,
-					1, la);
+		*pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, mc, 1, la);
 	if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
 		puc = ((u8 *)pbuf) + 3;
 	else
@@ -688,20 +734,20 @@
 	if (txn->rbuf)
 		*(puc++) = txn->tid;
 	if ((txn->mt == SLIM_MSG_MT_CORE) &&
-		((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
-		txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
-		(txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
-		 txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
+		((mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
+		mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
+		(mc >= SLIM_MSG_MC_REQUEST_VALUE &&
+		 mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
 		*(puc++) = (txn->ec & 0xFF);
 		*(puc++) = (txn->ec >> 8)&0xFF;
 	}
 	if (txn->wbuf)
 		memcpy(puc, txn->wbuf, txn->len);
 	if (txn->mt == SLIM_MSG_MT_CORE && txn->la == 0xFF &&
-		(txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
-		 txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
-		 txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
-		if (txn->mc != SLIM_MSG_MC_DISCONNECT_PORT)
+		(mc == SLIM_MSG_MC_CONNECT_SOURCE ||
+		 mc == SLIM_MSG_MC_CONNECT_SINK ||
+		 mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
+		if (mc != SLIM_MSG_MC_DISCONNECT_PORT)
 			dev->err = msm_slim_connect_pipe_port(dev, *puc);
 		else {
 			struct msm_slim_endp *endpoint = &dev->pipes[*puc];
@@ -715,25 +761,49 @@
 			 */
 			dev->pipes[*puc].connected = false;
 			mutex_unlock(&dev->tx_lock);
+			msm_slim_put_ctrl(dev);
 			return 0;
 		}
 		if (dev->err) {
 			dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
 			mutex_unlock(&dev->tx_lock);
+			msm_slim_put_ctrl(dev);
 			return dev->err;
 		}
 		*(puc) = *(puc) + dev->pipe_b;
 	}
 	if (txn->mt == SLIM_MSG_MT_CORE &&
-		txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION)
+		mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION)
 		dev->reconf_busy = true;
 	dev->wr_comp = &done;
 	msm_send_msg_buf(ctrl, pbuf, txn->rl);
 	timeout = wait_for_completion_timeout(&done, HZ);
+
+	if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
+				SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && timeout) {
+		timeout = wait_for_completion_timeout(&dev->reconf, HZ);
+		dev->reconf_busy = false;
+		if (timeout) {
+			clk_disable(dev->rclk);
+			disable_irq(dev->irq);
+		}
+	}
+	if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
+				SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && !timeout) {
+		dev->reconf_busy = false;
+		dev_err(dev->dev, "clock pause failed");
+		mutex_unlock(&dev->tx_lock);
+		return -ETIMEDOUT;
+	}
+
+	mutex_unlock(&dev->tx_lock);
+	if (!txn->rbuf && !(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+		msm_slim_put_ctrl(dev);
+
 	if (!timeout)
 		dev_err(dev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
 					txn->mt);
-	mutex_unlock(&dev->tx_lock);
+
 	return timeout ? dev->err : -ETIMEDOUT;
 }
 
@@ -763,6 +833,7 @@
 static int msm_clk_pause_wakeup(struct slim_controller *ctrl)
 {
 	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+	enable_irq(dev->irq);
 	clk_enable(dev->rclk);
 	writel_relaxed(1, dev->base + FRM_WAKEUP);
 	/* Make sure framer wakeup write goes through before exiting function */
@@ -921,6 +992,9 @@
 				e_addr[1] == QC_DEVID_PGD &&
 				e_addr[2] != QC_CHIPID_SL)
 				dev->pgdla = laddr;
+			if (!ret && !pm_runtime_enabled(dev->dev) &&
+				laddr == (QC_MSM_DEVS - 1))
+				pm_runtime_enable(dev->dev);
 
 		} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
 				mc == SLIM_MSG_MC_REPLY_VALUE) {
@@ -928,6 +1002,7 @@
 			dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len - 4);
 			slim_msg_response(&dev->ctrl, &buf[4], tid,
 						len - 4);
+			msm_slim_put_ctrl(dev);
 		} else if (mc == SLIM_MSG_MC_REPORT_INFORMATION) {
 			u8 l_addr = buf[2];
 			u16 ele = (u16)buf[4] << 4;
@@ -980,11 +1055,26 @@
 			for (i = 0; i < 6; i++)
 				e_addr[i] = buf[7-i];
 
+			if (pm_runtime_enabled(dev->dev)) {
+				msm_slim_get_ctrl(dev);
+				sat->pending_capability = true;
+			}
 			slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
 			sat->satcl.laddr = laddr;
-		}
+		} else if (mt != SLIM_MSG_MT_CORE &&
+				mc != SLIM_MSG_MC_REPORT_PRESENT)
+			msm_slim_get_ctrl(dev);
 		switch (mc) {
 		case SLIM_MSG_MC_REPORT_PRESENT:
+			/* Remove runtime_pm vote once satellite acks */
+			if (mt != SLIM_MSG_MT_CORE) {
+				if (pm_runtime_enabled(dev->dev) &&
+					sat->pending_capability) {
+					msm_slim_put_ctrl(dev);
+					sat->pending_capability = false;
+				}
+				continue;
+			}
 			/* send a Manager capability msg */
 			if (sat->sent_capability)
 				continue;
@@ -1040,11 +1130,19 @@
 					"SAT define_ch returned:%d",
 					ret);
 			}
+			if (!sat->pending_reconf) {
+				msm_slim_get_ctrl(dev);
+				sat->pending_reconf = true;
+			}
 			break;
 		case SLIM_USR_MC_RECONFIG_NOW:
 			tid = buf[3];
 			gen_ack = true;
 			ret = slim_reconfigure_now(&sat->satcl);
+			if (sat->pending_reconf) {
+				msm_slim_put_ctrl(dev);
+				sat->pending_reconf = false;
+			}
 			break;
 		case SLIM_USR_MC_REQ_BW:
 			/* what we get is in SLOTS */
@@ -1085,8 +1183,12 @@
 		default:
 			break;
 		}
-		if (!gen_ack)
+		if (!gen_ack) {
+			if (mc != SLIM_MSG_MC_REPORT_PRESENT)
+				msm_slim_put_ctrl(dev);
 			continue;
+		}
+
 		wbuf[0] = tid;
 		if (!ret)
 			wbuf[1] = MSM_SAT_SUCCSS;
@@ -1099,6 +1201,7 @@
 		txn.wbuf = wbuf;
 		txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
 		msm_xfer_msg(&dev->ctrl, &txn);
+		msm_slim_put_ctrl(dev);
 	}
 }
 
@@ -1606,11 +1709,7 @@
 		dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
 	dev->ctrl.a_framer = &dev->framer;
 	dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
-	ret = slim_add_numbered_controller(&dev->ctrl);
-	if (ret) {
-		dev_err(dev->dev, "error adding controller\n");
-		goto err_ctrl_failed;
-	}
+	dev->ctrl.dev.parent = &pdev->dev;
 
 	ret = request_irq(dev->irq, msm_slim_interrupt, IRQF_TRIGGER_HIGH,
 				"msm_slim_irq", dev);
@@ -1702,14 +1801,24 @@
 	 * function
 	 */
 	mb();
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev, MSM_SLIM_AUTOSUSPEND);
+	pm_runtime_set_active(&pdev->dev);
+
+	ret = slim_add_numbered_controller(&dev->ctrl);
+	if (ret) {
+		dev_err(dev->dev, "error adding controller\n");
+		goto err_ctrl_failed;
+	}
 	dev_dbg(dev->dev, "MSM SB controller is up!\n");
 	return 0;
 
+err_ctrl_failed:
+	writel_relaxed(0, dev->base + COMP_CFG);
+	kfree(dev->satd);
 err_sat_failed:
 	free_irq(dev->irq, dev);
 err_request_irq_failed:
-	slim_del_controller(&dev->ctrl);
-err_ctrl_failed:
 	clk_disable(dev->rclk);
 	clk_put(dev->rclk);
 err_clk_get_failed:
@@ -1735,12 +1844,13 @@
 	struct resource *slew_mem = dev->slew_mem;
 	struct msm_slim_sat *sat = dev->satd;
 	slim_remove_device(&sat->satcl);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
 	kfree(sat->satch);
 	destroy_workqueue(sat->wq);
 	kfree(sat);
 	free_irq(dev->irq, dev);
 	slim_del_controller(&dev->ctrl);
-	clk_disable(dev->rclk);
 	clk_put(dev->rclk);
 	msm_slim_sps_exit(dev);
 	kthread_stop(dev->rx_msgq_thread);
@@ -1760,79 +1870,89 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int msm_slim_suspend(struct device *device)
+#ifdef CONFIG_PM_RUNTIME
+static int msm_slim_runtime_idle(struct device *device)
+{
+	dev_dbg(device, "pm_runtime: idle...\n");
+	pm_request_autosuspend(device);
+	return -EAGAIN;
+}
+#endif
+
+/*
+ * If PM_RUNTIME is not defined, these 2 functions become helper
+ * functions to be called from system suspend/resume. So they are not
+ * inside ifdef CONFIG_PM_RUNTIME
+ */
+static int msm_slim_runtime_suspend(struct device *device)
 {
 	struct platform_device *pdev = to_platform_device(device);
 	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
-	int ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
-	/* Make sure clock pause goes through */
-	mutex_lock(&dev->tx_lock);
-	if (!ret && dev->reconf_busy) {
-		wait_for_completion(&dev->reconf);
-		dev->reconf_busy = false;
+	int ret;
+	dev_dbg(device, "pm_runtime: suspending...\n");
+	dev->state = MSM_CTRL_SLEEPING;
+	ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
+	if (ret)
+		dev->state = MSM_CTRL_AWAKE;
+	else
+		dev->state = MSM_CTRL_ASLEEP;
+	return ret;
+}
+
+static int msm_slim_runtime_resume(struct device *device)
+{
+	struct platform_device *pdev = to_platform_device(device);
+	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
+	int ret = 0;
+	dev_dbg(device, "pm_runtime: resuming...\n");
+	if (dev->state == MSM_CTRL_ASLEEP)
+		ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
+	if (ret)
+		dev->state = MSM_CTRL_ASLEEP;
+	else
+		dev->state = MSM_CTRL_AWAKE;
+	return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_slim_suspend(struct device *dev)
+{
+	int ret = 0;
+	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+		dev_dbg(dev, "system suspend");
+		ret = msm_slim_runtime_suspend(dev);
 	}
-	mutex_unlock(&dev->tx_lock);
-	if (!ret) {
-		clk_disable(dev->rclk);
-		disable_irq(dev->irq);
-		dev->suspended = 1;
-	} else if (ret == -EBUSY) {
+	if (ret == -EBUSY) {
 		/*
-		 * If the clock pause failed due to active channels, there is
-		 * a possibility that some audio stream is active during suspend
-		 * We dont want to return suspend failure in that case so that
-		 * display and relevant components can still go to suspend.
-		 * If there is some other error, then it should be passed-on
-		 * to system level suspend
-		 */
+		* If the clock pause failed due to active channels, there is
+		* a possibility that some audio stream is active during suspend
+		* We dont want to return suspend failure in that case so that
+		* display and relevant components can still go to suspend.
+		* If there is some other error, then it should be passed-on
+		* to system level suspend
+		*/
 		ret = 0;
 	}
 	return ret;
 }
 
-static int msm_slim_resume(struct device *device)
+static int msm_slim_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(device);
-	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
-	mutex_lock(&dev->tx_lock);
-	if (dev->suspended) {
-		dev->suspended = 0;
-		mutex_unlock(&dev->tx_lock);
-		enable_irq(dev->irq);
-		return slim_ctrl_clk_pause(&dev->ctrl, true, 0);
+	/* If runtime_pm is enabled, this resume shouldn't do anything */
+	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+		int ret;
+		dev_dbg(dev, "system resume");
+		ret = msm_slim_runtime_resume(dev);
+		if (!ret) {
+			pm_runtime_mark_last_busy(dev);
+			pm_request_autosuspend(dev);
+		}
+		return ret;
+
 	}
-	mutex_unlock(&dev->tx_lock);
 	return 0;
 }
-#else
-#define msm_slim_suspend NULL
-#define msm_slim_resume NULL
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_RUNTIME
-static int msm_slim_runtime_idle(struct device *dev)
-{
-	dev_dbg(dev, "pm_runtime: idle...\n");
-	return 0;
-}
-
-static int msm_slim_runtime_suspend(struct device *dev)
-{
-	dev_dbg(dev, "pm_runtime: suspending...\n");
-	return 0;
-}
-
-static int msm_slim_runtime_resume(struct device *dev)
-{
-	dev_dbg(dev, "pm_runtime: resuming...\n");
-	return 0;
-}
-#else
-#define msm_slim_runtime_idle NULL
-#define msm_slim_runtime_suspend NULL
-#define msm_slim_runtime_resume NULL
-#endif
+#endif /* CONFIG_PM_SLEEP */
 
 static const struct dev_pm_ops msm_slim_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 3b79129..d8003bf 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -377,7 +377,6 @@
 	dev_set_name(&ctrl->dev, "sb-%d", ctrl->nr);
 	ctrl->dev.bus = &slimbus_type;
 	ctrl->dev.type = &slim_ctrl_type;
-	ctrl->dev.parent = &slimbus_dev;
 	ctrl->num_dev = 0;
 	if (!ctrl->min_cg)
 		ctrl->min_cg = SLIM_MIN_CLK_GEAR;
@@ -581,7 +580,7 @@
 }
 EXPORT_SYMBOL_GPL(slim_msg_response);
 
-static int slim_processtxn(struct slim_controller *ctrl, u8 dt, u8 mc, u16 ec,
+static int slim_processtxn(struct slim_controller *ctrl, u8 dt, u16 mc, u16 ec,
 			u8 mt, u8 *rbuf, const u8 *wbuf, u8 len, u8 mlen,
 			struct completion *comp, u8 la, u8 *tid)
 {
@@ -870,7 +869,7 @@
  * All controllers may not support broadcast
  */
 int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev,
-			struct slim_ele_access *msg, u8 mc, u8 *rbuf,
+			struct slim_ele_access *msg, u16 mc, u8 *rbuf,
 			const u8 *wbuf, u8 len)
 {
 	DECLARE_COMPLETION_ONSTACK(complete);
@@ -892,10 +891,6 @@
 	cur = slim_slicecodefromsize(sl);
 	ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4));
 
-	ret = slim_ctrl_clk_pause(ctrl, true, 0);
-	if (ret)
-		return ret;
-
 	if (wbuf)
 		mlen += len;
 	if (rbuf) {
@@ -1069,7 +1064,7 @@
 				enum slim_port_flow flow)
 {
 	int ret;
-	u8 mc;
+	u16 mc;
 	u8 buf[2];
 	u32 la = SLIM_HDL_TO_LA(ph);
 	u8 pn = (u8)SLIM_HDL_TO_PORT(ph);
@@ -1093,7 +1088,7 @@
 static int disconnect_port_ch(struct slim_controller *ctrl, u32 ph)
 {
 	int ret;
-	u8 mc;
+	u16 mc;
 	u32 la = SLIM_HDL_TO_LA(ph);
 	u8 pn = (u8)SLIM_HDL_TO_PORT(ph);
 
@@ -1127,10 +1122,6 @@
 	u8 chan = (u8)(chanh & 0xFF);
 	struct slim_ich *slc = &ctrl->chans[chan];
 
-	ret = slim_ctrl_clk_pause(ctrl, true, 0);
-	if (ret)
-		return ret;
-
 	mutex_lock(&ctrl->m_ctrl);
 	/* Make sure the channel is not already pending reconf. or active */
 	if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
@@ -1193,11 +1184,8 @@
 int slim_disconnect_ports(struct slim_device *sb, u32 *ph, int nph)
 {
 	struct slim_controller *ctrl = sb->ctrl;
-	int i, ret;
+	int i;
 
-	ret = slim_ctrl_clk_pause(ctrl, true, 0);
-	if (ret)
-		return ret;
 	mutex_lock(&ctrl->m_ctrl);
 
 	for (i = 0; i < nph; i++)
@@ -2389,10 +2377,6 @@
 	u32 segdist;
 	struct slim_pending_ch *pch;
 
-	ret = slim_ctrl_clk_pause(ctrl, true, 0);
-	if (ret)
-		return ret;
-
 	mutex_lock(&ctrl->sched.m_reconf);
 	mutex_lock(&ctrl->m_ctrl);
 	ctrl->sched.pending_msgsl += sb->pending_msgsl - sb->cur_msgsl;
@@ -2785,20 +2769,20 @@
 	}
 
 	ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
-			SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, SLIM_MSG_MT_CORE,
-			NULL, NULL, 0, 3, NULL, 0, NULL);
-	if (ret)
-		goto clk_pause_ret;
-
-		ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
-			SLIM_MSG_MC_NEXT_PAUSE_CLOCK, 0, SLIM_MSG_MT_CORE,
-			NULL, &restart, 1, 4, NULL, 0, NULL);
+		SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_BEGIN_RECONFIGURATION,
+		0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL);
 	if (ret)
 		goto clk_pause_ret;
 
 	ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
-			SLIM_MSG_MC_RECONFIGURE_NOW, 0, SLIM_MSG_MT_CORE,
-			NULL, NULL, 0, 3, NULL, 0, NULL);
+		SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_NEXT_PAUSE_CLOCK, 0,
+		SLIM_MSG_MT_CORE, NULL, &restart, 1, 4, NULL, 0, NULL);
+	if (ret)
+		goto clk_pause_ret;
+
+	ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
+		SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_RECONFIGURE_NOW, 0,
+		SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL);
 	if (ret)
 		goto clk_pause_ret;
 
diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c
index d9f9c9e..1d518e3 100644
--- a/drivers/thermal/pm8xxx-tm.c
+++ b/drivers/thermal/pm8xxx-tm.c
@@ -30,6 +30,7 @@
 #include <linux/mfd/pm8xxx/tm.h>
 #include <linux/completion.h>
 #include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/msm_adc.h>
 
 /* Register TEMP_ALARM_CTRL bits */
 #define	TEMP_ALARM_CTRL_ST3_SD		0x80
@@ -226,6 +227,43 @@
 	return 0;
 }
 
+static int pm8xxx_tz_get_temp_pm8058_adc(struct thermal_zone_device *thermal,
+			      unsigned long *temp)
+{
+	struct pm8xxx_tm_chip *chip = thermal->devdata;
+	DECLARE_COMPLETION_ONSTACK(wait);
+	struct adc_chan_result adc_result = {
+		.physical = 0lu,
+	};
+	int rc;
+
+	if (!chip || !temp)
+		return -EINVAL;
+
+	*temp = chip->temp;
+
+	rc = adc_channel_request_conv(chip->adc_handle, &wait);
+	if (rc < 0) {
+		pr_err("%s: adc_channel_request_conv() failed, rc = %d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	wait_for_completion(&wait);
+
+	rc = adc_channel_read_result(chip->adc_handle, &adc_result);
+	if (rc < 0) {
+		pr_err("%s: adc_channel_read_result() failed, rc = %d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	*temp = adc_result.physical;
+	chip->temp = adc_result.physical;
+
+	return 0;
+}
+
 static int pm8xxx_tz_get_temp_pm8921_adc(struct thermal_zone_device *thermal,
 				      unsigned long *temp)
 {
@@ -372,6 +410,15 @@
 	.get_crit_temp = pm8xxx_tz_get_crit_temp,
 };
 
+static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8058_adc = {
+	.get_temp = pm8xxx_tz_get_temp_pm8058_adc,
+	.get_mode = pm8xxx_tz_get_mode,
+	.set_mode = pm8xxx_tz_set_mode,
+	.get_trip_type = pm8xxx_tz_get_trip_type,
+	.get_trip_temp = pm8xxx_tz_get_trip_temp,
+	.get_crit_temp = pm8xxx_tz_get_crit_temp,
+};
+
 static void pm8xxx_tm_work(struct work_struct *work)
 {
 	struct pm8xxx_tm_chip *chip
@@ -465,6 +512,24 @@
 	return rc;
 }
 
+static int pm8xxx_init_adc(struct pm8xxx_tm_chip *chip, bool enable)
+{
+	int rc = 0;
+
+	if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8058_ADC) {
+		if (enable) {
+			rc = adc_channel_open(chip->cdata.adc_channel,
+						&(chip->adc_handle));
+			if (rc < 0)
+				pr_err("adc_channel_open() failed.\n");
+		} else {
+			adc_channel_close(chip->adc_handle);
+		}
+	}
+
+	return rc;
+}
+
 static int __devinit pm8xxx_tm_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_tm_core_data *cdata = pdev->dev.platform_data;
@@ -505,18 +570,27 @@
 		goto err_free_chip;
 	}
 
+	rc = pm8xxx_init_adc(chip, true);
+	if (rc < 0) {
+		pr_err("Unable to initialize adc\n");
+		goto err_free_chip;
+	}
+
 	/* Select proper thermal zone ops functions based on ADC type. */
 	if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8921_ADC)
 		tz_ops = &pm8xxx_thermal_zone_ops_pm8921_adc;
+	else if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8058_ADC)
+		tz_ops = &pm8xxx_thermal_zone_ops_pm8058_adc;
 	else
 		tz_ops = &pm8xxx_thermal_zone_ops_no_adc;
 
 	chip->tz_dev = thermal_zone_device_register(chip->cdata.tm_name,
 			TRIP_NUM, chip, tz_ops, 0, 0, 0, 0);
+
 	if (chip->tz_dev == NULL) {
 		pr_err("thermal_zone_device_register() failed.\n");
 		rc = -ENODEV;
-		goto err_free_chip;
+		goto err_fail_adc;
 	}
 
 	rc = pm8xxx_tm_init_reg(chip);
@@ -564,6 +638,8 @@
 	cancel_work_sync(&chip->irq_work);
 err_free_tz:
 	thermal_zone_device_unregister(chip->tz_dev);
+err_fail_adc:
+	pm8xxx_init_adc(chip, false);
 err_free_chip:
 	kfree(chip);
 	return rc;
@@ -579,6 +655,7 @@
 		free_irq(chip->overtemp_irq, chip);
 		free_irq(chip->tempstat_irq, chip);
 		pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
+		pm8xxx_init_adc(chip, false);
 		thermal_zone_device_unregister(chip->tz_dev);
 		kfree(chip);
 	}
diff --git a/drivers/thermal/pmic8058-tm.c b/drivers/thermal/pmic8058-tm.c
index cc98f37..2589494 100644
--- a/drivers/thermal/pmic8058-tm.c
+++ b/drivers/thermal/pmic8058-tm.c
@@ -351,7 +351,6 @@
 
 static int __devinit pmic8058_tm_probe(struct platform_device *pdev)
 {
-	DECLARE_COMPLETION_ONSTACK(wait);
 	struct pm8058_tm_device *tmdev;
 	struct pm8058_chip *pm_chip;
 	unsigned int irq;
@@ -382,10 +381,6 @@
 		return rc;
 	}
 
-	/* calibrate the die temperature sensor */
-	if (adc_calib_request(tmdev->adc_handle, &wait) == CALIB_STARTED)
-		wait_for_completion(&wait);
-
 	tmdev->pm_chip = pm_chip;
 	tmdev->tz_dev = thermal_zone_device_register("pm8058_tz",
 						     PM8058_TRIP_NUM, tmdev,
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index e276be6..ccfd2e3 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -512,7 +512,6 @@
 	struct diag_context  *dev = func_to_diag(f);
 	struct usb_composite_dev *cdev = f->config->cdev;
 	unsigned long flags;
-	struct usb_diag_ch *ch;
 	int rc = 0;
 
 	dev->in_desc = ep_choose(cdev->gadget,
@@ -536,14 +535,9 @@
 	}
 	schedule_work(&dev->config_work);
 
-	list_for_each_entry(ch, &usb_diag_ch_list, list) {
-		struct diag_context *ctxt;
-
-		ctxt = ch->priv_usb;
-		ctxt->dpkts_tolaptop = 0;
-		ctxt->dpkts_tomodem = 0;
-		ctxt->dpkts_tolaptop_pending = 0;
-	}
+	dev->dpkts_tolaptop = 0;
+	dev->dpkts_tomodem = 0;
+	dev->dpkts_tolaptop_pending = 0;
 
 	spin_lock_irqsave(&dev->lock, flags);
 	dev->configured = 1;
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 6f0fb07..7686bf2 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -487,7 +487,7 @@
 	}
 
 	spin_lock_irqsave(&dev->lock, flags);
-	list_add(&cpkt->list, &dev->cpkt_resp_q);
+	list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	frmnet_ctrl_response_available(dev);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 73407bd..70cbd2f 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -33,37 +33,38 @@
 
 static const char *bam_ch_names[] = { "bam_dmux_ch_8" };
 
-#define TX_PKT_DROP_THRESHOLD			1000
-#define RX_PKT_FLOW_CTRL_EN_THRESHOLD		1000
-#define RX_PKT_FLOW_CTRL_DISABLE		500
-#define RX_PKT_FLOW_CTRL_SUPPORT		1
+#define BAM_PENDING_LIMIT			220
+#define BAM_MUX_TX_PKT_DROP_THRESHOLD		1000
+#define BAM_MUX_RX_PKT_FCTRL_EN_TSHOLD		500
+#define BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD		300
+#define BAM_MUX_RX_PKT_FLOW_CTRL_SUPPORT	1
 
 #define BAM_MUX_HDR				8
 
-#define RX_Q_SIZE				16
-#define TX_Q_SIZE				200
-#define RX_REQ_SIZE				(2048 - BAM_MUX_HDR)
+#define BAM_MUX_RX_Q_SIZE			16
+#define BAM_MUX_TX_Q_SIZE			200
+#define BAM_MUX_RX_REQ_SIZE			(2048 - BAM_MUX_HDR)
 
-unsigned int tx_pkt_drop_thld = TX_PKT_DROP_THRESHOLD;
-module_param(tx_pkt_drop_thld, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_tx_pkt_drop_thld = BAM_MUX_TX_PKT_DROP_THRESHOLD;
+module_param(bam_mux_tx_pkt_drop_thld, uint, S_IRUGO | S_IWUSR);
 
-unsigned int rx_fctrl_en_thld = RX_PKT_FLOW_CTRL_EN_THRESHOLD;
-module_param(rx_fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_fctrl_en_thld = BAM_MUX_RX_PKT_FCTRL_EN_TSHOLD;
+module_param(bam_mux_rx_fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
 
-unsigned int rx_fctrl_support = RX_PKT_FLOW_CTRL_SUPPORT;
-module_param(rx_fctrl_support, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_fctrl_support = BAM_MUX_RX_PKT_FLOW_CTRL_SUPPORT;
+module_param(bam_mux_rx_fctrl_support, uint, S_IRUGO | S_IWUSR);
 
-unsigned int rx_fctrl_dis_thld = RX_PKT_FLOW_CTRL_DISABLE;
-module_param(rx_fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_fctrl_dis_thld = BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD;
+module_param(bam_mux_rx_fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
 
-unsigned int tx_q_size = TX_Q_SIZE;
-module_param(tx_q_size, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_tx_q_size = BAM_MUX_TX_Q_SIZE;
+module_param(bam_mux_tx_q_size, uint, S_IRUGO | S_IWUSR);
 
-unsigned int rx_q_size = RX_Q_SIZE;
-module_param(rx_q_size, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_q_size = BAM_MUX_RX_Q_SIZE;
+module_param(bam_mux_rx_q_size, uint, S_IRUGO | S_IWUSR);
 
-unsigned int rx_req_size = RX_REQ_SIZE;
-module_param(rx_req_size, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_req_size = BAM_MUX_RX_REQ_SIZE;
+module_param(bam_mux_rx_req_size, uint, S_IRUGO | S_IWUSR);
 
 #define BAM_CH_OPENED	BIT(0)
 #define BAM_CH_READY	BIT(1)
@@ -99,6 +100,7 @@
 	struct bam_ch_info	data_ch;
 
 	struct work_struct	connect_w;
+	struct work_struct	disconnect_w;
 };
 
 static struct bam_portmaster {
@@ -211,7 +213,7 @@
 		return;
 	}
 
-	if (d->tx_skb_q.qlen > tx_pkt_drop_thld) {
+	if (d->tx_skb_q.qlen > bam_mux_tx_pkt_drop_thld) {
 		d->tohost_drp_cnt++;
 		if (printk_ratelimit())
 			pr_err("%s: tx pkt dropped: tx_drop_cnt:%u\n",
@@ -246,15 +248,9 @@
 			port, d, d->to_modem,
 			d->pending_with_bam, port->port_num);
 
-	if (rx_fctrl_support &&
-			d->pending_with_bam >= rx_fctrl_dis_thld) {
-
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return;
-	}
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
-	gbam_start_rx(port);
+	queue_work(gbam_wq, &d->write_tobam_w);
 }
 
 static void gbam_data_write_tobam(struct work_struct *w)
@@ -264,6 +260,7 @@
 	struct sk_buff		*skb;
 	unsigned long		flags;
 	int			ret;
+	int			qlen;
 
 	d = container_of(w, struct bam_ch_info, write_tobam_w);
 	port = d->port;
@@ -274,7 +271,12 @@
 		return;
 	}
 
-	while ((skb = __skb_dequeue(&d->rx_skb_q))) {
+	while (d->pending_with_bam < BAM_PENDING_LIMIT) {
+		skb =  __skb_dequeue(&d->rx_skb_q);
+		if (!skb) {
+			spin_unlock_irqrestore(&port->port_lock, flags);
+			return;
+		}
 		d->pending_with_bam++;
 		d->to_modem++;
 
@@ -294,7 +296,13 @@
 			break;
 		}
 	}
+
+	qlen = d->rx_skb_q.qlen;
+
 	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	if (qlen < BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD)
+		gbam_start_rx(port);
 }
 /*-------------------------------------------------------------*/
 
@@ -370,8 +378,8 @@
 	/* TODO: Handle flow control gracefully by having
 	 * having call back mechanism from bam driver
 	 */
-	if (rx_fctrl_support &&
-		d->pending_with_bam >= rx_fctrl_en_thld) {
+	if (bam_mux_rx_fctrl_support &&
+		d->rx_skb_q.qlen >= bam_mux_rx_fctrl_en_thld) {
 
 		list_add_tail(&req->list, &d->rx_idle);
 		spin_unlock(&port->port_lock);
@@ -379,7 +387,7 @@
 	}
 	spin_unlock(&port->port_lock);
 
-	skb = alloc_skb(rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
+	skb = alloc_skb(bam_mux_rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
 	if (!skb) {
 		spin_lock(&port->port_lock);
 		list_add_tail(&req->list, &d->rx_idle);
@@ -389,7 +397,7 @@
 	skb_reserve(skb, BAM_MUX_HDR);
 
 	req->buf = skb->data;
-	req->length = rx_req_size;
+	req->length = bam_mux_rx_req_size;
 	req->context = skb;
 
 	status = usb_ep_queue(ep, req, GFP_ATOMIC);
@@ -425,16 +433,21 @@
 	ep = port->port_usb->out;
 
 	while (port->port_usb && !list_empty(&d->rx_idle)) {
+
+		if (bam_mux_rx_fctrl_support &&
+			d->rx_skb_q.qlen >= bam_mux_rx_fctrl_en_thld)
+			break;
+
 		req = list_first_entry(&d->rx_idle, struct usb_request, list);
 
-		skb = alloc_skb(rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
+		skb = alloc_skb(bam_mux_rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
 		if (!skb)
 			break;
 		skb_reserve(skb, BAM_MUX_HDR);
 
 		list_del(&req->list);
 		req->buf = skb->data;
-		req->length = rx_req_size;
+		req->length = bam_mux_rx_req_size;
 		req->context = skb;
 
 		spin_unlock_irqrestore(&port->port_lock, flags);
@@ -473,7 +486,7 @@
 
 	d = &port->data_ch;
 	ep = port->port_usb->out;
-	ret = gbam_alloc_requests(ep, &d->rx_idle, rx_q_size,
+	ret = gbam_alloc_requests(ep, &d->rx_idle, bam_mux_rx_q_size,
 			gbam_epout_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: rx req allocation failed\n", __func__);
@@ -481,7 +494,7 @@
 	}
 
 	ep = port->port_usb->in;
-	ret = gbam_alloc_requests(ep, &d->tx_idle, tx_q_size,
+	ret = gbam_alloc_requests(ep, &d->tx_idle, bam_mux_tx_q_size,
 			gbam_epin_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: tx req allocation failed\n", __func__);
@@ -507,11 +520,32 @@
 	}
 }
 
+static void gbam_disconnect_work(struct work_struct *w)
+{
+	struct gbam_port *port =
+			container_of(w, struct gbam_port, disconnect_w);
+	struct bam_ch_info *d = &port->data_ch;
+
+	if (!test_bit(BAM_CH_OPENED, &d->flags))
+		return;
+
+	msm_bam_dmux_close(d->id);
+	clear_bit(BAM_CH_OPENED, &d->flags);
+}
+
 static void gbam_connect_work(struct work_struct *w)
 {
 	struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
 	struct bam_ch_info *d = &port->data_ch;
 	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	if (!test_bit(BAM_CH_READY, &d->flags))
 		return;
@@ -654,6 +688,7 @@
 	/* port initialization */
 	spin_lock_init(&port->port_lock);
 	INIT_WORK(&port->connect_w, gbam_connect_work);
+	INIT_WORK(&port->disconnect_w, gbam_disconnect_work);
 
 	/* data ch */
 	d = &port->data_ch;
@@ -713,13 +748,14 @@
 				"to_usbhost_dcnt:  %u\n"
 				"tomodem__dcnt:  %u\n"
 				"tx_buf_len:	 %u\n"
+				"rx_buf_len:	 %u\n"
 				"data_ch_open:   %d\n"
 				"data_ch_ready:  %d\n",
 				i, port, &port->data_ch,
 				d->to_host, d->to_modem,
 				d->pending_with_bam,
 				d->tohost_drp_cnt, d->tomodem_drp_cnt,
-				d->tx_skb_q.qlen,
+				d->tx_skb_q.qlen, d->rx_skb_q.qlen,
 				test_bit(BAM_CH_OPENED, &d->flags),
 				test_bit(BAM_CH_READY, &d->flags));
 
@@ -815,10 +851,7 @@
 	usb_ep_disable(gr->out);
 	usb_ep_disable(gr->in);
 
-	if (test_bit(BAM_CH_OPENED, &d->flags)) {
-		msm_bam_dmux_close(d->id);
-		clear_bit(BAM_CH_OPENED, &d->flags);
-	}
+	queue_work(gbam_wq, &port->disconnect_w);
 }
 
 int gbam_connect(struct grmnet *gr, u8 port_num)
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 350f286..ec303b9 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -400,8 +400,6 @@
 		dev_err(mehci->dev, "Unable to suspend PHY\n");
 		msm_hsic_config_gpios(mehci, 0);
 		msm_hsic_reset(mehci);
-		enable_irq(hcd->irq);
-		return -ETIMEDOUT;
 	}
 
 	/*
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 411fa97..f45f257 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -177,11 +177,6 @@
 	}
 
 	device_init_wakeup(&pdev->dev, 1);
-	/*
-	 * OTG device parent of HCD takes care of putting
-	 * hardware into low power mode.
-	 */
-	pm_runtime_no_callbacks(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
 	return 0;
@@ -212,7 +207,31 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int ehci_msm_runtime_idle(struct device *dev)
+{
+	dev_dbg(dev, "ehci runtime idle\n");
+	return 0;
+}
+
+static int ehci_msm_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "ehci runtime suspend\n");
+	/*
+	 * Notify OTG about suspend.  It takes care of
+	 * putting the hardware in LPM.
+	 */
+	return otg_set_suspend(otg, 1);
+}
+
+static int ehci_msm_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "ehci runtime resume\n");
+	return otg_set_suspend(otg, 0);
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
 static int ehci_msm_pm_suspend(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -236,7 +255,7 @@
 				wakeup);
 	}
 
-	return 0;
+	return otg_set_suspend(otg, 1);
 }
 
 static int ehci_msm_pm_resume(struct device *dev)
@@ -250,16 +269,14 @@
 
 	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
 
-	return 0;
+	return otg_set_suspend(otg, 0);
 }
-#else
-#define ehci_msm_pm_suspend	NULL
-#define ehci_msm_pm_resume	NULL
 #endif
 
 static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
-	.suspend         = ehci_msm_pm_suspend,
-	.resume          = ehci_msm_pm_resume,
+	SET_SYSTEM_SLEEP_PM_OPS(ehci_msm_pm_suspend, ehci_msm_pm_resume)
+	SET_RUNTIME_PM_OPS(ehci_msm_runtime_suspend, ehci_msm_runtime_resume,
+				ehci_msm_runtime_idle)
 };
 
 static struct platform_driver ehci_msm_driver = {
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 98e57d5..c5dcdbf 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -259,27 +259,29 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called yurex.
 
-config USB_QCOM_DIAG
-	tristate "USB Qualcomm diag port driver"
-	depends on USB && !USB_SERIAL_QUALCOMM
-	default n
+config USB_QCOM_DIAG_BRIDGE
+	tristate "USB Qualcomm diagnostic bridge driver"
+	depends on USB
 	help
-	  Say Y here if you want to use the diag ports provided
-	  by many Qualcomm chipsets.
+	  Say Y here if you have a Qualcomm modem device connected via USB that
+	  will be bridged in kernel space. This driver communicates with the
+	  diagnostic interface and allows for bridging with the diag forwarding
+	  driver.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called qcaux.  If unsure, choose N.
+	  module will be called diag_bridge.  If unsure, choose N.
 
-config USB_QCOM_DIAG_TEST
-	tristate "USB Qualcomm diag port unit test driver"
-	depends on USB && USB_QCOM_DIAG
-	default n
+config USB_QCOM_DIAG_BRIDGE_TEST
+	tristate "USB Qualcomm diagnostic bridge driver test"
+	depends on USB && USB_QCOM_DIAG_BRIDGE
 	help
-	  Say Y here if you want to use unit test diag port provided
-	  by many Qualcomm chipsets.
+	  Say Y here if you want to enable the test hook for the
+	  Qualcomm diag bridge driver. When enabled, this will create
+	  a debugfs file entry named "diag_bridge_test" which can be used
+	  to send a ping command to the diag port of the modem over USB.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called qcaux.  If unsure, choose N.
+	  module will be called diag_bridge_test.  If unsure, choose N.
 
 config USB_QCOM_DUN_BRIDGE
 	tristate "USB Qualcomm modem DUN bridge driver"
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 03568bc..bb69a02 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -29,7 +29,7 @@
 
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
 
-obj-$(CONFIG_USB_QCOM_DIAG)		+= diag_usb.o
-obj-$(CONFIG_USB_QCOM_DIAG_TEST)	+= diag_bridge_test.o
+obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE)	+= diag_bridge.o
+obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE_TEST)	+= diag_bridge_test.o
 obj-$(CONFIG_USB_QCOM_DUN_BRIDGE)	+= dun_bridge.o
 obj-$(CONFIG_USB_QCOM_DUN_BRIDGE_TEST)	+= dun_bridge_test.o
diff --git a/drivers/usb/misc/diag_usb.c b/drivers/usb/misc/diag_bridge.c
similarity index 79%
rename from drivers/usb/misc/diag_usb.c
rename to drivers/usb/misc/diag_bridge.c
index b3419f4..11f9ef6 100644
--- a/drivers/usb/misc/diag_usb.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -23,7 +23,7 @@
 #include <mach/diag_bridge.h>
 
 #define DRIVER_DESC	"USB host diag bridge driver"
-#define DRIVER_VERSION	"0.1"
+#define DRIVER_VERSION	"1.0"
 
 struct diag_bridge {
 	struct usb_device	*udev;
@@ -37,7 +37,7 @@
 };
 struct diag_bridge *__dev;
 
-int diag_open(struct diag_bridge_ops *ops)
+int diag_bridge_open(struct diag_bridge_ops *ops)
 {
 	struct diag_bridge	*dev = __dev;
 
@@ -50,9 +50,9 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(diag_open);
+EXPORT_SYMBOL(diag_bridge_open);
 
-void diag_close(void)
+void diag_bridge_close(void)
 {
 	struct diag_bridge	*dev = __dev;
 
@@ -62,25 +62,23 @@
 
 	dev->ops = 0;
 }
-EXPORT_SYMBOL(diag_close);
+EXPORT_SYMBOL(diag_bridge_close);
 
-static void diag_read_cb(struct urb *urb)
+static void diag_bridge_read_cb(struct urb *urb)
 {
 	struct diag_bridge	*dev = urb->context;
 	struct diag_bridge_ops	*cbs = dev->ops;
 
 	dev_dbg(&dev->udev->dev, "%s: status:%d actual:%d\n", __func__,
 			urb->status, urb->actual_length);
-	if (urb->status)
-		urb->actual_length = urb->status;
 
 	cbs->read_complete_cb(cbs->ctxt,
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
-			urb->actual_length);
+			urb->status < 0 ? urb->status : urb->actual_length);
 }
 
-int diag_read(char *data, size_t size)
+int diag_bridge_read(char *data, size_t size)
 {
 	struct urb		*urb = NULL;
 	unsigned int		pipe;
@@ -107,7 +105,7 @@
 
 	pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr);
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
-				diag_read_cb, dev);
+				diag_bridge_read_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
 
 	ret = usb_submit_urb(urb, GFP_KERNEL);
@@ -122,25 +120,22 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(diag_read);
+EXPORT_SYMBOL(diag_bridge_read);
 
-static void diag_write_cb(struct urb *urb)
+static void diag_bridge_write_cb(struct urb *urb)
 {
 	struct diag_bridge	*dev = urb->context;
 	struct diag_bridge_ops	*cbs = dev->ops;
 
 	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
 
-	if (urb->status)
-		urb->actual_length = urb->status;
-
 	cbs->write_complete_cb(cbs->ctxt,
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
-			urb->actual_length);
+			urb->status < 0 ? urb->status : urb->actual_length);
 }
 
-int diag_write(char *data, size_t size)
+int diag_bridge_write(char *data, size_t size)
 {
 	struct urb		*urb = NULL;
 	unsigned int		pipe;
@@ -167,7 +162,7 @@
 
 	pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
 	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
-				diag_write_cb, dev);
+				diag_bridge_write_cb, dev);
 	usb_anchor_urb(urb, &dev->submitted);
 
 	ret = usb_submit_urb(urb, GFP_KERNEL);
@@ -182,9 +177,9 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(diag_write);
+EXPORT_SYMBOL(diag_bridge_write);
 
-static void diag_delete(struct kref *kref)
+static void diag_bridge_delete(struct kref *kref)
 {
 	struct diag_bridge *dev =
 		container_of(kref, struct diag_bridge, kref);
@@ -195,7 +190,7 @@
 }
 
 static int
-diag_probe(struct usb_interface *ifc, const struct usb_device_id *id)
+diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
 {
 	struct diag_bridge		*dev;
 	struct usb_host_interface	*ifc_desc;
@@ -257,44 +252,44 @@
 
 error:
 	if (dev)
-		kref_put(&dev->kref, diag_delete);
+		kref_put(&dev->kref, diag_bridge_delete);
 
 	return ret;
 }
 
-static void diag_disconnect(struct usb_interface *ifc)
+static void diag_bridge_disconnect(struct usb_interface *ifc)
 {
 	struct diag_bridge	*dev = usb_get_intfdata(ifc);
 
 	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
 
 	platform_device_del(dev->pdev);
-	kref_put(&dev->kref, diag_delete);
+	kref_put(&dev->kref, diag_bridge_delete);
 	usb_set_intfdata(ifc, NULL);
 }
 
 
 #define VALID_INTERFACE_NUM	0
-static const struct usb_device_id diag_ids[] = {
+static const struct usb_device_id diag_bridge_ids[] = {
 	{ USB_DEVICE(0x5c6, 0x9001),
 	.driver_info = VALID_INTERFACE_NUM, },
 
 	{} /* terminating entry */
 };
-MODULE_DEVICE_TABLE(usb, diag_ids);
+MODULE_DEVICE_TABLE(usb, diag_bridge_ids);
 
-static struct usb_driver diag_driver = {
-	.name =		"diag_qc",
-	.probe =	diag_probe,
-	.disconnect =	diag_disconnect,
-	.id_table =	diag_ids,
+static struct usb_driver diag_bridge_driver = {
+	.name =		"diag_bridge",
+	.probe =	diag_bridge_probe,
+	.disconnect =	diag_bridge_disconnect,
+	.id_table =	diag_bridge_ids,
 };
 
-static int __init diag_init(void)
+static int __init diag_bridge_init(void)
 {
 	int ret;
 
-	ret = usb_register(&diag_driver);
+	ret = usb_register(&diag_bridge_driver);
 	if (ret) {
 		err("%s: unable to register diag driver",
 				__func__);
@@ -304,13 +299,14 @@
 	return 0;
 }
 
-static void __exit diag_exit(void)
+static void __exit diag_bridge_exit(void)
 {
-	usb_deregister(&diag_driver);
+	usb_deregister(&diag_bridge_driver);
 }
 
-module_init(diag_init);
-module_exit(diag_exit);
+module_init(diag_bridge_init);
+module_exit(diag_bridge_exit);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL V2");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/misc/diag_bridge_test.c b/drivers/usb/misc/diag_bridge_test.c
index 234aa72..5bc0828 100644
--- a/drivers/usb/misc/diag_bridge_test.c
+++ b/drivers/usb/misc/diag_bridge_test.c
@@ -19,10 +19,12 @@
 #include <linux/crc-ccitt.h>
 #include <mach/diag_bridge.h>
 
+#define DRIVER_DESC	"USB host diag bridge driver test"
+#define DRIVER_VERSION	"1.0"
+
 #define RD_BUF_SIZE	2048
 #define DIAG_TEST_CONNECTED	0
 
-
 struct diag_test_dev {
 	char *read_buf;
 	struct work_struct read_w;
@@ -49,7 +51,7 @@
 		container_of(w, struct diag_test_dev, read_w);
 
 	memset(dev->read_buf, 0, RD_BUF_SIZE);
-	diag_read(dev->read_buf, RD_BUF_SIZE);
+	diag_bridge_read(dev->read_buf, RD_BUF_SIZE);
 }
 
 static void
@@ -86,7 +88,7 @@
 	buf[2] = 0x3A;
 	buf[3] = 0x7E;
 
-	diag_write(buf, temp);
+	diag_bridge_write(buf, temp);
 
 	return count;
 }
@@ -114,7 +116,7 @@
 
 static int diag_test_remove(struct platform_device *pdev)
 {
-	diag_close();
+	diag_bridge_close();
 
 	if (dent) {
 		debugfs_remove_recursive(dent);
@@ -131,7 +133,7 @@
 
 	pr_info("%s:\n", __func__);
 
-	ret = diag_open(&dev->ops);
+	ret = diag_bridge_open(&dev->ops);
 	if (ret)
 		pr_err("diag open failed: %d", ret);
 
@@ -190,7 +192,7 @@
 	pr_info("%s:\n", __func__);
 
 	if (test_bit(DIAG_TEST_CONNECTED, &dev->flags))
-		diag_close();
+		diag_bridge_close();
 
 	kfree(dev->read_buf);
 	kfree(dev);
@@ -201,4 +203,5 @@
 module_exit(diag_test_exit);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL V2");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 71f36f2..8864f32 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -161,7 +161,7 @@
 config USB_MSM_STANDARD_ACA
 	bool "Support for Standard ACA"
 	depends on USB_MSM_ACA
-	default y
+	default USB_MSM_OTG_72K
 	help
 	  A Standard ACA has a Standard-A receptacle on the Accessory Port,
 	  and can only be attached to a B-device.  RID_A and RID_GND states
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index 84b8472..714099a 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -37,7 +37,13 @@
 #define DRIVER_NAME	"msm_otg"
 static void otg_reset(struct otg_transceiver *xceiv, int phy_reset);
 static void msm_otg_set_vbus_state(int online);
-static void msm_otg_set_id_state(int online);
+#ifdef CONFIG_USB_EHCI_MSM_72K
+static void msm_otg_set_id_state(int id);
+#else
+static void msm_otg_set_id_state(int id)
+{
+}
+#endif
 
 struct msm_otg *the_msm_otg;
 
@@ -45,9 +51,7 @@
 {
 	struct msm_otg *dev = the_msm_otg;
 
-	if (dev->pmic_id_notif_supp)
-		return dev->pmic_id_status ? 0 : 1;
-	else if (dev->pdata->otg_mode == OTG_ID)
+	if (dev->pdata->otg_mode == OTG_ID)
 		return (OTGSC_ID & readl(USB_OTGSC)) ? 0 : 1;
 	else
 		return !test_bit(ID, &dev->inputs);
@@ -135,24 +139,38 @@
 #ifdef CONFIG_USB_EHCI_MSM_72K
 static void enable_idgnd(struct msm_otg *dev)
 {
+	unsigned temp;
+
 	/* Do nothing if instead of ID pin, USER controls mode switch */
 	if (dev->pdata->otg_mode == OTG_USER_CONTROL)
 		return;
 
 	ulpi_write(dev, (1<<4), 0x0E);
 	ulpi_write(dev, (1<<4), 0x11);
-	writel(readl(USB_OTGSC) | OTGSC_IDIE, USB_OTGSC);
+	ulpi_write(dev, (1<<0), 0x0B);
+	temp = OTGSC_IDIE | OTGSC_IDPU;
+	writel_relaxed(readl_relaxed(USB_OTGSC) | temp, USB_OTGSC);
 }
 
 static void disable_idgnd(struct msm_otg *dev)
 {
+	unsigned temp;
+
 	/* Do nothing if instead of ID pin, USER controls mode switch */
 	if (dev->pdata->otg_mode == OTG_USER_CONTROL)
 		return;
-
+	temp = OTGSC_IDIE | OTGSC_IDPU;
+	writel_relaxed(readl_relaxed(USB_OTGSC) & ~temp, USB_OTGSC);
 	ulpi_write(dev, (1<<4), 0x0F);
 	ulpi_write(dev, (1<<4), 0x12);
-	writel(readl(USB_OTGSC) & ~OTGSC_IDIE, USB_OTGSC);
+	ulpi_write(dev, (1<<0), 0x0C);
+}
+#else
+static void enable_idgnd(struct msm_otg *dev)
+{
+}
+static void disable_idgnd(struct msm_otg *dev)
+{
 }
 #endif
 
@@ -224,6 +242,9 @@
 #define get_aca_bmaxpower(dev)		(dev->b_max_power)
 #define set_aca_bmaxpower(dev, power)	(dev->b_max_power = power)
 #else
+static void set_aca_id_inputs(struct msm_otg *dev)
+{
+}
 #define get_aca_bmaxpower(dev)		0
 #define set_aca_bmaxpower(dev, power)
 #endif
@@ -692,6 +713,31 @@
 	 * 4. peripheral is supported, but, vbus is not routed to pmic
 	 */
 	host_bus_suspend = dev->otg.host && is_host();
+
+	/*
+	 *  Configure the PMIC ID only in case of cable disconnect.
+	 *  PMIC doesn't generate interrupt for ID_GND to ID_A
+	 *  transistion. hence use the PHY ID cricuit.
+	 */
+	if (dev->pdata->pmic_id_notif_init && !host_bus_suspend &&
+		!test_bit(ID_A, &dev->inputs)) {
+		disable_idgnd(dev);
+		ret = dev->pdata->pmic_id_notif_init(
+			&msm_otg_set_id_state, 1);
+		if (!ret) {
+			dev->pmic_id_notif_supp = 1;
+			if (dev->pdata->pmic_id_irq)
+				dev->id_irq = dev->pdata->pmic_id_irq;
+		} else if (ret == -ENOTSUPP) {
+			pr_debug("%s:USB ID is not routed to pmic",
+			__func__);
+			enable_idgnd(dev);
+		} else {
+			pr_err("%s: pmic_id_ notif_init failed err:%d",
+				__func__, ret);
+		}
+	}
+
 	if ((dev->otg.gadget && chg_type == USB_CHG_TYPE__WALLCHARGER) ||
 		host_bus_suspend ||
 		(dev->otg.host && !dev->pmic_id_notif_supp) ||
@@ -760,7 +806,8 @@
 	 * that there is no harm with this. Till hw folks confirms this
 	 * put regulators in lpm.
 	 */
-	if (!host_bus_suspend && dev->pmic_vbus_notif_supp) {
+	 if (!host_bus_suspend && dev->pmic_vbus_notif_supp &&
+		!test_bit(ID_A, &dev->inputs)) {
 		pr_debug("phy can power collapse: (%d)\n",
 			can_phy_power_collapse(dev));
 		if (can_phy_power_collapse(dev) && dev->pdata->ldo_enable) {
@@ -881,9 +928,35 @@
 	}
 
 phy_resumed:
+	/*
+	 * It is observed that BSVIS may get set immediatly
+	 * after PHY becomes active upon micro-B cable connect.
+	 * But BSVIS might get cleared by below enable_idgnd
+	 * function which causes hw to not generate the BSV interrupt.
+	 * Hence check for BSV interrupt explictly and schedule the
+	 * work.
+	 */
+	if (readl_relaxed(USB_OTGSC) & OTGSC_BSVIS) {
+		set_bit(B_SESS_VLD, &dev->inputs);
+		queue_work(dev->wq, &dev->sm_work);
+	}
+	if (dev->pmic_id_notif_supp) {
+		dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 0);
+		dev->pmic_id_notif_supp = 0;
+		enable_idgnd(dev);
+	}
+
 	/* Enable Idabc interrupts as these were disabled before entering LPM */
 	enable_idabc(dev);
 
+	/*
+	 * There is corner case where host won't be resumed
+	 * while transitioning from ID_GND to ID_A. In that
+	 * IDGND might have cleared and ID_A might not have updated
+	 * yet. Hence update the ACA states explicitly.
+	 */
+	set_aca_id_inputs(dev);
+
 	/* If resume signalling finishes before lpm exit, PCD is not set in
 	 * USBSTS register. Drive resume signal to the downstream device now
 	 * so that host driver can process the upcoming port change interrupt.*/
@@ -996,6 +1069,12 @@
 			}
 			udelay(10);
 		}
+		if (dev->pmic_id_notif_supp) {
+			dev->pdata->pmic_id_notif_init(
+				&msm_otg_set_id_state, 0);
+			dev->pmic_id_notif_supp = 0;
+			enable_idgnd(dev);
+		}
 out:
 		enable_idabc(dev);
 		enable_irq(dev->irq);
@@ -1119,23 +1198,20 @@
 #endif
 	return 0;
 }
-#endif
 
-void msm_otg_set_id_state(int id)
+static void msm_otg_set_id_state(int id)
 {
 	struct msm_otg *dev = the_msm_otg;
 	unsigned long flags;
 
-	if (id == dev->pmic_id_status)
+	if (!atomic_read(&dev->in_lpm))
 		return;
 
 	if (id) {
 		set_bit(ID, &dev->inputs);
-		dev->pmic_id_status = 1;
 	} else {
 		clear_bit(ID, &dev->inputs);
 		set_bit(A_BUS_REQ, &dev->inputs);
-		dev->pmic_id_status = 0;
 	}
 	spin_lock_irqsave(&dev->lock, flags);
 	if (dev->otg.state != OTG_STATE_UNDEFINED) {
@@ -1144,6 +1220,7 @@
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
+#endif
 
 void msm_otg_set_vbus_state(int online)
 {
@@ -1973,6 +2050,7 @@
 		} else if (test_bit(ID_A, &dev->inputs)) {
 			dev->pdata->vbus_power(USB_PHY_INTEGRATED, 0);
 		} else if (!test_bit(ID, &dev->inputs)) {
+			msm_otg_set_power(&dev->otg, 0);
 			dev->pdata->vbus_power(USB_PHY_INTEGRATED, 1);
 		}
 		break;
@@ -2687,12 +2765,10 @@
 		}
 	}
 
-	if (dev->pdata->pmic_id_notif_init) {
-		ret = dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 1);
-		if (!ret) {
-			dev->pmic_id_notif_supp = 1;
-		} else if (ret != -ENOTSUPP) {
-			pr_err("%s: pmic_id_ notif_init failed err:%d",
+	if (dev->pdata->phy_id_setup_init) {
+		ret = dev->pdata->phy_id_setup_init(1);
+		if (ret) {
+			pr_err("%s: phy_id_setup_init failed err:%d",
 					__func__, ret);
 			goto free_pmic_vbus_notif;
 		}
@@ -2700,8 +2776,6 @@
 
 	if (dev->pdata->pmic_vbus_irq)
 		dev->vbus_on_irq = dev->pdata->pmic_vbus_irq;
-	if (dev->pdata->pmic_id_irq)
-		dev->id_irq = dev->pdata->pmic_id_irq;
 
 	/* vote for vddcx, as PHY cannot tolerate vddcx below 1.0V */
 	if (dev->pdata->init_vddcx) {
@@ -2709,7 +2783,7 @@
 		if (ret) {
 			pr_err("%s: unable to enable vddcx digital core:%d\n",
 				__func__, ret);
-			goto free_pmic_id_notif;
+			goto free_phy_id_setup;
 		}
 	}
 
@@ -2819,9 +2893,9 @@
 free_config_vddcx:
 	if (dev->pdata->init_vddcx)
 		dev->pdata->init_vddcx(0);
-free_pmic_id_notif:
-	if (dev->pdata->pmic_id_notif_init && dev->pmic_id_notif_supp)
-		dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 0);
+free_phy_id_setup:
+	if (dev->pdata->phy_id_setup_init)
+		dev->pdata->phy_id_setup_init(0);
 free_pmic_vbus_notif:
 	if (dev->pdata->pmic_vbus_notif_init && dev->pmic_vbus_notif_supp)
 		dev->pdata->pmic_vbus_notif_init(&msm_otg_set_vbus_state, 0);
@@ -2890,6 +2964,9 @@
 	if (dev->pmic_vbus_notif_supp)
 		dev->pdata->pmic_vbus_notif_init(&msm_otg_set_vbus_state, 0);
 
+	if (dev->pdata->phy_id_setup_init)
+		dev->pdata->phy_id_setup_init(0);
+
 	if (dev->pmic_id_notif_supp)
 		dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 0);
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 7f1641f..4622725 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -25,6 +25,8 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/usb.h>
 #include <linux/usb/otg.h>
@@ -41,27 +43,7 @@
 #define MSM_USB_BASE	(motg->regs)
 #define DRIVER_NAME	"msm_otg"
 
-#ifdef CONFIG_USB_MSM_ACA
-static void msm_chg_enable_aca_det(struct msm_otg *motg);
-static void msm_chg_enable_aca_intr(struct msm_otg *motg);
-#else
-static inline bool msm_chg_aca_detect(struct msm_otg *motg)
-{
-	return false;
-}
-
-static inline void msm_chg_enable_aca_det(struct msm_otg *motg)
-{
-}
-static inline void msm_chg_enable_aca_intr(struct msm_otg *motg)
-{
-}
-static inline bool msm_chg_check_aca_intr(struct msm_otg *motg)
-{
-	return false;
-}
-#endif
-
+#define ID_TIMER_FREQ		(jiffies + msecs_to_jiffies(2000))
 #define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
 
 #define USB_PHY_3P3_VOL_MIN	3050000 /* uV */
@@ -74,15 +56,25 @@
 #define USB_PHY_1P8_HPM_LOAD	50000	/* uA */
 #define USB_PHY_1P8_LPM_LOAD	4000	/* uA */
 
-#define USB_PHY_VDD_DIG_VOL_MIN	1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MIN	1045000 /* uV */
 #define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
 
 static struct msm_otg *the_msm_otg;
+static bool debug_aca_enabled;
 
 static struct regulator *hsusb_3p3;
 static struct regulator *hsusb_1p8;
 static struct regulator *hsusb_vddcx;
 
+static inline bool aca_enabled(void)
+{
+#ifdef CONFIG_USB_MSM_ACA
+	return true;
+#else
+	return debug_aca_enabled;
+#endif
+}
+
 static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
 {
 	int ret = 0;
@@ -291,6 +283,34 @@
 	return ret < 0 ? ret : 0;
 }
 
+static void msm_hsusb_mhl_switch_enable(struct msm_otg *motg, bool on)
+{
+	static struct regulator *mhl_analog_switch;
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	if (!pdata->mhl_enable)
+		return;
+
+	if (on) {
+		mhl_analog_switch = regulator_get(motg->otg.dev,
+					       "mhl_ext_3p3v");
+		if (IS_ERR(mhl_analog_switch)) {
+			pr_err("Unable to get mhl_analog_switch\n");
+			return;
+		}
+
+		if (regulator_enable(mhl_analog_switch)) {
+			pr_err("unable to enable mhl_analog_switch\n");
+			goto put_analog_switch;
+		}
+		return;
+	}
+
+	regulator_disable(mhl_analog_switch);
+put_analog_switch:
+	regulator_put(mhl_analog_switch);
+}
+
 static int ulpi_read(struct otg_transceiver *otg, u32 reg)
 {
 	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -449,11 +469,32 @@
 }
 
 #define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
+static int msm_otg_link_reset(struct msm_otg *motg)
+{
+	int cnt = 0;
+
+	writel_relaxed(USBCMD_RESET, USB_USBCMD);
+	while (cnt < LINK_RESET_TIMEOUT_USEC) {
+		if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
+			break;
+		udelay(1);
+		cnt++;
+	}
+	if (cnt >= LINK_RESET_TIMEOUT_USEC)
+		return -ETIMEDOUT;
+
+	/* select ULPI phy */
+	writel_relaxed(0x80000000, USB_PORTSC);
+	writel_relaxed(0x0, USB_AHBBURST);
+	writel_relaxed(0x00, USB_AHBMODE);
+
+	return 0;
+}
+
 static int msm_otg_reset(struct otg_transceiver *otg)
 {
 	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
 	struct msm_otg_platform_data *pdata = motg->pdata;
-	int cnt = 0;
 	int ret;
 	u32 val = 0;
 	u32 ulpi_val = 0;
@@ -467,26 +508,15 @@
 
 	ulpi_init(motg);
 
-	writel(USBCMD_RESET, USB_USBCMD);
-	while (cnt < LINK_RESET_TIMEOUT_USEC) {
-		if (!(readl(USB_USBCMD) & USBCMD_RESET))
-			break;
-		udelay(1);
-		cnt++;
+	ret = msm_otg_link_reset(motg);
+	if (ret) {
+		dev_err(otg->dev, "link reset failed\n");
+		return ret;
 	}
-	if (cnt >= LINK_RESET_TIMEOUT_USEC)
-		return -ETIMEDOUT;
-
-	/* select ULPI phy */
-	writel(0x80000000, USB_PORTSC);
-
 	msleep(100);
-
-	writel(0x0, USB_AHBBURST);
-	writel(0x00, USB_AHBMODE);
-
 	/* Ensure that RESET operation is completed before turning off clock */
 	mb();
+
 	clk_disable(motg->clk);
 
 	val = readl_relaxed(USB_OTGSC);
@@ -501,8 +531,27 @@
 	ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
 	ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
 
-	msm_chg_enable_aca_det(motg);
-	msm_chg_enable_aca_intr(motg);
+	return 0;
+}
+
+static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+	/*
+	 * Allow bus suspend only for host mode.  Device mode bus suspend
+	 * is not implemented yet.
+	 */
+	if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs)) {
+		/*
+		 * ID_GND --> ID_A transition can not be detected in LPM.
+		 * Disallow host bus suspend when ACA is enabled.
+		 */
+		if (suspend && !aca_enabled())
+			pm_runtime_put(otg->dev);
+		else
+			pm_runtime_resume(otg->dev);
+	}
 
 	return 0;
 }
@@ -611,8 +660,10 @@
 		motg->lpm_flags |= PHY_PWR_COLLAPSED;
 	}
 
-	if (motg->lpm_flags & PHY_RETENTIONED)
+	if (motg->lpm_flags & PHY_RETENTIONED) {
 		msm_hsusb_config_vddcx(0);
+		msm_hsusb_mhl_switch_enable(motg, 0);
+	}
 
 	if (device_may_wakeup(otg->dev)) {
 		enable_irq_wake(motg->irq);
@@ -658,6 +709,7 @@
 	}
 
 	if (motg->lpm_flags & PHY_RETENTIONED) {
+		msm_hsusb_mhl_switch_enable(motg, 1);
 		msm_hsusb_config_vddcx(1);
 		writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
 				USB_PHY_CTRL);
@@ -712,9 +764,13 @@
 
 	atomic_set(&motg->in_lpm, 0);
 
+	if (aca_enabled() && !irq_read_line(motg->pdata->pmic_id_irq)) {
+		clear_bit(ID, &motg->inputs);
+		schedule_work(&motg->sm_work);
+	}
+
 	if (motg->async_int) {
 		motg->async_int = 0;
-		pm_runtime_put(otg->dev);
 		enable_irq(motg->irq);
 	}
 
@@ -726,6 +782,13 @@
 
 static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
 {
+	if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
+		motg->chg_type == USB_ACA_A_CHARGER ||
+		motg->chg_type == USB_ACA_B_CHARGER ||
+		motg->chg_type == USB_ACA_C_CHARGER) &&
+			mA > IDEV_ACA_CHG_LIMIT)
+		mA = IDEV_ACA_CHG_LIMIT;
+
 	if (motg->cur_power == mA)
 		return;
 
@@ -777,6 +840,9 @@
 		dev_dbg(otg->dev, "host off\n");
 
 		usb_remove_hcd(hcd);
+		/* HCD core reset all bits of PORTSC. select ULPI phy */
+		writel_relaxed(0x80000000, USB_PORTSC);
+
 		if (pdata->setup_gpio)
 			pdata->setup_gpio(OTG_STATE_UNDEFINED);
 	}
@@ -786,32 +852,45 @@
 			unsigned long action, void *priv)
 {
 	struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
-	struct usb_device *udev;
+	struct usb_device *udev = priv;
+
+	if (!aca_enabled())
+		goto out;
+
+	if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
+		goto out;
+
+	if (udev->bus != motg->otg.host)
+		goto out;
+	/*
+	 * Interested in devices connected directly to the root hub.
+	 * ACA dock can supply IDEV_CHG irrespective devices connected
+	 * on the accessory port.
+	 */
+	if (!udev->parent || udev->parent->parent ||
+			motg->chg_type == USB_ACA_DOCK_CHARGER)
+		goto out;
 
 	switch (action) {
 	case USB_DEVICE_ADD:
+		usb_disable_autosuspend(udev);
+		/* fall through */
 	case USB_DEVICE_CONFIG:
-		udev = priv;
-		/*
-		 * Interested in devices connected directly to the root hub.
-		 * ACA dock can supply IDEV_CHG irrespective devices connected
-		 * on the accessory port.
-		 */
-		if (!udev->parent || udev->parent->parent ||
-				motg->chg_type == USB_ACA_DOCK_CHARGER)
-			break;
 		if (udev->actconfig)
 			motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
 		else
 			motg->mA_port = IUNIT;
-
-		if (test_bit(ID_A, &motg->inputs))
-			msm_otg_notify_charger(motg, IDEV_CHG_MIN -
-					motg->mA_port);
+		break;
+	case USB_DEVICE_REMOVE:
+		motg->mA_port = IUNIT;
 		break;
 	default:
 		break;
 	}
+	if (test_bit(ID_A, &motg->inputs))
+		msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX -
+				motg->mA_port);
+out:
 	return NOTIFY_OK;
 }
 
@@ -935,13 +1014,15 @@
 	return 0;
 }
 
-#ifdef CONFIG_USB_MSM_ACA
 static bool msm_chg_aca_detect(struct msm_otg *motg)
 {
 	struct otg_transceiver *otg = &motg->otg;
 	u32 int_sts;
 	bool ret = false;
 
+	if (!aca_enabled())
+		goto out;
+
 	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
 		goto out;
 
@@ -954,6 +1035,7 @@
 			motg->chg_state = USB_CHG_STATE_DETECTED;
 			clear_bit(ID_B, &motg->inputs);
 			clear_bit(ID_C, &motg->inputs);
+			set_bit(ID, &motg->inputs);
 			ret = true;
 		}
 		break;
@@ -964,6 +1046,7 @@
 			motg->chg_state = USB_CHG_STATE_DETECTED;
 			clear_bit(ID_A, &motg->inputs);
 			clear_bit(ID_C, &motg->inputs);
+			set_bit(ID, &motg->inputs);
 			ret = true;
 		}
 		break;
@@ -974,15 +1057,28 @@
 			motg->chg_state = USB_CHG_STATE_DETECTED;
 			clear_bit(ID_A, &motg->inputs);
 			clear_bit(ID_B, &motg->inputs);
+			set_bit(ID, &motg->inputs);
+			ret = true;
+		}
+		break;
+	case 0x04:
+		if (test_and_clear_bit(ID, &motg->inputs)) {
+			dev_dbg(otg->dev, "ID_GND\n");
+			motg->chg_type = USB_INVALID_CHARGER;
+			motg->chg_state = USB_CHG_STATE_UNDEFINED;
+			clear_bit(ID_A, &motg->inputs);
+			clear_bit(ID_B, &motg->inputs);
+			clear_bit(ID_C, &motg->inputs);
 			ret = true;
 		}
 		break;
 	default:
 		ret = test_and_clear_bit(ID_A, &motg->inputs) |
 			test_and_clear_bit(ID_B, &motg->inputs) |
-			test_and_clear_bit(ID_C, &motg->inputs);
+			test_and_clear_bit(ID_C, &motg->inputs) |
+			!test_and_set_bit(ID, &motg->inputs);
 		if (ret) {
-			dev_dbg(otg->dev, "ID A/B/C is no more\n");
+			dev_dbg(otg->dev, "ID A/B/C/GND is no more\n");
 			motg->chg_type = USB_INVALID_CHARGER;
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 		}
@@ -995,9 +1091,18 @@
 {
 	struct otg_transceiver *otg = &motg->otg;
 
+	if (!aca_enabled())
+		return;
+
 	switch (motg->pdata->phy_type) {
 	case SNPS_28NM_INTEGRATED_PHY:
-		/* ACA ID pin resistance detection enable */
+		/* Disable ID_GND in link and PHY */
+		writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU |
+				OTGSC_IDIE), USB_OTGSC);
+		ulpi_write(otg, 0x01, 0x0C);
+		ulpi_write(otg, 0x10, 0x0F);
+		ulpi_write(otg, 0x10, 0x12);
+		/* Enable ACA ID detection */
 		ulpi_write(otg, 0x20, 0x85);
 		break;
 	default:
@@ -1009,10 +1114,29 @@
 {
 	struct otg_transceiver *otg = &motg->otg;
 
+	if (!aca_enabled())
+		return;
+
 	switch (motg->pdata->phy_type) {
 	case SNPS_28NM_INTEGRATED_PHY:
-		/* Enables ACA Detection interrupt (on any RID change) */
-		ulpi_write(otg, 0x20, 0x94);
+		/* Enable ACA Detection interrupt (on any RID change) */
+		ulpi_write(otg, 0x01, 0x94);
+		break;
+	default:
+		break;
+	}
+}
+
+static void msm_chg_disable_aca_intr(struct msm_otg *motg)
+{
+	struct otg_transceiver *otg = &motg->otg;
+
+	if (!aca_enabled())
+		return;
+
+	switch (motg->pdata->phy_type) {
+	case SNPS_28NM_INTEGRATED_PHY:
+		ulpi_write(otg, 0x01, 0x95);
 		break;
 	default:
 		break;
@@ -1024,6 +1148,9 @@
 	struct otg_transceiver *otg = &motg->otg;
 	bool ret = false;
 
+	if (!aca_enabled())
+		return ret;
+
 	switch (motg->pdata->phy_type) {
 	case SNPS_28NM_INTEGRATED_PHY:
 		if (ulpi_read(otg, 0x91) & 1) {
@@ -1036,7 +1163,28 @@
 	}
 	return ret;
 }
-#endif
+
+static void msm_otg_id_timer_func(unsigned long data)
+{
+	struct msm_otg *motg = (struct msm_otg *) data;
+
+	if (!aca_enabled())
+		return;
+
+	if (atomic_read(&motg->in_lpm)) {
+		dev_dbg(motg->otg.dev, "timer: in lpm\n");
+		return;
+	}
+
+	if (msm_chg_check_aca_intr(motg)) {
+		dev_dbg(motg->otg.dev, "timer: aca work\n");
+		schedule_work(&motg->sm_work);
+	}
+
+	if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
+		mod_timer(&motg->id_timer, ID_TIMER_FREQ);
+}
+
 static bool msm_chg_check_secondary_det(struct msm_otg *motg)
 {
 	struct otg_transceiver *otg = &motg->otg;
@@ -1229,7 +1377,7 @@
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
 		/* Clear charger detecting control bits */
-		ulpi_write(otg, 0x3F, 0x86);
+		ulpi_write(otg, 0x1F, 0x86);
 		/* Clear alt interrupt latch and enable bits */
 		ulpi_write(otg, 0x1F, 0x92);
 		ulpi_write(otg, 0x1F, 0x95);
@@ -1298,7 +1446,6 @@
 	dev_dbg(otg->dev, "chg detection work\n");
 	switch (motg->chg_state) {
 	case USB_CHG_STATE_UNDEFINED:
-		pm_runtime_get_sync(otg->dev);
 		msm_chg_block_on(motg);
 		msm_chg_enable_dcd(motg);
 		msm_chg_enable_aca_det(motg);
@@ -1333,18 +1480,23 @@
 		break;
 	case USB_CHG_STATE_DCD_DONE:
 		vout = msm_chg_check_primary_det(motg);
-		is_aca = msm_chg_aca_detect(motg);
-		if (is_aca) {
-			if (vout && test_bit(ID_A, &motg->inputs))
-				motg->chg_type = USB_ACA_DOCK_CHARGER;
-			delay = 0;
-			break;
-		}
 		if (vout) {
+			if (test_bit(ID_A, &motg->inputs)) {
+				motg->chg_type = USB_ACA_DOCK_CHARGER;
+				motg->chg_state = USB_CHG_STATE_DETECTED;
+				delay = 0;
+				break;
+			}
 			msm_chg_enable_secondary_det(motg);
 			delay = MSM_CHG_SECONDARY_DET_TIME;
 			motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
 		} else {
+			if (test_bit(ID_A, &motg->inputs)) {
+				motg->chg_type = USB_ACA_A_CHARGER;
+				motg->chg_state = USB_CHG_STATE_DETECTED;
+				delay = 0;
+				break;
+			}
 			motg->chg_type = USB_SDP_CHARGER;
 			motg->chg_state = USB_CHG_STATE_DETECTED;
 			delay = 0;
@@ -1400,10 +1552,18 @@
 				clear_bit(B_SESS_VLD, &motg->inputs);
 			}
 		} else {
-			if (otgsc & OTGSC_ID)
-				set_bit(ID, &motg->inputs);
-			else
-				clear_bit(ID, &motg->inputs);
+			if (aca_enabled()) {
+				if (irq_read_line(motg->pdata->pmic_id_irq))
+					set_bit(ID, &motg->inputs);
+				else
+					clear_bit(ID, &motg->inputs);
+
+			} else {
+				if (otgsc & OTGSC_ID)
+					set_bit(ID, &motg->inputs);
+				else
+					clear_bit(ID, &motg->inputs);
+			}
 
 			if (otgsc & OTGSC_BSV)
 				set_bit(B_SESS_VLD, &motg->inputs);
@@ -1431,6 +1591,7 @@
 	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
 	struct otg_transceiver *otg = &motg->otg;
 
+	pm_runtime_resume(otg->dev);
 	switch (otg->state) {
 	case OTG_STATE_UNDEFINED:
 		dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
@@ -1442,15 +1603,26 @@
 		dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
 		if ((!test_bit(ID, &motg->inputs) ||
 				test_bit(ID_A, &motg->inputs)) && otg->host) {
-			/* disable BSV bit */
-			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
 			if (motg->chg_type == USB_ACA_DOCK_CHARGER)
 				msm_otg_notify_charger(motg,
-						IDEV_CHG_MAX);
-			else if (!test_bit(ID_A, &motg->inputs) &&
-					motg->pdata->vbus_power)
+						IDEV_ACA_CHG_MAX);
+			else if (test_bit(ID_A, &motg->inputs))
+				msm_otg_notify_charger(motg,
+						IDEV_ACA_CHG_MAX - IUNIT);
+			else if (motg->pdata->vbus_power)
 				motg->pdata->vbus_power(1);
 			msm_otg_start_host(otg, 1);
+			/*
+			 * Link can not generate PHY_ALT interrupt
+			 * in host mode when no device is attached
+			 * to the port.  It is also observed PHY_ALT
+			 * interrupt missing upon Micro-A cable disconnect.
+			 * Hence disable PHY_ALT interrupt and perform
+			 * polling to detect RID change.
+			 */
+			msm_chg_enable_aca_det(motg);
+			msm_chg_disable_aca_intr(motg);
+			mod_timer(&motg->id_timer, ID_TIMER_FREQ);
 			otg->state = OTG_STATE_A_HOST;
 		} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
 			switch (motg->chg_state) {
@@ -1460,17 +1632,31 @@
 			case USB_CHG_STATE_DETECTED:
 				switch (motg->chg_type) {
 				case USB_DCP_CHARGER:
+					msm_otg_notify_charger(motg,
+							IDEV_CHG_MAX);
+					pm_runtime_put_noidle(otg->dev);
+					pm_runtime_suspend(otg->dev);
+					break;
 				case USB_ACA_B_CHARGER:
 					msm_otg_notify_charger(motg,
-							IDEV_CHG_MAX);
+							IDEV_ACA_CHG_MAX);
+					/*
+					 * (ID_B --> ID_C) PHY_ALT interrupt can
+					 * not be detected in LPM.
+					 */
 					break;
 				case USB_CDP_CHARGER:
-				case USB_ACA_C_CHARGER:
 					msm_otg_notify_charger(motg,
 							IDEV_CHG_MAX);
 					msm_otg_start_peripheral(otg, 1);
 					otg->state = OTG_STATE_B_PERIPHERAL;
 					break;
+				case USB_ACA_C_CHARGER:
+					msm_otg_notify_charger(motg,
+							IDEV_ACA_CHG_MAX);
+					msm_otg_start_peripheral(otg, 1);
+					otg->state = OTG_STATE_B_PERIPHERAL;
+					break;
 				case USB_SDP_CHARGER:
 					msm_otg_notify_charger(motg, IUNIT);
 					msm_otg_start_peripheral(otg, 1);
@@ -1484,39 +1670,25 @@
 				break;
 			}
 		} else {
-			/*
-			 * If charger detection work is pending, decrement
-			 * the pm usage counter to balance with the one that
-			 * is incremented in charger detection work.
-			 */
-			if (cancel_delayed_work_sync(&motg->chg_work)) {
-				pm_runtime_put_sync(otg->dev);
-				msm_otg_reset(otg);
-			}
+			cancel_delayed_work_sync(&motg->chg_work);
 			msm_otg_notify_charger(motg, 0);
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 			motg->chg_type = USB_INVALID_CHARGER;
+			msm_otg_reset(otg);
+			pm_runtime_put_noidle(otg->dev);
+			pm_runtime_suspend(otg->dev);
 		}
-		pm_runtime_put_sync(otg->dev);
 		break;
 	case OTG_STATE_B_PERIPHERAL:
 		dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
 		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
 				!test_bit(ID, &motg->inputs) ||
 				!test_bit(ID_C, &motg->inputs)) {
-			msm_otg_notify_charger(motg, 0);
 			msm_otg_start_peripheral(otg, 0);
-			if (!test_bit(ID_B, &motg->inputs) &&
-				!test_bit(ID_A, &motg->inputs)) {
-				motg->chg_state = USB_CHG_STATE_UNDEFINED;
-				motg->chg_type = USB_INVALID_CHARGER;
-			}
 			otg->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg);
 			schedule_work(w);
 		} else if (test_bit(ID_C, &motg->inputs)) {
-			msm_otg_notify_charger(motg, IDEV_CHG_MAX);
-			pm_runtime_put_sync(otg->dev);
+			msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
 		}
 		break;
 	case OTG_STATE_A_HOST:
@@ -1524,29 +1696,39 @@
 		if (test_bit(ID, &motg->inputs) &&
 				!test_bit(ID_A, &motg->inputs)) {
 			msm_otg_start_host(otg, 0);
-			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
-			if (motg->pdata->vbus_power)
+			if (motg->pdata->vbus_power) {
 				motg->pdata->vbus_power(0);
-			motg->chg_state = USB_CHG_STATE_UNDEFINED;
-			motg->chg_type = USB_INVALID_CHARGER;
+				msleep(100); /* TA_WAIT_VFALL */
+			}
+			/*
+			 * Exit point of host mode.
+			 *
+			 * 1. Micro-A cable disconnect: Just schedule
+			 * the work. PHY is reset in B_IDLE and LPM
+			 * is allowed.
+			 * 2. ID_GND --> ID_B: No need to reset the PHY.
+			 * HCD core clears all PORTSC bits and initializes
+			 * the controller to host mode in remove_hcd.
+			 * Restore PORTSC transceiver select bits (ULPI)
+			 * and reset the controller to change MODE bits.
+			 * PHY_ALT interrupt can not occur in host mode.
+			 */
+			del_timer_sync(&motg->id_timer);
+			if (motg->chg_state != USB_CHG_STATE_UNDEFINED) {
+				msm_otg_link_reset(motg);
+				msm_chg_enable_aca_intr(motg);
+			}
 			otg->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg);
 			schedule_work(w);
 		} else if (test_bit(ID_A, &motg->inputs)) {
-			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
 			if (motg->pdata->vbus_power)
 				motg->pdata->vbus_power(0);
 			msm_otg_notify_charger(motg,
-					IDEV_CHG_MIN - motg->mA_port);
-			pm_runtime_put_sync(otg->dev);
+					IDEV_ACA_CHG_MAX - motg->mA_port);
 		} else if (!test_bit(ID, &motg->inputs)) {
-			motg->chg_state = USB_CHG_STATE_UNDEFINED;
-			motg->chg_type = USB_INVALID_CHARGER;
 			msm_otg_notify_charger(motg, 0);
-			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
 			if (motg->pdata->vbus_power)
 				motg->pdata->vbus_power(1);
-			pm_runtime_put_sync(otg->dev);
 		}
 		break;
 	default:
@@ -1563,15 +1745,16 @@
 	if (atomic_read(&motg->in_lpm)) {
 		disable_irq_nosync(irq);
 		motg->async_int = 1;
-		pm_runtime_get(otg->dev);
+		pm_request_resume(otg->dev);
 		return IRQ_HANDLED;
 	}
 
 	usbsts = readl(USB_USBSTS);
 	if ((usbsts & PHY_ALT_INT)) {
+		dev_dbg(otg->dev, "PHY_ALT interrupt\n");
 		writel(PHY_ALT_INT, USB_USBSTS);
 		if (msm_chg_check_aca_intr(motg)) {
-			pm_runtime_get_noresume(otg->dev);
+			dev_dbg(otg->dev, "ACA work from IRQ\n");
 			schedule_work(&motg->sm_work);
 		}
 		return IRQ_HANDLED;
@@ -1582,21 +1765,25 @@
 		return IRQ_NONE;
 
 	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
-		if (otgsc & OTGSC_ID)
+		if (otgsc & OTGSC_ID) {
+			dev_dbg(otg->dev, "ID set\n");
 			set_bit(ID, &motg->inputs);
-		else
+		} else {
+			dev_dbg(otg->dev, "ID clear\n");
 			clear_bit(ID, &motg->inputs);
-		dev_dbg(otg->dev, "ID set/clear\n");
+			msm_chg_enable_aca_det(motg);
+		}
 		schedule_work(&motg->sm_work);
-		pm_runtime_get_noresume(otg->dev);
 	} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
-		if (otgsc & OTGSC_BSV)
+		if (otgsc & OTGSC_BSV) {
+			dev_dbg(otg->dev, "BSV set\n");
 			set_bit(B_SESS_VLD, &motg->inputs);
-		else
+		} else {
+			dev_dbg(otg->dev, "BSV clear\n");
 			clear_bit(B_SESS_VLD, &motg->inputs);
-		dev_dbg(otg->dev, "BSV set/clear\n");
+			msm_chg_check_aca_intr(motg);
+		}
 		schedule_work(&motg->sm_work);
-		pm_runtime_get_noresume(otg->dev);
 	}
 
 	writel(otgsc, USB_OTGSC);
@@ -1718,7 +1905,7 @@
 		goto out;
 	}
 
-	pm_runtime_get_sync(otg->dev);
+	pm_runtime_resume(otg->dev);
 	schedule_work(&motg->sm_work);
 out:
 	return status;
@@ -1752,9 +1939,51 @@
 	.release = single_release,
 };
 
+static int msm_otg_aca_show(struct seq_file *s, void *unused)
+{
+	if (debug_aca_enabled)
+		seq_printf(s, "enabled\n");
+	else
+		seq_printf(s, "disabled\n");
+
+	return 0;
+}
+
+static int msm_otg_aca_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, msm_otg_aca_show, inode->i_private);
+}
+
+static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char buf[8];
+
+	memset(buf, 0x00, sizeof(buf));
+
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+		return -EFAULT;
+
+	if (!strncmp(buf, "enable", 6))
+		debug_aca_enabled = true;
+	else
+		debug_aca_enabled = false;
+
+	return count;
+}
+
+const struct file_operations msm_otg_aca_fops = {
+	.open = msm_otg_aca_open,
+	.read = seq_read,
+	.write = msm_otg_aca_write,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
 static struct dentry *msm_otg_dbg_root;
 static struct dentry *msm_otg_dbg_mode;
 static struct dentry *msm_otg_chg_type;
+static struct dentry *msm_otg_dbg_aca;
 
 static int msm_otg_debugfs_init(struct msm_otg *motg)
 {
@@ -1783,10 +2012,16 @@
 		&msm_otg_chg_fops);
 
 	if (!msm_otg_chg_type) {
-		debugfs_remove(msm_otg_dbg_mode);
-		debugfs_remove(msm_otg_dbg_root);
-		msm_otg_dbg_root = NULL;
-		msm_otg_dbg_mode = NULL;
+		debugfs_remove_recursive(msm_otg_dbg_root);
+		return -ENODEV;
+	}
+
+	msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
+		msm_otg_dbg_root, motg,
+		&msm_otg_aca_fops);
+
+	if (!msm_otg_dbg_aca) {
+		debugfs_remove_recursive(msm_otg_dbg_root);
 		return -ENODEV;
 	}
 
@@ -1798,17 +2033,147 @@
 	debugfs_remove_recursive(msm_otg_dbg_root);
 }
 
+static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
+static struct platform_device *msm_otg_add_pdev(
+		struct platform_device *ofdev, const char *name)
+{
+	struct platform_device *pdev;
+	const struct resource *res = ofdev->resource;
+	unsigned int num = ofdev->num_resources;
+	int retval;
+
+	pdev = platform_device_alloc(name, -1);
+	if (!pdev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	pdev->dev.dma_mask = &msm_otg_dma_mask;
+
+	if (num) {
+		retval = platform_device_add_resources(pdev, res, num);
+		if (retval)
+			goto error;
+	}
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto error;
+
+	return pdev;
+
+error:
+	platform_device_put(pdev);
+	return ERR_PTR(retval);
+}
+
+static int msm_otg_setup_devices(struct platform_device *ofdev,
+		enum usb_mode_type mode, bool init)
+{
+	const char *gadget_name = "msm_hsusb";
+	const char *host_name = "msm_hsusb_host";
+	static struct platform_device *gadget_pdev;
+	static struct platform_device *host_pdev;
+	int retval = 0;
+
+	if (!init) {
+		if (gadget_pdev)
+			platform_device_unregister(gadget_pdev);
+		if (host_pdev)
+			platform_device_unregister(host_pdev);
+		return 0;
+	}
+
+	switch (mode) {
+	case USB_OTG:
+		/* fall through */
+	case USB_PERIPHERAL:
+		gadget_pdev = msm_otg_add_pdev(ofdev, gadget_name);
+		if (IS_ERR(gadget_pdev)) {
+			retval = PTR_ERR(gadget_pdev);
+			break;
+		}
+		if (mode == USB_PERIPHERAL)
+			break;
+		/* fall through */
+	case USB_HOST:
+		host_pdev = msm_otg_add_pdev(ofdev, host_name);
+		if (IS_ERR(host_pdev)) {
+			retval = PTR_ERR(host_pdev);
+			if (mode == USB_OTG)
+				platform_device_unregister(gadget_pdev);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return retval;
+}
+
+struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct msm_otg_platform_data *pdata;
+	int len = 0;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("unable to allocate platform data\n");
+		return NULL;
+	}
+	of_get_property(node, "qcom,hsusb-otg-phy-init-seq", &len);
+	if (len) {
+		pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+		if (!pdata->phy_init_seq)
+			return NULL;
+		of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq",
+				pdata->phy_init_seq,
+				len/sizeof(*pdata->phy_init_seq));
+	}
+	of_property_read_u32(node, "qcom,hsusb-otg-power-budget",
+				&pdata->power_budget);
+	of_property_read_u32(node, "qcom,hsusb-otg-mode",
+				&pdata->mode);
+	of_property_read_u32(node, "qcom,hsusb-otg-otg-control",
+				&pdata->otg_control);
+	of_property_read_u32(node, "qcom,hsusb-otg-default-mode",
+				&pdata->default_mode);
+	of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
+				&pdata->phy_type);
+	of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
+				&pdata->pmic_id_irq);
+	of_property_read_string(node, "qcom,hsusb-otg-pclk-src-name",
+				&pdata->pclk_src_name);
+	return pdata;
+}
+
 static int __init msm_otg_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct resource *res;
 	struct msm_otg *motg;
 	struct otg_transceiver *otg;
+	struct msm_otg_platform_data *pdata;
 
 	dev_info(&pdev->dev, "msm_otg probe\n");
-	if (!pdev->dev.platform_data) {
+
+	if (pdev->dev.of_node) {
+		dev_dbg(&pdev->dev, "device tree enabled\n");
+		pdata = msm_otg_dt_to_pdata(pdev);
+		if (!pdata)
+			return -ENOMEM;
+		ret = msm_otg_setup_devices(pdev, pdata->mode, true);
+		if (ret) {
+			dev_err(&pdev->dev, "devices setup failed\n");
+			return ret;
+		}
+	} else if (!pdev->dev.platform_data) {
 		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
 		return -ENODEV;
+	} else {
+		pdata = pdev->dev.platform_data;
 	}
 
 	motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
@@ -1818,10 +2183,21 @@
 	}
 
 	the_msm_otg = motg;
-	motg->pdata = pdev->dev.platform_data;
+	motg->pdata = pdata;
 	otg = &motg->otg;
 	otg->dev = &pdev->dev;
 
+	/*
+	 * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT.  Hence
+	 * PHY treat ACA ID_GND as float and no interrupt is generated.  But
+	 * PMIC can detect ACA ID_GND and generate an interrupt.
+	 */
+	if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
+		dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
+		ret = -EINVAL;
+		goto free_motg;
+	}
+
 	/* Some targets don't support PHY clock. */
 	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
 	if (IS_ERR(motg->phy_reset_clk))
@@ -1931,6 +2307,8 @@
 	wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
 	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
 	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
+	setup_timer(&motg->id_timer, msm_otg_id_timer_func,
+				(unsigned long) motg);
 	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
 					"msm_otg", motg);
 	if (ret) {
@@ -1942,6 +2320,7 @@
 	otg->set_host = msm_otg_set_host;
 	otg->set_peripheral = msm_otg_set_peripheral;
 	otg->set_power = msm_otg_set_power;
+	otg->set_suspend = msm_otg_set_suspend;
 
 	otg->io_ops = &msm_otg_io_ops;
 
@@ -1969,6 +2348,8 @@
 		}
 	}
 
+	msm_hsusb_mhl_switch_enable(motg, 1);
+
 	platform_set_drvdata(pdev, motg);
 	device_init_wakeup(&pdev->dev, 1);
 	motg->mA_port = IUNIT;
@@ -2026,7 +2407,7 @@
 put_phy_reset_clk:
 	if (!IS_ERR(motg->phy_reset_clk))
 		clk_put(motg->phy_reset_clk);
-
+free_motg:
 	kfree(motg);
 	return ret;
 }
@@ -2040,6 +2421,8 @@
 	if (otg->host || otg->gadget)
 		return -EBUSY;
 
+	if (pdev->dev.of_node)
+		msm_otg_setup_devices(pdev, motg->pdata->mode, false);
 	if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
 		pm8921_charger_unregister_vbus_sn(0);
 	msm_otg_debugfs_cleanup();
@@ -2052,6 +2435,7 @@
 	pm_runtime_disable(&pdev->dev);
 	wake_lock_destroy(&motg->wlock);
 
+	msm_hsusb_mhl_switch_enable(motg, 0);
 	if (motg->pdata->pmic_id_irq)
 		free_irq(motg->pdata->pmic_id_irq, motg);
 	otg_set_transceiver(NULL);
@@ -2111,16 +2495,10 @@
 
 	dev_dbg(dev, "OTG runtime idle\n");
 
-	/*
-	 * It is observed some times that a spurious interrupt
-	 * comes when PHY is put into LPM immediately after PHY reset.
-	 * This 1 sec delay also prevents entering into LPM immediately
-	 * after asynchronous interrupt.
-	 */
-	if (otg->state != OTG_STATE_UNDEFINED)
-		pm_schedule_suspend(dev, 1000);
-
-	return -EAGAIN;
+	if (otg->state == OTG_STATE_UNDEFINED)
+		return -EAGAIN;
+	else
+		return 0;
 }
 
 static int msm_otg_runtime_suspend(struct device *dev)
@@ -2136,6 +2514,7 @@
 	struct msm_otg *motg = dev_get_drvdata(dev);
 
 	dev_dbg(dev, "OTG runtime resume\n");
+	pm_runtime_get_noresume(dev);
 	return msm_otg_resume(motg);
 }
 #endif
@@ -2143,10 +2522,18 @@
 #ifdef CONFIG_PM_SLEEP
 static int msm_otg_pm_suspend(struct device *dev)
 {
-	struct msm_otg *motg = dev_get_drvdata(dev);
+	int ret;
 
 	dev_dbg(dev, "OTG PM suspend\n");
-	return msm_otg_suspend(motg);
+
+#ifdef CONFIG_PM_RUNTIME
+	ret = pm_runtime_suspend(dev);
+	if (ret > 0)
+		ret = 0;
+#else
+	ret =  msm_otg_suspend(dev_get_drvdata(dev));
+#endif
+	return ret;
 }
 
 static int msm_otg_pm_resume(struct device *dev)
@@ -2175,6 +2562,12 @@
 };
 #endif
 
+static struct of_device_id msm_otg_dt_match[] = {
+	{	.compatible = "qcom,hsusb-otg",
+	},
+	{}
+};
+
 static struct platform_driver msm_otg_driver = {
 	.remove = __devexit_p(msm_otg_remove),
 	.driver = {
@@ -2183,6 +2576,7 @@
 #ifdef CONFIG_PM
 		.pm = &msm_otg_dev_pm_ops,
 #endif
+		.of_match_table = msm_otg_dt_match,
 	},
 };
 
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index f5a7c9e..dc02da4 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -10,6 +10,7 @@
 
 ifeq ($(CONFIG_FB_MSM_MDP40),y)
 obj-y += mdp4_util.o
+obj-y += mdp4_hsic.o
 else
 obj-y += mdp_hw_init.o
 obj-y += mdp_ppp.o
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 1d87de6..5d9795a 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -18,7 +18,6 @@
 /* #define DEBUG */
 #define DEV_DBG_PREFIX "EXT_COMMON: "
 
-/* #define CEC_COMPLIANCE_TESTING */
 #include "msm_fb.h"
 #include "hdmi_msm.h"
 #include "external_common.h"
@@ -370,7 +369,7 @@
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 
-#ifdef CEC_COMPLIANCE_TESTING
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
 	/*
 	 * Only for testing
 	 */
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 9805b6c..4ef0da6 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -16,7 +16,7 @@
 /* #define REG_DUMP */
 
 #define CEC_MSG_PRINT
-/* #define CEC_COMPLIANCE_TESTING */
+#define TOGGLE_CEC_HARDWARE_FSM
 
 #include <linux/types.h>
 #include <linux/bitops.h>
@@ -69,6 +69,11 @@
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+static boolean msg_send_complete = TRUE;
+static boolean msg_recv_complete = TRUE;
+#endif
+
 #define HDMI_MSM_CEC_REFTIMER_REFTIMER_ENABLE	BIT(16)
 #define HDMI_MSM_CEC_REFTIMER_REFTIMER(___t)	(((___t)&0xFFFF) << 0)
 
@@ -97,10 +102,9 @@
 #define HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT		BIT(0)
 
 #define HDMI_MSM_CEC_FRAME_WR_SUCCESS(___st)         (((___st)&0xF) ==\
-		(HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT &&\
-			HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK &&\
-			(HDMI_MSM_CEC_INT_FRAME_ERROR_MASK &&\
-				!(HDMI_MSM_CEC_INT_FRAME_ERROR_INT))))
+		(HDMI_MSM_CEC_INT_FRAME_WR_DONE_INT |\
+			HDMI_MSM_CEC_INT_FRAME_WR_DONE_MASK |\
+			HDMI_MSM_CEC_INT_FRAME_ERROR_MASK))
 
 #define HDMI_MSM_CEC_RETRANSMIT_NUM(___num)		(((___num)&0xF) << 4)
 #define HDMI_MSM_CEC_RETRANSMIT_ENABLE		BIT(0)
@@ -193,6 +197,10 @@
 
 	boolean frameType = (msg->recvr_id == 15 ? BIT(0) : 0);
 
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+	msg_send_complete = FALSE;
+#endif
+
 	INIT_COMPLETION(hdmi_msm_state->cec_frame_wr_done);
 	hdmi_msm_state->cec_frame_wr_status = 0;
 
@@ -251,13 +259,23 @@
 			msg->frame_size);
 		hdmi_msm_dump_cec_msg(msg);
 	}
+
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+	if (!msg_recv_complete) {
+		/* Toggle CEC hardware FSM */
+		HDMI_OUTP(0x028C, 0x0);
+		HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+		msg_recv_complete = TRUE;
+	}
+	msg_send_complete = TRUE;
+#endif
 }
 
 void hdmi_msm_cec_msg_recv(void)
 {
 	uint32 data;
 	int i;
-#ifdef CEC_COMPLIANCE_TESTING
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
 	struct hdmi_msm_cec_msg temp_msg;
 #endif
 	mutex_lock(&hdmi_msm_state_mutex);
@@ -265,7 +283,7 @@
 		&& hdmi_msm_state->cec_queue_full) {
 		mutex_unlock(&hdmi_msm_state_mutex);
 		DEV_ERR("CEC message queue is overflowing\n");
-#ifdef CEC_COMPLIANCE_TESTING
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
 		/*
 		 * Without CEC daemon:
 		 * Compliance tests fail once the queue gets filled up.
@@ -325,7 +343,7 @@
 	hdmi_msm_dump_cec_msg(hdmi_msm_state->cec_queue_wr);
 	DEV_DBG("=======================================\n");
 
-#ifdef CEC_COMPLIANCE_TESTING
+#ifdef DRVR_ONLY_CECT_NO_DAEMON
 	switch (hdmi_msm_state->cec_queue_wr->opcode) {
 	case 0x64:
 		/* Set OSD String */
@@ -490,7 +508,7 @@
 #endif /* __SEND_ABORT__ */
 	}
 
-#endif /* CEC_COMPLIANCE_TESTING */
+#endif /* DRVR_ONLY_CECT_NO_DAEMON */
 	mutex_lock(&hdmi_msm_state_mutex);
 	hdmi_msm_state->cec_queue_wr++;
 	if (hdmi_msm_state->cec_queue_wr == CEC_QUEUE_END)
@@ -1099,9 +1117,11 @@
 	}
 	if ((cec_intr_status & (1 << 2)) && (cec_intr_status & (1 << 3))) {
 		DEV_DBG("CEC_IRQ_FRAME_ERROR\n");
+#ifdef TOGGLE_CEC_HARDWARE_FSM
 		/* Toggle CEC hardware FSM */
 		HDMI_OUTP(0x028C, 0x0);
 		HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+#endif
 		HDMI_OUTP(0x029C, cec_intr_status);
 		mutex_lock(&hdmi_msm_state_mutex);
 		hdmi_msm_state->cec_frame_wr_status |= CEC_STATUS_WR_ERROR;
@@ -1119,9 +1139,15 @@
 			HDMI_MSM_CEC_INT_FRAME_RD_DONE_ACK);
 		hdmi_msm_cec_msg_recv();
 
-		/* Toggle CEC hardware FSM */
-		HDMI_OUTP(0x028C, 0x0);
-		HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+#ifdef TOGGLE_CEC_HARDWARE_FSM
+		if (!msg_send_complete)
+			msg_recv_complete = FALSE;
+		else {
+			/* Toggle CEC hardware FSM */
+			HDMI_OUTP(0x028C, 0x0);
+			HDMI_OUTP(0x028C, HDMI_MSM_CEC_CTRL_ENABLE);
+		}
+#endif
 
 		return IRQ_HANDLED;
 	}
@@ -3088,10 +3114,36 @@
 
 	HDMI_OUTP(HDMI_AUDIO_CFG, hdmi_audio_config);
 
+	mb();
+	pr_info("%s :HDMI_AUDIO_CFG 0x%08x\n", __func__,
+		HDMI_INP(HDMI_AUDIO_CFG));
+
 	return 0;
 }
 EXPORT_SYMBOL(hdmi_audio_enable);
 
+#define HDMI_AUDIO_PKT_CTRL			0x0020
+#define HDMI_AUDIO_SAMPLE_SEND_ENABLE		1
+
+int hdmi_audio_packet_enable(bool on)
+{
+	u32 hdmi_audio_pkt_ctrl;
+	hdmi_audio_pkt_ctrl = HDMI_INP(HDMI_AUDIO_PKT_CTRL);
+
+	if (on)
+		hdmi_audio_pkt_ctrl |= HDMI_AUDIO_SAMPLE_SEND_ENABLE;
+	else
+		hdmi_audio_pkt_ctrl &= ~(HDMI_AUDIO_SAMPLE_SEND_ENABLE);
+
+	HDMI_OUTP(HDMI_AUDIO_PKT_CTRL, hdmi_audio_pkt_ctrl);
+
+	mb();
+	pr_info("%s : HDMI_AUDIO_PKT_CTRL 0x%08x\n", __func__,
+	HDMI_INP(HDMI_AUDIO_PKT_CTRL));
+	return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_packet_enable);
+
 static void hdmi_msm_audio_info_setup(boolean enabled, int num_of_channels,
 	int level_shift, boolean down_mix)
 {
@@ -3294,7 +3346,6 @@
 		external_common_state->video_resolution,
 		MSM_HDMI_SAMPLE_RATE_48KHZ, channels);
 	hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
-	hdmi_msm_audio_ctrl_setup(TRUE, 1);
 
 	/* Turn on Audio FIFO and SAM DROP ISR */
 	HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) | BIT(1) | BIT(3));
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index c12a250..8817213 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -737,6 +737,10 @@
 {
 	/* empty */
 }
+static inline int mdp4_overlay_dsi_state_get(void)
+{
+	return 0;
+}
 #endif
 
 #endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 5d8c547..ad7fc04 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -138,11 +138,10 @@
 	OVERLAY_PIPE_MAX
 };
 
-/* 2 VG pipes can be shared by RGB and VIDEO */
-#define MDP4_MAX_PIPE (OVERLAY_PIPE_MAX + 2)
-
-#define OVERLAY_TYPE_RGB	0x01
-#define	OVERLAY_TYPE_VIDEO	0x02
+enum {
+	OVERLAY_TYPE_RGB,
+	OVERLAY_TYPE_VIDEO
+};
 
 enum {
 	MDP4_MIXER0,
@@ -150,8 +149,6 @@
 	MDP4_MIXER_MAX
 };
 
-#define MDP4_MAX_MIXER	2
-
 enum {
 	OVERLAY_PLANE_INTERLEAVED,
 	OVERLAY_PLANE_PLANAR,
@@ -222,6 +219,15 @@
 
 #define MDP4_MAX_PLANE		4
 
+struct mdp4_hsic_regs {
+	int32_t params[NUM_HSIC_PARAM];
+	int32_t conv_matrix[3][3];
+	int32_t	pre_limit[6];
+	int32_t post_limit[6];
+	int32_t pre_bias[3];
+	int32_t post_bias[3];
+	int32_t dirty;
+};
 
 struct mdp4_overlay_pipe {
 	uint32 pipe_used;
@@ -298,19 +304,11 @@
 	uint32 dmap_cnt;
 	uint32 blt_end;
 	uint32 luma_align_size;
+	struct mdp4_hsic_regs hsic_regs;
 	struct completion dmas_comp;
 	struct mdp_overlay req_data;
 };
 
-#define MDP4_MAX_SHARE	2
-
-struct mdp4_pipe_desc {
-	int share;
-	int ref_cnt;
-	int ndx_list[MDP4_MAX_SHARE];
-	struct mdp4_overlay_pipe *player;
-};
-
 struct mdp4_statistic {
 	ulong intr_tot;
 	ulong intr_dma_p;
@@ -331,7 +329,7 @@
 	ulong overlay_set[MDP4_MIXER_MAX];
 	ulong overlay_unset[MDP4_MIXER_MAX];
 	ulong overlay_play[MDP4_MIXER_MAX];
-	ulong pipe[MDP4_MAX_PIPE];
+	ulong pipe[OVERLAY_PIPE_MAX];
 	ulong dsi_clkoff;
 	ulong err_mixer;
 	ulong err_zorder;
@@ -410,6 +408,7 @@
 void mdp4_overlay0_done_dsi_cmd(struct mdp_dma_data *dma);
 void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd);
 void mdp4_overlay_dsi_state_set(int state);
+int mdp4_overlay_dsi_state_get(void);
 void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
 void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
 void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
@@ -428,11 +427,8 @@
 	struct mdp4_overlay_pipe *pipe);
 int mdp4_overlay_play_wait(struct fb_info *info,
 	struct msmfb_overlay_data *req);
-int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
-		struct file **pp_src_file, struct file **pp_src_plane1_file,
-		struct file **pp_src_plane2_file);
-struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer,
-				int req_share);
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer);
 void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
 void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
 void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
@@ -638,4 +634,6 @@
 int mdp4_writeback_init(struct fb_info *info);
 int mdp4_writeback_terminate(struct fb_info *info);
 
+void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl);
+void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe);
 #endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4_hsic.c b/drivers/video/msm/mdp4_hsic.c
new file mode 100644
index 0000000..5735f45
--- /dev/null
+++ b/drivers/video/msm/mdp4_hsic.c
@@ -0,0 +1,534 @@
+/* Copyright (c) 2009-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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/msm_mdp.h>
+#include "mdp.h"
+#include "mdp4.h"
+
+/* Definitions */
+#define MDP4_CSC_MV_OFF		0x4400
+#define MDP4_CSC_PRE_BV_OFF	0x4500
+#define MDP4_CSC_POST_BV_OFF	0x4580
+#define MDP4_CSC_PRE_LV_OFF	0x4600
+#define MDP4_CSC_POST_LV_OFF	0x4680
+#define MDP_VG1_BASE	(MDP_BASE + MDP4_VIDEO_BASE)
+
+#define MDP_VG1_CSC_MVn(n)	(MDP_VG1_BASE + MDP4_CSC_MV_OFF + 4 * (n))
+#define MDP_VG1_CSC_PRE_LVn(n)	(MDP_VG1_BASE + MDP4_CSC_PRE_LV_OFF + 4 * (n))
+#define MDP_VG1_CSC_POST_LVn(n)	(MDP_VG1_BASE + MDP4_CSC_POST_LV_OFF + 4 * (n))
+#define MDP_VG1_CSC_PRE_BVn(n)	(MDP_VG1_BASE + MDP4_CSC_PRE_BV_OFF + 4 * (n))
+#define MDP_VG1_CSC_POST_BVn(n)	(MDP_VG1_BASE + MDP4_CSC_POST_BV_OFF + 4 * (n))
+
+#define Q16	(16)
+#define Q16_ONE	(1 << Q16)
+
+#define Q16_VALUE(x)	((int32_t)((uint32_t)x << Q16))
+#define Q16_PERCENT_VALUE(x, n)	((int32_t)( \
+				div_s64(((int64_t)x * (int64_t)Q16_ONE), n)))
+
+#define Q16_WHOLE(x)	((int32_t)(x >> 16))
+#define Q16_FRAC(x)	((int32_t)(x & 0xFFFF))
+#define Q16_S1Q16_MUL(x, y)	(((x >> 1) * (y >> 1)) >> 14)
+
+#define Q16_MUL(x, y)	((int32_t)((((int64_t)x) * ((int64_t)y)) >> Q16))
+#define Q16_NEGATE(x)	(0 - (x))
+
+/*
+ * HSIC Control min/max values
+ *    These settings are based on the maximum/minimum allowed modifications to
+ *    HSIC controls for layer and display color.  Allowing too much variation in
+ *    the CSC block will result in color clipping resulting in unwanted color
+ *    shifts.
+ */
+#define TRIG_MAX	Q16_VALUE(128)
+#define CON_SAT_MAX	Q16_VALUE(128)
+#define INTENSITY_MAX	(Q16_VALUE(2047) >> 12)
+
+#define HUE_MAX	Q16_VALUE(100)
+#define HUE_MIN	Q16_VALUE(-100)
+#define HUE_DEF	Q16_VALUE(0)
+
+#define SAT_MAX	Q16_VALUE(100)
+#define SAT_MIN	Q16_VALUE(-100)
+#define SAT_DEF	CON_SAT_MAX
+
+#define CON_MAX	Q16_VALUE(100)
+#define CON_MIN	Q16_VALUE(-100)
+#define CON_DEF	CON_SAT_MAX
+
+#define INTEN_MAX	Q16_VALUE(100)
+#define INTEN_MIN	Q16_VALUE(-100)
+#define INTEN_DEF	Q16_VALUE(0)
+
+enum {
+	DIRTY,
+	GENERATED,
+	CLEAN
+};
+
+/* local vars*/
+static int32_t csc_matrix_tab[3][3] = {
+	{0x00012a00, 0x00000000, 0x00019880},
+	{0x00012a00, 0xffff9b80, 0xffff3000},
+	{0x00012a00, 0x00020480, 0x00000000}
+};
+
+static int32_t csc_yuv2rgb_conv_tab[3][3] = {
+	{0x00010000, 0x00000000, 0x000123cb},
+	{0x00010000, 0xffff9af9, 0xffff6b5e},
+	{0x00010000, 0x00020838, 0x00000000}
+};
+
+static int32_t csc_rgb2yuv_conv_tab[3][3] = {
+	{0x00004c8b, 0x00009645, 0x00001d2f},
+	{0xffffda56, 0xffffb60e, 0x00006f9d},
+	{0x00009d70, 0xffff7c2a, 0xffffe666}
+};
+
+static uint32_t csc_pre_bv_tab[3]  = {0xfffff800, 0xffffc000, 0xffffc000};
+static uint32_t csc_post_bv_tab[3] = {0x00000000, 0x00000000, 0x00000000};
+
+static uint32_t csc_pre_lv_tab[6] =  {0x00000000, 0x00007f80, 0x00000000,
+					0x00007f80, 0x00000000, 0x00007f80};
+static uint32_t csc_post_lv_tab[6] = {0x00000000, 0x00007f80, 0x00000000,
+					0x00007f80, 0x00000000, 0x00007f80};
+
+/* Lookup table for Sin/Cos lookup - Q16*/
+static const int32_t  trig_lut[65] = {
+	0x00000000, /* sin((2*M_PI/256) * 0x00);*/
+	0x00000648, /* sin((2*M_PI/256) * 0x01);*/
+	0x00000C90, /* sin((2*M_PI/256) * 0x02);*/
+	0x000012D5,
+	0x00001918,
+	0x00001F56,
+	0x00002590,
+	0x00002BC4,
+	0x000031F1,
+	0x00003817,
+	0x00003E34,
+	0x00004447,
+	0x00004A50,
+	0x0000504D,
+	0x0000563E,
+	0x00005C22,
+	0x000061F8,
+	0x000067BE,
+	0x00006D74,
+	0x0000731A,
+	0x000078AD,
+	0x00007E2F,
+	0x0000839C,
+	0x000088F6,
+	0x00008E3A,
+	0x00009368,
+	0x00009880,
+	0x00009D80,
+	0x0000A268,
+	0x0000A736,
+	0x0000ABEB,
+	0x0000B086,
+	0x0000B505,
+	0x0000B968,
+	0x0000BDAF,
+	0x0000C1D8,
+	0x0000C5E4,
+	0x0000C9D1,
+	0x0000CD9F,
+	0x0000D14D,
+	0x0000D4DB,
+	0x0000D848,
+	0x0000DB94,
+	0x0000DEBE,
+	0x0000E1C6,
+	0x0000E4AA,
+	0x0000E768,
+	0x0000EA0A,
+	0x0000EC83,
+	0x0000EED9,
+	0x0000F109,
+	0x0000F314,
+	0x0000F4FA,
+	0x0000F6BA,
+	0x0000F854,
+	0x0000F9C8,
+	0x0000FB15,
+	0x0000FC3B,
+	0x0000FD3B,
+	0x0000FE13,
+	0x0000FEC4,
+	0x0000FF4E,
+	0x0000FFB1,
+	0x0000FFEC,
+	0x00010000, /* sin((2*M_PI/256) * 0x40);*/
+};
+
+void trig_values_q16(int32_t deg, int32_t *cos, int32_t *sin)
+{
+	int32_t   angle;
+	int32_t   quad, anglei, anglef;
+	int32_t   v0 = 0, v1 = 0;
+	int32_t   t1, t2;
+
+	/*
+	 * Scale the angle so that 256 is one complete revolution and mask it
+	 * to this domain
+	 * NOTE: 0xB60B == 256/360
+	 */
+	angle = Q16_MUL(deg, 0xB60B) & 0x00FFFFFF;
+
+	/* Obtain a quadrant number, integer, and fractional part */
+	quad   =  angle >> 22;
+	anglei = (angle >> 16) & 0x3F;
+	anglef =  angle & 0xFFFF;
+
+	/*
+	 * Using the integer part, obtain the lookup table entry and its
+	 * complement. Using the quadrant, swap and negate these as
+	 * necessary.
+	 * (The values and all derivatives of sine and cosine functions
+	 * can be derived from these values)
+	 */
+	switch (quad) {
+	case 0x0:
+		v0 += trig_lut[anglei];
+		v1 += trig_lut[0x40-anglei];
+		break;
+
+	case 0x1:
+		v0 += trig_lut[0x40-anglei];
+		v1 -= trig_lut[anglei];
+		break;
+
+	case 0x2:
+		v0 -= trig_lut[anglei];
+		v1 -= trig_lut[0x40-anglei];
+		break;
+
+	case 0x3:
+		v0 -= trig_lut[0x40-anglei];
+		v1 += trig_lut[anglei];
+		break;
+	}
+
+	/*
+	 * Multiply the fractional part by 2*PI/256 to move it from lookup
+	 *  table units to radians, giving us the coefficient for first
+	 *  derivatives.
+	 */
+	t1 = Q16_S1Q16_MUL(anglef, 0x0648);
+
+	/*
+	 * Square this and divide by 2 to get the coefficient for second
+	 *   derivatives
+	 */
+	t2 = Q16_S1Q16_MUL(t1, t1) >> 1;
+
+	*sin = v0 + Q16_S1Q16_MUL(v1, t1) - Q16_S1Q16_MUL(v0, t2);
+
+	*cos = v1 - Q16_S1Q16_MUL(v0, t1) - Q16_S1Q16_MUL(v1, t2);
+}
+
+/* Convert input Q16 value to s4.9 */
+int16_t convert_q16_s49(int32_t q16Value)
+{	/* Top half is the whole number, Bottom half is fractional portion*/
+	int16_t whole = Q16_WHOLE(q16Value);
+	int32_t fraction  = Q16_FRAC(q16Value);
+
+	/* Clamp whole to 3 bits */
+	if (whole > 7)
+		whole = 7;
+	else if (whole < -7)
+		whole = -7;
+
+	/* Reduce fraction to 9 bits. */
+	fraction = (fraction<<9)>>Q16;
+
+	return (int16_t) ((int16_t)whole<<9) | ((int16_t)fraction);
+}
+
+/* Convert input Q16 value to uint16 */
+int16_t convert_q16_int16(int32_t val)
+{
+	int32_t rounded;
+
+	if (val >= 0) {
+		/* Add 0.5 */
+		rounded = val + (Q16_ONE>>1);
+	} else {
+		/* Subtract 0.5 */
+		rounded = val - (Q16_ONE>>1);
+	}
+
+	/* Truncate rounded value */
+	return (int16_t)(rounded>>Q16);
+}
+
+/*
+ * norm_q16
+ *              Return a Q16 value represeting a normalized value
+ *
+ * value       -100%                 0%               +100%
+ *                 |-----------------|----------------|
+ *                 ^                 ^                ^
+ *             q16MinValue     q16DefaultValue       q16MaxValue
+ *
+ */
+int32_t norm_q16(int32_t value, int32_t min, int32_t default_val, int32_t max,
+								int32_t range)
+{
+	int32_t diff, perc, mul, result;
+
+	if (0 == value) {
+		result = default_val;
+	} else if (value > 0) {
+		/* value is between 0% and +100% represent 1.0 -> QRange Max */
+		diff = range;
+		perc = Q16_PERCENT_VALUE(value, max);
+		mul = Q16_MUL(perc, diff);
+		result = default_val + mul;
+	} else {
+		/* if (value <= 0) */
+		diff = -range;
+		perc = Q16_PERCENT_VALUE(-value, -min);
+		mul = Q16_MUL(perc, diff);
+		result = default_val + mul;
+	}
+	return result;
+}
+
+void matrix_mul_3x3(int32_t dest[][3], int32_t a[][3], int32_t b[][3])
+{
+	int32_t i, j, k;
+	int32_t tmp[3][3];
+
+	for (i = 0; i < 3; i++) {
+		for (j = 0; j < 3; j++) {
+			tmp[i][j] = 0;
+			for (k = 0; k < 3; k++)
+				tmp[i][j] += Q16_MUL(a[i][k], b[k][j]);
+		}
+	}
+
+	/* in case dest = a or b*/
+	for (i = 0; i < 3; i++) {
+		for (j = 0; j < 3; j++)
+			dest[i][j] = tmp[i][j];
+	}
+}
+
+#define CONVERT(x)	(x)/*convert_q16_s49((x))*/
+void pr_params(struct mdp4_hsic_regs *regs)
+{
+	int i;
+	if (regs) {
+		for (i = 0; i < NUM_HSIC_PARAM; i++) {
+			pr_info("\t: hsic->params[%d] =	0x%08x [raw = 0x%08x]\n",
+			i, CONVERT(regs->params[i]), regs->params[i]);
+		}
+	}
+}
+
+void pr_3x3_matrix(int32_t in[][3])
+{
+	pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[0][0]),
+	CONVERT(in[0][1]), CONVERT(in[0][2]));
+	pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[1][0]),
+	CONVERT(in[1][1]), CONVERT(in[1][2]));
+	pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[2][0]),
+	CONVERT(in[2][1]), CONVERT(in[2][2]));
+}
+
+void _hsic_get(struct mdp4_hsic_regs *regs, int32_t type, int8_t *val)
+{
+	if (type < 0 || type >= NUM_HSIC_PARAM)
+		BUG_ON(-EINVAL);
+	*val = regs->params[type];
+	pr_info("%s: getting params[%d] = %d\n", __func__, type, *val);
+}
+
+void _hsic_set(struct mdp4_hsic_regs *regs, int32_t type, int8_t val)
+{
+	if (type < 0 || type >= NUM_HSIC_PARAM)
+		BUG_ON(-EINVAL);
+
+	if (regs->params[type] != Q16_VALUE(val)) {
+		regs->params[type] = Q16_VALUE(val);
+		regs->dirty = DIRTY;
+	}
+}
+
+void _hsic_generate_csc_matrix(struct mdp4_overlay_pipe *pipe)
+{
+	int i, j;
+	int32_t sin, cos;
+
+	int32_t hue_matrix[3][3];
+	int32_t con_sat_matrix[3][3];
+	struct mdp4_hsic_regs *regs = &(pipe->hsic_regs);
+
+	memset(con_sat_matrix, 0x0, sizeof(con_sat_matrix));
+	memset(hue_matrix, 0x0, sizeof(hue_matrix));
+
+	/*
+	 * HSIC control require matrix multiplication of these two tables
+	 *  [T 0 0][1 0  0]   T = Contrast       C=Cos(Hue)
+	 *  [0 S 0][0 C -N]   S = Saturation     N=Sin(Hue)
+	 *  [0 0 S][0 N  C]
+	 */
+
+	con_sat_matrix[0][0] = norm_q16(regs->params[HSIC_CON], CON_MIN,
+						CON_DEF, CON_MAX, CON_SAT_MAX);
+	con_sat_matrix[1][1] = norm_q16(regs->params[HSIC_SAT], SAT_MIN,
+						SAT_DEF, SAT_MAX, CON_SAT_MAX);
+	con_sat_matrix[2][2] = con_sat_matrix[1][1];
+
+	hue_matrix[0][0] = TRIG_MAX;
+
+	trig_values_q16(norm_q16(regs->params[HSIC_HUE], HUE_MIN, HUE_DEF,
+					 HUE_MAX, TRIG_MAX), &cos, &sin);
+
+	cos = Q16_MUL(cos, TRIG_MAX);
+	sin = Q16_MUL(sin, TRIG_MAX);
+
+	hue_matrix[1][1] = cos;
+	hue_matrix[2][2] = cos;
+	hue_matrix[2][1] = sin;
+	hue_matrix[1][2] = Q16_NEGATE(sin);
+
+	/* Generate YUV CSC matrix */
+	matrix_mul_3x3(regs->conv_matrix, con_sat_matrix, hue_matrix);
+
+	if (!(pipe->op_mode & MDP4_OP_SRC_DATA_YCBCR)) {
+		/* Convert input RGB to YUV then apply CSC matrix */
+		pr_info("Pipe %d, has RGB input\n", pipe->pipe_num);
+		matrix_mul_3x3(regs->conv_matrix, regs->conv_matrix,
+							csc_rgb2yuv_conv_tab);
+	}
+
+	/* Normalize the matrix */
+	for (i = 0; i < 3; i++) {
+		for (j = 0; j < 3; j++)
+			regs->conv_matrix[i][j] = (regs->conv_matrix[i][j]>>14);
+	}
+
+	/* Multiply above result by current csc table */
+	matrix_mul_3x3(regs->conv_matrix, regs->conv_matrix, csc_matrix_tab);
+
+	if (!(pipe->op_mode & MDP4_OP_SRC_DATA_YCBCR)) {
+		/*HACK:only "works"for src side*/
+		/* Convert back to RGB */
+		pr_info("Pipe %d, has RGB output\n", pipe->pipe_num);
+		matrix_mul_3x3(regs->conv_matrix, csc_yuv2rgb_conv_tab,
+							regs->conv_matrix);
+	}
+
+	/* Update clamps pre and post. */
+	/* TODO: different tables for different color formats? */
+	for (i = 0; i < 6; i++) {
+		regs->pre_limit[i] = csc_pre_lv_tab[i];
+		regs->post_limit[i] = csc_post_lv_tab[i];
+	}
+
+	/* update bias values, pre and post */
+	for (i = 0; i < 3; i++) {
+		regs->pre_bias[i] = csc_pre_bv_tab[i];
+		regs->post_bias[i] = csc_post_bv_tab[i] +
+				norm_q16(regs->params[HSIC_INT],
+				INTEN_MIN, INTEN_DEF, INTEN_MAX, INTENSITY_MAX);
+	}
+
+	regs->dirty = GENERATED;
+}
+
+void _hsic_update_mdp(struct mdp4_overlay_pipe *pipe)
+{
+	struct mdp4_hsic_regs *regs = &(pipe->hsic_regs);
+	int i, j, k;
+
+	uint32_t *csc_mv;
+	uint32_t *pre_lv;
+	uint32_t *post_lv;
+	uint32_t *pre_bv;
+	uint32_t *post_bv;
+
+	switch (pipe->pipe_num) {
+	case OVERLAY_PIPE_VG2:
+		csc_mv = (uint32_t *) (MDP_VG1_CSC_MVn(0) +
+					MDP4_VIDEO_OFF);
+		pre_lv = (uint32_t *) (MDP_VG1_CSC_PRE_LVn(0) +
+					MDP4_VIDEO_OFF);
+		post_lv = (uint32_t *) (MDP_VG1_CSC_POST_LVn(0) +
+					MDP4_VIDEO_OFF);
+		pre_bv = (uint32_t *) (MDP_VG1_CSC_PRE_BVn(0) +
+					MDP4_VIDEO_OFF);
+		post_bv = (uint32_t *) (MDP_VG1_CSC_POST_BVn(0) +
+					MDP4_VIDEO_OFF);
+		break;
+	case OVERLAY_PIPE_VG1:
+	default:
+			csc_mv = (uint32_t *) MDP_VG1_CSC_MVn(0);
+			pre_lv = (uint32_t *) MDP_VG1_CSC_PRE_LVn(0);
+			post_lv = (uint32_t *) MDP_VG1_CSC_POST_LVn(0);
+			pre_bv = (uint32_t *) MDP_VG1_CSC_PRE_BVn(0);
+			post_bv = (uint32_t *) MDP_VG1_CSC_POST_BVn(0);
+		break;
+	}
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	for (i = 0; i < 3; i++) {
+		for (j = 0; j < 3; j++) {
+			k = (3*i) + j;
+			MDP_OUTP(csc_mv + k, convert_q16_s49(
+						regs->conv_matrix[i][j]));
+		}
+	}
+
+	for (i = 0; i < 6; i++) {
+		MDP_OUTP(pre_lv + i, convert_q16_s49(regs->pre_limit[i]));
+		MDP_OUTP(post_lv + i, convert_q16_s49(regs->post_limit[i]));
+	}
+
+	for (i = 0; i < 3; i++) {
+		MDP_OUTP(pre_bv + i, convert_q16_s49(regs->pre_bias[i]));
+		MDP_OUTP(post_bv + i, convert_q16_s49(regs->post_bias[i]));
+	}
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	regs->dirty = CLEAN;
+}
+
+void mdp4_hsic_get(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl)
+{
+	int i;
+	for (i = 0; i < NUM_HSIC_PARAM; i++)
+		_hsic_get(&(pipe->hsic_regs), i, &(ctrl->hsic_params[i]));
+}
+
+void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl)
+{
+	int i;
+	for (i = 0; i < NUM_HSIC_PARAM; i++)
+		_hsic_set(&(pipe->hsic_regs), i, ctrl->hsic_params[i]);
+
+	if (pipe->hsic_regs.dirty == DIRTY)
+		_hsic_generate_csc_matrix(pipe);
+}
+
+void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe)
+{
+	if (pipe->hsic_regs.dirty == GENERATED)
+		_hsic_update_mdp(pipe);
+}
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 6d63229..1b80d4c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -41,28 +41,13 @@
 #define VERSION_KEY_MASK	0xFFFFFF00
 
 struct mdp4_overlay_ctrl {
-	struct mdp4_pipe_desc ov_pipe[OVERLAY_PIPE_MAX];/* 4 */
-	struct mdp4_overlay_pipe plist[MDP4_MAX_PIPE];	/* 4 + 2 */
-	struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MIXER_STAGE_MAX];
+	struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
+	struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
 	uint32 panel_3d;
 	uint32 panel_mode;
 	uint32 mixer0_played;
 	uint32 mixer1_played;
 } mdp4_overlay_db = {
-	.ov_pipe = {
-			{
-				.share = 0,	/* RGB 1 */
-			},
-			{
-				.share = 0,	/* RGB 2 */
-			},
-			{
-				.share = 1,	/* VG 1 */
-			},
-			{
-				.share = 1,	/* VG 2 */
-			},
-		},
 	.plist = {
 		{
 			.pipe_type = OVERLAY_TYPE_RGB,
@@ -75,25 +60,15 @@
 			.pipe_ndx = 2,
 		},
 		{
-			.pipe_type = OVERLAY_TYPE_RGB, /* shared */
+			.pipe_type = OVERLAY_TYPE_VIDEO,
 			.pipe_num = OVERLAY_PIPE_VG1,
 			.pipe_ndx = 3,
 		},
 		{
-			.pipe_type = OVERLAY_TYPE_RGB, /* shared */
+			.pipe_type = OVERLAY_TYPE_VIDEO,
 			.pipe_num = OVERLAY_PIPE_VG2,
 			.pipe_ndx = 4,
 		},
-		{
-			.pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
-			.pipe_num = OVERLAY_PIPE_VG1,
-			.pipe_ndx = 5,
-		},
-		{
-			.pipe_type = OVERLAY_TYPE_VIDEO, /* shared */
-			.pipe_num = OVERLAY_PIPE_VG2,
-			.pipe_ndx = 6,
-		},
 	},
 };
 
@@ -1198,7 +1173,7 @@
 	struct mdp4_overlay_pipe *spipe;
 
 	spipe = mdp4_overlay_stage_pipe(pipe->mixer_num, pipe->mixer_stage);
-	if ((spipe != NULL) && (spipe != pipe)) {
+	if ((spipe != NULL) && (spipe->pipe_num != pipe->pipe_num)) {
 		pr_err("%s: unable to stage pipe=%d at mixer_stage=%d\n",
 				__func__, pipe->pipe_ndx, pipe->mixer_stage);
 		return;
@@ -1421,7 +1396,7 @@
 {
 	struct mdp4_overlay_pipe *pipe;
 
-	if (ndx <= 0 || ndx > MDP4_MAX_PIPE)
+	if (ndx <= 0 || ndx > OVERLAY_PIPE_MAX)
 		return NULL;
 
 	pipe = &ctrl->plist[ndx - 1];	/* ndx start from 1 */
@@ -1432,65 +1407,25 @@
 	return pipe;
 }
 
-struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(
-		int ptype, int mixer, int req_share)
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer)
 {
-	int i, j, ndx, found;
-	struct mdp4_overlay_pipe *pipe, *opipe;
-	struct mdp4_pipe_desc  *pd;
+	int i;
+	struct mdp4_overlay_pipe *pipe;
 
-	found = 0;
-	pipe = &ctrl->plist[0];
-
-	for (i = 0; i < MDP4_MAX_PIPE; i++) {
-		if (pipe->pipe_type == ptype && pipe->pipe_used == 0) {
-			pd = &ctrl->ov_pipe[pipe->pipe_num];
-			if (pd->share) { /* pipe can be shared */
-				if (pd->ref_cnt == 0) {
-					/* not yet been used */
-					found++;
-					break;
-				}
-				/* pipe occupied already */
-				if (req_share && pd->ref_cnt < MDP4_MAX_SHARE) {
-					for (j = 0; j < MDP4_MAX_SHARE; j++) {
-						ndx = pd->ndx_list[j];
-						if (ndx != 0)
-							break;
-					}
-					/* ndx satrt from 1 */
-					opipe = &ctrl->plist[ndx - 1];
-					/*
-					 * occupied pipe willing to share and
-					 * same mixer
-					 */
-					if (opipe->pipe_share &&
-						opipe->mixer_num == mixer) {
-						found++;
-						break;
-					}
-				}
-			} else {	/* not a shared pipe */
-				if (req_share == 0  && pd->ref_cnt == 0) {
-					found++;
-					break;
-				}
-			}
+	for (i = 0; i < OVERLAY_PIPE_MAX; i++) {
+		pipe = &ctrl->plist[i];
+		if ((pipe->pipe_used == 0) && ((pipe->pipe_type == ptype) ||
+		    (ptype == OVERLAY_TYPE_RGB &&
+		     pipe->pipe_type == OVERLAY_TYPE_VIDEO))) {
+			init_completion(&pipe->comp);
+			init_completion(&pipe->dmas_comp);
+			pr_info("%s: pipe=%x ndx=%d num=%d\n", __func__,
+				(int)pipe, pipe->pipe_ndx, pipe->pipe_num);
+			return pipe;
 		}
-		pipe++;
 	}
 
-	if (found) {
-		init_completion(&pipe->comp);
-		init_completion(&pipe->dmas_comp);
-		pr_info("%s: pipe=%x ndx=%d num=%d share=%d cnt=%d\n",
-			__func__, (int)pipe, pipe->pipe_ndx, pipe->pipe_num,
-			pd->share, pd->ref_cnt);
-		return pipe;
-	}
-
-	pr_debug("%s: ptype=%d mixer=%d req_share=%d FAILED\n",
-			__func__, ptype, mixer, req_share);
+	pr_err("%s: ptype=%d FAILED\n", __func__, ptype);
 
 	return NULL;
 }
@@ -1498,24 +1433,9 @@
 
 void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
 {
-	int i;
 	uint32 ptype, num, ndx;
-	struct mdp4_pipe_desc  *pd;
 
-	pr_info("%s: pipe=%x ndx=%d\n", __func__,
-				(int)pipe, pipe->pipe_ndx);
-	pd = &ctrl->ov_pipe[pipe->pipe_num];
-	if (pd->ref_cnt) {
-		pd->ref_cnt--;
-		for (i = 0; i < MDP4_MAX_SHARE; i++) {
-			if (pd->ndx_list[i] == pipe->pipe_ndx) {
-				pd->ndx_list[i] = 0;
-				break;
-			}
-		}
-	}
-
-	pd->player = NULL;
+	pr_info("%s: pipe=%x ndx=%d\n", __func__, (int)pipe, pipe->pipe_ndx);
 
 	ptype = pipe->pipe_type;
 	num = pipe->pipe_num;
@@ -1627,16 +1547,14 @@
 			struct msm_fb_data_type *mfd)
 {
 	struct mdp4_overlay_pipe *pipe;
-	struct mdp4_pipe_desc  *pd;
-	int ret, ptype, req_share;
-	int j;
+	int ret, ptype;
 
 	if (mfd == NULL) {
 		pr_err("%s: mfd == NULL, -ENODEV\n", __func__);
 		return -ENODEV;
 	}
 
-	if (mixer >= MDP4_MAX_MIXER) {
+	if (mixer >= MDP4_MIXER_MAX) {
 		pr_err("%s: mixer out of range!\n", __func__);
 		mdp4_stat.err_mixer++;
 		return -ERANGE;
@@ -1729,10 +1647,11 @@
 		return ptype;
 	}
 
-	req_share = (req->flags & MDP_OV_PIPE_SHARE);
+	if (req->flags & MDP_OV_PIPE_SHARE)
+		ptype = OVERLAY_TYPE_VIDEO; /* VG pipe supports both RGB+YUV */
 
 	if (req->id == MSMFB_NEW_REQUEST)  /* new request */
-		pipe = mdp4_overlay_pipe_alloc(ptype, mixer, req_share);
+		pipe = mdp4_overlay_pipe_alloc(ptype, mixer);
 	else
 		pipe = mdp4_overlay_ndx2pipe(req->id);
 
@@ -1764,15 +1683,6 @@
 	 * zorder 2 == stage 2 == 4
 	 */
 	if (req->id == MSMFB_NEW_REQUEST) {  /* new request */
-		pd = &ctrl->ov_pipe[pipe->pipe_num];
-		for (j = 0; j < MDP4_MAX_SHARE; j++) {
-			if (pd->ndx_list[j] == 0) {
-				pd->ndx_list[j] = pipe->pipe_ndx;
-				break;
-			}
-		}
-		pipe->pipe_share = req_share;
-		pd->ref_cnt++;
 		pipe->pipe_used++;
 		pipe->mixer_num = mixer;
 		pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
@@ -1821,39 +1731,57 @@
 }
 
 static int get_img(struct msmfb_data *img, struct fb_info *info,
-	unsigned long *start, unsigned long *len, struct file **pp_file)
+	unsigned long *start, unsigned long *len, struct file **srcp_file,
+	struct ion_handle **srcp_ihdl)
 {
-	int put_needed, ret = 0, fb_num;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+#endif
 	struct file *file;
+	int put_needed, ret = 0, fb_num;
 #ifdef CONFIG_ANDROID_PMEM
 	unsigned long vstart;
 #endif
-
 	if (img->flags & MDP_BLIT_SRC_GEM) {
-		*pp_file = NULL;
+		*srcp_file = NULL;
 		return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
 					 start, len);
 	}
 
-#ifdef CONFIG_ANDROID_PMEM
-	if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
-		return 0;
-#endif
-	file = fget_light(img->memory_id, &put_needed);
-	if (file == NULL)
-		return -1;
+	if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+		file = fget_light(img->memory_id, &put_needed);
+		if (file == NULL)
+			return -EINVAL;
 
-	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
-		fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
-		if (get_fb_phys_info(start, len, fb_num))
+		if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+			if (get_fb_phys_info(start, len, fb_num))
+				ret = -1;
+			else
+				*srcp_file = file;
+		} else
 			ret = -1;
-		else
-			*pp_file = file;
-	} else
-		ret = -1;
-	if (ret)
-		fput_light(file, put_needed);
-	return ret;
+		if (ret)
+			fput_light(file, put_needed);
+		return ret;
+	}
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	*srcp_ihdl = ion_import_fd(mfd->client, img->memory_id);
+	if (IS_ERR_OR_NULL(*srcp_ihdl))
+		return PTR_ERR(*srcp_ihdl);
+	if (!ion_phys(mfd->client, *srcp_ihdl, start, (size_t *) len))
+		return 0;
+	else
+		return -EINVAL;
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+	if (!get_pmem_file(img->memory_id, start, &vstart,
+					    len, srcp_file))
+		return 0;
+	else
+		return -EINVAL;
+#endif
 }
 
 #ifdef CONFIG_FB_MSM_MIPI_DSI
@@ -1986,8 +1914,8 @@
 	else if (mdp4_overlay_is_rgb_type(req->src.format))
 		return OVERLAY_PERF_LEVEL1;
 
-	if (ctrl->ov_pipe[OVERLAY_PIPE_VG1].ref_cnt &&
-		ctrl->ov_pipe[OVERLAY_PIPE_VG2].ref_cnt)
+	if (ctrl->plist[OVERLAY_PIPE_VG1].pipe_used &&
+		ctrl->plist[OVERLAY_PIPE_VG2].pipe_used)
 		return OVERLAY_PERF_LEVEL1;
 
 	if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE)
@@ -2096,6 +2024,10 @@
 		}
 	}
 
+	/* precompute HSIC matrices */
+	if (req->flags & MDP_DPP_HSIC)
+		mdp4_hsic_set(pipe, &(req->dpp));
+
 	mdp4_stat.overlay_set[pipe->mixer_num]++;
 
 	if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
@@ -2145,6 +2077,8 @@
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 	struct mdp4_overlay_pipe *pipe;
 	uint32 flags;
+	struct dpp_ctrl dpp;
+	int i;
 
 	if (mfd == NULL)
 		return -ENODEV;
@@ -2229,13 +2163,22 @@
 	}
 #endif
 
+	/* Reset any HSIC settings to default */
+	if (pipe->flags & MDP_DPP_HSIC) {
+		for (i = 0; i < NUM_HSIC_PARAM; i++)
+			dpp.hsic_params[i] = 0;
+
+		mdp4_hsic_set(pipe, &dpp);
+		mdp4_hsic_update(pipe);
+	}
+
 	mdp4_stat.overlay_unset[pipe->mixer_num]++;
 
 	mdp4_overlay_pipe_free(pipe);
 
-	if (!(ctrl->ov_pipe[OVERLAY_PIPE_VG1].ref_cnt +
-		ctrl->ov_pipe[OVERLAY_PIPE_VG2].ref_cnt))
-			mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
+	if (!(ctrl->plist[OVERLAY_PIPE_VG1].pipe_used +
+	      ctrl->plist[OVERLAY_PIPE_VG2].pipe_used))
+		mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
 
@@ -2306,19 +2249,19 @@
 	return 0;
 }
 
-int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
-		struct file **pp_src_file, struct file **pp_src_plane1_file,
-		struct file **pp_src_plane2_file)
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 	struct msmfb_data *img;
 	struct mdp4_overlay_pipe *pipe;
-	struct mdp4_pipe_desc *pd;
 	ulong start, addr;
 	ulong len = 0;
-	struct file *p_src_file = 0;
-	struct file *p_src_plane1_file = 0, *p_src_plane2_file = 0;
+	struct file *srcp0_file = NULL;
+	struct file *srcp1_file = NULL, *srcp2_file = NULL;
+	struct ion_handle *srcp0_ihdl = NULL;
+	struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
 	uint32_t overlay_version = 0;
+	int ret = 0;
 
 	if (mfd == NULL)
 		return -ENODEV;
@@ -2335,24 +2278,14 @@
 	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
 		return -EINTR;
 
-	pd = &ctrl->ov_pipe[pipe->pipe_num];
-	if (pd->player && pipe != pd->player) {
-		if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
-			mutex_unlock(&mfd->dma->ov_mutex);
-			return 0; /* ignore it, kicked out already */
-		}
-	}
-
-	pd->player = pipe;	/* keep */
-
 	img = &req->data;
-	get_img(img, info, &start, &len, &p_src_file);
+	get_img(img, info, &start, &len, &srcp0_file, &srcp0_ihdl);
 	if (len == 0) {
 		mutex_unlock(&mfd->dma->ov_mutex);
 		pr_err("%s: pmem Error\n", __func__);
-		return -1;
+		ret = -1;
+		goto end;
 	}
-	*pp_src_file = p_src_file;
 
 	addr = start + img->offset;
 	pipe->srcp0_addr = addr;
@@ -2364,14 +2297,15 @@
 	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
 		if (overlay_version > 0) {
 			img = &req->plane1_data;
-			get_img(img, info, &start, &len, &p_src_plane1_file);
+			get_img(img, info, &start, &len, &srcp1_file,
+				&srcp1_ihdl);
 			if (len == 0) {
 				mutex_unlock(&mfd->dma->ov_mutex);
 				pr_err("%s: Error to get plane1\n", __func__);
-				return -EINVAL;
+				ret = -EINVAL;
+				goto end;
 			}
 			pipe->srcp1_addr = start + img->offset;
-			*pp_src_plane1_file = p_src_plane1_file;
 		} else if (pipe->frame_format ==
 				MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
 			struct tile_desc tile;
@@ -2395,24 +2329,26 @@
 	} else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
 		if (overlay_version > 0) {
 			img = &req->plane1_data;
-			get_img(img, info, &start, &len, &p_src_plane1_file);
+			get_img(img, info, &start, &len, &srcp1_file,
+				&srcp1_ihdl);
 			if (len == 0) {
 				mutex_unlock(&mfd->dma->ov_mutex);
 				pr_err("%s: Error to get plane1\n", __func__);
-				return -EINVAL;
+				ret = -EINVAL;
+				goto end;
 			}
 			pipe->srcp1_addr = start + img->offset;
-			*pp_src_plane1_file = p_src_plane1_file;
 
 			img = &req->plane2_data;
-			get_img(img, info, &start, &len, &p_src_plane2_file);
+			get_img(img, info, &start, &len, &srcp2_file,
+				&srcp2_ihdl);
 			if (len == 0) {
 				mutex_unlock(&mfd->dma->ov_mutex);
 				pr_err("%s: Error to get plane2\n", __func__);
-				return -EINVAL;
+				ret = -EINVAL;
+				goto end;
 			}
 			pipe->srcp2_addr = start + img->offset;
-			*pp_src_plane2_file = p_src_plane2_file;
 		} else {
 			if (pipe->src_format == MDP_Y_CR_CB_GH2V2) {
 				addr += (ALIGN(pipe->src_width, 16) *
@@ -2495,7 +2431,7 @@
 			if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
 				mdp4_stat.overlay_play[pipe->mixer_num]++;
 				mutex_unlock(&mfd->dma->ov_mutex);
-				return 0;
+				goto end;
 			}
 #ifdef CONFIG_FB_MSM_MIPI_DSI
 			if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
@@ -2511,9 +2447,28 @@
 		}
 	}
 
+	/* write out DPP HSIC registers */
+	if (pipe->flags & MDP_DPP_HSIC)
+		mdp4_hsic_update(pipe);
+
 	mdp4_stat.overlay_play[pipe->mixer_num]++;
-
 	mutex_unlock(&mfd->dma->ov_mutex);
-
-	return 0;
+end:
+#ifdef CONFIG_ANDROID_PMEM
+	if (srcp0_file)
+		put_pmem_file(srcp0_file);
+	if (srcp1_file)
+		put_pmem_file(srcp1_file);
+	if (srcp2_file)
+		put_pmem_file(srcp2_file);
+#endif
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	if (!IS_ERR_OR_NULL(srcp0_ihdl))
+		ion_free(mfd->client, srcp0_ihdl);
+	if (!IS_ERR_OR_NULL(srcp1_ihdl))
+		ion_free(mfd->client, srcp1_ihdl);
+	if (!IS_ERR_OR_NULL(srcp2_ihdl))
+		ion_free(mfd->client, srcp2_ihdl);
+#endif
+	return ret;
 }
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 420a9bc..f9951e9 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -62,7 +62,7 @@
 
 	if (atv_pipe == NULL) {
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1, 0);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
 		if (pipe == NULL)
 			return -EBUSY;
 		pipe->pipe_used++;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 0020fd5..143df46 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -56,6 +56,11 @@
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 }
 
+int mdp4_overlay_dsi_state_get(void)
+{
+	return dsi_state;
+}
+
 static void dsi_clock_tout(unsigned long data)
 {
 	if (mipi_dsi_clk_on) {
@@ -134,7 +139,7 @@
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
 		if (ptype < 0)
 			printk(KERN_INFO "%s: format2type failed\n", __func__);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0);
 		if (pipe == NULL)
 			printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
 		pipe->pipe_used++;
@@ -530,6 +535,7 @@
 	/* mutex holded by caller */
 	if (dsi_mfd && dsi_pipe) {
 		mdp4_dsi_cmd_dma_busy_wait(dsi_mfd);
+		mipi_dsi_mdp_busy_wait(dsi_mfd);
 		mdp4_overlay_update_dsi_cmd(dsi_mfd);
 
 		if (dsi_pipe->blt_addr)
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 5cf79c1..1a5cb65 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -124,7 +124,7 @@
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
 		if (ptype < 0)
 			printk(KERN_INFO "%s: format2type failed\n", __func__);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0);
 		if (pipe == NULL) {
 			printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
 			return -EBUSY;
@@ -555,11 +555,11 @@
 void mdp4_overlay0_done_dsi_video(struct mdp_dma_data *dma)
 {
 	spin_lock(&mdp_spin_lock);
+	dma->busy = FALSE;
 	if (dsi_pipe->blt_addr == 0) {
 		spin_unlock(&mdp_spin_lock);
 		return;
 	}
-	dma->busy = FALSE;
 	mdp4_dsi_video_blt_dmap_update(dsi_pipe);
 	dsi_pipe->dmap_cnt++;
 	mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 13449d6..636d350 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -127,7 +127,7 @@
 		ptype = mdp4_overlay_format2type(format);
 		if (ptype < 0)
 			printk(KERN_INFO "%s: format2type failed\n", __func__);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1, 0);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER1);
 		if (pipe == NULL) {
 			printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
 			return -EBUSY;
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 0eda69a..f44a409 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -114,7 +114,7 @@
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
 		if (ptype < 0)
 			printk(KERN_INFO "%s: format2type failed\n", __func__);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0);
 		if (pipe == NULL)
 			printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
 		pipe->pipe_used++;
@@ -451,11 +451,11 @@
 void mdp4_overlay0_done_lcdc(struct mdp_dma_data *dma)
 {
 	spin_lock(&mdp_spin_lock);
+	dma->busy = FALSE;
 	if (lcdc_pipe->blt_addr == 0) {
 		spin_unlock(&mdp_spin_lock);
 		return;
 	}
-	dma->busy = FALSE;
 	mdp4_lcdc_blt_dmap_update(lcdc_pipe);
 	lcdc_pipe->dmap_cnt++;
 	mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index bd94c56..928ac32 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -112,7 +112,7 @@
 		ptype = mdp4_overlay_format2type(mfd->fb_imgType);
 		if (ptype < 0)
 			printk(KERN_INFO "%s: format2type failed\n", __func__);
-		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0, 0);
+		pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0);
 		if (pipe == NULL)
 			printk(KERN_INFO "%s: pipe_alloc failed\n", __func__);
 		pipe->pipe_used++;
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index 00256e6..aa210f1 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -137,7 +137,7 @@
 	else
 		up(&mfd->dma->mutex);
 
-	pr_debug("%s:\n", __func__);
+	pr_debug("%s-:\n", __func__);
 
 	return ret;
 }
@@ -171,11 +171,6 @@
 	clk_rate = mfd->fbi->var.pixclock;
 	clk_rate = min(clk_rate, mfd->panel_info.clk_max);
 
-
-#ifndef CONFIG_FB_MSM_MDP303
-	mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
-#endif
-
 	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
 	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);
 
@@ -266,6 +261,11 @@
 		wmb();
 	}
 
+	if (mdp_rev >= MDP_REV_41)
+		mutex_lock(&mfd->dma->ov_mutex);
+	else
+		down(&mfd->dma->mutex);
+
 	ret = panel_next_on(pdev);
 
 	mipi_dsi_op_mode_config(mipi->mode);
@@ -320,6 +320,16 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	mdp_bus_scale_update_request(2);
 #endif
+
+	mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
+
+	if (mdp_rev >= MDP_REV_41)
+		mutex_unlock(&mfd->dma->ov_mutex);
+	else
+		up(&mfd->dma->mutex);
+
+	pr_debug("%s-:\n", __func__);
+
 	return ret;
 }
 
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index cb4bd1b..5e2e515 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -439,6 +439,10 @@
 		return;
 
 	mutex_lock(&mfd->dma->ov_mutex);
+	if (mdp4_overlay_dsi_state_get() <= ST_DSI_SUSPEND) {
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return;
+	}
 	/* mdp4_dsi_cmd_busy_wait: will turn on dsi clock also */
 	mdp4_dsi_cmd_dma_busy_wait(mfd);
 	mdp4_dsi_blt_dmap_busy_wait(mfd);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 7595838..10e4156 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2526,8 +2526,6 @@
 	int	ret;
 	struct msmfb_overlay_data req;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct file *p_src_file = 0;
-	struct file *p_src_plane1_file = 0, *p_src_plane2_file = 0;
 
 	if (mfd->overlay_play_enable == 0)	/* nothing to do */
 		return 0;
@@ -2549,17 +2547,7 @@
 	add_timer(&mfd->msmfb_no_update_notify_timer);
 	mutex_unlock(&msm_fb_notify_update_sem);
 
-	ret = mdp4_overlay_play(info, &req, &p_src_file, &p_src_plane1_file,
-				&p_src_plane2_file);
-
-#ifdef CONFIG_ANDROID_PMEM
-	if (p_src_file)
-		put_pmem_file(p_src_file);
-	if (p_src_plane1_file)
-		put_pmem_file(p_src_plane1_file);
-	if (p_src_plane2_file)
-		put_pmem_file(p_src_plane2_file);
-#endif
+	ret = mdp4_overlay_play(info, &req);
 
 	return ret;
 }
@@ -3304,7 +3292,9 @@
 	mfd->fb_page = fb_num;
 	mfd->index = fbi_list_index;
 	mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
-
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	mfd->client = msm_ion_client_create(-1, pdev->name);
+#endif
 	/* link to the latest pdev */
 	mfd->pdev = this_dev;
 
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index a650e73..bc25062 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -37,6 +37,7 @@
 #include <linux/fb.h>
 #include <linux/list.h>
 #include <linux/types.h>
+#include <linux/ion.h>
 
 #include <linux/msm_mdp.h>
 #ifdef CONFIG_HAS_EARLYSUSPEND
@@ -172,6 +173,7 @@
 	struct list_head writeback_free_queue;
 	struct list_head writeback_register_queue;
 	wait_queue_head_t		wait_q;
+	struct ion_client *client;
 };
 
 struct dentry *msm_fb_get_debugfs_root(void);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 2ee2e38..f883fd7 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -41,6 +41,15 @@
 	}
 	memset(ddl_context, 0, sizeof(struct ddl_context));
 	DDL_BUSY(ddl_context);
+	if (res_trk_get_enable_ion()) {
+		DDL_MSG_LOW("ddl_dev_init:ION framework enabled");
+		ddl_context->video_ion_client  =
+			res_trk_get_ion_client();
+		if (!ddl_context->video_ion_client) {
+			DDL_MSG_ERROR("ION client create failed");
+			return VCD_ERR_ILLEGAL_OP;
+		}
+	}
 	ddl_context->ddl_callback = ddl_init_config->ddl_callback;
 	if (ddl_init_config->interrupt_clr)
 		ddl_context->interrupt_clr =
@@ -127,6 +136,7 @@
 	DDL_MSG_LOW("FW_ENDDONE");
 	ddl_context->core_virtual_base_addr = NULL;
 	ddl_release_context_buffers(ddl_context);
+	ddl_context->video_ion_client = NULL;
 	DDL_IDLE(ddl_context);
 	return VCD_S_SUCCESS;
 }
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 6a7031f..cc0acc3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -91,6 +91,7 @@
 	u8  *align_virtual_addr;
 	phys_addr_t alloced_phys_addr;
 	struct msm_mapped_buffer *mapped_buffer;
+	struct ion_handle *alloc_handle;
 	u32 buffer_size;
 };
 enum ddl_cmd_state{
@@ -317,6 +318,7 @@
 	struct ddl_buf_addr dram_base_a;
 	struct ddl_buf_addr dram_base_b;
 	struct ddl_hw_interface ddl_hw_response;
+	struct ion_client *video_ion_client;
 	void (*ddl_callback) (u32 event, u32 status, void *payload,
 		size_t sz, u32 *ddl_handle, void *const client_data);
 	void (*interrupt_clr) (void);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 040d050..df65d26 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -37,13 +37,15 @@
 static void ddl_print_buffer_port(struct ddl_context *ddl_context,
 	struct ddl_buf_addr *buf, u32 idx, u8 *str);
 #endif
-
 void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment)
 {
 	u32 alloc_size, offset = 0, flags = 0;
 	u32 index = 0;
 	struct ddl_context *ddl_context;
 	struct msm_mapped_buffer *mapped_buffer = NULL;
+	int rc = -EINVAL;
+	ion_phys_addr_t phyaddr = 0;
+	size_t len = 0;
 	DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz);
 	if (!addr) {
 		DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__);
@@ -51,13 +53,41 @@
 	}
 	ddl_context = ddl_get_context();
 	alloc_size = (sz + alignment);
-	addr->alloced_phys_addr = (phys_addr_t)
-	allocate_contiguous_memory_nomap(alloc_size,
-		res_trk_get_mem_type(), SZ_4K);
-	if (!addr->alloced_phys_addr) {
-		DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n", __func__,
-			alloc_size);
-		goto bail_out;
+	if (res_trk_get_enable_ion()) {
+		if (!ddl_context->video_ion_client)
+			ddl_context->video_ion_client =
+				res_trk_get_ion_client();
+		if (!ddl_context->video_ion_client) {
+			DDL_MSG_ERROR("%s() :DDL ION Client Invalid handle\n",
+						 __func__);
+			goto bail_out;
+		}
+		addr->alloc_handle = ion_alloc(
+		ddl_context->video_ion_client, alloc_size, SZ_4K,
+			(1<<res_trk_get_mem_type()));
+		if (!addr->alloc_handle) {
+			DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
+						 __func__);
+			goto bail_out;
+		}
+		rc = ion_phys(ddl_context->video_ion_client,
+				addr->alloc_handle, &phyaddr,
+				 &len);
+		if (rc || !phyaddr) {
+			DDL_MSG_ERROR("%s():DDL ION client physical failed\n",
+						 __func__);
+			goto free_acm_ion_alloc;
+		}
+		addr->alloced_phys_addr = phyaddr;
+	} else {
+		addr->alloced_phys_addr = (phys_addr_t)
+		allocate_contiguous_memory_nomap(alloc_size,
+			res_trk_get_mem_type(), SZ_4K);
+		if (!addr->alloced_phys_addr) {
+			DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n",
+					 __func__, alloc_size);
+			goto bail_out;
+		}
 	}
 	flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
 	if (alignment == DDL_KILO_BYTE(128))
@@ -71,7 +101,7 @@
 	sizeof(vidc_mmu_subsystem[index])/sizeof(unsigned int));
 	if (IS_ERR(addr->mapped_buffer)) {
 		pr_err(" %s() buffer map failed", __func__);
-		goto free_acm_alloc;
+		goto free_acm_ion_alloc;
 	}
 	mapped_buffer = addr->mapped_buffer;
 	if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
@@ -91,9 +121,16 @@
 free_map_buffers:
 	msm_subsystem_unmap_buffer(addr->mapped_buffer);
 	addr->mapped_buffer = NULL;
-free_acm_alloc:
-	free_contiguous_memory_by_paddr(
-		(unsigned long)addr->alloced_phys_addr);
+free_acm_ion_alloc:
+	if (ddl_context->video_ion_client) {
+		if (addr->alloc_handle) {
+			ion_free(ddl_context->video_ion_client,
+				addr->alloc_handle);
+		}
+	} else
+		free_contiguous_memory_by_paddr(
+			(unsigned long)addr->alloced_phys_addr);
+	addr->alloc_handle = NULL;
 	addr->alloced_phys_addr = (phys_addr_t)NULL;
 bail_out:
 	return NULL;
@@ -101,13 +138,22 @@
 
 void ddl_pmem_free(struct ddl_buf_addr *addr)
 {
+	struct ddl_context *ddl_context;
+	ddl_context = ddl_get_context();
 	if (!addr) {
 		pr_err("%s() invalid args\n", __func__);
 		return;
 	}
-	if (addr->alloced_phys_addr)
-		free_contiguous_memory_by_paddr(
-			(unsigned long)addr->alloced_phys_addr);
+	if (ddl_context->video_ion_client) {
+		if (addr->alloc_handle) {
+			ion_free(ddl_context->video_ion_client,
+				addr->alloc_handle);
+		}
+	} else {
+		if (addr->alloced_phys_addr)
+			free_contiguous_memory_by_paddr(
+				(unsigned long)addr->alloced_phys_addr);
+	}
 	if (addr->mapped_buffer)
 		msm_subsystem_unmap_buffer(addr->mapped_buffer);
 	memset(addr, 0, sizeof(struct ddl_buf_addr));
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 8f745ec..03d4681 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -222,6 +222,13 @@
 	return false;
 }
 
+static struct ion_client *res_trk_create_ion_client(void){
+	struct ion_client *video_client;
+	video_client = msm_ion_client_create((1<<ION_HEAP_TYPE_CARVEOUT),
+						"video_client");
+	return video_client;
+}
+
 u32 res_trk_power_up(void)
 {
 	VCDRES_MSG_LOW("clk_regime_rail_enable");
@@ -416,6 +423,15 @@
 		if (resource_context.vidc_platform_data) {
 			resource_context.memtype =
 			resource_context.vidc_platform_data->memtype;
+			if (resource_context.vidc_platform_data->enable_ion) {
+				resource_context.res_ion_client =
+					res_trk_create_ion_client();
+				if (!(resource_context.res_ion_client)) {
+					VCDRES_MSG_ERROR("%s()ION createfail\n",
+							__func__);
+					return;
+				}
+			}
 #ifdef CONFIG_MSM_BUS_SCALING
 			resource_context.vidc_bus_client_pdata =
 			resource_context.vidc_platform_data->
@@ -453,3 +469,16 @@
 u32 res_trk_get_mem_type(void){
 	return resource_context.memtype;
 }
+
+u32 res_trk_get_enable_ion(void)
+{
+	if (resource_context.vidc_platform_data->enable_ion)
+		return 1;
+	else
+		return 0;
+}
+
+struct ion_client *res_trk_get_ion_client(void)
+{
+	return resource_context.res_ion_client;
+}
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
index 6e61a81..4766019 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
@@ -14,6 +14,7 @@
 #define _VIDEO_720P_RESOURCE_TRACKER_H_
 
 #include <linux/regulator/consumer.h>
+#include <linux/ion.h>
 #include "vcd_res_tracker_api.h"
 #ifdef CONFIG_MSM_BUS_SCALING
 #include <mach/msm_bus.h>
@@ -45,6 +46,7 @@
 #endif
 	u32 core_type;
 	struct ddl_buf_addr firmware_addr;
+	struct ion_client *res_ion_client;
 };
 
 #if DEBUG
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
index 2a083cd..30a784c 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
@@ -30,5 +30,6 @@
 u32 res_trk_get_core_type(void);
 u32 res_trk_get_firmware_addr(struct ddl_buf_addr *firm_addr);
 u32 res_trk_get_mem_type(void);
-
+u32 res_trk_get_enable_ion(void);
+struct ion_client *res_trk_get_ion_client(void);
 #endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
index c388407..e5a5a84 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -195,6 +195,7 @@
 	struct vcd_buffer_requirement actual_output_buf_req;
 	struct vcd_buffer_requirement min_output_buf_req;
 	struct vcd_buffer_requirement client_output_buf_req;
+	u32 idr_only_decoding;
 };
 
 union ddl_codec_data {
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
index ad2fd37..e17107e 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
@@ -356,6 +356,11 @@
 	case ACTIVE_SPS_NOT_PRESENT:
 	case ACTIVE_PPS_NOT_PRESENT:
 		{
+			if (ddl->codec_data.decoder.idr_only_decoding) {
+				DBG("Consider warnings as errors in idr mode");
+				ddl_client_fatal_cb(ddl_context);
+				return true;
+			}
 			vcd_status = VCD_ERR_BITSTREAM_ERR;
 			break;
 		}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
index bb9b9c1..f09bd71 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
@@ -771,6 +771,7 @@
 	struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
 	u32 comv_buf_size = DDL_COMV_BUFLINE_NO, comv_buf_no = 0;
 	u32 ref_buf_no = 0;
+	struct ddl_context  *ddl_ctxt = NULL;
 
 	if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
 		VIDC_LOG_STRING("STATE-CRITICAL");
@@ -806,8 +807,13 @@
 		}
 	case VCD_CODEC_H264:
 		{
-			comv_buf_no =
-			    decoder->client_output_buf_req.actual_count;
+			if (decoder->idr_only_decoding)
+				comv_buf_no = decoder->min_dpb_num;
+			else
+				comv_buf_no =
+					decoder->
+					client_output_buf_req.
+					actual_count;
 			break;
 		}
 	}
@@ -857,6 +863,10 @@
 	}
 	ddl_decode_set_metadata_output(decoder);
 	ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_INIT);
+	ddl_ctxt = ddl_get_context();
+	vidc_720p_set_deblock_line_buffer(
+		ddl_ctxt->db_line_buffer.align_physical_addr,
+		ddl_ctxt->db_line_buffer.buffer_size);
 	ddl_move_client_state(ddl, DDL_CLIENT_WAIT_FOR_DPBDONE);
 	ddl_move_command_state(ddl->ddl_context, DDL_CMD_DECODE_SET_DPB);
 
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
index 2899df6..2ec8419 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
@@ -124,6 +124,7 @@
 	u32 loopc;
 	struct ddl_frame_data_tag *found_frame = NULL;
 	struct ddl_mask *dpb_mask = &decoder->dpb_mask;
+	u32 temp_mask;
 
 	switch (operation) {
 	case DDL_DPB_OP_MARK_BUSY:
@@ -145,13 +146,17 @@
 
 			if (found_frame) {
 				if (operation == DDL_DPB_OP_MARK_BUSY) {
-					dpb_mask->hw_mask &=
-					    (~(0x1 << loopc));
+					temp_mask = (~(0x1 << loopc));
+					if (decoder->idr_only_decoding)
+						temp_mask = ~(0xffffffff);
+					dpb_mask->hw_mask &= temp_mask;
 					*in_out_frame = *found_frame;
 				} else if (operation ==
 					DDL_DPB_OP_MARK_FREE) {
-					dpb_mask->client_mask |=
-					    (0x1 << loopc);
+					temp_mask = (0x1 << loopc);
+					if (decoder->idr_only_decoding)
+						temp_mask = 0xffffffff;
+					dpb_mask->client_mask |= temp_mask;
 					*found_frame = *in_out_frame;
 				}
 			} else {
@@ -172,29 +177,35 @@
 		}
 	case DDL_DPB_OP_INIT:
 		{
-			u32 dpb_size;
+			u32 dpb_size, index, num_dpb;
 			dpb_size = (!decoder->meta_data_offset) ?
 			    decoder->dp_buf.dec_pic_buffers[0].vcd_frm.
 			    alloc_len : decoder->meta_data_offset;
-			vidc_720p_decode_set_dpb_details(decoder->dp_buf.
-						  no_of_dec_pic_buf,
+			if (decoder->idr_only_decoding)
+				num_dpb = decoder->min_dpb_num;
+			else
+				num_dpb = decoder->dp_buf.no_of_dec_pic_buf;
+			vidc_720p_decode_set_dpb_details(
+						  num_dpb,
 						  dpb_size,
 						  decoder->ref_buffer.
 						  align_physical_addr);
-			for (loopc = 0;
-			     loopc < decoder->dp_buf.no_of_dec_pic_buf;
-			     ++loopc) {
+			for (loopc = 0; loopc < num_dpb; ++loopc) {
+				if (decoder->idr_only_decoding)
+					index = 0;
+				else
+					index = loopc;
 				vidc_720p_decode_set_dpb_buffers(loopc,
 							  (u32 *)
 							  decoder->
 							  dp_buf.
 							  dec_pic_buffers
-							  [loopc].
+							  [index].
 							  vcd_frm.
 							  physical);
-				VIDC_LOG1("DEC_DPB_BUFn_SIZE",
+				VIDC_LOG1("DEC_DPB_BUFn_SIZE=%d",
 					   decoder->dp_buf.
-					   dec_pic_buffers[loopc].vcd_frm.
+					   dec_pic_buffers[index].vcd_frm.
 					   alloc_len);
 			}
 			break;
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
index 17c2028..d1b1952 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
@@ -365,6 +365,18 @@
 			}
 			break;
 		}
+	case VCD_I_DEC_PICTYPE:
+		{
+			if ((sizeof(u32) == property_hdr->sz) &&
+				DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+				decoder->idr_only_decoding =
+					*(u32 *)property_value;
+				ddl_set_default_decoder_buffer_req(
+						decoder, true);
+				vcd_status = VCD_S_SUCCESS;
+			}
+		}
+		break;
 	case VCD_I_FRAME_RATE:
 		{
 			vcd_status = VCD_S_SUCCESS;
@@ -1462,6 +1474,7 @@
 	decoder->client_frame_size.stride = 176;
 	decoder->client_frame_size.scan_lines = 144;
 	decoder->progressive_only = 1;
+	decoder->idr_only_decoding = 0;
 	decoder->profile.profile = VCD_PROFILE_UNKNOWN;
 	decoder->level.level = VCD_LEVEL_UNKNOWN;
 	decoder->output_order = VCD_DEC_ORDER_DISPLAY;
@@ -1689,18 +1702,24 @@
 		min_dpb = decoder->min_dpb_num;
 	}
 
+	if (decoder->idr_only_decoding)
+		min_dpb = 1;
+
 	memset(output_buf_req, 0, sizeof(struct vcd_buffer_requirement));
 
 	output_buf_req->min_count = min_dpb;
 
 	num_mb = DDL_NO_OF_MB(frame_size->width, frame_size->height);
-	if (num_mb >= DDL_WVGA_MBS) {
-		output_buf_req->actual_count = min_dpb + 2;
-		if (output_buf_req->actual_count < 10)
-			output_buf_req->actual_count = 10;
-	} else
-		output_buf_req->actual_count = min_dpb + 5;
-
+	if (decoder->idr_only_decoding) {
+		output_buf_req->actual_count = output_buf_req->min_count;
+	} else {
+		if (num_mb >= DDL_WVGA_MBS) {
+			output_buf_req->actual_count = min_dpb + 2;
+			if (output_buf_req->actual_count < 10)
+				output_buf_req->actual_count = 10;
+		} else
+			output_buf_req->actual_count = min_dpb + 5;
+	}
 	output_buf_req->max_count = DDL_MAX_BUFFER_COUNT;
 	output_buf_req->sz = y_cb_cr_size;
 	if (decoder->buf_format.buffer_format != VCD_BUFFER_FORMAT_NV12)
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index 7ac32b7..fe8e185 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -708,3 +708,13 @@
 u32 res_trk_get_mem_type(void){
 	return resource_context.memtype;
 }
+
+u32 res_trk_get_enable_ion(void)
+{
+	return 0;
+}
+
+struct ion_client *res_trk_get_ion_client(void)
+{
+	return NULL;
+}
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
index db84743..7f9a2be 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
@@ -27,4 +27,6 @@
 u32 res_trk_download_firmware(void);
 u32 res_trk_get_core_type(void);
 u32 res_trk_get_mem_type(void);
+u32 res_trk_get_enable_ion(void);
+struct ion_client *res_trk_get_ion_client(void);
 #endif
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index a5994dc..184da27 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -750,6 +750,7 @@
 	u32 vcd_status = VCD_ERR_FAIL;
 	u32 len = 0, flags = 0;
 	struct file *file;
+	int rc = 0;
 
 	if (!client_ctx || !mv_data)
 		return false;
@@ -765,15 +766,44 @@
 	vcd_h264_mv_buffer->pmem_fd = mv_data->pmem_fd;
 	vcd_h264_mv_buffer->offset = mv_data->offset;
 
-	if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd,
-		(unsigned long *) (&(vcd_h264_mv_buffer->physical_addr)),
-		(unsigned long *) (&vcd_h264_mv_buffer->kernel_virtual_addr),
-		(unsigned long *) (&len), &file)) {
-		ERR("%s(): get_pmem_file failed\n", __func__);
-		return false;
+	if (!vcd_get_ion_status()) {
+		if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd,
+			(unsigned long *) (&(vcd_h264_mv_buffer->
+			physical_addr)),
+			(unsigned long *) (&vcd_h264_mv_buffer->
+						kernel_virtual_addr),
+			(unsigned long *) (&len), &file)) {
+			ERR("%s(): get_pmem_file failed\n", __func__);
+			return false;
+		}
+		put_pmem_file(file);
+	} else {
+		client_ctx->h264_mv_ion_handle = ion_import_fd(
+					client_ctx->user_ion_client,
+					vcd_h264_mv_buffer->pmem_fd);
+		if (!client_ctx->h264_mv_ion_handle) {
+			ERR("%s(): get_ION_handle failed\n", __func__);
+			goto ion_error;
+		}
+		vcd_h264_mv_buffer->kernel_virtual_addr = (u8 *) ion_map_kernel(
+			client_ctx->user_ion_client,
+			client_ctx->h264_mv_ion_handle,
+			0);
+		if (!vcd_h264_mv_buffer->kernel_virtual_addr) {
+			ERR("%s(): get_ION_kernel virtual addr failed\n",
+				 __func__);
+			goto ion_error;
+		}
+		rc = ion_phys(client_ctx->user_ion_client,
+				client_ctx->h264_mv_ion_handle,
+				(unsigned long *) (&(vcd_h264_mv_buffer->
+				physical_addr)), &len);
+		if (rc) {
+			ERR("%s():get_ION_kernel physical addr fail\n",
+					 __func__);
+			goto ion_error;
+		}
 	}
-	put_pmem_file(file);
-
 	flags = MSM_SUBSYSTEM_MAP_IOVA;
 	mapped_buffer = msm_subsystem_map_buffer(
 		(unsigned long)vcd_h264_mv_buffer->physical_addr, len,
@@ -796,6 +826,14 @@
 		return false;
 	else
 		return true;
+ion_error:
+	if (vcd_h264_mv_buffer->kernel_virtual_addr)
+		ion_unmap_kernel(client_ctx->user_ion_client,
+				client_ctx->h264_mv_ion_handle);
+	if (client_ctx->h264_mv_ion_handle)
+		ion_free(client_ctx->user_ion_client,
+			client_ctx->h264_mv_ion_handle);
+	return false;
 }
 
 static u32 vid_dec_set_cont_on_reconfig(struct video_client_ctx *client_ctx)
@@ -861,6 +899,14 @@
 
 	vcd_status = vcd_set_property(client_ctx->vcd_handle,
 				      &vcd_property_hdr, &h264_mv_buffer_size);
+
+	if (client_ctx->h264_mv_ion_handle != NULL) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle);
+		ion_free(client_ctx->user_ion_client,
+					client_ctx->h264_mv_ion_handle);
+	}
+
 	if (vcd_status)
 		return false;
 	else
@@ -953,6 +999,7 @@
 		dir_buffer = BUFFER_TYPE_OUTPUT;
 		buffer = VCD_BUFFER_OUTPUT;
 	}
+
 	/*If buffer NOT set, ignore */
 	if (!vidc_delete_addr_table(client_ctx, dir_buffer,
 				(unsigned long)buffer_info->buffer.bufferaddr,
@@ -961,7 +1008,6 @@
 		    __func__, buffer_info->buffer.bufferaddr);
 		return true;
 	}
-
 	vcd_status = vcd_free_buffer(client_ctx->vcd_handle, buffer,
 					 (u8 *)kernel_vaddr);
 
@@ -1255,9 +1301,12 @@
 	struct vdec_ioctl_msg vdec_msg;
 	u32 vcd_status;
 	unsigned long kernel_vaddr, phy_addr, len;
+	unsigned long ker_vaddr;
 	struct file *pmem_file;
 	u32 result = true;
 	void __user *arg = (void __user *)u_arg;
+	int rc = 0;
+	size_t ion_len;
 
 	DBG("%s\n", __func__);
 	if (_IOC_TYPE(cmd) != VDEC_IOCTL_MAGIC)
@@ -1540,13 +1589,46 @@
 			return -EFAULT;
 		}
 
-		if (get_pmem_file(seq_header.pmem_fd,
+		if (!vcd_get_ion_status()) {
+			if (get_pmem_file(seq_header.pmem_fd,
 				  &phy_addr, &kernel_vaddr, &len, &pmem_file)) {
-			ERR("%s(): get_pmem_file failed\n", __func__);
-			return false;
+				ERR("%s(): get_pmem_file failed\n", __func__);
+				return false;
+			}
+			put_pmem_file(pmem_file);
+		} else {
+			client_ctx->seq_hdr_ion_handle = ion_import_fd(
+				client_ctx->user_ion_client,
+				seq_header.pmem_fd);
+			if (!client_ctx->seq_hdr_ion_handle) {
+				ERR("%s(): get_ION_handle failed\n", __func__);
+				return false;
+			}
+			ker_vaddr = (unsigned long) ion_map_kernel(
+				client_ctx->user_ion_client,
+				client_ctx->seq_hdr_ion_handle, 0);
+			if (!ker_vaddr) {
+				ERR("%s():get_ION_kernel virtual addr fail\n",
+							 __func__);
+				ion_free(client_ctx->user_ion_client,
+					client_ctx->seq_hdr_ion_handle);
+				return false;
+			}
+			kernel_vaddr = ker_vaddr;
+			rc = ion_phys(client_ctx->user_ion_client,
+					client_ctx->seq_hdr_ion_handle,
+					&phy_addr, &ion_len);
+			if (rc) {
+				ERR("%s():get_ION_kernel physical addr fail\n",
+						 __func__);
+				ion_unmap_kernel(client_ctx->user_ion_client,
+					client_ctx->seq_hdr_ion_handle);
+				ion_free(client_ctx->user_ion_client,
+					client_ctx->seq_hdr_ion_handle);
+				return false;
+			}
+			len = ion_len;
 		}
-		put_pmem_file(pmem_file);
-
 		vcd_seq_hdr.sequence_header_len = seq_header.seq_header_len;
 		kernel_vaddr += (unsigned long)seq_header.pmem_offset;
 		vcd_seq_hdr.sequence_header = (u8 *)kernel_vaddr;
@@ -1567,6 +1649,14 @@
 			ERR("Set Seq Header status is failed");
 			return -EFAULT;
 		}
+		if (vcd_get_ion_status()) {
+			if (client_ctx->seq_hdr_ion_handle) {
+				ion_unmap_kernel(client_ctx->user_ion_client,
+						client_ctx->seq_hdr_ion_handle);
+				ion_free(client_ctx->user_ion_client,
+					client_ctx->seq_hdr_ion_handle);
+			}
+		}
 		break;
 	}
 	case VDEC_IOCTL_GET_NUMBER_INSTANCES:
@@ -1745,6 +1835,7 @@
 		mutex_unlock(&vid_dec_device_p->lock);
 		return false;
 	}
+	client_ctx->user_ion_client = NULL;
 	memset((void *)client_ctx, 0, sizeof(struct video_client_ctx));
 	vid_dec_device_p->num_clients--;
 	mutex_unlock(&vid_dec_device_p->lock);
@@ -1789,6 +1880,13 @@
 	client_ctx->stop_msg = 0;
 	client_ctx->stop_called = false;
 	client_ctx->stop_sync_cb = false;
+	if (vcd_get_ion_status()) {
+		client_ctx->user_ion_client = vcd_get_ion_client();
+		if (!client_ctx->user_ion_client) {
+			ERR("vcd_open ion client get failed");
+			return -EFAULT;
+		}
+	}
 	vcd_status = vcd_open(vid_dec_device_p->device_handle, true,
 			      vid_dec_vcd_cb, client_ctx);
 	if (!vcd_status) {
@@ -1804,7 +1902,6 @@
 		mutex_unlock(&vid_dec_device_p->lock);
 		return -EFAULT;
 	}
-
 	client_ctx->seq_header_set = false;
 	file->private_data = client_ctx;
 	mutex_unlock(&vid_dec_device_p->lock);
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 125355e..1435b86 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -493,7 +493,6 @@
 		mutex_unlock(&vid_enc_device_p->lock);
 		return false;
 	}
-
 	memset((void *)client_ctx, 0,
 		sizeof(struct video_client_ctx));
 
@@ -546,6 +545,13 @@
 	mutex_init(&client_ctx->msg_queue_lock);
 	INIT_LIST_HEAD(&client_ctx->msg_queue);
 	init_waitqueue_head(&client_ctx->msg_wait);
+	if (vcd_get_ion_status()) {
+		client_ctx->user_ion_client = vcd_get_ion_client();
+		if (!client_ctx->user_ion_client) {
+			ERR("vcd_open ion get client failed");
+			return -EFAULT;
+		}
+	}
 	vcd_status = vcd_open(vid_enc_device_p->device_handle, false,
 		vid_enc_vcd_cb, client_ctx);
 	client_ctx->stop_msg = 0;
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index c3f0219..ee38098 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1589,7 +1589,6 @@
 		    __func__, buffer_info->pbuffer);
 		return true;
 	}
-
 	vcd_status = vcd_free_buffer(client_ctx->vcd_handle, buffer_vcd,
 					 (u8 *)kernel_vaddr);
 
@@ -1705,6 +1704,9 @@
 	struct vcd_property_hdr vcd_property_hdr;
 	struct vcd_property_enc_recon_buffer *control = NULL;
 	struct msm_mapped_buffer *mapped_buffer = NULL;
+	size_t ion_len = -1;
+	unsigned long phy_addr;
+	int rc = -1;
 	if (!client_ctx || !venc_recon) {
 		pr_err("%s() Invalid params", __func__);
 		return false;
@@ -1727,39 +1729,78 @@
 	control->pmem_fd = venc_recon->pmem_fd;
 	control->offset = venc_recon->offset;
 	control->user_virtual_addr = venc_recon->pbuffer;
-	if (get_pmem_file(control->pmem_fd, (unsigned long *)
-		(&(control->physical_addr)), (unsigned long *)
-		(&control->kernel_virtual_addr),
-		(unsigned long *) (&len), &file)) {
-			ERR("%s(): get_pmem_file failed\n", __func__);
-			return false;
-		}
-		put_pmem_file(file);
-		flags = MSM_SUBSYSTEM_MAP_IOVA;
-		mapped_buffer = msm_subsystem_map_buffer(
-		(unsigned long)control->physical_addr, len,
-		flags, vidc_mmu_subsystem,
-		sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
-		if (IS_ERR(mapped_buffer)) {
-			pr_err("buffer map failed");
-			return false;
-		}
-		control->client_data = (void *) mapped_buffer;
-		control->dev_addr = (u8 *)mapped_buffer->iova[0];
-		vcd_property_hdr.prop_id = VCD_I_RECON_BUFFERS;
-		vcd_property_hdr.sz =
-			sizeof(struct vcd_property_enc_recon_buffer);
 
-		vcd_status = vcd_set_property(client_ctx->vcd_handle,
-						&vcd_property_hdr, control);
-		if (!vcd_status) {
-			DBG("vcd_set_property returned success\n");
-			return true;
-		} else {
-			ERR("%s(): vid_enc_set_recon_buffers failed = %u\n",
-					__func__, vcd_status);
-			return false;
+	if (!vcd_get_ion_status()) {
+		if (get_pmem_file(control->pmem_fd, (unsigned long *)
+			(&(control->physical_addr)), (unsigned long *)
+			(&control->kernel_virtual_addr),
+			(unsigned long *) (&len), &file)) {
+				ERR("%s(): get_pmem_file failed\n", __func__);
+				return false;
+			}
+			put_pmem_file(file);
+	} else {
+		client_ctx->recon_buffer_ion_handle[i] = ion_import_fd(
+				client_ctx->user_ion_client, control->pmem_fd);
+		if (!client_ctx->recon_buffer_ion_handle[i]) {
+			ERR("%s(): get_ION_handle failed\n", __func__);
+			goto ion_error;
 		}
+		control->kernel_virtual_addr = (u8 *) ion_map_kernel(
+			client_ctx->user_ion_client,
+			client_ctx->recon_buffer_ion_handle[i],
+			0);
+		if (!control->kernel_virtual_addr) {
+			ERR("%s(): get_ION_kernel virtual addr fail\n",
+				 __func__);
+			goto ion_error;
+		}
+		rc = ion_phys(client_ctx->user_ion_client,
+				client_ctx->recon_buffer_ion_handle[i],
+				&phy_addr, &ion_len);
+		if (rc) {
+			ERR("%s():get_ION_kernel physical addr fail\n",
+				 __func__);
+			goto ion_error;
+		}
+		control->physical_addr =  (u8 *) phy_addr;
+		len = (unsigned long) ion_len;
+	}
+	flags = MSM_SUBSYSTEM_MAP_IOVA;
+	mapped_buffer = msm_subsystem_map_buffer(
+	(unsigned long)control->physical_addr, len,
+	flags, vidc_mmu_subsystem,
+	sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
+	if (IS_ERR(mapped_buffer)) {
+		pr_err("buffer map failed");
+		return false;
+	}
+	control->client_data = (void *) mapped_buffer;
+	control->dev_addr = (u8 *)mapped_buffer->iova[0];
+
+	vcd_property_hdr.prop_id = VCD_I_RECON_BUFFERS;
+	vcd_property_hdr.sz =
+		sizeof(struct vcd_property_enc_recon_buffer);
+
+	vcd_status = vcd_set_property(client_ctx->vcd_handle,
+					&vcd_property_hdr, control);
+	if (!vcd_status) {
+		DBG("vcd_set_property returned success\n");
+		return true;
+	} else {
+		ERR("%s(): vid_enc_set_recon_buffers failed = %u\n",
+				__func__, vcd_status);
+		return false;
+	}
+ion_error:
+	if (control->kernel_virtual_addr)
+		ion_unmap_kernel(client_ctx->user_ion_client,
+			client_ctx->recon_buffer_ion_handle[i]);
+	if (client_ctx->recon_buffer_ion_handle[i])
+		ion_free(client_ctx->user_ion_client,
+			client_ctx->recon_buffer_ion_handle[i]);
+		client_ctx->recon_buffer_ion_handle[i] = NULL;
+	return false;
 }
 
 u32 vid_enc_free_recon_buffers(struct video_client_ctx *client_ctx,
@@ -1798,6 +1839,15 @@
 	vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
 	vcd_status = vcd_set_property(client_ctx->vcd_handle,
 						&vcd_property_hdr, control);
+	if (vcd_get_ion_status()) {
+		if (client_ctx->recon_buffer_ion_handle[i]) {
+			ion_unmap_kernel(client_ctx->user_ion_client,
+				client_ctx->recon_buffer_ion_handle[i]);
+			ion_free(client_ctx->user_ion_client,
+				client_ctx->recon_buffer_ion_handle[i]);
+			client_ctx->recon_buffer_ion_handle[i] = NULL;
+		}
+	}
 	memset(control, 0, sizeof(struct vcd_property_enc_recon_buffer));
 	return true;
 }
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 902a9aa..1217f1f 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -455,6 +455,8 @@
 	u32 i, flags;
 	struct buf_addr_table *buf_addr_table;
 	struct msm_mapped_buffer *mapped_buffer = NULL;
+	size_t ion_len;
+	struct ion_handle *buff_ion_handle = NULL;
 
 	if (!client_ctx || !length)
 		return false;
@@ -488,15 +490,44 @@
 			__func__, client_ctx, user_vaddr);
 		return false;
 	} else {
-		if (get_pmem_file(pmem_fd, &phys_addr,
-				kernel_vaddr, &len, &file)) {
-			ERR("%s(): get_pmem_file failed\n", __func__);
-			return false;
+		if (!vcd_get_ion_status()) {
+			if (get_pmem_file(pmem_fd, &phys_addr,
+					kernel_vaddr, &len, &file)) {
+				ERR("%s(): get_pmem_file failed\n", __func__);
+				return false;
+			}
+			put_pmem_file(file);
+		} else {
+			buff_ion_handle = ion_import_fd(
+				client_ctx->user_ion_client, pmem_fd);
+			if (!buff_ion_handle) {
+				ERR("%s(): get_ION_handle failed\n",
+				 __func__);
+				goto ion_error;
+			}
+			*kernel_vaddr = (unsigned long)
+				ion_map_kernel(
+				client_ctx->user_ion_client,
+				buff_ion_handle,
+				0);
+			if (!(*kernel_vaddr)) {
+				ERR("%s():ION virtual addr fail\n",
+				 __func__);
+				goto ion_error;
+			}
+			if (ion_phys(client_ctx->user_ion_client,
+					buff_ion_handle,
+					&phys_addr, &ion_len)) {
+				ERR("%s():ION physical addr fail\n",
+				 __func__);
+				goto ion_error;
+			}
+			len = (unsigned long) ion_len;
 		}
-		put_pmem_file(file);
 		phys_addr += buffer_addr_offset;
 		(*kernel_vaddr) += buffer_addr_offset;
-		flags = MSM_SUBSYSTEM_MAP_IOVA;
+		flags = (buffer == BUFFER_TYPE_INPUT) ? MSM_SUBSYSTEM_MAP_IOVA :
+		MSM_SUBSYSTEM_MAP_IOVA|MSM_SUBSYSTEM_ALIGN_IOVA_8K;
 		mapped_buffer = msm_subsystem_map_buffer(phys_addr, length,
 		flags, vidc_mmu_subsystem,
 		sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
@@ -513,12 +544,20 @@
 		buf_addr_table[*num_of_buffers].pmem_fd = pmem_fd;
 		buf_addr_table[*num_of_buffers].file = file;
 		buf_addr_table[*num_of_buffers].phy_addr = phys_addr;
+		buf_addr_table[*num_of_buffers].buff_ion_handle =
+						buff_ion_handle;
 		*num_of_buffers = *num_of_buffers + 1;
 		DBG("%s() : client_ctx = %p, user_virt_addr = 0x%08lx, "
 			"kernel_vaddr = 0x%08lx inserted!", __func__,
 			client_ctx, user_vaddr, *kernel_vaddr);
 	}
 	return true;
+ion_error:
+	if (*kernel_vaddr)
+		ion_unmap_kernel(client_ctx->user_ion_client, buff_ion_handle);
+	if (buff_ion_handle)
+		ion_free(client_ctx->user_ion_client, buff_ion_handle);
+	return false;
 }
 EXPORT_SYMBOL(vidc_insert_addr_table);
 
@@ -559,6 +598,13 @@
 	msm_subsystem_unmap_buffer(
 	(struct msm_mapped_buffer *)buf_addr_table[i].client_data);
 	*kernel_vaddr = buf_addr_table[i].kernel_vaddr;
+	if (buf_addr_table[i].buff_ion_handle) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+				buf_addr_table[i].buff_ion_handle);
+		ion_free(client_ctx->user_ion_client,
+				buf_addr_table[i].buff_ion_handle);
+		buf_addr_table[i].buff_ion_handle = NULL;
+	}
 	if (i < (*num_of_buffers - 1)) {
 		buf_addr_table[i].client_data =
 			buf_addr_table[*num_of_buffers - 1].client_data;
@@ -574,6 +620,8 @@
 			buf_addr_table[*num_of_buffers - 1].pmem_fd;
 		buf_addr_table[i].file =
 			buf_addr_table[*num_of_buffers - 1].file;
+		buf_addr_table[i].buff_ion_handle =
+			buf_addr_table[*num_of_buffers - 1].buff_ion_handle;
 	}
 	*num_of_buffers = *num_of_buffers - 1;
 	DBG("%s() : client_ctx = %p."
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.h b/drivers/video/msm/vidc/common/init/vidc_init.h
index fecbf59..2bd8ecd 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.h
+++ b/drivers/video/msm/vidc/common/init/vidc_init.h
@@ -13,7 +13,7 @@
 
 #ifndef VIDC_INIT_H
 #define VIDC_INIT_H
-
+#include <linux/ion.h>
 #include "vidc_type.h"
 
 #define VIDC_MAX_NUM_CLIENTS 4
@@ -28,6 +28,7 @@
 	unsigned long user_vaddr;
 	unsigned long kernel_vaddr;
 	unsigned long phy_addr;
+	struct ion_handle *buff_ion_handle;
 	int pmem_fd;
 	struct file *file;
 	unsigned long dev_addr;
@@ -51,6 +52,10 @@
 	u32 stop_msg;
 	u32 stop_called;
 	u32 stop_sync_cb;
+	struct ion_client *user_ion_client;
+	struct ion_handle *seq_hdr_ion_handle;
+	struct ion_handle *h264_mv_ion_handle;
+	struct ion_handle *recon_buffer_ion_handle[4];
 };
 
 void __iomem *vidc_get_ioaddr(void);
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index a57675e..4889761 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -876,6 +876,18 @@
 }
 EXPORT_SYMBOL(vcd_get_num_of_clients);
 
+u32 vcd_get_ion_status(void)
+{
+	return res_trk_get_enable_ion();
+}
+EXPORT_SYMBOL(vcd_get_ion_status);
+
+struct ion_client *vcd_get_ion_client(void)
+{
+	return res_trk_get_ion_client();
+}
+EXPORT_SYMBOL(vcd_get_ion_client);
+
 
 
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.h b/drivers/video/msm/vidc/common/vcd/vcd_api.h
index dec0326..4fcd085 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.h
@@ -139,5 +139,6 @@
 void vcd_read_and_clear_interrupt(void);
 void vcd_response_handler(void);
 u8 vcd_get_num_of_clients(void);
-
+u32 vcd_get_ion_status(void);
+struct ion_client *vcd_get_ion_client(void);
 #endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index ae27266..b424059 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -13,6 +13,7 @@
 #ifndef _VCD_CORE_H_
 #define _VCD_CORE_H_
 
+#include <linux/ion.h>
 #include "vcd_api.h"
 #include "vcd_ddl_api.h"
 
@@ -204,7 +205,8 @@
 	struct vcd_sequence_hdr seq_hdr;
 	u8 *seq_hdr_phy_addr;
 	struct vcd_clnt_status status;
-
+	struct ion_client *vcd_ion_client;
+	u32 vcd_enable_ion;
 	struct vcd_clnt_ctxt *next;
 };
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index f8fb0fa..4c477cb 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -523,8 +523,8 @@
 		config->map_dev_base_addr
 		|| dev_ctxt->config.un_map_dev_base_addr !=
 		config->un_map_dev_base_addr) {
-		VCD_MSG_ERROR("Device config mismatch");
-		VCD_MSG_HIGH("VCD will be using config from 1st vcd_init");
+		VCD_MSG_HIGH("Device config mismatch. "
+			"VCD will be using config from 1st vcd_init");
 	}
 
 	*driver_handle = 0;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 54ba7a3..3924088 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -24,18 +24,23 @@
 struct vcd_msm_map_buffer {
 	phys_addr_t phy_addr;
 	struct msm_mapped_buffer *mapped_buffer;
+	struct ion_handle *alloc_handle;
 	u32 in_use;
 };
 static struct vcd_msm_map_buffer msm_mapped_buffer_table[MAP_TABLE_SZ];
 static unsigned int vidc_mmu_subsystem[] = {MSM_SUBSYSTEM_VIDEO};
 
-static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr)
+static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr,
+			 struct vcd_clnt_ctxt *cctxt)
 {
 	u32 memtype, i = 0, flags = 0;
 	struct vcd_msm_map_buffer *map_buffer = NULL;
 	struct msm_mapped_buffer *mapped_buffer = NULL;
+	int rc = 0;
+	ion_phys_addr_t phyaddr = 0;
+	size_t len = 0;
 
-	if (!kernel_vaddr || !phy_addr) {
+	if (!kernel_vaddr || !phy_addr || !cctxt) {
 		pr_err("\n%s: Invalid parameters", __func__);
 		goto bailout;
 	}
@@ -53,17 +58,40 @@
 		goto bailout;
 	}
 	memtype = res_trk_get_mem_type();
-	map_buffer->phy_addr = (phys_addr_t)
-	allocate_contiguous_memory_nomap(sz, memtype, SZ_4K);
-	if (!map_buffer->phy_addr) {
-		pr_err("%s() acm alloc failed", __func__);
-		goto free_map_table;
+	if (!cctxt->vcd_enable_ion) {
+		map_buffer->phy_addr = (phys_addr_t)
+		allocate_contiguous_memory_nomap(sz, memtype, SZ_4K);
+		if (!map_buffer->phy_addr) {
+			pr_err("%s() acm alloc failed", __func__);
+			goto free_map_table;
+		}
+	} else {
+		map_buffer->alloc_handle = ion_alloc(
+			    cctxt->vcd_ion_client, sz, SZ_4K,
+			    (1<<memtype));
+		if (!map_buffer->alloc_handle) {
+			pr_err("%s() ION alloc failed", __func__);
+			goto bailout;
+		}
+		rc = ion_phys(cctxt->vcd_ion_client,
+		map_buffer->alloc_handle, &phyaddr, &len);
+		if (rc) {
+			pr_err("%s() : ION client physical fail\n",
+			 __func__);
+			goto free_acm_alloc;
+		}
+		map_buffer->phy_addr = phyaddr;
+		if (!map_buffer->phy_addr) {
+			pr_err("%s() acm alloc failed", __func__);
+			goto free_map_table;
+		}
+
 	}
 
 	flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
 	map_buffer->mapped_buffer =
-	msm_subsystem_map_buffer((unsigned long)*phy_addr,
-	sz,	flags, vidc_mmu_subsystem,
+	msm_subsystem_map_buffer((unsigned long)map_buffer->phy_addr,
+	sz, flags, vidc_mmu_subsystem,
 	sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
 	if (IS_ERR(map_buffer->mapped_buffer)) {
 		pr_err(" %s() buffer map failed", __func__);
@@ -81,26 +109,32 @@
 free_map_buffers:
 	msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
 free_acm_alloc:
-	free_contiguous_memory_by_paddr(
+	if (!cctxt->vcd_enable_ion) {
+		free_contiguous_memory_by_paddr(
 		(unsigned long)map_buffer->phy_addr);
+	} else {
+		ion_free(cctxt->vcd_ion_client, map_buffer->alloc_handle);
+	}
 free_map_table:
 	map_buffer->in_use = 0;
 bailout:
 	return -ENOMEM;
 }
 
-static int vcd_pmem_free(u8 *kernel_vaddr, u8 *phy_addr)
+static int vcd_pmem_free(u8 *kernel_vaddr, u8 *phy_addr,
+			 struct vcd_clnt_ctxt *cctxt)
 {
 	u32 i = 0;
 	struct vcd_msm_map_buffer *map_buffer = NULL;
-	if (!kernel_vaddr || !phy_addr) {
+
+	if (!kernel_vaddr || !phy_addr || !cctxt) {
 		pr_err("\n%s: Invalid parameters", __func__);
 		goto bailout;
 	}
 	for (i = 0; i  < MAP_TABLE_SZ; i++) {
 		if (msm_mapped_buffer_table[i].in_use &&
 			(msm_mapped_buffer_table[i]
-			 .mapped_buffer->vaddr == kernel_vaddr)) {
+			.mapped_buffer->vaddr == kernel_vaddr)) {
 			map_buffer = &msm_mapped_buffer_table[i];
 			map_buffer->in_use = 0;
 			break;
@@ -111,14 +145,22 @@
 		goto bailout;
 	}
 	msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
-	free_contiguous_memory_by_paddr(
-		(unsigned long)map_buffer->phy_addr);
+	if (cctxt->vcd_enable_ion) {
+		if (map_buffer->alloc_handle) {
+			ion_free(cctxt->vcd_ion_client,
+			map_buffer->alloc_handle);
+		}
+	} else {
+		free_contiguous_memory_by_paddr(
+			(unsigned long)map_buffer->phy_addr);
+	}
 bailout:
 	kernel_vaddr = NULL;
 	phy_addr = NULL;
 	return 0;
 }
 
+
 u8 *vcd_pmem_get_physical(struct video_client_ctx *client_ctx,
 			  unsigned long kernel_vaddr)
 {
@@ -543,7 +585,7 @@
 	buf_size += buf_req->align;
 
 	rc = vcd_pmem_alloc(buf_size, &buf_entry->alloc,
-				&buf_entry->physical);
+				&buf_entry->physical, cctxt);
 
 	if (rc < 0) {
 		VCD_MSG_ERROR("Buffer allocation failed");
@@ -633,7 +675,7 @@
 			buf_entry->virtual, buf_entry->allocated);
 
 	if (buf_entry->allocated) {
-		vcd_pmem_free(buf_entry->alloc, buf_entry->physical);
+		vcd_pmem_free(buf_entry->alloc, buf_entry->physical, cctxt);
 		buf_pool->allocated--;
 	}
 
@@ -660,7 +702,7 @@
 				buf_pool->entries[i].allocated) {
 				vcd_pmem_free(buf_pool->entries[i].alloc,
 						  buf_pool->entries[i].
-						  physical);
+						  physical, cctxt);
 			}
 		}
 
@@ -987,6 +1029,14 @@
 	VCD_MSG_LOW("vcd_init_client_context:");
 	rc = ddl_open(&cctxt->ddl_handle, cctxt->decoding);
 	VCD_FAILED_RETURN(rc, "Failed: ddl_open");
+	cctxt->vcd_enable_ion = res_trk_get_enable_ion();
+	if (cctxt->vcd_enable_ion) {
+		cctxt->vcd_ion_client = res_trk_get_ion_client();
+		if (!cctxt->vcd_ion_client) {
+			VCD_MSG_LOW("vcd_init_ion_get_client_failed:");
+			return -EINVAL;
+		}
+	}
 	cctxt->ddl_hdl_valid = true;
 	cctxt->clnt_state.state = VCD_CLIENT_STATE_OPEN;
 	cctxt->clnt_state.state_table =
@@ -1045,7 +1095,7 @@
 
 	if (cctxt->seq_hdr.sequence_header) {
 		vcd_pmem_free(cctxt->seq_hdr.sequence_header,
-				  cctxt->seq_hdr_phy_addr);
+				  cctxt->seq_hdr_phy_addr, cctxt);
 		cctxt->seq_hdr.sequence_header = NULL;
 	}
 
@@ -1063,7 +1113,7 @@
 	cctxt->signature = 0;
 	cctxt->clnt_state.state = VCD_CLIENT_STATE_NULL;
 	cctxt->clnt_state.state_table = NULL;
-
+	cctxt->vcd_ion_client = NULL;
 	kfree(cctxt);
 }
 
@@ -2684,7 +2734,7 @@
 		VCD_MSG_HIGH("Old seq hdr detected");
 
 		vcd_pmem_free(cctxt->seq_hdr.sequence_header,
-				  cctxt->seq_hdr_phy_addr);
+				  cctxt->seq_hdr_phy_addr, cctxt);
 		cctxt->seq_hdr.sequence_header = NULL;
 	}
 
@@ -2704,7 +2754,7 @@
 	ret = vcd_pmem_alloc(cctxt->seq_hdr.sequence_header_len + align +
 				 VCD_SEQ_HDR_PADDING_BYTES,
 				 &(cctxt->seq_hdr.sequence_header),
-				 &(cctxt->seq_hdr_phy_addr));
+				 &(cctxt->seq_hdr_phy_addr), cctxt);
 
 	if (ret < 0) {
 		VCD_MSG_ERROR("Seq hdr allocation failed");
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index e3fbecb..ec8a176 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -420,6 +420,8 @@
 header-y += msm_audio_wma.h
 header-y += msm_audio_wmapro.h
 header-y += msm_audio_mvs.h
+header-y += msm_audio_qcp.h
+header-y += msm_audio_amrnb.h
 header-y += msm_ipc.h
 header-y += msm_charm.h
 header-y += tzcom.h
diff --git a/include/linux/input.h b/include/linux/input.h
index d9133f2..b1f7161 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -812,6 +812,8 @@
 #define SW_KEYPAD_SLIDE		0x0a  /* set = keypad slide out */
 #define SW_FRONT_PROXIMITY	0x0b  /* set = front proximity sensor active */
 #define SW_ROTATE_LOCK		0x0c  /* set = rotate locked/disabled */
+#define SW_HPHL_OVERCURRENT	0x0d  /* set = over current on left hph */
+#define SW_HPHR_OVERCURRENT	0x0e  /* set = over current on right hph */
 #define SW_MAX			0x0f
 #define SW_CNT			(SW_MAX+1)
 
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 4b7b8b7d1..7de40d4 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -113,13 +113,21 @@
 
 /**
  * struct ion_platform_data - array of platform heaps passed from board file
- * @nr:		number of structures in the array
- * @heaps:	array of platform_heap structions
+ * @nr:    number of structures in the array
+ * @request_region: function to be called when the number of allocations goes
+ *						from 0 -> 1
+ * @release_region: function to be called when the number of allocations goes
+ *						from 1 -> 0
+ * @setup_region:   function to be called upon ion registration
+ * @heaps: array of platform_heap structions
  *
  * Provided by the board file in the form of platform data to a platform device.
  */
 struct ion_platform_data {
 	int nr;
+	void (*request_region)(void *);
+	void (*release_region)(void *);
+	void *(*setup_region)(void);
 	struct ion_platform_heap heaps[];
 };
 
diff --git a/include/linux/mfd/pm8xxx/gpio.h b/include/linux/mfd/pm8xxx/gpio.h
index 0a9c95d..f2e4a21 100644
--- a/include/linux/mfd/pm8xxx/gpio.h
+++ b/include/linux/mfd/pm8xxx/gpio.h
@@ -59,6 +59,16 @@
 #define	PM_GPIO_VIN_L3			5
 #define	PM_GPIO_VIN_L17			6
 
+/* vin_sel: Voltage Input select on PM8058 */
+#define PM8058_GPIO_VIN_VPH		0
+#define PM8058_GPIO_VIN_BB		1
+#define PM8058_GPIO_VIN_S3		2
+#define PM8058_GPIO_VIN_L3		3
+#define PM8058_GPIO_VIN_L7		4
+#define PM8058_GPIO_VIN_L6		5
+#define PM8058_GPIO_VIN_L5		6
+#define PM8058_GPIO_VIN_L2		7
+
 /* out_strength */
 #define	PM_GPIO_STRENGTH_NO		0
 #define	PM_GPIO_STRENGTH_HIGH		1
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index 2374d11..32189b2 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -35,6 +35,44 @@
 	UART_TX3_RX3,
 };
 
+enum pm8xxx_coincell_chg_voltage {
+	PM8XXX_COINCELL_VOLTAGE_3p2V = 1,
+	PM8XXX_COINCELL_VOLTAGE_3p1V,
+	PM8XXX_COINCELL_VOLTAGE_3p0V,
+	PM8XXX_COINCELL_VOLTAGE_2p5V = 16
+};
+
+enum pm8xxx_coincell_chg_resistor {
+	PM8XXX_COINCELL_RESISTOR_2100_OHMS,
+	PM8XXX_COINCELL_RESISTOR_1700_OHMS,
+	PM8XXX_COINCELL_RESISTOR_1200_OHMS,
+	PM8XXX_COINCELL_RESISTOR_800_OHMS
+};
+
+enum pm8xxx_coincell_chg_state {
+	PM8XXX_COINCELL_CHG_DISABLE,
+	PM8XXX_COINCELL_CHG_ENABLE
+};
+
+struct pm8xxx_coincell_chg {
+	enum pm8xxx_coincell_chg_state		state;
+	enum pm8xxx_coincell_chg_voltage	voltage;
+	enum pm8xxx_coincell_chg_resistor	resistor;
+};
+
+enum pm8xxx_smpl_delay {
+	PM8XXX_SMPL_DELAY_0p5,
+	PM8XXX_SMPL_DELAY_1p0,
+	PM8XXX_SMPL_DELAY_1p5,
+	PM8XXX_SMPL_DELAY_2p0,
+};
+
+enum pm8xxx_pon_config {
+	PM8XXX_DISABLE_HARD_RESET = 0,
+	PM8XXX_SHUTDOWN_ON_HARD_RESET,
+	PM8XXX_RESTART_ON_HARD_RESET,
+};
+
 #if defined(CONFIG_MFD_PM8XXX_MISC) || defined(CONFIG_MFD_PM8XXX_MISC_MODULE)
 
 /**
@@ -48,19 +86,116 @@
 
 int pm8xxx_uart_gpio_mux_ctrl(enum pm8xxx_uart_path_sel uart_path_sel);
 
+/**
+ * pm8xxx_coincell_chg_config - Disables or enables the coincell charger, and
+ *				configures its voltage and resistor settings.
+ * @chg_config:			Holds both voltage and resistor values, and a
+ *				switch to change the state of charger.
+ *				If state is to disable the charger then
+ *				both voltage and resistor are disregarded.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config);
+
+/**
+ * pm8xxx_smpl_control - enables/disables SMPL detection
+ * @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
+ *
+ * This function enables or disables the Sudden Momentary Power Loss detection
+ * module.  If SMPL detection is enabled, then when a sufficiently long power
+ * loss event occurs, the PMIC will automatically reset itself.  If SMPL
+ * detection is disabled, then the PMIC will shutdown when power loss occurs.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_control(int enable);
+
+/**
+ * pm8xxx_smpl_set_delay - sets the SMPL detection time delay
+ * @delay: enum value corresponding to delay time
+ *
+ * This function sets the time delay of the SMPL detection module.  If power
+ * is reapplied within this interval, then the PMIC reset automatically.  The
+ * SMPL detection module must be enabled for this delay time to take effect.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay);
+
+/**
+ * pm8xxx_watchdog_reset_control - enables/disables watchdog reset detection
+ * @enable: 0 = shutdown when PS_HOLD goes low, 1 = reset when PS_HOLD goes low
+ *
+ * This function enables or disables the PMIC watchdog reset detection feature.
+ * If watchdog reset detection is enabled, then the PMIC will reset itself
+ * when PS_HOLD goes low.  If it is not enabled, then the PMIC will shutdown
+ * when PS_HOLD goes low.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_watchdog_reset_control(int enable);
+
+/**
+ * pm8xxx_hard_reset_config - Allows different reset configurations
+ *
+ * config = DISABLE_HARD_RESET to disable hard reset
+ *	  = SHUTDOWN_ON_HARD_RESET to turn off the system on hard reset
+ *	  = RESTART_ON_HARD_RESET to restart the system on hard reset
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_hard_reset_config(enum pm8xxx_pon_config config);
+
+/**
+ * pm8xxx_stay_on - enables stay_on feature
+ *
+ * PMIC stay-on feature allows PMIC to ignore MSM PS_HOLD=low
+ * signal so that some special functions like debugging could be
+ * performed.
+ *
+ * This feature should not be used in any product release.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_stay_on(void);
+
 #else
 
 static inline int pm8xxx_reset_pwr_off(int reset)
 {
 	return -ENODEV;
 }
-
 static inline int
 pm8xxx_uart_gpio_mux_ctrl(enum pm8xxx_uart_path_sel uart_path_sel)
 {
 	return -ENODEV;
 }
-
+static inline int
+pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config)
+{
+	return -ENODEV;
+}
+static inline int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay)
+{
+	return -ENODEV;
+}
+static inline int pm8xxx_smpl_control(int enable)
+{
+	return -ENODEV;
+}
+static inline int pm8xxx_watchdog_reset_control(int enable)
+{
+	return -ENODEV;
+}
+static inline int pm8xxx_hard_reset_config(enum pm8xxx_pon_config config)
+{
+	return -ENODEV;
+}
+static inline int pm8xxx_stay_on(void)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
diff --git a/include/linux/pmic8058-nfc.h b/include/linux/mfd/pm8xxx/nfc.h
similarity index 70%
rename from include/linux/pmic8058-nfc.h
rename to include/linux/mfd/pm8xxx/nfc.h
index 5b2d6cf..e58e0a9 100644
--- a/include/linux/pmic8058-nfc.h
+++ b/include/linux/mfd/pm8xxx/nfc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010,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
@@ -10,10 +10,12 @@
  * GNU General Public License for more details.
  *
  */
-#ifndef __PMIC8058_NFC_H__
-#define __PMIC8058_NFC_H__
+#ifndef __PM8XXX_NFC_H__
+#define __PM8XXX_NFC_H__
 
-struct pm8058_nfc_device;
+struct pm8xxx_nfc_device;
+
+#define PM8XXX_NFC_DEV_NAME		"pm8xxx-nfc"
 
 /* masks, flags and status */
 #define	PM_NFC_VDDLDO_MON_LEVEL		0x0003
@@ -46,32 +48,32 @@
 					PM_NFC_VDDLDO_OK_HIGH)
 
 /*
- * pm8058_nfc_request - request a handle to access NFC device
+ * pm8xxx_nfc_request - request a handle to access NFC device
  */
-struct pm8058_nfc_device *pm8058_nfc_request(void);
+struct pm8xxx_nfc_device *pm8xxx_nfc_request(void);
 
 /*
- * pm8058_nfc_config - configure NFC signals
+ * pm8xxx_nfc_config - configure NFC signals
  *
  * @nfcdev: the NFC device
  * @mask: signal mask to configure
  * @flags: control flags
  */
-int pm8058_nfc_config(struct pm8058_nfc_device *nfcdev, u32 mask, u32 flags);
+int pm8xxx_nfc_config(struct pm8xxx_nfc_device *nfcdev, u32 mask, u32 flags);
 
 /*
- * pm8058_nfc_get_status - get NFC status
+ * pm8xxx_nfc_get_status - get NFC status
  *
  * @nfcdev: the NFC device
  * @mask: of status mask to read
  * @status: pointer to the status variable
  */
-int pm8058_nfc_get_status(struct pm8058_nfc_device *nfcdev,
+int pm8xxx_nfc_get_status(struct pm8xxx_nfc_device *nfcdev,
 			  u32 mask, u32 *status);
 
 /*
- * pm8058_nfc_free - free the NFC device
+ * pm8xxx_nfc_free - free the NFC device
  */
-void pm8058_nfc_free(struct pm8058_nfc_device *nfcdev);
+void pm8xxx_nfc_free(struct pm8xxx_nfc_device *nfcdev);
 
-#endif /* __PMIC8058_NFC_H__ */
+#endif /* __PM8XXX_NFC_H__ */
diff --git a/include/linux/mfd/pm8xxx/pm8xxx-adc.h b/include/linux/mfd/pm8xxx/pm8xxx-adc.h
index aa642cc..ba4b29c 100644
--- a/include/linux/mfd/pm8xxx/pm8xxx-adc.h
+++ b/include/linux/mfd/pm8xxx/pm8xxx-adc.h
@@ -221,6 +221,8 @@
  * @offset: Offset with respect to the actual curve
  * @dy: Numerator slope to calculate the gain
  * @dx: Denominator slope to calculate the gain
+ * @adc_vref: A/D word of the voltage reference used for the channel
+ * @adc_gnd: A/D word of the ground reference used for the channel
  *
  * Each ADC device has different offset and gain parameters which are computed
  * to calibrate the device.
@@ -229,6 +231,8 @@
 	int32_t offset;
 	int32_t dy;
 	int32_t dx;
+	int32_t adc_vref;
+	int32_t adc_gnd;
 };
 
 /**
@@ -453,8 +457,8 @@
  * levels once the thresholds are reached
  */
 struct pm8xxx_adc_arb_btm_param {
-	uint32_t	low_thr_temp;
-	uint32_t	high_thr_temp;
+	int32_t		low_thr_temp;
+	int32_t		high_thr_temp;
 	uint64_t	low_thr_voltage;
 	uint64_t	high_thr_voltage;
 	int32_t		interval;
@@ -462,8 +466,9 @@
 	void		(*btm_cool_fn) (bool);
 };
 
-int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *);
-
+int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *,
+			const struct pm8xxx_adc_properties *adc_prop,
+			const struct pm8xxx_adc_chan_properties *chan_prop);
 /**
  * struct pm8xxx_adc_platform_data - PM8XXX ADC platform data
  * @adc_prop: ADC specific parameters, voltage and channel setup
diff --git a/include/linux/mfd/pm8xxx/tm.h b/include/linux/mfd/pm8xxx/tm.h
index 01edb97..5eeefd9 100644
--- a/include/linux/mfd/pm8xxx/tm.h
+++ b/include/linux/mfd/pm8xxx/tm.h
@@ -24,6 +24,7 @@
 
 enum pm8xxx_tm_adc_type {
 	PM8XXX_TM_ADC_NONE,	/* Estimates temp based on overload level. */
+	PM8XXX_TM_ADC_PM8058_ADC,
 	PM8XXX_TM_ADC_PM8921_ADC,
 };
 
diff --git a/include/linux/mfd/pm8xxx/upl.h b/include/linux/mfd/pm8xxx/upl.h
new file mode 100644
index 0000000..b0e94a9
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/upl.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2010,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 __PM8XXX_UPL_H__
+#define __PM8XXX_UPL_H__
+
+struct pm8xxx_upl_device;
+
+#define PM8XXX_UPL_DEV_NAME		"pm8xxx-upl"
+
+/* control masks and flags */
+#define PM8XXX_UPL_MOD_ENABLE_MASK	(0x10)
+#define PM8XXX_UPL_MOD_ENABLE		(0x10)
+#define PM8XXX_UPL_MOD_DISABLE		(0x00)
+
+#define PM8XXX_UPL_OUT_DTEST_MASK	(0xE0)
+#define PM8XXX_UPL_OUT_GPIO_ONLY	(0x00)
+#define PM8XXX_UPL_OUT_DTEST_1		(0x80)
+#define PM8XXX_UPL_OUT_DTEST_2		(0xA0)
+#define PM8XXX_UPL_OUT_DTEST_3		(0xC0)
+#define PM8XXX_UPL_OUT_DTEST_4		(0xE0)
+
+#define PM8XXX_UPL_IN_A_MASK		(0x01)
+#define PM8XXX_UPL_IN_A_GPIO		(0x00)
+#define PM8XXX_UPL_IN_A_DTEST		(0x01)
+#define PM8XXX_UPL_IN_B_MASK		(0x02)
+#define PM8XXX_UPL_IN_B_GPIO		(0x00)
+#define PM8XXX_UPL_IN_B_DTEST		(0x02)
+#define PM8XXX_UPL_IN_C_MASK		(0x04)
+#define PM8XXX_UPL_IN_C_GPIO		(0x00)
+#define PM8XXX_UPL_IN_C_DTEST		(0x04)
+#define PM8XXX_UPL_IN_D_MASK		(0x08)
+#define PM8XXX_UPL_IN_D_GPIO		(0x00)
+#define PM8XXX_UPL_IN_D_DTEST		(0x08)
+
+/*
+ * pm8xxx_upl_request - request a handle to access UPL device
+ */
+struct pm8xxx_upl_device *pm8xxx_upl_request(void);
+
+int pm8xxx_upl_read_truthtable(struct pm8xxx_upl_device *upldev,
+				u16 *truthtable);
+
+int pm8xxx_upl_write_truthtable(struct pm8xxx_upl_device *upldev,
+				u16 truthtable);
+
+/*
+ * pm8xxx_upl_config - configure UPL I/O settings and UPL enable/disable
+ *
+ * @upldev: the UPL device
+ * @mask: setting mask to configure
+ * @flags: setting flags
+ */
+int pm8xxx_upl_config(struct pm8xxx_upl_device *upldev, u32 mask, u32 flags);
+
+#endif /* __PM8XXX_UPL_H__ */
diff --git a/include/linux/mfd/pm8xxx/vibrator.h b/include/linux/mfd/pm8xxx/vibrator.h
index 3a269a0..cfea1c9 100644
--- a/include/linux/mfd/pm8xxx/vibrator.h
+++ b/include/linux/mfd/pm8xxx/vibrator.h
@@ -15,10 +15,25 @@
 
 #define PM8XXX_VIBRATOR_DEV_NAME "pm8xxx-vib"
 
+enum pm8xxx_vib_en_mode {
+	PM8XXX_VIB_MANUAL,
+	PM8XXX_VIB_DTEST1,
+	PM8XXX_VIB_DTEST2,
+	PM8XXX_VIB_DTEST3
+};
+
+struct pm8xxx_vib_config {
+	u16			drive_mV;
+	u8			active_low;
+	enum pm8xxx_vib_en_mode	enable_mode;
+};
+
 struct pm8xxx_vibrator_platform_data {
 	int initial_vibrate_ms;
 	int max_timeout_ms;
 	int level_mV;
 };
 
+int pm8xxx_vibrator_config(struct pm8xxx_vib_config *vib_config);
+
 #endif /* __PMIC8XXX_VIBRATOR_H__ */
diff --git a/include/linux/mfd/pmic8058.h b/include/linux/mfd/pmic8058.h
index 4d9f257..cf753b5d 100644
--- a/include/linux/mfd/pmic8058.h
+++ b/include/linux/mfd/pmic8058.h
@@ -15,12 +15,39 @@
  *
  */
 
+#ifndef __MFD_PMIC8058_H__
+#define __MFD_PMIC8058_H__
+
 #include <linux/irq.h>
 #include <linux/mfd/core.h>
+#include <linux/mfd/pm8xxx/irq.h>
+#include <linux/mfd/pm8xxx/gpio.h>
+#include <linux/mfd/pm8xxx/mpp.h>
+#include <linux/mfd/pm8xxx/rtc.h>
+#include <linux/input/pmic8xxx-pwrkey.h>
+#include <linux/input/pmic8xxx-keypad.h>
+#include <linux/mfd/pm8xxx/vibrator.h>
+#include <linux/mfd/pm8xxx/nfc.h>
+#include <linux/mfd/pm8xxx/upl.h>
+#include <linux/mfd/pm8xxx/misc.h>
+#include <linux/mfd/pm8xxx/batt-alarm.h>
+#include <linux/leds-pmic8058.h>
+#include <linux/pmic8058-othc.h>
+#include <linux/mfd/pm8xxx/tm.h>
+#include <linux/pmic8058-xoadc.h>
+#include <linux/regulator/pmic8058-regulator.h>
+#include <linux/regulator/pm8058-xo.h>
+#include <linux/pwm.h>
+#include <linux/pmic8058-pwm.h>
 
 #define PM8058_GPIOS		40
 #define PM8058_MPPS		12
 
+#define PM8058_GPIO_BLOCK_START	24
+#define PM8058_MPP_BLOCK_START	16
+
+#define PM8058_NR_IRQS		256
+
 #define PM8058_IRQ_BLOCK_BIT(block, bit) ((block) * 8 + (bit))
 
 /* MPPs and GPIOs [0,N) */
@@ -29,146 +56,58 @@
 #define PM8058_GPIO_IRQ(base, gpio)	((base) + \
 					PM8058_IRQ_BLOCK_BIT(24, (gpio)))
 
-#define PM8058_KEYPAD_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(9, 2))
-#define PM8058_KEYSTUCK_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(9, 3))
+/* PM8058 IRQ's */
+#define PM8058_VCP_IRQ			PM8058_IRQ_BLOCK_BIT(1, 0)
+#define PM8058_CHGILIM_IRQ		PM8058_IRQ_BLOCK_BIT(1, 3)
+#define PM8058_VBATDET_LOW_IRQ		PM8058_IRQ_BLOCK_BIT(1, 4)
+#define PM8058_BATT_REPLACE_IRQ		PM8058_IRQ_BLOCK_BIT(1, 5)
+#define PM8058_CHGINVAL_IRQ		PM8058_IRQ_BLOCK_BIT(1, 6)
+#define PM8058_CHGVAL_IRQ		PM8058_IRQ_BLOCK_BIT(1, 7)
+#define PM8058_CHG_END_IRQ		PM8058_IRQ_BLOCK_BIT(2, 0)
+#define PM8058_FASTCHG_IRQ		PM8058_IRQ_BLOCK_BIT(2, 1)
+#define PM8058_CHGSTATE_IRQ		PM8058_IRQ_BLOCK_BIT(2, 3)
+#define PM8058_AUTO_CHGFAIL_IRQ		PM8058_IRQ_BLOCK_BIT(2, 4)
+#define PM8058_AUTO_CHGDONE_IRQ		PM8058_IRQ_BLOCK_BIT(2, 5)
+#define PM8058_ATCFAIL_IRQ		PM8058_IRQ_BLOCK_BIT(2, 6)
+#define PM8058_ATC_DONE_IRQ		PM8058_IRQ_BLOCK_BIT(2, 7)
+#define PM8058_OVP_OK_IRQ		PM8058_IRQ_BLOCK_BIT(3, 0)
+#define PM8058_COARSE_DET_OVP_IRQ	PM8058_IRQ_BLOCK_BIT(3, 1)
+#define PM8058_VCPMAJOR_IRQ		PM8058_IRQ_BLOCK_BIT(3, 2)
+#define PM8058_CHG_GONE_IRQ		PM8058_IRQ_BLOCK_BIT(3, 3)
+#define PM8058_CHGTLIMIT_IRQ		PM8058_IRQ_BLOCK_BIT(3, 4)
+#define PM8058_CHGHOT_IRQ		PM8058_IRQ_BLOCK_BIT(3, 5)
+#define PM8058_BATTTEMP_IRQ		PM8058_IRQ_BLOCK_BIT(3, 6)
+#define PM8058_BATTCONNECT_IRQ		PM8058_IRQ_BLOCK_BIT(3, 7)
+#define PM8058_BATFET_IRQ		PM8058_IRQ_BLOCK_BIT(5, 4)
+#define PM8058_VBATDET_IRQ		PM8058_IRQ_BLOCK_BIT(5, 5)
+#define PM8058_VBAT_IRQ			PM8058_IRQ_BLOCK_BIT(5, 6)
 
-#define PM8058_VCP_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(1, 0))
-#define PM8058_CHGILIM_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(1, 3))
-#define PM8058_VBATDET_LOW_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(1, 4))
-#define PM8058_BATT_REPLACE_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(1, 5))
-#define PM8058_CHGINVAL_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(1, 6))
-#define PM8058_CHGVAL_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(1, 7))
-#define PM8058_CHG_END_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(2, 0))
-#define PM8058_FASTCHG_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(2, 1))
-#define PM8058_CHGSTATE_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(2, 3))
-#define PM8058_AUTO_CHGFAIL_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(2, 4))
-#define PM8058_AUTO_CHGDONE_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(2, 5))
-#define PM8058_ATCFAIL_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(2, 6))
-#define PM8058_ATC_DONE_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(2, 7))
-#define PM8058_OVP_OK_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(3, 0))
-#define PM8058_COARSE_DET_OVP_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(3, 1))
-#define PM8058_VCPMAJOR_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(3, 2))
-#define PM8058_CHG_GONE_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(3, 3))
-#define PM8058_CHGTLIMIT_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(3, 4))
-#define PM8058_CHGHOT_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(3, 5))
-#define PM8058_BATTTEMP_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(3, 6))
-#define PM8058_BATTCONNECT_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(3, 7))
-#define PM8058_BATFET_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(5, 4))
-#define PM8058_VBATDET_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(5, 5))
-#define PM8058_VBAT_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(5, 6))
-
-#define PM8058_CBLPWR_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(4, 3))
-
-#define PM8058_PWRKEY_REL_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(6, 2))
-#define PM8058_PWRKEY_PRESS_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(6, 3))
-#define PM8058_SW_0_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(7, 1))
-#define PM8058_IR_0_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(7, 0))
-#define PM8058_SW_1_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(7, 3))
-#define PM8058_IR_1_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(7, 2))
-#define PM8058_SW_2_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(7, 5))
-#define PM8058_IR_2_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(7, 4))
-#define PM8058_RTC_IRQ(base) 		((base) + PM8058_IRQ_BLOCK_BIT(6, 5))
-#define PM8058_RTC_ALARM_IRQ(base) 	((base) + PM8058_IRQ_BLOCK_BIT(4, 7))
-#define PM8058_ADC_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(9, 4))
-#define PM8058_TEMP_ALARM_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(6, 7))
-#define PM8058_OSCHALT_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(4, 6))
-#define PM8058_BATT_ALARM_IRQ(base)	((base) + PM8058_IRQ_BLOCK_BIT(5, 6))
-#define PM8058_RESOUT_IRQ(base)		((base) + PM8058_IRQ_BLOCK_BIT(6, 4))
-
-struct pm8058_chip;
-
-struct pm8058_platform_data {
-	/* This table is only needed for misc interrupts. */
-	int		irq_base;
-	int		irq;
-	int 		(*init)(struct pm8058_chip *pm_chip);
-
-	int		num_subdevs;
-	struct mfd_cell *sub_devices;
-	int		irq_trigger_flags;
-	struct mfd_cell *charger_sub_device;
-};
-
-struct pm8058_gpio_platform_data {
-	int	gpio_base;
-	int	irq_base;
-	int	(*init)(void);
-};
-
-/* GPIO parameters */
-/* direction */
-#define	PM_GPIO_DIR_OUT			0x01
-#define	PM_GPIO_DIR_IN			0x02
-#define	PM_GPIO_DIR_BOTH		(PM_GPIO_DIR_OUT | PM_GPIO_DIR_IN)
-
-/* output_buffer */
-#define	PM_GPIO_OUT_BUF_OPEN_DRAIN	1
-#define	PM_GPIO_OUT_BUF_CMOS		0
-
-/* pull */
-#define	PM_GPIO_PULL_UP_30		0
-#define	PM_GPIO_PULL_UP_1P5		1
-#define	PM_GPIO_PULL_UP_31P5		2
-#define	PM_GPIO_PULL_UP_1P5_30		3
-#define	PM_GPIO_PULL_DN			4
-#define	PM_GPIO_PULL_NO			5
-
-/* vin_sel: Voltage Input Select */
-#define	PM_GPIO_VIN_VPH			0
-#define	PM_GPIO_VIN_BB			1
-#define	PM_GPIO_VIN_S3			2
-#define	PM_GPIO_VIN_L3			3
-#define	PM_GPIO_VIN_L7			4
-#define	PM_GPIO_VIN_L6			5
-#define	PM_GPIO_VIN_L5			6
-#define	PM_GPIO_VIN_L2			7
-
-/* out_strength */
-#define	PM_GPIO_STRENGTH_NO		0
-#define	PM_GPIO_STRENGTH_HIGH		1
-#define	PM_GPIO_STRENGTH_MED		2
-#define	PM_GPIO_STRENGTH_LOW		3
-
-/* function */
-#define	PM_GPIO_FUNC_NORMAL		0
-#define	PM_GPIO_FUNC_PAIRED		1
-#define	PM_GPIO_FUNC_1			2
-#define	PM_GPIO_FUNC_2			3
-#define	PM_GPIO_DTEST1			4
-#define	PM_GPIO_DTEST2			5
-#define	PM_GPIO_DTEST3			6
-#define	PM_GPIO_DTEST4			7
-
-struct pm8058_gpio {
-	int		direction;
-	int		output_buffer;
-	int		output_value;
-	int		pull;
-	int		vin_sel;	/* 0..7 */
-	int		out_strength;
-	int		function;
-	int		inv_int_pol;	/* invert interrupt polarity */
-	int		disable_pin;	/* disable pin and tri-state its pad */
-};
+#define PM8058_RTC_IRQ			PM8058_IRQ_BLOCK_BIT(6, 5)
+#define PM8058_RTC_ALARM_IRQ		PM8058_IRQ_BLOCK_BIT(4, 7)
+#define PM8058_PWRKEY_REL_IRQ		PM8058_IRQ_BLOCK_BIT(6, 2)
+#define PM8058_PWRKEY_PRESS_IRQ		PM8058_IRQ_BLOCK_BIT(6, 3)
+#define PM8058_KEYPAD_IRQ		PM8058_IRQ_BLOCK_BIT(9, 2)
+#define PM8058_KEYSTUCK_IRQ		PM8058_IRQ_BLOCK_BIT(9, 3)
+#define PM8058_BATT_ALARM_IRQ		PM8058_IRQ_BLOCK_BIT(5, 6)
+#define PM8058_SW_0_IRQ			PM8058_IRQ_BLOCK_BIT(7, 1)
+#define PM8058_IR_0_IRQ			PM8058_IRQ_BLOCK_BIT(7, 0)
+#define PM8058_SW_1_IRQ			PM8058_IRQ_BLOCK_BIT(7, 3)
+#define PM8058_IR_1_IRQ			PM8058_IRQ_BLOCK_BIT(7, 2)
+#define PM8058_SW_2_IRQ			PM8058_IRQ_BLOCK_BIT(7, 5)
+#define PM8058_IR_2_IRQ			PM8058_IRQ_BLOCK_BIT(7, 4)
+#define PM8058_TEMPSTAT_IRQ		PM8058_IRQ_BLOCK_BIT(6, 7)
+#define PM8058_OVERTEMP_IRQ		PM8058_IRQ_BLOCK_BIT(4, 2)
+#define PM8058_ADC_IRQ			PM8058_IRQ_BLOCK_BIT(9, 4)
+#define PM8058_OSCHALT_IRQ		PM8058_IRQ_BLOCK_BIT(4, 6)
+#define PM8058_CBLPWR_IRQ		PM8058_IRQ_BLOCK_BIT(4, 3)
+#define PM8058_RESOUT_IRQ		PM8058_IRQ_BLOCK_BIT(6, 4)
 
 struct pmic8058_charger_data {
 	unsigned int max_source_current;
 	int charger_type;
+	bool charger_data_valid;
 };
 
-/* chip revision */
-#define PM_8058_REV_1p0			0xE1
-#define PM_8058_REV_2p0			0xE2
-#define PM_8058_REV_2p1			0xE3
-
-/* misc: control mask and flag */
-#define	PM8058_UART_MUX_MASK		0x60
-
-#define PM8058_UART_MUX_NO		0x0
-#define PM8058_UART_MUX_1		0x20
-#define PM8058_UART_MUX_2		0x40
-#define PM8058_UART_MUX_3		0x60
-
 enum pon_config{
 	DISABLE_HARD_RESET = 0,
 	SHUTDOWN_ON_HARD_RESET,
@@ -183,19 +122,27 @@
 	PM8058_SMPL_DELAY_2p0,
 };
 
-/* Note -do not call pm8058_read and pm8058_write in an atomic context */
-int pm8058_read(struct pm8058_chip *pm_chip, u16 addr, u8 *values,
-		unsigned int len);
-int pm8058_write(struct pm8058_chip *pm_chip, u16 addr, u8 *values,
-		 unsigned int len);
-
-int pm8058_gpio_config(int gpio, struct pm8058_gpio *param);
-
-int pm8058_rev(struct pm8058_chip *pm_chip);
-
-int pm8058_irq_get_rt_status(struct pm8058_chip *pm_chip, int irq);
-
-int pm8058_misc_control(struct pm8058_chip *pm_chip, int mask, int flag);
+struct pm8058_platform_data {
+	struct pm8xxx_mpp_platform_data		*mpp_pdata;
+	struct pm8xxx_keypad_platform_data      *keypad_pdata;
+	struct pm8xxx_gpio_platform_data	*gpio_pdata;
+	struct pm8xxx_irq_platform_data		*irq_pdata;
+	struct pm8xxx_rtc_platform_data		*rtc_pdata;
+	struct pm8xxx_pwrkey_platform_data	*pwrkey_pdata;
+	struct pm8xxx_vibrator_platform_data	*vibrator_pdata;
+	struct pm8xxx_misc_platform_data	*misc_pdata;
+	struct pmic8058_leds_platform_data	*leds_pdata;
+	struct pmic8058_othc_config_pdata	*othc0_pdata;
+	struct pmic8058_othc_config_pdata	*othc1_pdata;
+	struct pmic8058_othc_config_pdata	*othc2_pdata;
+	struct xoadc_platform_data		*xoadc_pdata;
+	struct pm8058_pwm_pdata			*pwm_pdata;
+	struct pm8058_vreg_pdata		*regulator_pdatas;
+	int					num_regulators;
+	struct pm8058_xo_pdata			*xo_buffer_pdata;
+	int					num_xo_buffers;
+	struct pmic8058_charger_data		*charger_pdata;
+};
 
 #ifdef CONFIG_PMIC8058
 int pm8058_reset_pwr_off(int reset);
@@ -256,3 +203,5 @@
  * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
  */
 int pm8058_stay_on(void);
+
+#endif  /* __MFD_PMIC8058_H__ */
diff --git a/include/linux/mfd/wcd9310/pdata.h b/include/linux/mfd/wcd9310/pdata.h
index 9ca6a8c..af801f0 100644
--- a/include/linux/mfd/wcd9310/pdata.h
+++ b/include/linux/mfd/wcd9310/pdata.h
@@ -27,6 +27,30 @@
 
 #define MAX_AMIC_CHANNEL 7
 
+#define TABLA_OCP_300_MA 0x0
+#define TABLA_OCP_350_MA 0x2
+#define TABLA_OCP_365_MA 0x3
+#define TABLA_OCP_150_MA 0x4
+#define TABLA_OCP_190_MA 0x6
+#define TABLA_OCP_220_MA 0x7
+
+#define TABLA_DCYCLE_255  0x0
+#define TABLA_DCYCLE_511  0x1
+#define TABLA_DCYCLE_767  0x2
+#define TABLA_DCYCLE_1023 0x3
+#define TABLA_DCYCLE_1279 0x4
+#define TABLA_DCYCLE_1535 0x5
+#define TABLA_DCYCLE_1791 0x6
+#define TABLA_DCYCLE_2047 0x7
+#define TABLA_DCYCLE_2303 0x8
+#define TABLA_DCYCLE_2559 0x9
+#define TABLA_DCYCLE_2815 0xA
+#define TABLA_DCYCLE_3071 0xB
+#define TABLA_DCYCLE_3327 0xC
+#define TABLA_DCYCLE_3583 0xD
+#define TABLA_DCYCLE_3839 0xE
+#define TABLA_DCYCLE_4095 0xF
+
 struct tabla_amic {
 	/*legacy mode, txfe_enable and txfe_buff take 7 input
 	 * each bit represent the channel / TXFE number
@@ -62,6 +86,14 @@
 	u8 bias4_cfilt_sel;
 };
 
+struct tabla_ocp_setting {
+	unsigned int	use_pdata:1; /* 0 - use sys default as recommended */
+	unsigned int	num_attempts:4; /* up to 15 attempts */
+	unsigned int	run_time:4; /* in duty cycle */
+	unsigned int	wait_time:4; /* in duty cycle */
+	unsigned int	hph_ocp_limit:3; /* Headphone OCP current limit */
+};
+
 struct tabla_pdata {
 	int irq;
 	int irq_base;
@@ -70,6 +102,7 @@
 	struct tabla_amic amic_settings;
 	struct slim_device slimbus_slave_device;
 	struct tabla_micbias_setting micbias;
+	struct tabla_ocp_setting ocp;
 };
 
 #endif
diff --git a/include/linux/msm_adc.h b/include/linux/msm_adc.h
index 9818cf0..51371a6 100644
--- a/include/linux/msm_adc.h
+++ b/include/linux/msm_adc.h
@@ -343,29 +343,25 @@
 int32_t adc_channel_close(void *h);
 int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt);
 int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result);
-int32_t adc_calib_request(void *h, struct completion *calib_complete_evt);
 #else
-int32_t adc_channel_open(uint32_t channel, void **h)
+static int32_t adc_channel_open(uint32_t channel, void **h)
 {
 	pr_err("%s.not supported.\n", __func__);
 	return -ENODEV;
 }
-int32_t adc_channel_close(void *h)
+static int32_t adc_channel_close(void *h)
 {
 	pr_err("%s.not supported.\n", __func__);
 	return -ENODEV;
 }
-int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt)
+static int32_t
+adc_channel_request_conv(void *h, struct completion *conv_complete_evt)
 {
 	pr_err("%s.not supported.\n", __func__);
 	return -ENODEV;
 }
-int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result)
-{
-	pr_err("%s.not supported.\n", __func__);
-	return -ENODEV;
-}
-int32_t adc_calib_request(void *h, struct completion *calib_complete_evt)
+static int32_t
+adc_channel_read_result(void *h, struct adc_chan_result *chan_result)
 {
 	pr_err("%s.not supported.\n", __func__);
 	return -ENODEV;
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 84e8564..9db6bc6 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -111,6 +111,7 @@
 struct kgsl_pwrlevel {
 	unsigned int gpu_freq;
 	unsigned int bus_freq;
+	unsigned int io_fraction;
 };
 
 struct kgsl_version {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index d909c8b..5c67471 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -106,6 +106,14 @@
 	FB_IMG,
 };
 
+enum {
+	HSIC_HUE = 0,
+	HSIC_SAT,
+	HSIC_INT,
+	HSIC_CON,
+	NUM_HSIC_PARAM,
+};
+
 /* mdp_blit_req flag values */
 #define MDP_ROT_NOP 0
 #define MDP_FLIP_LR 0x1
@@ -131,6 +139,8 @@
 #define MDP_DEINTERLACE_ODD		0x00400000
 #define MDP_OV_PLAY_NOWAIT		0x00200000
 #define MDP_SOURCE_ROTATED_90		0x00100000
+#define MDP_MEMORY_ID_TYPE_FB		0x00001000
+#define MDP_DPP_HSIC			0x00080000
 
 #define MDP_TRANSP_NOP 0xffffffff
 #define MDP_ALPHA_NOP 0xff
@@ -249,6 +259,7 @@
 	 *  smoothed picture.
 	 */
 	int8_t sharp_strength;
+	int8_t hsic_params[NUM_HSIC_PARAM];
 };
 
 struct mdp_overlay {
diff --git a/include/linux/pmic8058-upl.h b/include/linux/pmic8058-upl.h
deleted file mode 100644
index a8979f4..0000000
--- a/include/linux/pmic8058-upl.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (c) 2010, 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 __PMIC8058_UPL_H__
-#define __PMIC8058_UPL_H__
-
-struct pm8058_upl_device;
-
-/* control masks and flags */
-#define PM8058_UPL_MOD_ENABLE_MASK	(0x10)
-#define PM8058_UPL_MOD_ENABLE		(0x10)
-#define PM8058_UPL_MOD_DISABLE		(0x00)
-
-#define PM8058_UPL_OUT_DTEST_MASK	(0xE0)
-#define PM8058_UPL_OUT_GPIO_ONLY	(0x00)
-#define PM8058_UPL_OUT_DTEST_1		(0x80)
-#define PM8058_UPL_OUT_DTEST_2		(0xA0)
-#define PM8058_UPL_OUT_DTEST_3		(0xC0)
-#define PM8058_UPL_OUT_DTEST_4		(0xE0)
-
-#define PM8058_UPL_IN_A_MASK		(0x01)
-#define PM8058_UPL_IN_A_GPIO		(0x00)
-#define PM8058_UPL_IN_A_DTEST		(0x01)
-#define PM8058_UPL_IN_B_MASK		(0x02)
-#define PM8058_UPL_IN_B_GPIO		(0x00)
-#define PM8058_UPL_IN_B_DTEST		(0x02)
-#define PM8058_UPL_IN_C_MASK		(0x04)
-#define PM8058_UPL_IN_C_GPIO		(0x00)
-#define PM8058_UPL_IN_C_DTEST		(0x04)
-#define PM8058_UPL_IN_D_MASK		(0x08)
-#define PM8058_UPL_IN_D_GPIO		(0x00)
-#define PM8058_UPL_IN_D_DTEST		(0x08)
-
-/*
- * pm8058_upl_request - request a handle to access UPL device
- */
-struct pm8058_upl_device *pm8058_upl_request(void);
-
-int pm8058_upl_read_truthtable(struct pm8058_upl_device *upldev,
-				u16 *truthtable);
-
-int pm8058_upl_write_truthtable(struct pm8058_upl_device *upldev,
-				u16 truthtable);
-
-/*
- * pm8058_upl_config - configure UPL I/O settings and UPL enable/disable
- *
- * @upldev: the UPL device
- * @mask: setting mask to configure
- * @flags: setting flags
- */
-int pm8058_upl_config(struct pm8058_upl_device *upldev, u32 mask, u32 flags);
-
-#endif /* __PMIC8058_UPL_H__ */
diff --git a/include/linux/pmic8058-xoadc.h b/include/linux/pmic8058-xoadc.h
index 8a5820f..f72ad66 100644
--- a/include/linux/pmic8058-xoadc.h
+++ b/include/linux/pmic8058-xoadc.h
@@ -65,20 +65,57 @@
 	u32 xoadc_wakeup;
 };
 
-int32_t pm8058_xoadc_read_adc_code(uint32_t , int32_t *data);
+#ifdef CONFIG_PMIC8058_XOADC
+int32_t pm8058_xoadc_read_adc_code(uint32_t adc_instance, int32_t *data);
 
-int32_t pm8058_xoadc_select_chan_and_start_conv(uint32_t,
-						struct adc_conv_slot *);
+int32_t pm8058_xoadc_select_chan_and_start_conv(uint32_t adc_instance,
+						struct adc_conv_slot *slot);
 
-void pm8058_xoadc_slot_request(uint32_t, struct adc_conv_slot **slot);
+void pm8058_xoadc_slot_request(uint32_t adc_instance,
+		struct adc_conv_slot **slot);
 
-void pm8058_xoadc_restore_slot(uint32_t, struct adc_conv_slot *slot);
+void pm8058_xoadc_restore_slot(uint32_t adc_instance,
+		struct adc_conv_slot *slot);
 
-struct adc_properties *pm8058_xoadc_get_properties(uint32_t);
+struct adc_properties *pm8058_xoadc_get_properties(uint32_t dev_instance);
 
-int32_t pm8058_xoadc_calibrate(uint32_t, struct adc_conv_slot *, int *);
+int32_t pm8058_xoadc_calibrate(uint32_t dev_instance,
+		struct adc_conv_slot *slot, int * calib_status);
 
 int32_t pm8058_xoadc_registered(void);
 
 int32_t pm8058_xoadc_calib_device(uint32_t adc_instance);
+
+#else
+
+static inline int32_t pm8058_xoadc_read_adc_code(uint32_t adc_instance,
+		int32_t *data)
+{ return -ENXIO; }
+
+static inline int32_t pm8058_xoadc_select_chan_and_start_conv(
+		uint32_t adc_instance, struct adc_conv_slot *slot)
+{ return -ENXIO; }
+
+static inline void pm8058_xoadc_slot_request(uint32_t adc_instance,
+		struct adc_conv_slot **slot)
+{ return; }
+
+static inline void pm8058_xoadc_restore_slot(uint32_t adc_instance,
+		struct adc_conv_slot *slot)
+{ return; }
+
+static inline struct adc_properties *pm8058_xoadc_get_properties(
+		uint32_t dev_instance)
+{ return NULL; }
+
+static inline int32_t pm8058_xoadc_calibrate(uint32_t dev_instance,
+		struct adc_conv_slot *slot, int *calib_status)
+{ return -ENXIO; }
+
+static inline int32_t pm8058_xoadc_registered(void)
+{ return -ENXIO; }
+
+static inline int32_t pm8058_xoadc_calib_device(uint32_t adc_instance)
+{ return -ENXIO; }
+#endif
 #endif
diff --git a/include/linux/regulator/pm8058-xo.h b/include/linux/regulator/pm8058-xo.h
index 9b363c4..a2b8aeb 100644
--- a/include/linux/regulator/pm8058-xo.h
+++ b/include/linux/regulator/pm8058-xo.h
@@ -25,6 +25,7 @@
 
 struct pm8058_xo_pdata {
 	struct regulator_init_data	init_data;
+	int id;
 };
 
 #endif
diff --git a/include/linux/regulator/pmic8058-regulator.h b/include/linux/regulator/pmic8058-regulator.h
index 83d4412..3eeaa61 100644
--- a/include/linux/regulator/pmic8058-regulator.h
+++ b/include/linux/regulator/pmic8058-regulator.h
@@ -80,6 +80,7 @@
 
 struct pm8058_vreg_pdata {
 	struct regulator_init_data	init_data;
+	int				id;
 	unsigned			pull_down_enable;
 	unsigned			pin_ctrl;
 	enum pm8058_vreg_pin_fn		pin_fn;
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index 26ca79a..2b5adb3 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -83,6 +83,12 @@
 #define SLIM_MSG_MC_NEXT_REMOVE_CHANNEL          0x58
 #define SLIM_MSG_MC_RECONFIGURE_NOW              0x5F
 
+/*
+ * Clock pause flag to indicate that the reconfig message
+ * corresponds to clock pause sequence
+ */
+#define SLIM_MSG_CLK_PAUSE_SEQ_FLG		(1U << 8)
+
 /* Value management messages */
 #define SLIM_MSG_MC_REQUEST_VALUE                0x60
 #define SLIM_MSG_MC_REQUEST_CHANGE_VALUE         0x61
@@ -150,7 +156,9 @@
  * For the header information, refer to Table 34-36.
  * @rl: Header field. remaining length.
  * @mt: Header field. Message type.
- * @mc: Header field. Message code for type mt.
+ * @mc: Header field. LSB is message code for type mt. Framework will set MSB to
+ *	SLIM_MSG_CLK_PAUSE_SEQ_FLG in case "mc" in the reconfiguration sequence
+ *	is for pausing the clock.
  * @dt: Header field. Destination type.
  * @ec: Element size. Used for elemental access APIs.
  * @len: Length of payload. (excludes ec)
@@ -166,7 +174,7 @@
 struct slim_msg_txn {
 	u8			rl;
 	u8			mt;
-	u8			mc;
+	u16			mc;
 	u8			dt;
 	u16			ec;
 	u8			len;
@@ -670,7 +678,7 @@
  */
 extern int slim_xfer_msg(struct slim_controller *ctrl,
 			struct slim_device *sbdev, struct slim_ele_access *msg,
-			u8 mc, u8 *rbuf, const u8 *wbuf, u8 len);
+			u16 mc, u8 *rbuf, const u8 *wbuf, u8 len);
 /* end of message apis */
 
 /* Port management for manager device APIs */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 62d58de..4c01f5b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -72,6 +72,9 @@
 #define IDEV_CHG_MIN	500
 #define IUNIT		100
 
+#define IDEV_ACA_CHG_MAX	1500
+#define IDEV_ACA_CHG_LIMIT	500
+
 /**
  * Different states involved in USB charger detection.
  *
@@ -141,6 +144,7 @@
  * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
  *              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.
  */
 struct msm_otg_platform_data {
 	int *phy_init_seq;
@@ -151,8 +155,9 @@
 	enum usb_mode_type default_mode;
 	enum msm_usb_phy_type phy_type;
 	void (*setup_gpio)(enum usb_otg_state state);
-	char *pclk_src_name;
+	const char *pclk_src_name;
 	int pmic_id_irq;
+	bool mhl_enable;
 };
 
 /**
@@ -183,6 +188,7 @@
  *             connected. Useful only when ACA_A charger is
  *             connected.
  * @mA_port: The amount of current drawn by the attached B-device.
+ * @id_timer: The timer used for polling ID line to detect ACA states.
  */
 struct msm_otg {
 	struct otg_transceiver otg;
@@ -212,6 +218,7 @@
 	struct wake_lock wlock;
 	struct notifier_block usbdev_nb;
 	unsigned mA_port;
+	struct timer_list id_timer;
 	unsigned long caps;
 	/*
 	 * Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 79b0415..9cb8356 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -54,6 +54,7 @@
 
 /* OTG definitions */
 #define OTGSC_INTSTS_MASK	(0x7f << 16)
+#define OTGSC_IDPU		(1 << 5)
 #define OTGSC_ID		(1 << 8)
 #define OTGSC_BSV		(1 << 11)
 #define OTGSC_IDIS		(1 << 16)
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index fa19613..65ca534 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -13,6 +13,9 @@
 #include <linux/time.h>
 #endif
 
+#ifdef __KERNEL__
+#include <linux/ion.h>
+#endif
 #define MSM_CAM_IOCTL_MAGIC 'm'
 
 #define MSM_CAM_IOCTL_GET_SENSOR_INFO \
@@ -522,6 +525,9 @@
 	uint32_t frame_id;
 	int stcam_quality_ind;
 	uint32_t stcam_conv_value;
+
+	struct ion_allocation_data ion_alloc;
+	struct ion_fd_data fd_data;
 };
 
 enum msm_st_frame_packing {
@@ -1094,6 +1100,7 @@
 	uint32_t ext_mode;
 	uint8_t num_planes;
 	struct plane_data plane[MAX_PLANES];
+	uint32_t sp_y_offset;
 	uint8_t vpe_can_use;
 };
 
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index aff1ce8..9126bbb 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -870,6 +870,8 @@
 #define G711_MLAW_FS 0x00010BF8
 #define G711_PCM_FS  0x00010BF9
 #define MPEG4_MULTI_AAC 0x00010D86
+#define US_POINT_EPOS_FORMAT 0x00012310
+#define US_RAW_FORMAT        0x0001127C
 
 #define ASM_ENCDEC_SBCRATE         0x00010C13
 #define ASM_ENCDEC_IMMDIATE_DECODE 0x00010C14
diff --git a/include/sound/dai.h b/include/sound/dai.h
index 27ff980..4d3fb96 100644
--- a/include/sound/dai.h
+++ b/include/sound/dai.h
@@ -43,6 +43,7 @@
 void unregister_dma_irq_handler(int dma_ch);
 void dai_set_master_mode(uint32_t dma_ch, int mode);
 int dai_start_hdmi(uint32_t dma_ch);
+int wait_for_dma_cnt_stop(uint32_t dma_ch);
 void dai_stop_hdmi(uint32_t dma_ch);
 
 #endif
diff --git a/include/sound/jack.h b/include/sound/jack.h
index c140fc7..5fedf19 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -42,7 +42,8 @@
 	SND_JACK_MECHANICAL	= 0x0008, /* If detected separately */
 	SND_JACK_VIDEOOUT	= 0x0010,
 	SND_JACK_AVOUT		= SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
-
+	SND_JACK_OC_HPHL	= 0x0020,
+	SND_JACK_OC_HPHR	= 0x0040,
 	/* Kept separate from switches to facilitate implementation */
 	SND_JACK_BTN_0		= 0x4000,
 	SND_JACK_BTN_1		= 0x2000,
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index f146684..16439e8 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -147,6 +147,8 @@
 
 struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv);
 
+struct audio_client *q6asm_get_audio_client(int session_id);
+
 int q6asm_audio_client_buf_alloc(unsigned int dir/* 1:Out,0:In */,
 				struct audio_client *ac,
 				unsigned int bufsz,
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
index b257424..892e3ec 100644
--- a/kernel/power/wakelock.c
+++ b/kernel/power/wakelock.c
@@ -19,7 +19,6 @@
 #include <linux/suspend.h>
 #include <linux/syscalls.h> /* sys_sync */
 #include <linux/wakelock.h>
-#include <linux/syscore_ops.h>
 #ifdef CONFIG_WAKELOCK_STAT
 #include <linux/proc_fs.h>
 #endif
@@ -53,8 +52,6 @@
 struct wake_lock main_wake_lock;
 suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
 static struct wake_lock unknown_wakeup;
-/* flag to warn/bug if wakelocks are taken after suspend_noirq */
-static int msm_suspend_check_done;
 
 #ifdef CONFIG_WAKELOCK_STAT
 static struct wake_lock deleted_wake_locks;
@@ -386,9 +383,6 @@
 #endif
 	if (debug_mask & DEBUG_SUSPEND)
 		pr_info("power_suspend_late return %d\n", ret);
-
-	if (ret == 0)
-		msm_suspend_check_done = 1;
 	return ret;
 }
 
@@ -404,14 +398,6 @@
 	.name = "power",
 };
 
-static void power_resume_early(void)
-{
-	msm_suspend_check_done = 0;
-}
-static struct syscore_ops wakelock_syscore_ops = {
-	.resume = power_resume_early,
-};
-
 void wake_lock_init(struct wake_lock *lock, int type, const char *name)
 {
 	unsigned long irqflags = 0;
@@ -544,24 +530,12 @@
 
 void wake_lock(struct wake_lock *lock)
 {
-	/*
-	 * if wake lock is being called too late in the suspend sequence,
-	 * call bug so we get to analyze the callstack
-	 */
-	BUG_ON(msm_suspend_check_done);
-
 	wake_lock_internal(lock, 0, 0);
 }
 EXPORT_SYMBOL(wake_lock);
 
 void wake_lock_timeout(struct wake_lock *lock, long timeout)
 {
-	/*
-	 * if wake lock is being called too late in the suspend sequence,
-	 * call bug so we get to analyze the callstack
-	 */
-	BUG_ON(msm_suspend_check_done);
-
 	wake_lock_internal(lock, timeout, 1);
 }
 EXPORT_SYMBOL(wake_lock_timeout);
@@ -663,7 +637,6 @@
 	proc_create("wakelocks", S_IRUGO, NULL, &wakelock_stats_fops);
 #endif
 
-	register_syscore_ops(&wakelock_syscore_ops);
 	return 0;
 
 err_suspend_work_queue:
diff --git a/mm/memblock.c b/mm/memblock.c
index a0562d1..5338237 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -38,6 +38,12 @@
 		return "unknown";
 }
 
+/* adjust *@size so that (@base + *@size) doesn't overflow, return new size */
+static inline phys_addr_t memblock_cap_size(phys_addr_t base, phys_addr_t *size)
+{
+	return *size = min(*size, (phys_addr_t)ULLONG_MAX - base);
+}
+
 /*
  * Address comparison utilities
  */
@@ -276,7 +282,7 @@
 static long __init_memblock memblock_add_region(struct memblock_type *type,
 						phys_addr_t base, phys_addr_t size)
 {
-	phys_addr_t end = base + size;
+	phys_addr_t end = base + memblock_cap_size(base, &size);
 	int i, slot = -1;
 
 	/* First try and coalesce this MEMBLOCK with others */
@@ -412,7 +418,7 @@
 static long __init_memblock __memblock_remove(struct memblock_type *type,
 					      phys_addr_t base, phys_addr_t size)
 {
-	phys_addr_t end = base + size;
+	phys_addr_t end = base + memblock_cap_size(base, &size);
 	int i;
 
 	/* Walk through the array for collisions */
@@ -705,16 +711,18 @@
 int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
 {
 	int idx = memblock_search(&memblock.memory, base);
+	phys_addr_t end = base + memblock_cap_size(base, &size);
 
 	if (idx == -1)
 		return 0;
 	return memblock.memory.regions[idx].base <= base &&
 		(memblock.memory.regions[idx].base +
-		 memblock.memory.regions[idx].size) >= (base + size);
+		 memblock.memory.regions[idx].size) >= end;
 }
 
 int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
 {
+	memblock_cap_size(base, &size);
 	return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
 }
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 094bfdb..0e7ff51 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2608,7 +2608,10 @@
 	loc_mitm = conn->auth_type & 0x01;
 	rem_mitm = conn->remote_auth & 0x01;
 
-	if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03))
+	if ((conn->auth_type & HCI_AT_DEDICATED_BONDING) &&
+			conn->auth_initiator && rem_cap == 0x03)
+		ev.auto_confirm = 1;
+	else if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03))
 		goto no_auto_confirm;
 
 
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 53b53e9..80453a9 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -30,6 +30,8 @@
 	SW_LINEOUT_INSERT,
 	SW_JACK_PHYSICAL_INSERT,
 	SW_VIDEOOUT_INSERT,
+	SW_HPHL_OVERCURRENT,
+	SW_HPHR_OVERCURRENT,
 };
 
 static int snd_jack_dev_free(struct snd_device *device)
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 88f02e3..3e5724f 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -147,7 +147,9 @@
 		.le = -1, .signd = -1,
 	},
 	[SNDRV_PCM_FORMAT_SPECIAL] = {
-		.le = -1, .signd = -1,
+		/* set the width and phys same as S16_LE */
+		.width = 16, .phys = 16, .le = -1, .signd = -1,
+		.silence = {},
 	},
 	[SNDRV_PCM_FORMAT_S24_3LE] = {
 		.width = 24, .phys = 24, .le = 1, .signd = 1,
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index ad8190c..7f7bdc9 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -37,6 +37,8 @@
 #define TABLA_RX_DAI_ID 1
 #define TABLA_TX_DAI_ID 2
 
+#define TABLA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
+
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
@@ -84,6 +86,14 @@
 	struct mbhc_micbias_regs mbhc_bias_regs;
 	u8 cfilt_k_value;
 	bool mbhc_micbias_switched;
+
+	u32 hph_status; /* track headhpone status */
+	/* define separate work for left and right headphone OCP to avoid
+	 * additional checking on which OCP event to report so no locking
+	 * to ensure synchronization is required
+	 */
+	struct work_struct hphlocp_work; /* reporting left hph ocp off */
+	struct work_struct hphrocp_work; /* reporting right hph ocp off */
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -1285,6 +1295,42 @@
 	return 0;
 }
 
+static void hphocp_off_report(struct tabla_priv *tabla,
+	u32 jack_status, int irq)
+{
+	struct snd_soc_codec *codec;
+
+	if (tabla) {
+		pr_info("%s: clear ocp status %x\n", __func__, jack_status);
+		codec = tabla->codec;
+		tabla->hph_status &= ~jack_status;
+		if (tabla->headset_jack)
+			snd_soc_jack_report(tabla->headset_jack,
+			tabla->hph_status, TABLA_JACK_MASK);
+		snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
+		0x00);
+		snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
+		0x10);
+		tabla_enable_irq(codec->control_data, irq);
+	} else {
+		pr_err("%s: Bad tabla private data\n", __func__);
+	}
+}
+
+static void hphlocp_off_report(struct work_struct *work)
+{
+	struct tabla_priv *tabla = container_of(work, struct tabla_priv,
+		hphlocp_work);
+	hphocp_off_report(tabla, SND_JACK_OC_HPHL, TABLA_IRQ_HPH_PA_OCPL_FAULT);
+}
+
+static void hphrocp_off_report(struct work_struct *work)
+{
+	struct tabla_priv *tabla = container_of(work, struct tabla_priv,
+		hphrocp_work);
+	hphocp_off_report(tabla, SND_JACK_OC_HPHR, TABLA_IRQ_HPH_PA_OCPR_FAULT);
+}
+
 static int tabla_hph_pa_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -1305,7 +1351,17 @@
 		break;
 
 	case SND_SOC_DAPM_POST_PMD:
-
+		/* schedule work is required because at the time HPH PA DAPM
+		 * event callback is called by DAPM framework, CODEC dapm mutex
+		 * would have been locked while snd_soc_jack_report also
+		 * attempts to acquire same lock.
+		 */
+		if ((tabla->hph_status & SND_JACK_OC_HPHL) &&
+			strnstr(w->name, "HPHL", 4))
+			schedule_work(&tabla->hphlocp_work);
+		else if ((tabla->hph_status & SND_JACK_OC_HPHR) &&
+			strnstr(w->name, "HPHR", 4))
+			schedule_work(&tabla->hphrocp_work);
 		if (tabla->mbhc_micbias_switched)
 			tabla_codec_switch_micbias(codec, 0);
 
@@ -2495,6 +2551,8 @@
 	struct tabla_mbhc_calibration *calibration)
 {
 	struct tabla_priv *tabla;
+	int rc;
+
 	if (!codec || !calibration) {
 		pr_err("Error: no codec or calibration\n");
 		return -EINVAL;
@@ -2506,7 +2564,20 @@
 	tabla_get_mbhc_micbias_regs(codec, &tabla->mbhc_bias_regs);
 
 	INIT_DELAYED_WORK(&tabla->btn0_dwork, btn0_lpress_fn);
-	return tabla_codec_enable_hs_detect(codec, 1);
+	INIT_WORK(&tabla->hphlocp_work, hphlocp_off_report);
+	INIT_WORK(&tabla->hphrocp_work, hphrocp_off_report);
+	rc =  tabla_codec_enable_hs_detect(codec, 1);
+
+	if (!IS_ERR_VALUE(rc)) {
+		snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
+			0x10);
+		tabla_enable_irq(codec->control_data,
+			TABLA_IRQ_HPH_PA_OCPL_FAULT);
+		tabla_enable_irq(codec->control_data,
+			TABLA_IRQ_HPH_PA_OCPR_FAULT);
+	}
+
+	return rc;
 }
 EXPORT_SYMBOL_GPL(tabla_hs_detect);
 
@@ -2636,6 +2707,52 @@
 	tabla->mbhc_polling_active = false;
 }
 
+static irqreturn_t tabla_hphl_ocp_irq(int irq, void *data)
+{
+	struct tabla_priv *tabla = data;
+	struct snd_soc_codec *codec;
+
+	pr_info("%s: received HPHL OCP irq\n", __func__);
+
+	if (tabla) {
+		codec = tabla->codec;
+		tabla_disable_irq(codec->control_data,
+			TABLA_IRQ_HPH_PA_OCPL_FAULT);
+		tabla->hph_status |= SND_JACK_OC_HPHL;
+		if (tabla->headset_jack) {
+			snd_soc_jack_report(tabla->headset_jack,
+				tabla->hph_status, TABLA_JACK_MASK);
+		}
+	} else {
+		pr_err("%s: Bad tabla private data\n", __func__);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t tabla_hphr_ocp_irq(int irq, void *data)
+{
+	struct tabla_priv *tabla = data;
+	struct snd_soc_codec *codec;
+
+	pr_info("%s: received HPHR OCP irq\n", __func__);
+
+	if (tabla) {
+		codec = tabla->codec;
+		tabla_disable_irq(codec->control_data,
+			TABLA_IRQ_HPH_PA_OCPR_FAULT);
+		tabla->hph_status |= SND_JACK_OC_HPHR;
+		if (tabla->headset_jack) {
+			snd_soc_jack_report(tabla->headset_jack,
+				tabla->hph_status, TABLA_JACK_MASK);
+		}
+	} else {
+		pr_err("%s: Bad tabla private data\n", __func__);
+	}
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t tabla_hs_insert_irq(int irq, void *data)
 {
 	struct tabla_priv *priv = data;
@@ -2683,10 +2800,11 @@
 		 */
 		if (priv->mbhc_micbias_switched)
 			tabla_codec_switch_micbias(codec, 0);
+		priv->hph_status &= ~SND_JACK_HEADSET;
 		if (priv->headset_jack) {
 			pr_debug("%s: Reporting removal\n", __func__);
-			snd_soc_jack_report(priv->headset_jack, 0,
-				SND_JACK_HEADSET);
+			snd_soc_jack_report(priv->headset_jack,
+				priv->hph_status, TABLA_JACK_MASK);
 		}
 		tabla_codec_shutdown_hs_removal_detect(codec);
 		tabla_codec_enable_hs_detect(codec, 1);
@@ -2702,12 +2820,12 @@
 	} else if (mic_voltage < threshold_no_mic) {
 		pr_debug("%s: Headphone Detected, mic_voltage = %x\n",
 			__func__, mic_voltage);
-
+		priv->hph_status |= SND_JACK_HEADPHONE;
 		if (priv->headset_jack) {
 			pr_debug("%s: Reporting insertion %d\n", __func__,
 				SND_JACK_HEADPHONE);
 			snd_soc_jack_report(priv->headset_jack,
-				SND_JACK_HEADPHONE, SND_JACK_HEADSET);
+				priv->hph_status, TABLA_JACK_MASK);
 		}
 		tabla_codec_shutdown_hs_polling(codec);
 		tabla_codec_enable_hs_detect(codec, 0);
@@ -2715,11 +2833,12 @@
 	} else {
 		pr_debug("%s: Headset detected, mic_voltage = %x\n",
 			__func__, mic_voltage);
+		priv->hph_status |= SND_JACK_HEADSET;
 		if (priv->headset_jack) {
 			pr_debug("%s: Reporting insertion %d\n", __func__,
 				SND_JACK_HEADSET);
 			snd_soc_jack_report(priv->headset_jack,
-				SND_JACK_HEADSET, SND_JACK_HEADSET);
+				priv->hph_status,  TABLA_JACK_MASK);
 		}
 		tabla_codec_start_hs_polling(codec);
 	}
@@ -2754,10 +2873,11 @@
 		 */
 		if (priv->mbhc_micbias_switched)
 			tabla_codec_switch_micbias(codec, 0);
+		priv->hph_status &= ~SND_JACK_HEADSET;
 		if (priv->headset_jack) {
 			pr_debug("%s: Reporting removal\n", __func__);
 			snd_soc_jack_report(priv->headset_jack, 0,
-				SND_JACK_HEADSET);
+				 TABLA_JACK_MASK);
 		}
 		tabla_codec_shutdown_hs_polling(codec);
 
@@ -2888,6 +3008,21 @@
 		snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN,
 			0x13, value);
 	}
+
+	if (pdata->ocp.use_pdata) {
+		/* not defined in CODEC specification */
+		if (pdata->ocp.hph_ocp_limit == 1 ||
+			pdata->ocp.hph_ocp_limit == 5) {
+			rc = -EINVAL;
+			goto done;
+		}
+		snd_soc_update_bits(codec, TABLA_A_RX_COM_OCP_CTL,
+			0x0F, pdata->ocp.num_attempts);
+		snd_soc_write(codec, TABLA_A_RX_COM_OCP_COUNT,
+			((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
+		snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL,
+			0xE0, (pdata->ocp.hph_ocp_limit << 5));
+	}
 done:
 	return rc;
 }
@@ -2956,6 +3091,8 @@
 }
 
 static const struct tabla_reg_mask_val tabla_codec_reg_init_val[] = {
+	/* Initialize current threshold to 350MA */
+	{TABLA_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
 
 	{TABLA_A_QFUSE_CTL, 0xFF, 0x03},
 
@@ -3118,12 +3255,34 @@
 		tabla_interface_reg_write(codec->control_data,
 			TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
 
+	ret = tabla_request_irq(codec->control_data,
+		TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla_hphl_ocp_irq,
+		"HPH_L OCP detect", tabla);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TABLA_IRQ_HPH_PA_OCPL_FAULT);
+		goto err_hphl_ocp_irq;
+	}
+
+	ret = tabla_request_irq(codec->control_data,
+		TABLA_IRQ_HPH_PA_OCPR_FAULT, tabla_hphr_ocp_irq,
+		"HPH_R OCP detect", tabla);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+			TABLA_IRQ_HPH_PA_OCPR_FAULT);
+		goto err_hphr_ocp_irq;
+	}
+
 #ifdef CONFIG_DEBUG_FS
 	debug_tabla_priv = tabla;
 #endif
 
 	return ret;
 
+err_hphr_ocp_irq:
+	tabla_free_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
+err_hphl_ocp_irq:
+	tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
 err_slimbus_irq:
 	tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
 err_release_irq:
diff --git a/sound/soc/msm/lpass-dma.c b/sound/soc/msm/lpass-dma.c
index 84b6f1f..66c1836 100644
--- a/sound/soc/msm/lpass-dma.c
+++ b/sound/soc/msm/lpass-dma.c
@@ -93,6 +93,7 @@
 	spin_lock_irqsave(&dai_lock, flag);
 	intrsrc = readl(dai_info.base + LPAIF_IRQ_STAT(0));
 	writel(intrsrc, dai_info.base + LPAIF_IRQ_CLEAR(0));
+	mb();
 	while (intrsrc) {
 		dma_ch = dai_find_dma_channel(intrsrc);
 
@@ -149,6 +150,7 @@
 			dai_info.base + LPAIF_DMA_BUFF_LEN(dma_ch));
 	writel(((dai[dma_ch]->period_len >> 2) - 1),
 			dai_info.base + LPAIF_DMA_PER_LEN(dma_ch));
+	mb();
 }
 
 static void dai_enable_codec(uint32_t dma_ch, int codec)
@@ -237,6 +239,7 @@
 	dai[dma_ch]->channels = params->channels;
 	dai[dma_ch]->buffer_len = params->buffer_size;
 	dai[dma_ch]->period_len = params->period_size;
+	mb();
 	dai_config_dma(dma_ch);
 	return dma_ch;
 }
@@ -278,6 +281,7 @@
 		val = readl(dai_info.base + LPAIF_IRQ_EN(0));
 		val = val | (7 << (dma_ch * 3));
 		writel(val, dai_info.base + LPAIF_IRQ_EN(0));
+		mb();
 
 
 		val = (HDMI_BURST_INCR4 | HDMI_WPSCNT | HDMI_AUDIO_INTF |
@@ -287,10 +291,58 @@
 	}
 	spin_unlock_irqrestore(&dai_lock, flag);
 
+	mb();
 	dai_print_state(dma_ch);
 	return 0;
 }
 
+int wait_for_dma_cnt_stop(uint32_t dma_ch)
+{
+	uint32_t dma_per_cnt_reg_val, dma_per_cnt, prev_dma_per_cnt;
+	uint32_t i;
+
+	pr_info("%s dma_ch %u\n", __func__, dma_ch);
+
+	dma_per_cnt_reg_val =  readl_relaxed(dai_info.base +
+					LPAIF_DMA_PER_CNT(dma_ch));
+
+	dma_per_cnt =
+		((LPAIF_DMA_PER_CNT_PER_CNT_MASK & dma_per_cnt_reg_val) >>
+			LPAIF_DMA_PER_CNT_PER_CNT_SHIFT) -
+		((LPAIF_DMA_PER_CNT_FIFO_WORDCNT_MASK & dma_per_cnt_reg_val) >>
+			LPAIF_DMA_PER_CNT_FIFO_WORDCNT_SHIFT);
+
+	prev_dma_per_cnt = dma_per_cnt;
+
+	i = 1;
+	pr_info("%s: i = %u dma_per_cnt_reg_val 0x%08x , dma_per_cnt %u\n",
+		__func__, i, dma_per_cnt_reg_val, dma_per_cnt);
+
+	while (i <= 50) {
+		msleep(50);
+
+		dma_per_cnt_reg_val =  readl_relaxed(dai_info.base +
+						LPAIF_DMA_PER_CNT(dma_ch));
+
+		dma_per_cnt =
+		((LPAIF_DMA_PER_CNT_PER_CNT_MASK & dma_per_cnt_reg_val) >>
+			LPAIF_DMA_PER_CNT_PER_CNT_SHIFT) -
+		((LPAIF_DMA_PER_CNT_FIFO_WORDCNT_MASK & dma_per_cnt_reg_val) >>
+			LPAIF_DMA_PER_CNT_FIFO_WORDCNT_SHIFT);
+
+		i++;
+
+		pr_info("%s: i = %u dma_per_cnt_reg_val 0x%08x , dma_per_cnt %u\n",
+			__func__, i, dma_per_cnt_reg_val, dma_per_cnt);
+
+		if (prev_dma_per_cnt == dma_per_cnt)
+			break;
+
+		prev_dma_per_cnt = dma_per_cnt;
+	}
+	return 0;
+}
+
 void dai_stop_hdmi(uint32_t dma_ch)
 {
 	unsigned long flag = 0x0;
@@ -307,14 +359,18 @@
 	intrVal = 0x0;
 	writel(intrVal, dai_info.base + LPAIF_DMA_CTL(dma_ch));
 
+	mb();
+
 	intrVal = readl(dai_info.base + LPAIF_IRQ_EN(0));
 
 	int_mask = ((int_mask) << (dma_ch * 3));
 	int_mask = ~int_mask;
 
-	intrVal = intrVal && int_mask;
+	intrVal = intrVal & int_mask;
 	writel(intrVal, dai_info.base + LPAIF_IRQ_EN(0));
 
+	mb();
+
 	spin_unlock_irqrestore(&dai_lock, flag);
 }
 
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 2ad7f3e..401c1a9 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -117,7 +117,8 @@
 		.playback = {
 			.stream_name = "VoIP Playback",
 			.rates = SNDRV_PCM_RATE_8000_48000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+					SNDRV_PCM_FMTBIT_SPECIAL,
 			.channels_min = 1,
 			.channels_max = 2,
 			.rate_min =	8000,
@@ -126,7 +127,8 @@
 		.capture = {
 			.stream_name = "VoIP Capture",
 			.rates = SNDRV_PCM_RATE_8000_48000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+					SNDRV_PCM_FMTBIT_SPECIAL,
 			.channels_min = 1,
 			.channels_max = 2,
 			.rate_min =	8000,
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index a34b774..01b8463 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -149,8 +149,6 @@
 			}
 			case AFE_EVENT_RTPORT_STOP:
 				pr_debug("%s: event!=0\n", __func__);
-				prtd->start = 0;
-				snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
 				break;
 			case AFE_EVENT_RTPORT_LOW_WM:
 				pr_debug("%s: Underrun\n", __func__);
@@ -215,8 +213,6 @@
 		}
 		case AFE_EVENT_RTPORT_STOP:
 			pr_debug("%s: event!=0\n", __func__);
-			prtd->start = 0;
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
 			break;
 		case AFE_EVENT_RTPORT_LOW_WM:
 			pr_debug("%s: Underrun\n", __func__);
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 115453c..738e024 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -51,9 +51,9 @@
 	.rate_max =             48000,
 	.channels_min =         1,
 	.channels_max =         2,
-	.buffer_bytes_max =     512 * 8,
-	.period_bytes_min =	512,
-	.period_bytes_max =     512,
+	.buffer_bytes_max =     320 * 8,
+	.period_bytes_min =	320,
+	.period_bytes_max =     320,
 	.periods_min =          8,
 	.periods_max =          8,
 	.fifo_size =            0,
@@ -335,7 +335,7 @@
 		}
 	}
 
-	pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
+	pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
 
 	prtd->session_id = prtd->audio_client->session;
 	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 70e081c..97d0760 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -25,6 +25,7 @@
 #include <sound/initval.h>
 #include <sound/control.h>
 #include <sound/q6adm.h>
+#include <sound/q6asm.h>
 #include <sound/q6afe.h>
 #include <sound/tlv.h>
 #include "msm-pcm-routing.h"
@@ -59,6 +60,43 @@
 static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
 			INT_LPA_RX_VOL_MAX_STEPS, 0);
 
+/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
+#define MAX_EQ_SESSIONS		MSM_FRONTEND_DAI_CS_VOICE
+
+enum {
+	EQ_BAND1 = 0,
+	EQ_BAND2,
+	EQ_BAND3,
+	EQ_BAND4,
+	EQ_BAND5,
+	EQ_BAND6,
+	EQ_BAND7,
+	EQ_BAND8,
+	EQ_BAND9,
+	EQ_BAND10,
+	EQ_BAND11,
+	EQ_BAND12,
+	EQ_BAND_MAX,
+};
+
+struct msm_audio_eq_band {
+	uint16_t     band_idx; /* The band index, 0 .. 11 */
+	uint32_t     filter_type; /* Filter band type */
+	uint32_t     center_freq_hz; /* Filter band center frequency */
+	uint32_t     filter_gain; /* Filter band initial gain (dB) */
+			/* Range is +12 dB to -12 dB with 1dB increments. */
+	uint32_t     q_factor;
+} __packed;
+
+struct msm_audio_eq_stream_config {
+	uint32_t	enable; /* Number of consequtive bands specified */
+	uint32_t	num_bands;
+	struct msm_audio_eq_band	eq_bands[EQ_BAND_MAX];
+} __packed;
+
+struct msm_audio_eq_stream_config	eq_data[MAX_EQ_SESSIONS];
+
+static void msm_send_eq_values(int eq_idx);
 /* This array is indexed by back-end DAI ID defined in msm-pcm-routing.h
  * If new back-end is defined, add new back-end DAI ID at the end of enum
  */
@@ -132,6 +170,9 @@
 
 	payload.num_copps = 0; /* only RX needs to use payload */
 	fe_dai_map[fedai_id][session_type] = dspst_id;
+	/* re-enable EQ if active */
+	if (eq_data[fedai_id].enable)
+		msm_send_eq_values(fedai_id);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
 		if ((afe_get_port_type(msm_bedais[i].port_id) ==
 			port_type) && msm_bedais[i].active &&
@@ -448,6 +489,122 @@
 	return 0;
 }
 
+static void msm_send_eq_values(int eq_idx)
+{
+	int result;
+	struct audio_client *ac =
+		q6asm_get_audio_client(fe_dai_map[eq_idx][SESSION_TYPE_RX]);
+
+	if (ac == NULL) {
+		pr_err("%s: Could not get audio client for session: %d\n",
+		       __func__, fe_dai_map[eq_idx][SESSION_TYPE_RX]);
+		goto done;
+	}
+
+	result = q6asm_equalizer(ac, &eq_data[eq_idx]);
+
+	if (result < 0)
+		pr_err("%s: Call to ASM equalizer failed, returned = %d\n",
+		       __func__, result);
+done:
+	return;
+}
+
+static int msm_routing_get_eq_enable_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+
+	pr_debug("%s: EQ #%d enable %d\n", __func__,
+		eq_idx, eq_data[eq_idx].enable);
+	return eq_data[eq_idx].enable;
+}
+
+static int msm_routing_put_eq_enable_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int value = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: EQ #%d enable %d\n", __func__,
+		eq_idx, value);
+	eq_data[eq_idx].enable = value;
+
+	msm_send_eq_values(eq_idx);
+	return 0;
+}
+
+static int msm_routing_get_eq_band_count_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+
+	pr_debug("%s: EQ #%d bands %d\n", __func__,
+		eq_idx, eq_data[eq_idx].num_bands);
+	return eq_data[eq_idx].num_bands;
+}
+
+static int msm_routing_put_eq_band_count_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					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;
+	return 0;
+}
+
+static int msm_routing_get_eq_band_audio_mixer(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	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__,
+			eq_data[eq_idx].eq_bands[band_idx].filter_type);
+	pr_debug("%s: center_freq_hz = %d\n", __func__,
+			eq_data[eq_idx].eq_bands[band_idx].center_freq_hz);
+	pr_debug("%s: filter_gain = %d\n", __func__,
+			eq_data[eq_idx].eq_bands[band_idx].filter_gain);
+	pr_debug("%s: q_factor = %d\n", __func__,
+			eq_data[eq_idx].eq_bands[band_idx].q_factor);
+	return 0;
+}
+
+static int msm_routing_put_eq_band_audio_mixer(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int eq_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	eq_data[eq_idx].eq_bands[band_idx].band_idx =
+					ucontrol->value.integer.value[0];
+	eq_data[eq_idx].eq_bands[band_idx].filter_type =
+					ucontrol->value.integer.value[1];
+	eq_data[eq_idx].eq_bands[band_idx].center_freq_hz =
+					ucontrol->value.integer.value[2];
+	eq_data[eq_idx].eq_bands[band_idx].filter_gain =
+					ucontrol->value.integer.value[3];
+	eq_data[eq_idx].eq_bands[band_idx].q_factor =
+					ucontrol->value.integer.value[4];
+	return 0;
+}
+
 static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_I2S_RX ,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -604,6 +761,15 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
+	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -666,6 +832,180 @@
 	msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
 };
 
+static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
+	msm_routing_put_eq_enable_mixer),
+	SOC_SINGLE_EXT("MultiMedia2 EQ Enable", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_eq_enable_mixer,
+	msm_routing_put_eq_enable_mixer),
+	SOC_SINGLE_EXT("MultiMedia3 EQ Enable", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_eq_enable_mixer,
+	msm_routing_put_eq_enable_mixer),
+};
+
+static const struct snd_kcontrol_new eq_band_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1 EQ Band Count", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 11, 0,
+	msm_routing_get_eq_band_count_audio_mixer,
+	msm_routing_put_eq_band_count_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2 EQ Band Count", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 11, 0,
+	msm_routing_get_eq_band_count_audio_mixer,
+	msm_routing_put_eq_band_count_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia3 EQ Band Count", SND_SOC_NOPM,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 11, 0,
+	msm_routing_get_eq_band_count_audio_mixer,
+	msm_routing_put_eq_band_count_audio_mixer),
+};
+
+static const struct snd_kcontrol_new eq_coeff_mixer_controls[] = {
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band1", EQ_BAND1,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band2", EQ_BAND2,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band3", EQ_BAND3,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band4", EQ_BAND4,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band5", EQ_BAND5,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band6", EQ_BAND6,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band7", EQ_BAND7,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band8", EQ_BAND8,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band9", EQ_BAND9,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band10", EQ_BAND10,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band11", EQ_BAND11,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band12", EQ_BAND12,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band1", EQ_BAND1,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band2", EQ_BAND2,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band3", EQ_BAND3,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band4", EQ_BAND4,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band5", EQ_BAND5,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band6", EQ_BAND6,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band7", EQ_BAND7,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band8", EQ_BAND8,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band9", EQ_BAND9,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band10", EQ_BAND10,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band11", EQ_BAND11,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band12", EQ_BAND12,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band1", EQ_BAND1,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band2", EQ_BAND2,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band3", EQ_BAND3,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band4", EQ_BAND4,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band5", EQ_BAND5,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band6", EQ_BAND6,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band7", EQ_BAND7,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band8", EQ_BAND8,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band9", EQ_BAND9,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band10", EQ_BAND10,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band11", EQ_BAND11,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band12", EQ_BAND12,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
+	msm_routing_get_eq_band_audio_mixer,
+	msm_routing_put_eq_band_audio_mixer),
+};
+
 static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
 	/* Frontend AIF */
 	/* Widget name equals to Front-End DAI name<Need confirmation>,
@@ -746,6 +1086,10 @@
 				SND_SOC_NOPM, 0, 0,
 				aux_pcm_rx_voice_mixer_controls,
 				ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("HDMI_RX_Voice Mixer",
+				SND_SOC_NOPM, 0, 0,
+				hdmi_rx_voice_mixer_controls,
+				ARRAY_SIZE(hdmi_rx_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
 				SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
 				ARRAY_SIZE(tx_voice_mixer_controls)),
@@ -831,6 +1175,10 @@
 	{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
+	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
+
 	{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
 	{"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
 	{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
@@ -994,6 +1342,18 @@
 	snd_soc_add_platform_controls(platform,
 				lpa_vol_mixer_controls,
 			ARRAY_SIZE(lpa_vol_mixer_controls));
+
+	snd_soc_add_platform_controls(platform,
+				eq_enable_mixer_controls,
+			ARRAY_SIZE(eq_enable_mixer_controls));
+
+	snd_soc_add_platform_controls(platform,
+				eq_band_mixer_controls,
+			ARRAY_SIZE(eq_band_mixer_controls));
+
+	snd_soc_add_platform_controls(platform,
+				eq_coeff_mixer_controls,
+			ARRAY_SIZE(eq_coeff_mixer_controls));
 	return 0;
 }
 
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index dd02c98..56b4cf5 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -34,12 +34,47 @@
 #define VOIP_MAX_VOC_PKT_SIZE 640
 #define VOIP_MIN_VOC_PKT_SIZE 320
 
+/* Length of the DSP frame info header added to the voc packet. */
+#define DSP_FRAME_HDR_LEN 1
+
+#define MODE_AMR		0x5
+#define MODE_AMR_WB		0xD
+#define MODE_PCM		0xC
+
+enum format {
+	FORMAT_S16_LE = 2,
+	FORMAT_SPECIAL = 31,
+};
+
+
+enum amr_rate_type {
+	AMR_RATE_4750, /* AMR 4.75 kbps */
+	AMR_RATE_5150, /* AMR 5.15 kbps */
+	AMR_RATE_5900, /* AMR 5.90 kbps */
+	AMR_RATE_6700, /* AMR 6.70 kbps */
+	AMR_RATE_7400, /* AMR 7.40 kbps */
+	AMR_RATE_7950, /* AMR 7.95 kbps */
+	AMR_RATE_10200, /* AMR 10.20 kbps */
+	AMR_RATE_12200, /* AMR 12.20 kbps */
+	AMR_RATE_6600, /* AMR-WB 6.60 kbps */
+	AMR_RATE_8850, /* AMR-WB 8.85 kbps */
+	AMR_RATE_12650, /* AMR-WB 12.65 kbps */
+	AMR_RATE_14250, /* AMR-WB 14.25 kbps */
+	AMR_RATE_15850, /* AMR-WB 15.85 kbps */
+	AMR_RATE_18250, /* AMR-WB 18.25 kbps */
+	AMR_RATE_19850, /* AMR-WB 19.85 kbps */
+	AMR_RATE_23050, /* AMR-WB 23.05 kbps */
+	AMR_RATE_23850, /* AMR-WB 23.85 kbps */
+	AMR_RATE_UNDEF
+};
+
 enum voip_state {
 	VOIP_STOPPED,
 	VOIP_STARTED,
 };
 
 struct voip_frame {
+	uint32_t frame_type;
 	uint32_t len;
 	uint8_t voc_pkt[VOIP_MAX_VOC_PKT_SIZE];
 };
@@ -70,6 +105,9 @@
 
 	spinlock_t dsp_lock;
 
+	uint32_t mode;
+	uint32_t rate_type;
+	uint32_t rate;
 
 	uint8_t capture_start;
 	uint8_t playback_start;
@@ -91,6 +129,16 @@
 	unsigned int pcm_capture_buf_pos;       /* position in buffer */
 };
 
+static int voip_get_media_type(uint32_t mode,
+				unsigned int samp_rate);
+static int voip_get_rate_type(uint32_t mode,
+				uint32_t rate,
+				uint32_t *rate_type);
+static int msm_voip_mode_rate_config_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol);
+static int msm_voip_mode_rate_config_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol);
+
 static struct voip_drv_info voip_info;
 
 static struct snd_pcm_hardware msm_pcm_hardware = {
@@ -98,13 +146,14 @@
 				SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED),
-	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
+	.formats =              SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_SPECIAL,
 	.rates =                SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
 	.rate_min =             8000,
 	.rate_max =             16000,
 	.channels_min =         1,
 	.channels_max =         1,
-	.buffer_bytes_max =	VOIP_MAX_VOC_PKT_SIZE * VOIP_MAX_Q_LEN,
+	.buffer_bytes_max =	sizeof(struct voip_buf_node) * VOIP_MAX_Q_LEN,
 	.period_bytes_min =	VOIP_MIN_VOC_PKT_SIZE,
 	.period_bytes_max =	VOIP_MAX_VOC_PKT_SIZE,
 	.periods_min =		VOIP_MAX_Q_LEN,
@@ -156,6 +205,9 @@
 				msm_voip_mute_get, msm_voip_mute_put),
 	SOC_SINGLE_EXT("Voip Rx Volume", SND_SOC_NOPM, 0, 5, 0,
 				msm_voip_volume_get, msm_voip_volume_put),
+	SOC_SINGLE_MULTI_EXT("Voip Mode Rate Config", SND_SOC_NOPM, 0, 23850,
+				0, 2, msm_voip_mode_rate_config_get,
+				msm_voip_mode_rate_config_put),
 };
 
 static int msm_pcm_voip_probe(struct snd_soc_platform *platform)
@@ -189,12 +241,32 @@
 		buf_node = list_first_entry(&prtd->free_out_queue,
 					struct voip_buf_node, list);
 		list_del(&buf_node->list);
-
-		buf_node->frame.len = pkt_len;
-		memcpy(&buf_node->frame.voc_pkt[0], voc_pkt,
-					buf_node->frame.len);
-
-		list_add_tail(&buf_node->list, &prtd->out_queue);
+		switch (prtd->mode) {
+		case MODE_AMR_WB:
+		case MODE_AMR: {
+			/* Remove the DSP frame info header. Header format:
+			 * Bits 0-3: Frame rate
+			 * Bits 4-7: Frame type
+			 */
+			buf_node->frame.frame_type = ((*voc_pkt) & 0xF0) >> 4;
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+			memcpy(&buf_node->frame.voc_pkt[0],
+				voc_pkt,
+				buf_node->frame.len);
+			list_add_tail(&buf_node->list, &prtd->out_queue);
+			break;
+		}
+		default: {
+			buf_node->frame.len = pkt_len;
+			memcpy(&buf_node->frame.voc_pkt[0],
+				voc_pkt,
+				buf_node->frame.len);
+			list_add_tail(&buf_node->list, &prtd->out_queue);
+		}
+		}
+		pr_debug("ul_pkt: pkt_len =%d, frame.len=%d\n", pkt_len,
+			buf_node->frame.len);
 		prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
 		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 		snd_pcm_period_elapsed(prtd->capture_substream);
@@ -225,15 +297,35 @@
 		buf_node = list_first_entry(&prtd->in_queue,
 				struct voip_buf_node, list);
 		list_del(&buf_node->list);
+		switch (prtd->mode) {
+		case MODE_AMR:
+		case MODE_AMR_WB: {
+			/* Add the DSP frame info header. Header format:
+			 * Bits 0-3: Frame rate
+			 * Bits 4-7: Frame type
+			 */
+			*voc_pkt = ((buf_node->frame.frame_type & 0x0F) << 4) |
+					(prtd->rate_type & 0x0F);
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
+			memcpy(voc_pkt,
+				&buf_node->frame.voc_pkt[0],
+				buf_node->frame.len);
+			list_add_tail(&buf_node->list, &prtd->free_in_queue);
+			break;
+		}
+		default: {
+			*pkt_len = buf_node->frame.len;
 
-		*pkt_len = buf_node->frame.len;
+			memcpy(voc_pkt,
+				&buf_node->frame.voc_pkt[0],
+				buf_node->frame.len);
 
-		memcpy(voc_pkt,
-			&buf_node->frame.voc_pkt[0],
+			list_add_tail(&buf_node->list, &prtd->free_in_queue);
+		}
+		}
+		pr_debug("dl_pkt: pkt_len=%d, frame_len=%d\n", *pkt_len,
 			buf_node->frame.len);
-
-		list_add_tail(&buf_node->list, &prtd->free_in_queue);
-
 		prtd->pcm_playback_irq_pos += prtd->pcm_count;
 		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 		snd_pcm_period_elapsed(prtd->playback_substream);
@@ -369,10 +461,13 @@
 				list_first_entry(&prtd->free_in_queue,
 						struct voip_buf_node, list);
 			list_del(&buf_node->list);
-
-			ret = copy_from_user(&buf_node->frame.voc_pkt,
-						buf, count);
-			buf_node->frame.len = count;
+			if (prtd->mode == MODE_PCM) {
+				ret = copy_from_user(&buf_node->frame.voc_pkt,
+							buf, count);
+				buf_node->frame.len = count;
+			} else
+				ret = copy_from_user(&buf_node->frame,
+							buf, count);
 			list_add_tail(&buf_node->list, &prtd->in_queue);
 		} else {
 			pr_err("%s: Write cnt %d is > VOIP_MAX_VOC_PKT_SIZE\n",
@@ -416,11 +511,14 @@
 			buf_node = list_first_entry(&prtd->out_queue,
 					struct voip_buf_node, list);
 			list_del(&buf_node->list);
-
-			ret = copy_to_user(buf,
-					&buf_node->frame.voc_pkt,
-					buf_node->frame.len);
-
+			if (prtd->mode == MODE_PCM)
+				ret = copy_to_user(buf,
+						   &buf_node->frame.voc_pkt,
+						   count);
+			else
+				ret = copy_to_user(buf,
+						   &buf_node->frame,
+						   count);
 			if (ret) {
 				pr_err("%s: Copy to user retuned %d\n",
 					__func__, ret);
@@ -565,6 +663,8 @@
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
+	uint32_t media_type = 0;
+	uint32_t rate_type = 0;
 
 	mutex_lock(&prtd->lock);
 
@@ -573,17 +673,51 @@
 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		ret = msm_pcm_capture_prepare(substream);
 
+	if ((runtime->format != FORMAT_SPECIAL) &&
+		 ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB))) {
+		pr_err("mode:%d and format:%u are not mached\n",
+			prtd->mode, (uint32_t)runtime->format);
+		ret =  -EINVAL;
+		goto done;
+	}
+
+	if ((runtime->format != FORMAT_S16_LE) &&
+		(prtd->mode == MODE_PCM)) {
+		pr_err("mode:%d and format:%u are not mached\n",
+			prtd->mode, (uint32_t)runtime->format);
+		ret = -EINVAL;
+		goto done;
+	}
+
 	if (prtd->playback_instance && prtd->capture_instance
 				&& (prtd->state != VOIP_STARTED)) {
 
+		ret = voip_get_rate_type(prtd->mode,
+					prtd->rate,
+					&rate_type);
+		if (ret < 0) {
+			pr_err("fail at getting rate_type\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		prtd->rate_type = rate_type;
+		media_type = voip_get_media_type(prtd->mode,
+						prtd->play_samp_rate);
+		if (media_type < 0) {
+			pr_err("fail at getting media_type\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		pr_debug(" media_type=%d, rate_type=%d\n", media_type,
+			rate_type);
 		if ((prtd->play_samp_rate == 8000) &&
 					(prtd->cap_samp_rate == 8000))
-			voc_config_vocoder(VSS_MEDIA_ID_PCM_NB,
-						0, VSS_NETWORK_ID_VOIP_NB);
+			voc_config_vocoder(media_type, rate_type,
+					VSS_NETWORK_ID_VOIP_NB);
 		else if ((prtd->play_samp_rate == 16000) &&
 					(prtd->cap_samp_rate == 16000))
-			voc_config_vocoder(VSS_MEDIA_ID_PCM_WB,
-						0, VSS_NETWORK_ID_VOIP_WB);
+			voc_config_vocoder(media_type, rate_type,
+					VSS_NETWORK_ID_VOIP_WB);
 		else {
 			pr_debug("%s: Invalid rate playback %d, capture %d\n",
 				 __func__, prtd->play_samp_rate,
@@ -704,6 +838,154 @@
 	return 0;
 }
 
+static int msm_voip_mode_rate_config_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	mutex_lock(&voip_info.lock);
+
+	ucontrol->value.integer.value[0] = voip_info.mode;
+	ucontrol->value.integer.value[1] = voip_info.rate;
+
+	mutex_unlock(&voip_info.lock);
+
+	return 0;
+}
+
+static int msm_voip_mode_rate_config_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	mutex_lock(&voip_info.lock);
+
+	voip_info.mode = ucontrol->value.integer.value[0];
+	voip_info.rate = ucontrol->value.integer.value[1];
+
+	pr_debug("%s: mode=%d,rate=%d\n", __func__, voip_info.mode,
+		voip_info.rate);
+
+	mutex_unlock(&voip_info.lock);
+
+	return 0;
+}
+
+static int voip_get_rate_type(uint32_t mode, uint32_t rate,
+				 uint32_t *rate_type)
+{
+	int ret = 0;
+
+	switch (mode) {
+	case MODE_AMR: {
+		switch (rate) {
+		case 4750:
+			*rate_type = AMR_RATE_4750;
+			break;
+		case 5150:
+			*rate_type = AMR_RATE_5150;
+			break;
+		case 5900:
+			*rate_type = AMR_RATE_5900;
+			break;
+		case 6700:
+			*rate_type = AMR_RATE_6700;
+			break;
+		case 7400:
+			*rate_type = AMR_RATE_7400;
+			break;
+		case 7950:
+			*rate_type = AMR_RATE_7950;
+			break;
+		case 10200:
+			*rate_type = AMR_RATE_10200;
+			break;
+		case 12200:
+			*rate_type = AMR_RATE_12200;
+			break;
+		default:
+			pr_err("wrong rate for AMR NB.\n");
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	}
+	case MODE_AMR_WB: {
+		switch (rate) {
+		case 6600:
+			*rate_type = AMR_RATE_6600 - AMR_RATE_6600;
+			break;
+		case 8850:
+			*rate_type = AMR_RATE_8850 - AMR_RATE_6600;
+			break;
+		case 12650:
+			*rate_type = AMR_RATE_12650 - AMR_RATE_6600;
+			break;
+		case 14250:
+			*rate_type = AMR_RATE_14250 - AMR_RATE_6600;
+			break;
+		case 15850:
+			*rate_type = AMR_RATE_15850 - AMR_RATE_6600;
+			break;
+		case 18250:
+			*rate_type = AMR_RATE_18250 - AMR_RATE_6600;
+			break;
+		case 19850:
+			*rate_type = AMR_RATE_19850 - AMR_RATE_6600;
+			break;
+		case 23050:
+			*rate_type = AMR_RATE_23050 - AMR_RATE_6600;
+			break;
+		case 23850:
+			*rate_type = AMR_RATE_23850 - AMR_RATE_6600;
+			break;
+		default:
+			pr_err("wrong rate for AMR_WB.\n");
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	}
+	case MODE_PCM: {
+		*rate_type = 0;
+		break;
+	}
+	default:
+		pr_err("wrong mode type.\n");
+		ret = -EINVAL;
+	}
+	pr_debug("%s, mode=%d, rate=%u, rate_type=%d\n",
+		__func__, mode, rate, *rate_type);
+	return ret;
+}
+
+static int voip_get_media_type(uint32_t mode,
+				unsigned int samp_rate)
+{
+	uint32_t media_type;
+
+	pr_debug("%s: mode=%d, samp_rate=%d\n", __func__,
+		mode, samp_rate);
+	switch (mode) {
+	case MODE_AMR:
+		media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
+		break;
+	case MODE_AMR_WB:
+		media_type = VSS_MEDIA_ID_AMR_WB_MODEM;
+		break;
+	case MODE_PCM:
+		if (samp_rate == 8000)
+			media_type = VSS_MEDIA_ID_PCM_NB;
+		else
+			media_type = VSS_MEDIA_ID_PCM_WB;
+		break;
+	default:
+		pr_debug(" input mode is not supported\n");
+		media_type = -EINVAL;
+	}
+
+	pr_debug("%s: media_type is 0x%x\n", __func__, media_type);
+
+	return media_type;
+}
+
+
 static struct snd_pcm_ops msm_pcm_ops = {
 	.open           = msm_pcm_open,
 	.copy		= msm_pcm_copy,
@@ -757,7 +1039,7 @@
 static int __init msm_soc_platform_init(void)
 {
 	memset(&voip_info, 0, sizeof(voip_info));
-
+	voip_info.mode = MODE_PCM;
 	mutex_init(&voip_info.lock);
 	mutex_init(&voip_info.in_lock);
 	mutex_init(&voip_info.out_lock);
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index f5f5893..0082339 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -32,8 +32,6 @@
 #define PM8921_GPIO_BASE		NR_GPIO_IRQS
 #define PM8921_GPIO_PM_TO_SYS(pm_gpio)  (pm_gpio - 1 + PM8921_GPIO_BASE)
 
-#define TOP_SPK_PAMP_GPIO (PM8921_GPIO_PM_TO_SYS(18))
-#define BOTTOM_SPK_PAMP_GPIO (PM8921_GPIO_PM_TO_SYS(19))
 #define MSM8960_SPK_ON 1
 #define MSM8960_SPK_OFF 0
 
@@ -53,6 +51,8 @@
 #define GPIO_AUX_PCM_SYNC 65
 #define GPIO_AUX_PCM_CLK 66
 
+static u32 top_spk_pamp_gpio  = PM8921_GPIO_PM_TO_SYS(18);
+static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
 static int msm8960_spk_control;
 static int msm8960_ext_bottom_spk_pamp;
 static int msm8960_ext_top_spk_pamp;
@@ -96,38 +96,38 @@
 			function       = PM_GPIO_FUNC_NORMAL,
 	};
 
-	if (spk_amp_gpio == BOTTOM_SPK_PAMP_GPIO) {
+	if (spk_amp_gpio == bottom_spk_pamp_gpio) {
 
-		ret = gpio_request(BOTTOM_SPK_PAMP_GPIO, "BOTTOM_SPK_AMP");
+		ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
 		if (ret) {
 			pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
-				__func__, BOTTOM_SPK_PAMP_GPIO);
+				__func__, bottom_spk_pamp_gpio);
 			return;
 		}
-		ret = pm8xxx_gpio_config(BOTTOM_SPK_PAMP_GPIO, &param);
+		ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
 		if (ret)
 			pr_err("%s: Failed to configure Bottom Spk Ampl"
-				" gpio %u\n", __func__, BOTTOM_SPK_PAMP_GPIO);
+				" gpio %u\n", __func__, bottom_spk_pamp_gpio);
 		else {
 			pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
-			gpio_direction_output(BOTTOM_SPK_PAMP_GPIO, 1);
+			gpio_direction_output(bottom_spk_pamp_gpio, 1);
 		}
 
-	} else if (spk_amp_gpio == TOP_SPK_PAMP_GPIO) {
+	} else if (spk_amp_gpio == top_spk_pamp_gpio) {
 
-		ret = gpio_request(TOP_SPK_PAMP_GPIO, "TOP_SPK_AMP");
+		ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
 		if (ret) {
 			pr_err("%s: Error requesting GPIO %d\n", __func__,
-				TOP_SPK_PAMP_GPIO);
+				top_spk_pamp_gpio);
 			return;
 		}
-		ret = pm8xxx_gpio_config(TOP_SPK_PAMP_GPIO, &param);
+		ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
 		if (ret)
 			pr_err("%s: Failed to configure Top Spk Ampl"
-				" gpio %u\n", __func__, TOP_SPK_PAMP_GPIO);
+				" gpio %u\n", __func__, top_spk_pamp_gpio);
 		else {
 			pr_debug("%s: enable Top spkr amp gpio\n", __func__);
-			gpio_direction_output(TOP_SPK_PAMP_GPIO, 1);
+			gpio_direction_output(top_spk_pamp_gpio, 1);
 		}
 	} else {
 		pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
@@ -153,7 +153,7 @@
 		if ((msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
 			(msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
 
-			msm8960_enable_ext_spk_amp_gpio(BOTTOM_SPK_PAMP_GPIO);
+			msm8960_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
 			pr_debug("%s: slepping 4 ms after turning on external "
 				" Bottom Speaker Ampl\n", __func__);
 			usleep_range(4000, 4000);
@@ -174,7 +174,7 @@
 		if ((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
 			(msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
 
-			msm8960_enable_ext_spk_amp_gpio(TOP_SPK_PAMP_GPIO);
+			msm8960_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
 			pr_debug("%s: sleeping 4 ms after turning on "
 				" external Top Speaker Ampl\n", __func__);
 			usleep_range(4000, 4000);
@@ -194,8 +194,8 @@
 		if (!msm8960_ext_bottom_spk_pamp)
 			return;
 
-		gpio_direction_output(BOTTOM_SPK_PAMP_GPIO, 0);
-		gpio_free(BOTTOM_SPK_PAMP_GPIO);
+		gpio_direction_output(bottom_spk_pamp_gpio, 0);
+		gpio_free(bottom_spk_pamp_gpio);
 		msm8960_ext_bottom_spk_pamp = 0;
 
 		pr_debug("%s: sleeping 4 ms after turning off external Bottom"
@@ -208,8 +208,8 @@
 		if (!msm8960_ext_top_spk_pamp)
 			return;
 
-		gpio_direction_output(TOP_SPK_PAMP_GPIO, 0);
-		gpio_free(TOP_SPK_PAMP_GPIO);
+		gpio_direction_output(top_spk_pamp_gpio, 0);
+		gpio_free(top_spk_pamp_gpio);
 		msm8960_ext_top_spk_pamp = 0;
 
 		pr_debug("%s: sleeping 4 ms after turning off external Top"
@@ -577,6 +577,11 @@
 
 	pr_debug("%s()\n", __func__);
 
+	if (machine_is_msm8960_liquid()) {
+		top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
+		bottom_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(18));
+	}
+
 	rtd->pmdown_time = 0;
 
 	err = snd_soc_add_controls(codec, tabla_msm8960_controls,
@@ -598,7 +603,8 @@
 	snd_soc_dapm_sync(dapm);
 
 	err = snd_soc_jack_new(codec, "Headset Jack",
-				SND_JACK_HEADSET, &hs_jack);
+		(SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
+		&hs_jack);
 	if (err) {
 		pr_err("failed to create new jack\n");
 		return err;
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index eb55f77..268d2e5 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -440,6 +440,23 @@
 	return NULL;
 }
 
+struct audio_client *q6asm_get_audio_client(int session_id)
+{
+	if ((session_id <= 0) || (session_id > SESSION_MAX)) {
+		pr_err("%s: invalid session: %d\n", __func__, session_id);
+		goto err;
+	}
+
+	if (!session[session_id]) {
+		pr_err("%s: session not active: %d\n", __func__, session_id);
+		goto err;
+	}
+
+	return session[session_id];
+err:
+	return NULL;
+}
+
 int q6asm_audio_client_buf_alloc(unsigned int dir,
 			struct audio_client *ac,
 			unsigned int bufsz,