Merge "Bluetooth: Kernel panic fix when marimba->client is NULL"
diff --git a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
index d82284d..53a67a4 100644
--- a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
+++ b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
@@ -5,10 +5,14 @@
 - reg : the location and size of the BAM hardware
 - interrupts : the BAM hardware to apps processor interrupt line
 
+Optional properties:
+-qcom,satellite-mode: the hardware needs to be configured in satellite mode
+
 Example:
 
 	qcom,bam_dmux@fc834000 {
 		compatible = "qcom,bam_dmux";
 		reg = <0xfc834000 0x7000>;
 		interrupts = <0 29 1>;
+		qcom,satellite-mode;
 	};
diff --git a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
index 068e256..5f18893 100644
--- a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
+++ b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
@@ -40,3 +40,21 @@
 EXPORT_COMPAT("qcom,a-driver") to the driver, similar to EXPORT_SYMBOL.
 The EXPORT_COMPAT is to ensure that memory is only carved out if the
 driver is actually enabled, otherwise the memory will not be used.
+
+In order to specify the size and address of the fixed memory which has
+previously been removed the memory-fixed binding can be used. This assumes
+that the region has been removed by a separate memblock-remove property
+present in the device tree.
+
+Required parameters:
+-qcom,memory-fixed: base and size of the fixed memory region
+
+	qcom,a-driver {
+		compatible = "qcom,a-driver";
+		/* Fixed Memory region of 4MB at 0x200000*/
+		qcom,memory-fixed = <0x200000 0x400000>;
+	};
+
+This region is assumed to be a part of a separate hole that has been removed
+and this binding specifies the fixed location and size of the region within
+that hole.
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index eda7cba..ef77e1e 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -37,6 +37,17 @@
 - linux,default-trigger: trigger the led from external modules such as display
 - qcom,default-state:  default state of the led, should be "on" or "off"
 
+Flash is used primarily as a camera or video flash.
+
+Optional properties for flash:
+- qcom,headroom: headroom to use, mV
+- qcom,duration: duration of the flash, ms
+- qcom,clamp-curr: current to clamp at, mA
+- qcom,startup-dly: delay before flashing after flash executed, us
+- qcom,saftey-timer: include for safety timer use, otherwise watchdog timer will be used
+- linux,default-trigger: trigger the led from external modules such as display
+- qcom,default-state:  default state of the led, should be "on" or "off"
+
 Example:
 
 	qcom,leds@d800 {
@@ -60,3 +71,22 @@
 			};
 	};
 
+	qcom,leds@d300 {
+			compatible = "qcom,leds-qpnp";
+			status = "okay";
+			qcom,flash_0 {
+				qcom,max-current = <1000>;
+				qcom,default-state = "off";
+				qcom,headroom = <0>;
+				qcom,duration = <200>;
+				qcom,clamp-curr = <200>;
+				qcom,startup-dly = <1>;
+				qcom,safety-timer;
+				label = "flash";
+				linux,default-trigger =
+					"flash0_trigger";
+				linux,name = "led:flash_0";
+				qcom,current = <625>;
+				qcom,id = <1>;
+			};
+	};
diff --git a/Documentation/devicetree/bindings/pil/pil-mba.txt b/Documentation/devicetree/bindings/pil/pil-mba.txt
deleted file mode 100644
index ce6bb8f..0000000
--- a/Documentation/devicetree/bindings/pil/pil-mba.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Qualcomm Modem Boot Authenticator Peripheral Image Loader
-
-pil-mba is a peripheral image loader (PIL) driver. It is used for loading
-modem images using the self-authenticating hardware and software features
-of the Modem Boot Authenticator.
-
-Required properties:
-- compatible:	      Must be "qcom,pil-mba"
-- reg:		      Two pairs of physical base addresses and sizes. The
-		      first corresponds to the Relay Message Buffer (RMB)
-		      register base. The second specifies the address at which
-		      the primary modem image metadata should be stored.
-- reg-names:	      Names for the above base addresses. "rmb_base" and
-	              "metadata_base" are expected.
-- interrupts:         The modem watchdog interrupt
-- qcom,firmware-name: Base name of the firmware image. Ex. "modem"
-
-Optional properties:
-- qcom,depends-on:    firmware-name of a prerequisite image that must already
-		      be running.
-
-Example:
-	qcom,mba@fc820000 {
-		compatible = "qcom,pil-mba";
-		reg = <0xfc820000 0x0020>,
-		      <0x0d1f0000 0x4000>;
-		reg-names = "rmb_base", "metadata_base";
-		interrupts = <0 56 1>;
-
-		qcom,firmware-name = "modem";
-		qcom,depends-on    = "mba";
-	};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 41ffd8a..f83de7e 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -10,8 +10,9 @@
 - reg:		      Pairs of physical base addresses and region sizes of
 		      memory mapped registers.
 - reg-names:	      Names of the bases for the above registers. "qdsp6_base",
-		      "halt_base", "rmb_base", "restart_reg" and "clamp_reg"
-		      are expected.
+		      "halt_base", "rmb_base", "restart_reg", and
+		      "metadata_base" are expected.
+- interrupts:         The modem watchdog interrupt
 - vdd_mss-supply:     Reference to the regulator that supplies the processor.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
 - qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
@@ -25,9 +26,10 @@
 		      <0xfd485000 0x400>,
 		      <0xfc820000 0x020>,
 		      <0xfc401680 0x004>,
-		      <0xfc980008 0x004>;
+		      <0x0d1f0000 0x4000>;
 		reg-names = "qdsp6_base", "halt_base", "rmb_base",
-			    "restart_reg", "clamp_reg";
+			    "restart_reg", metadata_base";
+		interrupts = <0 24 1>;
 		vdd_mss-supply = <&pm8841_s3>;
 
 		qcom,firmware-name = "mba";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index de30884..341b49b 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -993,6 +993,36 @@
 			status = "disabled";
 		};
 
+		qcom,leds@d300 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd300 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d400 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd400 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d500 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd500 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d600 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd600 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d700 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd700 0x100>;
+			label = "flash";
+		};
+
 		qcom,leds@d800 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xd800 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
new file mode 100644
index 0000000..8fe94a5
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -0,0 +1,274 @@
+/* Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+ /* Stub Regulators */
+
+ / {
+	pm8026_s1: regulator-s1 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_s1";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1150000>;
+		regulator-max-microvolt = <1150000>;
+	};
+
+	pm8026_s2: regulator-s2 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_s2";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+	};
+
+	pm8026_s3: regulator-s3 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_s3";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1300000>;
+		regulator-max-microvolt = <1300000>;
+	};
+
+	pm8026_s4: regulator-s4 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_s4";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <2100000>;
+		regulator-max-microvolt = <2100000>;
+	};
+
+	pm8026_s5: regulator-s5 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_s5";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1150000>;
+		regulator-max-microvolt = <1150000>;
+	};
+
+	pm8026_l1: regulator-l1 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l1";
+		parent-supply = <&pm8026_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1225000>;
+		regulator-max-microvolt = <1225000>;
+	};
+
+	pm8026_l2: regulator-l2 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l2";
+		parent-supply = <&pm8026_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+	};
+
+	pm8026_l3: regulator-l3 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l3";
+		parent-supply = <&pm8026_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1150000>;
+		regulator-max-microvolt = <1150000>;
+	};
+
+	pm8026_l4: regulator-l4 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l4";
+		parent-supply = <&pm8026_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+	};
+
+	pm8026_l5: regulator-l5 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l5";
+		parent-supply = <&pm8026_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+	};
+
+	pm8026_l6: regulator-l6 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l6";
+		parent-supply = <&pm8026_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8026_l7: regulator-l7 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l7";
+		parent-supply = <&pm8026_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1850000>;
+		regulator-max-microvolt = <1850000>;
+	};
+
+	pm8026_l8: regulator-l8 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l8";
+		parent-supply = <&pm8026_s4>;
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8026_l9: regulator-l9 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l9";
+		parent-supply = <&pm8026_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2050000>;
+		regulator-max-microvolt = <2050000>;
+	};
+
+	pm8026_l10: regulator-l10 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l10";
+		parent-supply = <&pm8026_s4>;
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8026_l12: regulator-l12 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l12";
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8026_l14: regulator-l14 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l14";
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <2750000>;
+		regulator-max-microvolt = <2750000>;
+	};
+
+	pm8026_l15: regulator-l15 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l15";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+	};
+
+	pm8026_l16: regulator-l16 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l16";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <3000000>;
+		regulator-max-microvolt = <3000000>;
+	};
+
+	pm8026_l17: regulator-l17 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l17";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2950000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	pm8026_l18: regulator-l18 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l18";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2950000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	pm8026_l19: regulator-l19 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l19";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2850000>;
+		regulator-max-microvolt = <2850000>;
+	};
+
+	pm8026_l20: regulator-l20 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l20";
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <3075000>;
+		regulator-max-microvolt = <3075000>;
+	};
+
+	pm8026_l21: regulator-l21 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l21";
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	pm8026_l22: regulator-l22 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l22";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	pm8026_l23: regulator-l23 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l23";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	pm8026_l24: regulator-l24 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l24";
+		parent-supply = <&pm8026_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1300000>;
+		regulator-max-microvolt = <1300000>;
+	};
+
+	pm8026_l26: regulator-l26 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l26";
+		parent-supply = <&pm8026_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1225000>;
+		regulator-max-microvolt = <1225000>;
+	};
+
+	pm8026_l27: regulator-l27 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l27";
+		parent-supply = <&pm8026_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2050000>;
+		regulator-max-microvolt = <2050000>;
+	};
+
+	pm8026_l28: regulator-l28 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_l28";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	 pm8026_lvs1: regulator-lvs1 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8026_lvs1";
+		parent-supply = <&pm8026_l6>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 6d2ffec..db2bfb3 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -58,6 +58,9 @@
 		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0>;
 		interrupt-names = "core_irq";
+                HSUSB_VDDCX-supply = <&pm8026_s1>;
+                HSUSB_1p8-supply = <&pm8026_l10>;
+                HSUSB_3p3-supply = <&pm8026_l20>;
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
@@ -70,3 +73,5 @@
 	};
 
 };
+
+/include/ "msm8226-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm8910-regulator.dtsi b/arch/arm/boot/dts/msm8910-regulator.dtsi
new file mode 100644
index 0000000..a32d4ab
--- /dev/null
+++ b/arch/arm/boot/dts/msm8910-regulator.dtsi
@@ -0,0 +1,218 @@
+/* Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+ /* Stub Regulators */
+
+ / {
+	pm8110_s1: regulator-s1 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_s1";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1150000>;
+		regulator-max-microvolt = <1150000>;
+	};
+
+	pm8110_s2: regulator-s2 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_s2";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1050000>;
+	};
+
+	pm8110_s3: regulator-s3 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_s3";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <1350000>;
+		regulator-max-microvolt = <1350000>;
+	};
+
+	pm8110_s4: regulator-s4 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_s4";
+		qcom,hpm-min-load = <100000>;
+		regulator-min-microvolt = <2150000>;
+		regulator-max-microvolt = <2150000>;
+	};
+
+	pm8110_l1: regulator-l1 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l1";
+		parent-supply = <&pm8110_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1225000>;
+		regulator-max-microvolt = <1225000>;
+	};
+
+	pm8110_l2: regulator-l2 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l2";
+		parent-supply = <&pm8110_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+	};
+
+	pm8110_l3: regulator-l3 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l3";
+		parent-supply = <&pm8110_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1150000>;
+		regulator-max-microvolt = <1150000>;
+	};
+
+	pm8110_l4: regulator-l4 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l4";
+		parent-supply = <&pm8110_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+	};
+
+	pm8110_l5: regulator-l5 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l5";
+		parent-supply = <&pm8110_s3>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1300000>;
+		regulator-max-microvolt = <1300000>;
+	};
+
+	pm8110_l6: regulator-l6 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l6";
+		parent-supply = <&pm8110_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8110_l7: regulator-l7 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l7";
+		parent-supply = <&pm8110_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2050000>;
+		regulator-max-microvolt = <2050000>;
+	};
+
+	pm8110_l8: regulator-l8 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l8";
+		parent-supply = <&pm8110_s4>;
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8110_l9: regulator-l9 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l9";
+		parent-supply = <&pm8110_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2050000>;
+		regulator-max-microvolt = <2050000>;
+	};
+
+	pm8110_l10: regulator-l10 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l10";
+		parent-supply = <&pm8110_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8110_l12: regulator-l12 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l12";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	pm8110_l14: regulator-l14 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l14";
+		parent-supply = <&pm8110_s4>;
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	pm8110_l15: regulator-l15 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l15";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	pm8110_l16: regulator-l16 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l16";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <3000000>;
+		regulator-max-microvolt = <3000000>;
+	};
+
+	pm8110_l17: regulator-l17 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l17";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2900000>;
+		regulator-max-microvolt = <2900000>;
+	};
+
+	pm8110_l18: regulator-l18 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l18";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	pm8110_l19: regulator-l19 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l19";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <2850000>;
+		regulator-max-microvolt = <2850000>;
+	};
+
+	pm8110_l20: regulator-l20 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l20";
+		qcom,hpm-min-load = <5000>;
+		regulator-min-microvolt = <3075000>;
+		regulator-max-microvolt = <3075000>;
+	};
+
+	pm8110_l21: regulator-l21 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l21";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <2950000>;
+	};
+
+	pm8110_l22: regulator-l22 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "8110_l22";
+		qcom,hpm-min-load = <10000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index 83dabfb..a2e1338 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -62,4 +62,47 @@
 		compatible = "qcom,android-usb";
 	};
 
+	sdcc1: qcom,sdcc@f9824000 {
+		cell-index = <1>; /* SDC1 eMMC slot */
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf9824000 0x800>;
+		reg-names = "core_mem";
+		interrupts = <0 123 0>;
+		interrupt-names = "core_irq";
+
+		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sdcc-sup-voltages = <2950 2950>;
+		qcom,sdcc-bus-width = <8>;
+		qcom,sdcc-nonremovable;
+		qcom,sdcc-bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	};
+
+	sdcc2: qcom,sdcc@f98a4000 {
+		cell-index = <2>; /* SDC2 SD card slot */
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf98a4000 0x800>;
+		reg-names = "core_mem";
+		interrupts = <0 125 0>;
+		interrupt-names = "core_irq";
+
+		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sdcc-sup-voltages = <2950 2950>;
+		qcom,sdcc-bus-width = <4>;
+		qcom,sdcc-xpc;
+		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+		qcom,sdcc-current-limit = <800>;
+	};
+
 };
+
+/include/ "msm8910-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index 0e0f6cf..b8b3141 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -13,356 +13,10 @@
 /dts-v1/;
 
 /include/ "msm8974.dtsi"
-/include/ "dsi-panel-toshiba-720p-video.dtsi"
+/include/ "msm8974-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974 CDP";
 	compatible = "qcom,msm8974-cdp", "qcom,msm8974";
 	qcom,msm-id = <126 1 0>;
-
-	serial@f991e000 {
-		status = "ok";
-	};
-
-	qcom,mdss_dsi@fd922800 {
-		qcom,mdss_dsi_toshiba_720p_video {
-			status = "ok";
-		};
-	};
-
-	qcom,hdmi_tx@fd922100 {
-		status = "ok";
-	};
-
-	i2c@f9924000 {
-		atmel_mxt_ts@4a {
-			compatible = "atmel,mxt-ts";
-			reg = <0x4a>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <61 0x2>;
-			vdd_ana-supply = <&pm8941_l18>;
-			vcc_i2c-supply = <&pm8941_lvs1>;
-			atmel,reset-gpio = <&msmgpio 60 0x00>;
-			atmel,irq-gpio = <&msmgpio 61 0x00>;
-			atmel,panel-coords = <0  0 760 1424>;
-			atmel,display-coords = <0 0 720 1280>;
-			atmel,i2c-pull-up = <1>;
-			atmel,cfg_1 {
-				atmel,family-id = <0x82>;
-				atmel,variant-id = <0x19>;
-				atmel,version = <0x10>;
-				atmel,build = <0xaa>;
-				atmel,config = [
-					/* Object 6, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 38, Instance = 0 */
-					15 00 02 10 08 0C 00 00
-					/* Object 7, Instance = 0 */
-					FF FF 32 03
-					/* Object 8, Instance = 0 */
-					0F 00 0A 0A 00 00 0A 00 00 00
-					/* Object 9, Instance = 0 */
-					83 00 00 18 0E 00 70 32 02 01
-					00 03 01 01 05 0A 0A 0A 90 05
-					F8 02 00 00 0F 0F 00 00 48 2D
-					07 0C 00 00 00 00
-					/* Object 15, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00
-					/* Object 18, Instance = 0 */
-					00 00
-					/* Object 19, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 23, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 25, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 40, Instance = 0 */
-					00 00 00 00 00
-					/* Object 42, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					/* Object 46, Instance = 0 */
-					00 00 10 10 00 00 03 00 00 01
-					/* Object 47, Instance = 0 */
-					08 0A 28 0A 02 0A 00 8C 00 20
-					00 00 00
-					/* Object 55, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 56, Instance = 0 */
-					03 00 01 18 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00
-					/* Object 57, Instance = 0 */
-					00 00 00
-					/* Object 61, Instance = 0 */
-					00 00 00 00 00
-					/* Object 61, Instance = 1 */
-					00 00 00 00 00
-					/* Object 62, Instance = 0 */
-					7F 03 00 16 00 00 00 00 00 00
-					04 08 10 18 05 00 0A 05 05 50
-					14 19 34 1A 64 00 00 04 40 00
-					00 00 00 00 30 32 02 00 01 00
-					05 00 00 00 00 00 00 00 00 00
-					00 00 0C 00
-					];
-			};
-		};
-	};
-
-	gpio_keys {
-		compatible = "gpio-keys";
-		input-name = "gpio-keys";
-
-		camera_snapshot {
-			label = "camera_snapshot";
-			gpios = <&pm8941_gpios 3 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x2fe>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		camera_focus {
-			label = "camera_focus";
-			gpios = <&pm8941_gpios 4 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x210>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		vol_up {
-			label = "volume_up";
-			gpios = <&pm8941_gpios 5 0x1>;
-			linux,input-type = <1>;
-			linux,code = <115>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-	};
-
-	spi@f9923000 {
-		ethernet-switch@2 {
-			compatible = "micrel,ks8851";
-			reg = <2>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <94 0>;
-			spi-max-frequency = <4800000>;
-			rst-gpio = <&pm8941_mpps 6 0>;
-			vdd-io-supply = <&spi_eth_vreg>;
-			vdd-phy-supply = <&spi_eth_vreg>;
-		};
-	};
-};
-
-&sdcc2 {
-	#address-cells = <0>;
-	interrupt-parent = <&sdcc2>;
-	interrupts = <0 1 2>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 125 0
-			1 &intc 0 220 0
-			2 &msmgpio 62 0x3>;
-	interrupt-names = "core_irq", "bam_irq", "status_irq";
-	cd-gpios = <&msmgpio 62 0x1>;
-	wp-gpios = <&pm8941_gpios 29 0x1>;
-};
-
-&pm8941_gpios {
-	gpio@c000 { /* GPIO 1 */
-	};
-
-	gpio@c100 { /* GPIO 2 */
-	};
-
-	gpio@c200 { /* GPIO 3 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c300 { /* GPIO 4 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c400 { /* GPIO 5 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c500 { /* GPIO 6 */
-	};
-
-	gpio@c600 { /* GPIO 7 */
-	};
-
-	gpio@c700 { /* GPIO 8 */
-	};
-
-	gpio@c800 { /* GPIO 9 */
-	};
-
-	gpio@c900 { /* GPIO 10 */
-	};
-
-	gpio@ca00 { /* GPIO 11 */
-	};
-
-	gpio@cb00 { /* GPIO 12 */
-	};
-
-	gpio@cc00 { /* GPIO 13 */
-	};
-
-	gpio@cd00 { /* GPIO 14 */
-	};
-
-	gpio@ce00 { /* GPIO 15 */
-		qcom,mode = <1>;
-		qcom,output-type = <0>;
-		qcom,pull = <5>;
-		qcom,vin-sel = <2>;
-		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
-		qcom,master-en = <1>;
-	};
-
-	gpio@cf00 { /* GPIO 16 */
-	};
-
-	gpio@d000 { /* GPIO 17 */
-	};
-
-	gpio@d100 { /* GPIO 18 */
-	};
-
-	gpio@d200 { /* GPIO 19 */
-		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
-		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
-		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
-		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
-		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
-		qcom,master-en = <1>;
-	};
-
-	gpio@d300 { /* GPIO 20 */
-	};
-
-	gpio@d400 { /* GPIO 21 */
-	};
-
-	gpio@d500 { /* GPIO 22 */
-	};
-
-	gpio@d600 { /* GPIO 23 */
-	};
-
-	gpio@d700 { /* GPIO 24 */
-	};
-
-	gpio@d800 { /* GPIO 25 */
-	};
-
-	gpio@d900 { /* GPIO 26 */
-	};
-
-	gpio@da00 { /* GPIO 27 */
-	};
-
-	gpio@db00 { /* GPIO 28 */
-	};
-
-	gpio@dc00 { /* GPIO 29 */
-		qcom,pull = <0>; /* set to default pull */
-		qcom,master-en = <1>;
-		qcom,vin-sel = <2>; /* select 1.8 V source */
-	};
-
-	gpio@dd00 { /* GPIO 30 */
-	};
-
-	gpio@de00 { /* GPIO 31 */
-	};
-
-	gpio@df00 { /* GPIO 32 */
-	};
-
-	gpio@e000 { /* GPIO 33 */
-	};
-
-	gpio@e100 { /* GPIO 34 */
-	};
-
-	gpio@e200 { /* GPIO 35 */
-	};
-
-	gpio@e300 { /* GPIO 36 */
-	};
-};
-
-&pm8941_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
-
-	mpp@a400 { /* MPP 5 */
-		/* SPI_ETH config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a500 { /* MPP 6 */
-		/* SPI_ETH_RST config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a600 { /* MPP 7 */
-	};
-
-	mpp@a700 { /* MPP 8 */
-	};
-};
-
-&pm8841_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
 };
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
new file mode 100644
index 0000000..00f20ad
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -0,0 +1,361 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/ "dsi-panel-toshiba-720p-video.dtsi"
+
+/ {
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	qcom,mdss_dsi@fd922800 {
+		qcom,mdss_dsi_toshiba_720p_video {
+			status = "ok";
+		};
+	};
+
+	qcom,hdmi_tx@fd922100 {
+		status = "ok";
+	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l18>;
+			vcc_i2c-supply = <&pm8941_lvs1>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0  0 760 1424>;
+			atmel,display-coords = <0 0 720 1280>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0x82>;
+				atmel,variant-id = <0x19>;
+				atmel,version = <0x10>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					15 00 02 10 08 0C 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 32 03
+					/* Object 8, Instance = 0 */
+					0F 00 0A 0A 00 00 0A 00 00 00
+					/* Object 9, Instance = 0 */
+					83 00 00 18 0E 00 70 32 02 01
+					00 03 01 01 05 0A 0A 0A 90 05
+					F8 02 00 00 0F 0F 00 00 48 2D
+					07 0C 00 00 00 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					00 00
+					/* Object 19, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 23, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 00 00 00 00
+					/* Object 42, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 03 00 00 01
+					/* Object 47, Instance = 0 */
+					08 0A 28 0A 02 0A 00 8C 00 20
+					00 00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					03 00 01 18 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 61, Instance = 1 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					7F 03 00 16 00 00 00 00 00 00
+					04 08 10 18 05 00 0A 05 05 50
+					14 19 34 1A 64 00 00 04 40 00
+					00 00 00 00 30 32 02 00 01 00
+					05 00 00 00 00 00 00 00 00 00
+					00 00 0C 00
+					];
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&pm8941_gpios 3 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&pm8941_gpios 4 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	spi@f9923000 {
+		ethernet-switch@2 {
+			compatible = "micrel,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <94 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&pm8941_mpps 6 0>;
+			vdd-io-supply = <&spi_eth_vreg>;
+			vdd-phy-supply = <&spi_eth_vreg>;
+		};
+	};
+};
+
+&sdcc2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdcc2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 220 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "core_irq", "bam_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+	wp-gpios = <&pm8941_gpios 29 0x1>;
+};
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dts b/arch/arm/boot/dts/msm8974-fluid.dts
index 891379f..b014e14 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-fluid.dts
@@ -13,359 +13,10 @@
 /dts-v1/;
 
 /include/ "msm8974.dtsi"
-/include/ "dsi-panel-toshiba-720p-video.dtsi"
+/include/ "msm8974-fluid.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974 FLUID";
 	compatible = "qcom,msm8974-fluid", "qcom,msm8974";
 	qcom,msm-id = <126 3 0>;
-
-	serial@f991e000 {
-		status = "ok";
-	};
-
-	qcom,mdss_dsi@fd922800 {
-		qcom,mdss_dsi_toshiba_720p_video {
-			status = "ok";
-		};
-	};
-
-	qcom,hdmi_tx@fd922100 {
-		status = "ok";
-	};
-
-	i2c@f9924000 {
-		atmel_mxt_ts@4a {
-			compatible = "atmel,mxt-ts";
-			reg = <0x4a>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <61 0x2>;
-			vdd_ana-supply = <&pm8941_l18>;
-			vcc_i2c-supply = <&pm8941_lvs1>;
-			atmel,reset-gpio = <&msmgpio 60 0x00>;
-			atmel,irq-gpio = <&msmgpio 61 0x00>;
-			atmel,panel-coords = <0  0 760 1424>;
-			atmel,display-coords = <0 0 720 1280>;
-			atmel,i2c-pull-up = <1>;
-			atmel,cfg_1 {
-				atmel,family-id = <0x82>;
-				atmel,variant-id = <0x19>;
-				atmel,version = <0x10>;
-				atmel,build = <0xaa>;
-				atmel,config = [
-					/* Object 6, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 38, Instance = 0 */
-					15 00 02 10 08 0C 00 00
-					/* Object 7, Instance = 0 */
-					FF FF 32 03
-					/* Object 8, Instance = 0 */
-					0F 00 0A 0A 00 00 0A 00 00 00
-					/* Object 9, Instance = 0 */
-					83 00 00 18 0E 00 70 32 02 01
-					00 03 01 01 05 0A 0A 0A 90 05
-					F8 02 00 00 0F 0F 00 00 48 2D
-					07 0C 00 00 00 00
-					/* Object 15, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00
-					/* Object 18, Instance = 0 */
-					00 00
-					/* Object 19, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 23, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 25, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 40, Instance = 0 */
-					00 00 00 00 00
-					/* Object 42, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					/* Object 46, Instance = 0 */
-					00 00 10 10 00 00 03 00 00 01
-					/* Object 47, Instance = 0 */
-					08 0A 28 0A 02 0A 00 8C 00 20
-					00 00 00
-					/* Object 55, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 56, Instance = 0 */
-					03 00 01 18 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00
-					/* Object 57, Instance = 0 */
-					00 00 00
-					/* Object 61, Instance = 0 */
-					00 00 00 00 00
-					/* Object 61, Instance = 1 */
-					00 00 00 00 00
-					/* Object 62, Instance = 0 */
-					7F 03 00 16 00 00 00 00 00 00
-					04 08 10 18 05 00 0A 05 05 50
-					14 19 34 1A 64 00 00 04 40 00
-					00 00 00 00 30 32 02 00 01 00
-					05 00 00 00 00 00 00 00 00 00
-					00 00 0C 00
-					];
-			};
-		};
-	};
-
-	gpio_keys {
-		compatible = "gpio-keys";
-		input-name = "gpio-keys";
-
-		camera_snapshot {
-			label = "camera_snapshot";
-			gpios = <&pm8941_gpios 3 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x2fe>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		camera_focus {
-			label = "camera_focus";
-			gpios = <&pm8941_gpios 4 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x210>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		vol_up {
-			label = "volume_up";
-			gpios = <&pm8941_gpios 5 0x1>;
-			linux,input-type = <1>;
-			linux,code = <115>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-	};
-
-	spi@f9923000 {
-		ethernet-switch@2 {
-			compatible = "micrel,ks8851";
-			reg = <2>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <94 0>;
-			spi-max-frequency = <4800000>;
-			rst-gpio = <&pm8941_mpps 6 0>;
-			vdd-io-supply = <&spi_eth_vreg>;
-			vdd-phy-supply = <&spi_eth_vreg>;
-		};
-	};
-};
-
-&sdcc1 {
-	qcom,sdcc-bus-width = <4>;
-};
-
-&sdcc2 {
-	#address-cells = <0>;
-	interrupt-parent = <&sdcc2>;
-	interrupts = <0 1 2>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 125 0
-			1 &intc 0 220 0
-			2 &msmgpio 62 0x3>;
-	interrupt-names = "core_irq", "bam_irq", "status_irq";
-	cd-gpios = <&msmgpio 62 0x1>;
-};
-
-&pm8941_gpios {
-	gpio@c000 { /* GPIO 1 */
-	};
-
-	gpio@c100 { /* GPIO 2 */
-	};
-
-	gpio@c200 { /* GPIO 3 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c300 { /* GPIO 4 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c400 { /* GPIO 5 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c500 { /* GPIO 6 */
-	};
-
-	gpio@c600 { /* GPIO 7 */
-	};
-
-	gpio@c700 { /* GPIO 8 */
-	};
-
-	gpio@c800 { /* GPIO 9 */
-	};
-
-	gpio@c900 { /* GPIO 10 */
-	};
-
-	gpio@ca00 { /* GPIO 11 */
-	};
-
-	gpio@cb00 { /* GPIO 12 */
-	};
-
-	gpio@cc00 { /* GPIO 13 */
-	};
-
-	gpio@cd00 { /* GPIO 14 */
-	};
-
-	gpio@ce00 { /* GPIO 15 */
-		qcom,mode = <1>;
-		qcom,output-type = <0>;
-		qcom,pull = <5>;
-		qcom,vin-sel = <2>;
-		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
-		qcom,master-en = <1>;
-	};
-
-	gpio@cf00 { /* GPIO 16 */
-	};
-
-	gpio@d000 { /* GPIO 17 */
-	};
-
-	gpio@d100 { /* GPIO 18 */
-	};
-
-	gpio@d200 { /* GPIO 19 */
-		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
-		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
-		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
-		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
-		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
-		qcom,master-en = <1>;
-	};
-
-	gpio@d300 { /* GPIO 20 */
-	};
-
-	gpio@d400 { /* GPIO 21 */
-	};
-
-	gpio@d500 { /* GPIO 22 */
-	};
-
-	gpio@d600 { /* GPIO 23 */
-	};
-
-	gpio@d700 { /* GPIO 24 */
-	};
-
-	gpio@d800 { /* GPIO 25 */
-	};
-
-	gpio@d900 { /* GPIO 26 */
-	};
-
-	gpio@da00 { /* GPIO 27 */
-	};
-
-	gpio@db00 { /* GPIO 28 */
-	};
-
-	gpio@dc00 { /* GPIO 29 */
-		qcom,pull = <0>; /* set to default pull */
-		qcom,master-en = <1>;
-		qcom,vin-sel = <2>; /* select 1.8 V source */
-	};
-
-	gpio@dd00 { /* GPIO 30 */
-	};
-
-	gpio@de00 { /* GPIO 31 */
-	};
-
-	gpio@df00 { /* GPIO 32 */
-	};
-
-	gpio@e000 { /* GPIO 33 */
-	};
-
-	gpio@e100 { /* GPIO 34 */
-	};
-
-	gpio@e200 { /* GPIO 35 */
-	};
-
-	gpio@e300 { /* GPIO 36 */
-	};
-};
-
-&pm8941_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
-
-	mpp@a400 { /* MPP 5 */
-		/* SPI_ETH config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a500 { /* MPP 6 */
-		/* SPI_ETH_RST config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a600 { /* MPP 7 */
-	};
-
-	mpp@a700 { /* MPP 8 */
-	};
-};
-
-&pm8841_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
 };
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
new file mode 100644
index 0000000..a55e6d4
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -0,0 +1,364 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/ "dsi-panel-toshiba-720p-video.dtsi"
+
+/ {
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	qcom,mdss_dsi@fd922800 {
+		qcom,mdss_dsi_toshiba_720p_video {
+			status = "ok";
+		};
+	};
+
+	qcom,hdmi_tx@fd922100 {
+		status = "ok";
+	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l18>;
+			vcc_i2c-supply = <&pm8941_lvs1>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0  0 760 1424>;
+			atmel,display-coords = <0 0 720 1280>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0x82>;
+				atmel,variant-id = <0x19>;
+				atmel,version = <0x10>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					15 00 02 10 08 0C 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 32 03
+					/* Object 8, Instance = 0 */
+					0F 00 0A 0A 00 00 0A 00 00 00
+					/* Object 9, Instance = 0 */
+					83 00 00 18 0E 00 70 32 02 01
+					00 03 01 01 05 0A 0A 0A 90 05
+					F8 02 00 00 0F 0F 00 00 48 2D
+					07 0C 00 00 00 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					00 00
+					/* Object 19, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 23, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 00 00 00 00
+					/* Object 42, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 03 00 00 01
+					/* Object 47, Instance = 0 */
+					08 0A 28 0A 02 0A 00 8C 00 20
+					00 00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					03 00 01 18 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 61, Instance = 1 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					7F 03 00 16 00 00 00 00 00 00
+					04 08 10 18 05 00 0A 05 05 50
+					14 19 34 1A 64 00 00 04 40 00
+					00 00 00 00 30 32 02 00 01 00
+					05 00 00 00 00 00 00 00 00 00
+					00 00 0C 00
+					];
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&pm8941_gpios 3 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&pm8941_gpios 4 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	spi@f9923000 {
+		ethernet-switch@2 {
+			compatible = "micrel,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <94 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&pm8941_mpps 6 0>;
+			vdd-io-supply = <&spi_eth_vreg>;
+			vdd-phy-supply = <&spi_eth_vreg>;
+		};
+	};
+};
+
+&sdcc1 {
+	qcom,sdcc-bus-width = <4>;
+};
+
+&sdcc2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdcc2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 220 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "core_irq", "bam_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+};
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 9b5aaac..634ac43 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -45,6 +45,13 @@
 			qcom,memory-reservation-size = <0x2000>;
 		};
 
+		qcom,ion-heap@23 { /* PIL1 HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <23>;
+			qcom,heap-align = <0x10000>;
+			qcom,memory-fixed = <0xd200000 0x2800000>;
+		};
+
 		qcom,ion-heap@24 { /* SF HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <24>;
@@ -57,6 +64,13 @@
 			reg = <25>;
 		};
 
+		qcom,ion-heap@26 { /* PIL2 HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <26>;
+			qcom,heap-align = <0x10000>;
+			qcom,memory-fixed = <0x8400000 0x4e00000>;
+		};
+
 		qcom,ion-heap@27 { /* QSECOM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <27>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dts b/arch/arm/boot/dts/msm8974-liquid.dts
index d1a6148..ef38036 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-liquid.dts
@@ -13,392 +13,10 @@
 /dts-v1/;
 
 /include/ "msm8974.dtsi"
+/include/ "msm8974-liquid.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974 LIQUID";
 	compatible = "qcom,msm8974-liquid", "qcom,msm8974";
 	qcom,msm-id = <126 9 0>;
-
-	serial@f991e000 {
-		status = "ok";
-	};
-
-	qcom,mdss_edp@fd923400 {
-		status = "ok";
-	};
-
-	i2c@f9967000 {
-		battery@b {
-			compatible = "ti,bq28400-battery";
-			reg = <0xb>;
-		};
-	};
-
-	gpio_keys {
-		compatible = "gpio-keys";
-		input-name = "gpio-keys";
-
-		home {
-			label = "home";
-			gpios = <&pm8941_gpios 1 0x1>;
-			linux,input-type = <1>;
-			linux,code = <102>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		vol_down {
-			label = "volume_down";
-			gpios = <&pm8941_gpios 2 0x1>;
-			linux,input-type = <1>;
-			linux,code = <114>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		vol_up {
-			label = "volume_up";
-			gpios = <&pm8941_gpios 5 0x1>;
-			linux,input-type = <1>;
-			linux,code = <115>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-	};
-
-	qcom,mdss_mdp@fd900000 {
-		qcom,memory-reservation-size = <0x1000000>; /* size 16MB */
-	};
-
-	qcom,hdmi_tx@fd922100 {
-		status = "ok";
-	};
-
-	i2c@f9924000 {
-		atmel_mxt_ts@4a {
-			compatible = "atmel,mxt-ts";
-			reg = <0x4a>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <61 0x2>;
-			vdd_ana-supply = <&pm8941_l22>;
-			vcc_i2c-supply = <&pm8941_s3>;
-			atmel,reset-gpio = <&msmgpio 60 0x00>;
-			atmel,irq-gpio = <&msmgpio 61 0x00>;
-			atmel,panel-coords = <0 0 1080 1920>;
-			atmel,display-coords = <0 0 1080 1920>;
-			atmel,i2c-pull-up = <1>;
-			atmel,cfg_1 {
-				atmel,family-id = <0xa2>;
-				atmel,variant-id = <0x00>;
-				atmel,version = <0x11>;
-				atmel,build = <0xaa>;
-				atmel,config = [
-					/* Object 6, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 38, Instance = 0 */
-					16 00 00 14 09 0C 00 00 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00
-					/* Object 7, Instance = 0 */
-					FF FF 0A 03
-					/* Object 8, Instance = 0 */
-					5F 00 14 14 00 00 00 01 00 00
-					/* Object 9, Instance = 0 */
-					8F 00 00 20 34 00 87 3C 08 03
-					00 05 03 80 0A 14 14 0A 80 07
-					38 04 00 00 00 00 00 00 00 00
-					0F 0F 2E 33 02 00
-					/* Object 15, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00
-					/* Object 18, Instance = 0 */
-					04 00
-					/* Object 24, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00 00 00 00 00
-					/* Object 25, Instance = 0 */
-					00 00 54 6F F0 55 00 00 00 00
-					00 00 00 00 00
-					/* Object 27, Instance = 0 */
-					00 00 00 00 00 00 00
-					/* Object 40, Instance = 0 */
-					00 14 14 14 14
-					/* Object 42, Instance = 0 */
-					20 14 00 00 00 14 11 00 03 00
-					/* Object 43, Instance = 0 */
-					09 00 01 01 91 00 80 00 00 00
-					00 00
-					/* Object 46, Instance = 0 */
-					00 00 10 10 00 00 01 00 00 0F
-					0A
-					/* Object 47, Instance = 0 */
-					00 14 23 02 05 1E 01 78 03 10
-					00 00 0C 00 00 00 00 00 00 00
-					00 00
-					/* Object 55, Instance = 0 */
-					00 00 00 00 00 00 00
-					/* Object 56, Instance = 0 */
-					02 00 01 30 13 14 14 14 15 15
-					15 15 15 15 15 16 16 16 16 16
-					16 16 16 16 16 15 14 14 14 14
-					15 14 14 14 14 13 00 00 01 02
-					05 05 00 00 00 00 00 00 00 00
-					00
-					/* Object 57, Instance = 0 */
-					00 00 00
-					/* Object 61, Instance = 0 */
-					00 00 00 00 00
-					/* Object 62, Instance = 0 */
-					00 01 03 01 00 00 00 00 00 0A
-					0F 14 19 23 05 00 0A 05 05 69
-					23 23 34 11 64 06 06 04 40 00
-					00 00 00 00 69 4B 02 00 00 80
-					0A 14 14 18 18 10 10 80 00 80
-					00 00 0F 02 00 00 00 00 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00
-					/* Object 63, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00
-					];
-			};
-		};
-	};
-
-	ext_5v: regulator-smb210 {
-		compatible = "regulator-fixed";
-		regulator-name = "ext_5v";
-		gpio = <&pm8941_mpps 2 0>;
-		enable-active-high;
-	};
-};
-
-&pm8941_mvs1 {
-	parent-supply = <&ext_5v>;
-};
-
-&pm8941_mvs2 {
-	parent-supply = <&ext_5v>;
-};
-
-&pm8941_gpios {
-	gpio@c000 { /* GPIO 1 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c100 { /* GPIO 2 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c200 { /* GPIO 3 */
-	};
-
-	gpio@c300 { /* GPIO 4 */
-	};
-
-	gpio@c400 { /* GPIO 5 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c500 { /* GPIO 6 */
-	};
-
-	gpio@c600 { /* GPIO 7 */
-	};
-
-	gpio@c700 { /* GPIO 8 */
-	};
-
-	gpio@c800 { /* GPIO 9 */
-	};
-
-	gpio@c900 { /* GPIO 10 */
-	};
-
-	gpio@ca00 { /* GPIO 11 */
-	};
-
-	gpio@cb00 { /* GPIO 12 */
-	};
-
-	gpio@cc00 { /* GPIO 13 */
-	};
-
-	gpio@cd00 { /* GPIO 14 */
-	};
-
-	gpio@ce00 { /* GPIO 15 */
-		qcom,mode = <1>;
-		qcom,output-type = <0>;
-		qcom,pull = <5>;
-		qcom,vin-sel = <2>;
-		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
-		qcom,master-en = <1>;
-	};
-
-	gpio@cf00 { /* GPIO 16 */
-	};
-
-	gpio@d000 { /* GPIO 17 */
-	};
-
-	gpio@d100 { /* GPIO 18 */
-	};
-
-	gpio@d200 { /* GPIO 19 */
-		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
-		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
-		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
-		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
-		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
-		qcom,master-en = <1>;
-	};
-
-	gpio@d300 { /* GPIO 20 */
-	};
-
-	gpio@d400 { /* GPIO 21 */
-	};
-
-	gpio@d500 { /* GPIO 22 */
-	};
-
-	gpio@d600 { /* GPIO 23 */
-	};
-
-	gpio@d700 { /* GPIO 24 */
-	};
-
-	gpio@d800 { /* GPIO 25 */
-	};
-
-	gpio@d900 { /* GPIO 26 */
-	};
-
-	gpio@da00 { /* GPIO 27 */
-	};
-
-	gpio@db00 { /* GPIO 28 */
-	};
-
-	gpio@dc00 { /* GPIO 29 */
-		qcom,pull = <0>; /* set to default pull */
-		qcom,master-en = <1>;
-		qcom,vin-sel = <2>; /* select 1.8 V source */
-	};
-
-	gpio@dd00 { /* GPIO 30 */
-	};
-
-	gpio@de00 { /* GPIO 31 */
-	};
-
-	gpio@df00 { /* GPIO 32 */
-	};
-
-	gpio@e000 { /* GPIO 33 */
-	};
-
-	gpio@e100 { /* GPIO 34 */
-	};
-
-	gpio@e200 { /* GPIO 35 */
-	};
-
-	gpio@e300 { /* GPIO 36 */
-		qcom,mode = <1>;  /* QPNP_PIN_MODE_DIG_OUT */
-		qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
-		qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
-		qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
-		qcom,out-strength = <3>; /* QPNP_PIN_OUT_STRENGTH_HIGH */
-		qcom,src-select = <3>; /* QPNP_PIN_SEL_FUNC_2 */
-		qcom,master-en = <1>;
-	};
-};
-
-&pm8941_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-		/* ext_5v regulator enable */
-		qcom,mode = <1>; /* Digital output */
-		qcom,invert = <0>; /* Output low initially */
-		qcom,vin-sel = <2>; /* PM8941 S3 = 1.8 V */
-		qcom,src-select = <0>; /* Constant */
-		qcom,master-en = <1>; /* Enable MPP */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
-
-	mpp@a400 { /* MPP 5 */
-		/* SPI_ETH config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a500 { /* MPP 6 */
-		/* SPI_ETH_RST config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a600 { /* MPP 7 */
-	};
-
-	mpp@a700 { /* MPP 8 */
-	};
-};
-
-&pm8841_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* HDMI_MUX_SEL MPP 3*/
-		status = "ok";
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8841_S3A 1.8V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a300 { /* HDMI_MUX_EN MPP 4*/
-		status = "ok";
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <0>; /* PM8841_VPH 3.4V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
 };
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
new file mode 100644
index 0000000..1e3d1b3
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -0,0 +1,396 @@
+/* Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+/ {
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	qcom,mdss_edp@fd923400 {
+		status = "ok";
+	};
+
+	i2c@f9967000 {
+		battery@b {
+			compatible = "ti,bq28400-battery";
+			reg = <0xb>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+
+		home {
+			label = "home";
+			gpios = <&pm8941_gpios 1 0x1>;
+			linux,input-type = <1>;
+			linux,code = <102>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_down {
+			label = "volume_down";
+			gpios = <&pm8941_gpios 2 0x1>;
+			linux,input-type = <1>;
+			linux,code = <114>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	qcom,mdss_mdp@fd900000 {
+		qcom,memory-reservation-size = <0x1000000>; /* size 16MB */
+	};
+
+	qcom,hdmi_tx@fd922100 {
+		status = "ok";
+	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l22>;
+			vcc_i2c-supply = <&pm8941_s3>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0 0 1080 1920>;
+			atmel,display-coords = <0 0 1080 1920>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0xa2>;
+				atmel,variant-id = <0x00>;
+				atmel,version = <0x11>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					16 00 00 14 09 0C 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 0A 03
+					/* Object 8, Instance = 0 */
+					5F 00 14 14 00 00 00 01 00 00
+					/* Object 9, Instance = 0 */
+					8F 00 00 20 34 00 87 3C 08 03
+					00 05 03 80 0A 14 14 0A 80 07
+					38 04 00 00 00 00 00 00 00 00
+					0F 0F 2E 33 02 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					04 00
+					/* Object 24, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 54 6F F0 55 00 00 00 00
+					00 00 00 00 00
+					/* Object 27, Instance = 0 */
+					00 00 00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 14 14 14 14
+					/* Object 42, Instance = 0 */
+					20 14 00 00 00 14 11 00 03 00
+					/* Object 43, Instance = 0 */
+					09 00 01 01 91 00 80 00 00 00
+					00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 01 00 00 0F
+					0A
+					/* Object 47, Instance = 0 */
+					00 14 23 02 05 1E 01 78 03 10
+					00 00 0C 00 00 00 00 00 00 00
+					00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					02 00 01 30 13 14 14 14 15 15
+					15 15 15 15 15 16 16 16 16 16
+					16 16 16 16 16 15 14 14 14 14
+					15 14 14 14 14 13 00 00 01 02
+					05 05 00 00 00 00 00 00 00 00
+					00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					00 01 03 01 00 00 00 00 00 0A
+					0F 14 19 23 05 00 0A 05 05 69
+					23 23 34 11 64 06 06 04 40 00
+					00 00 00 00 69 4B 02 00 00 80
+					0A 14 14 18 18 10 10 80 00 80
+					00 00 0F 02 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00
+					/* Object 63, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					];
+			};
+		};
+	};
+
+	ext_5v: regulator-smb210 {
+		compatible = "regulator-fixed";
+		regulator-name = "ext_5v";
+		gpio = <&pm8941_mpps 2 0>;
+		enable-active-high;
+	};
+};
+
+&pm8941_mvs1 {
+	parent-supply = <&ext_5v>;
+};
+
+&pm8941_mvs2 {
+	parent-supply = <&ext_5v>;
+};
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c100 { /* GPIO 2 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+		qcom,mode = <1>;  /* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>; /* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-select = <3>; /* QPNP_PIN_SEL_FUNC_2 */
+		qcom,master-en = <1>;
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+		/* ext_5v regulator enable */
+		qcom,mode = <1>; /* Digital output */
+		qcom,invert = <0>; /* Output low initially */
+		qcom,vin-sel = <2>; /* PM8941 S3 = 1.8 V */
+		qcom,src-select = <0>; /* Constant */
+		qcom,master-en = <1>; /* Enable MPP */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* HDMI_MUX_SEL MPP 3*/
+		status = "ok";
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8841_S3A 1.8V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a300 { /* HDMI_MUX_EN MPP 4*/
+		status = "ok";
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <0>; /* PM8841_VPH 3.4V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index c5fabab..9946cf0 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -13,403 +13,10 @@
 /dts-v1/;
 
 /include/ "msm8974.dtsi"
-/include/ "dsi-panel-toshiba-720p-video.dtsi"
+/include/ "msm8974-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974 MTP";
 	compatible = "qcom,msm8974-mtp", "qcom,msm8974";
 	qcom,msm-id = <126 8 0>;
-
-	serial@f991e000 {
-		status = "ok";
-	};
-
-	qcom,mdss_dsi@fd922800 {
-		qcom,mdss_dsi_toshiba_720p_video {
-			status = "ok";
-		};
-	};
-
-	qcom,hdmi_tx@fd922100 {
-		status = "disabled";
-	};
-
-	i2c@f9924000 {
-		atmel_mxt_ts@4a {
-			compatible = "atmel,mxt-ts";
-			reg = <0x4a>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <61 0x2>;
-			vdd_ana-supply = <&pm8941_l18>;
-			vcc_i2c-supply = <&pm8941_lvs1>;
-			atmel,reset-gpio = <&msmgpio 60 0x00>;
-			atmel,irq-gpio = <&msmgpio 61 0x00>;
-			atmel,panel-coords = <0  0 760 1424>;
-			atmel,display-coords = <0 0 720 1280>;
-			atmel,i2c-pull-up = <1>;
-			atmel,cfg_1 {
-				atmel,family-id = <0x82>;
-				atmel,variant-id = <0x19>;
-				atmel,version = <0x10>;
-				atmel,build = <0xaa>;
-				atmel,config = [
-					/* Object 6, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 38, Instance = 0 */
-					15 00 02 10 08 0C 00 00
-					/* Object 7, Instance = 0 */
-					FF FF 32 03
-					/* Object 8, Instance = 0 */
-					0F 00 0A 0A 00 00 0A 00 00 00
-					/* Object 9, Instance = 0 */
-					83 00 00 18 0E 00 70 32 02 01
-					00 03 01 01 05 0A 0A 0A 90 05
-					F8 02 00 00 0F 0F 00 00 48 2D
-					07 0C 00 00 00 00
-					/* Object 15, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00
-					/* Object 18, Instance = 0 */
-					00 00
-					/* Object 19, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 23, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 25, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					00 00 00 00 00
-					/* Object 40, Instance = 0 */
-					00 00 00 00 00
-					/* Object 42, Instance = 0 */
-					00 00 00 00 00 00 00 00 00 00
-					/* Object 46, Instance = 0 */
-					00 00 10 10 00 00 03 00 00 01
-					/* Object 47, Instance = 0 */
-					08 0A 28 0A 02 0A 00 8C 00 20
-					00 00 00
-					/* Object 55, Instance = 0 */
-					00 00 00 00 00 00
-					/* Object 56, Instance = 0 */
-					03 00 01 18 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 05 05
-					05 05 05 05 05 05 05 05 00 00
-					00 00 00 00 00 00 00 00 00 00
-					00 00
-					/* Object 57, Instance = 0 */
-					00 00 00
-					/* Object 61, Instance = 0 */
-					00 00 00 00 00
-					/* Object 61, Instance = 1 */
-					00 00 00 00 00
-					/* Object 62, Instance = 0 */
-					7F 03 00 16 00 00 00 00 00 00
-					04 08 10 18 05 00 0A 05 05 50
-					14 19 34 1A 64 00 00 04 40 00
-					00 00 00 00 30 32 02 00 01 00
-					05 00 00 00 00 00 00 00 00 00
-					00 00 0C 00
-					];
-			};
-		};
-	};
-
-	gpio_keys {
-		compatible = "gpio-keys";
-		input-name = "gpio-keys";
-
-		camera_snapshot {
-			label = "camera_snapshot";
-			gpios = <&pm8941_gpios 3 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x2fe>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		camera_focus {
-			label = "camera_focus";
-			gpios = <&pm8941_gpios 4 0x1>;
-			linux,input-type = <1>;
-			linux,code = <0x210>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-
-		vol_up {
-			label = "volume_up";
-			gpios = <&pm8941_gpios 5 0x1>;
-			linux,input-type = <1>;
-			linux,code = <115>;
-			gpio-key,wakeup;
-			debounce-interval = <15>;
-		};
-	};
-
-	spi@f9923000 {
-		ethernet-switch@2 {
-			compatible = "micrel,ks8851";
-			reg = <2>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <94 0>;
-			spi-max-frequency = <4800000>;
-			rst-gpio = <&pm8941_mpps 6 0>;
-			vdd-io-supply = <&spi_eth_vreg>;
-			vdd-phy-supply = <&spi_eth_vreg>;
-		};
-	};
-};
-
-&sdcc2 {
-	#address-cells = <0>;
-	interrupt-parent = <&sdcc2>;
-	interrupts = <0 1 2>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 125 0
-			1 &intc 0 220 0
-			2 &msmgpio 62 0x3>;
-	interrupt-names = "core_irq", "bam_irq", "status_irq";
-	cd-gpios = <&msmgpio 62 0x1>;
-};
-
-&usb_otg {
-	qcom,hsusb-otg-otg-control = <2>;
-};
-
-&usb3 {
-	qcom,dwc-usb3-msm-otg-capability;
-};
-
-&pm8941_chg {
-	status = "ok";
-
-	qcom,chg-charging-disabled;
-
-	qcom,chg-chgr@1000 {
-		status = "ok";
-	};
-
-	qcom,chg-buck@1100 {
-		status = "ok";
-	};
-
-	qcom,chg-bat-if@1200 {
-		status = "ok";
-	};
-
-	qcom,chg-usb-chgpth@1300 {
-		status = "ok";
-	};
-
-	qcom,chg-dc-chgpth@1400 {
-		status = "ok";
-	};
-
-	qcom,chg-boost@1500 {
-		status = "ok";
-	};
-
-	qcom,chg-misc@1600 {
-		status = "ok";
-	};
-};
-
-&pm8941_gpios {
-	gpio@c000 { /* GPIO 1 */
-	};
-
-	gpio@c100 { /* GPIO 2 */
-	};
-
-	gpio@c200 { /* GPIO 3 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c300 { /* GPIO 4 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c400 { /* GPIO 5 */
-		qcom,mode = <0>;
-		qcom,pull = <0>;
-		qcom,vin-sel = <2>;
-		qcom,select = <0>;
-	};
-
-	gpio@c500 { /* GPIO 6 */
-	};
-
-	gpio@c600 { /* GPIO 7 */
-	};
-
-	gpio@c700 { /* GPIO 8 */
-	};
-
-	gpio@c800 { /* GPIO 9 */
-	};
-
-	gpio@c900 { /* GPIO 10 */
-	};
-
-	gpio@ca00 { /* GPIO 11 */
-	};
-
-	gpio@cb00 { /* GPIO 12 */
-	};
-
-	gpio@cc00 { /* GPIO 13 */
-	};
-
-	gpio@cd00 { /* GPIO 14 */
-	};
-
-	gpio@ce00 { /* GPIO 15 */
-		qcom,mode = <1>;
-		qcom,output-type = <0>;
-		qcom,pull = <5>;
-		qcom,vin-sel = <2>;
-		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
-		qcom,master-en = <1>;
-	};
-
-	gpio@cf00 { /* GPIO 16 */
-	};
-
-	gpio@d000 { /* GPIO 17 */
-	};
-
-	gpio@d100 { /* GPIO 18 */
-	};
-
-	gpio@d200 { /* GPIO 19 */
-		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
-		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
-		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
-		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
-		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
-		qcom,master-en = <1>;
-	};
-
-	gpio@d300 { /* GPIO 20 */
-	};
-
-	gpio@d400 { /* GPIO 21 */
-	};
-
-	gpio@d500 { /* GPIO 22 */
-	};
-
-	gpio@d600 { /* GPIO 23 */
-	};
-
-	gpio@d700 { /* GPIO 24 */
-	};
-
-	gpio@d800 { /* GPIO 25 */
-	};
-
-	gpio@d900 { /* GPIO 26 */
-	};
-
-	gpio@da00 { /* GPIO 27 */
-	};
-
-	gpio@db00 { /* GPIO 28 */
-	};
-
-	gpio@dc00 { /* GPIO 29 */
-		qcom,pull = <0>; /* set to default pull */
-		qcom,master-en = <1>;
-		qcom,vin-sel = <2>; /* select 1.8 V source */
-	};
-
-	gpio@dd00 { /* GPIO 30 */
-	};
-
-	gpio@de00 { /* GPIO 31 */
-	};
-
-	gpio@df00 { /* GPIO 32 */
-	};
-
-	gpio@e000 { /* GPIO 33 */
-	};
-
-	gpio@e100 { /* GPIO 34 */
-	};
-
-	gpio@e200 { /* GPIO 35 */
-	};
-
-	gpio@e300 { /* GPIO 36 */
-	};
-};
-
-&pm8941_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
-
-	mpp@a400 { /* MPP 5 */
-		/* SPI_ETH config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a500 { /* MPP 6 */
-		/* SPI_ETH_RST config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
-	};
-
-	mpp@a600 { /* MPP 7 */
-	};
-
-	mpp@a700 { /* MPP 8 */
-	};
-};
-
-&pm8841_mpps {
-
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-	};
-
-	mpp@a200 { /* MPP 3 */
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
-};
-
-&slim_msm {
-	taiko_codec {
-		qcom,cdc-micbias2-ext-cap;
-	};
 };
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
new file mode 100644
index 0000000..f1f4286
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -0,0 +1,408 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/ "dsi-panel-toshiba-720p-video.dtsi"
+
+/ {
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	qcom,mdss_dsi@fd922800 {
+		qcom,mdss_dsi_toshiba_720p_video {
+			status = "ok";
+		};
+	};
+
+	qcom,hdmi_tx@fd922100 {
+		status = "disabled";
+	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l18>;
+			vcc_i2c-supply = <&pm8941_lvs1>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0  0 760 1424>;
+			atmel,display-coords = <0 0 720 1280>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0x82>;
+				atmel,variant-id = <0x19>;
+				atmel,version = <0x10>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					15 00 02 10 08 0C 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 32 03
+					/* Object 8, Instance = 0 */
+					0F 00 0A 0A 00 00 0A 00 00 00
+					/* Object 9, Instance = 0 */
+					83 00 00 18 0E 00 70 32 02 01
+					00 03 01 01 05 0A 0A 0A 90 05
+					F8 02 00 00 0F 0F 00 00 48 2D
+					07 0C 00 00 00 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					00 00
+					/* Object 19, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 23, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 00 00 00 00
+					/* Object 42, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 03 00 00 01
+					/* Object 47, Instance = 0 */
+					08 0A 28 0A 02 0A 00 8C 00 20
+					00 00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					03 00 01 18 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 61, Instance = 1 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					7F 03 00 16 00 00 00 00 00 00
+					04 08 10 18 05 00 0A 05 05 50
+					14 19 34 1A 64 00 00 04 40 00
+					00 00 00 00 30 32 02 00 01 00
+					05 00 00 00 00 00 00 00 00 00
+					00 00 0C 00
+					];
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&pm8941_gpios 3 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&pm8941_gpios 4 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	spi@f9923000 {
+		ethernet-switch@2 {
+			compatible = "micrel,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <94 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&pm8941_mpps 6 0>;
+			vdd-io-supply = <&spi_eth_vreg>;
+			vdd-phy-supply = <&spi_eth_vreg>;
+		};
+	};
+};
+
+&sdcc2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdcc2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 220 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "core_irq", "bam_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+};
+
+&usb_otg {
+	qcom,hsusb-otg-otg-control = <2>;
+};
+
+&usb3 {
+	qcom,dwc-usb3-msm-otg-capability;
+};
+
+&pm8941_chg {
+	status = "ok";
+
+	qcom,chg-charging-disabled;
+
+	qcom,chg-chgr@1000 {
+		status = "ok";
+	};
+
+	qcom,chg-buck@1100 {
+		status = "ok";
+	};
+
+	qcom,chg-bat-if@1200 {
+		status = "ok";
+	};
+
+	qcom,chg-usb-chgpth@1300 {
+		status = "ok";
+	};
+
+	qcom,chg-dc-chgpth@1400 {
+		status = "ok";
+	};
+
+	qcom,chg-boost@1500 {
+		status = "ok";
+	};
+
+	qcom,chg-misc@1600 {
+		status = "ok";
+	};
+};
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
+
+&slim_msm {
+	taiko_codec {
+		qcom,cdc-micbias2-ext-cap;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974-pm.dtsi
similarity index 98%
rename from arch/arm/boot/dts/msm8974_pm.dtsi
rename to arch/arm/boot/dts/msm8974-pm.dtsi
index c6cbca3..8da4ae6 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-pm.dtsi
@@ -422,4 +422,10 @@
 		compatible = "qcom,pc-cntr";
 		reg = <0xfe805664 0x40>;
 	};
+
+	qcom,pm-8x60 {
+		compatible = "qcom,pm-8x60";
+		qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+		qcom,use-sync-timer;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8974-rumi.dts b/arch/arm/boot/dts/msm8974-rumi.dts
index 3533151..738ff86 100644
--- a/arch/arm/boot/dts/msm8974-rumi.dts
+++ b/arch/arm/boot/dts/msm8974-rumi.dts
@@ -13,103 +13,10 @@
 /dts-v1/;
 
 /include/ "msm8974.dtsi"
+/include/ "msm8974-rumi.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974 RUMI";
 	compatible = "qcom,msm8974-rumi", "qcom,msm8974";
 	qcom,msm-id = <126 15 0>;
-
-	timer {
-		clock-frequency = <5000000>;
-	};
-
-	serial@f995e000 {
-		status = "ok";
-	};
-
-	usb@f9a55000 {
-		status = "disable";
-	};
-
-	qcom,sdcc@f9824000 {
-                qcom,sdcc-clk-rates = <400000 19200000>;
-        };
-
-        qcom,sdcc@f98a4000 {
-                qcom,sdcc-clk-rates = <400000 19200000>;
-        };
-
-	qcom,sps@f998000 {
-		status = "disable";
-	};
-
-	spi@f9924000 {
-		status = "disable";
-	};
-
-	spi@f9923000 {
-		compatible = "qcom,spi-qup-v2";
-		reg = <0xf9923000 0x1000>;
-		interrupts = <0 95 0>;
-		spi-max-frequency = <24000000>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		gpios = <&msmgpio 3 0>, /* CLK  */
-			<&msmgpio 1 0>, /* MISO */
-			<&msmgpio 0 0>; /* MOSI */
-		cs-gpios = <&msmgpio 9 0>;
-
-		ethernet-switch@2 {
-			compatible = "simtec,ks8851";
-			reg = <2>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <90 0>;
-			spi-max-frequency = <5000000>;
-		};
-	};
-
-	i2c@f9966000 {
-		status = "disable";
-	};
-
-	i2c@f9967000 {
-		cell-index = <0>;
-		compatible = "qcom,i2c-qup";
-		reg = <0Xf9967000 0x1000>;
-		reg-names = "qup_phys_addr";
-		interrupts = <0 105 0>;
-		interrupt-names = "qup_err_intr";
-		qcom,i2c-bus-freq = <100000>;
-		qcom,i2c-src-freq = <24000000>;
-		gpios = <&msmgpio 83 0>, /* DAT  */
-			<&msmgpio 84 0>; /* CLK */
-	};
-
-	slim@fe12f000 {
-		status = "disable";
-	};
-
-	qcom,mdss_dsi@fd922800 {
-		status = "disable";
-	};
-
-	qcom,spmi@fc4c0000 {
-		status = "disable";
-	};
-
-	qcom,ssusb@F9200000 {
-		status = "disable";
-	};
-
-	qcom,lpass@fe200000 {
-		status = "disable";
-	};
-
-	qcom,pronto@fb21b000 {
-		status = "disable";
-	};
-
-	qcom,mss@fc880000 {
-		status = "disable";
-	};
 };
diff --git a/arch/arm/boot/dts/msm8974-rumi.dtsi b/arch/arm/boot/dts/msm8974-rumi.dtsi
new file mode 100644
index 0000000..d4b7793
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-rumi.dtsi
@@ -0,0 +1,107 @@
+/* Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+/ {
+	timer {
+		clock-frequency = <5000000>;
+	};
+
+	serial@f995e000 {
+		status = "ok";
+	};
+
+	usb@f9a55000 {
+		status = "disable";
+	};
+
+	qcom,sdcc@f9824000 {
+                qcom,sdcc-clk-rates = <400000 19200000>;
+        };
+
+        qcom,sdcc@f98a4000 {
+                qcom,sdcc-clk-rates = <400000 19200000>;
+        };
+
+	qcom,sps@f998000 {
+		status = "disable";
+	};
+
+	spi@f9924000 {
+		status = "disable";
+	};
+
+	spi@f9923000 {
+		compatible = "qcom,spi-qup-v2";
+		reg = <0xf9923000 0x1000>;
+		interrupts = <0 95 0>;
+		spi-max-frequency = <24000000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		gpios = <&msmgpio 3 0>, /* CLK  */
+			<&msmgpio 1 0>, /* MISO */
+			<&msmgpio 0 0>; /* MOSI */
+		cs-gpios = <&msmgpio 9 0>;
+
+		ethernet-switch@2 {
+			compatible = "simtec,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <90 0>;
+			spi-max-frequency = <5000000>;
+		};
+	};
+
+	i2c@f9966000 {
+		status = "disable";
+	};
+
+	i2c@f9967000 {
+		cell-index = <0>;
+		compatible = "qcom,i2c-qup";
+		reg = <0Xf9967000 0x1000>;
+		reg-names = "qup_phys_addr";
+		interrupts = <0 105 0>;
+		interrupt-names = "qup_err_intr";
+		qcom,i2c-bus-freq = <100000>;
+		qcom,i2c-src-freq = <24000000>;
+		gpios = <&msmgpio 83 0>, /* DAT  */
+			<&msmgpio 84 0>; /* CLK */
+	};
+
+	slim@fe12f000 {
+		status = "disable";
+	};
+
+	qcom,mdss_dsi@fd922800 {
+		status = "disable";
+	};
+
+	qcom,spmi@fc4c0000 {
+		status = "disable";
+	};
+
+	qcom,ssusb@F9200000 {
+		status = "disable";
+	};
+
+	qcom,lpass@fe200000 {
+		status = "disable";
+	};
+
+	qcom,pronto@fb21b000 {
+		status = "disable";
+	};
+
+	qcom,mss@fc880000 {
+		status = "disable";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-sim.dts b/arch/arm/boot/dts/msm8974-sim.dts
index d5368fa..09ea419 100644
--- a/arch/arm/boot/dts/msm8974-sim.dts
+++ b/arch/arm/boot/dts/msm8974-sim.dts
@@ -13,86 +13,10 @@
 /dts-v1/;
 
 /include/ "msm8974.dtsi"
-/include/ "dsi-panel-sim-video.dtsi"
+/include/ "msm8974-sim.dtsi"
 
 / {
 	model = "Qualcomm MSM 8974 Simulator";
 	compatible = "qcom,msm8974-sim", "qcom,msm8974";
 	qcom,msm-id = <126 16 0>;
-
-	qcom,mdss_dsi@fd922800 {
-		qcom,mdss_dsi_sim_video {
-			status = "ok";
-		};
-	};
-
-	serial@f991f000 {
-		status = "ok";
-	};
-
-	serial@f995e000 {
-		status = "ok";
-	};
-};
-
-&jpeg_iommu {
-		qcom,iommu-ctx@fda6c000 {
-			interrupts = <0 69 0>;
-		};
-
-		qcom,iommu-ctx@fda6d000 {
-			interrupts = <0 70 0>;
-		};
-
-		qcom,iommu-ctx@fda6e000 {
-			interrupts = <0 71 0>;
-		};
-};
-
-&mdp_iommu {
-		qcom,iommu-ctx@fd930000 {
-			interrupts = <0 46 0>;
-		};
-
-		qcom,iommu-ctx@fd931000 {
-			interrupts = <0 47 0>;
-		};
-};
-
-&venus_iommu {
-		qcom,iommu-ctx@fdc8c000 {
-			interrupts = <0 43 0>;
-		};
-
-		qcom,iommu-ctx@fdc8d000 {
-			interrupts = <0 42 0>;
-		};
-
-		qcom,iommu-ctx@fdc8e000 {
-			interrupts = <0 41 0>;
-		};
-};
-
-&kgsl_iommu {
-		qcom,iommu-ctx@fdb18000 {
-			interrupts = <0 240 0>;
-		};
-
-		qcom,iommu-ctx@fdb19000 {
-			interrupts = <0 241 0>;
-		};
-};
-
-&vfe_iommu {
-		qcom,iommu-ctx@fda4c000 {
-			interrupts = <0 64 0>;
-		};
-
-		qcom,iommu-ctx@fda4d000 {
-			interrupts = <0 65 0>;
-		};
-
-		qcom,iommu-ctx@fda4e000 {
-			interrupts = <0 66 0>;
-		};
 };
diff --git a/arch/arm/boot/dts/msm8974-sim.dtsi b/arch/arm/boot/dts/msm8974-sim.dtsi
new file mode 100644
index 0000000..41e37de
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-sim.dtsi
@@ -0,0 +1,91 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/ "dsi-panel-sim-video.dtsi"
+
+/ {
+	qcom,mdss_dsi@fd922800 {
+		qcom,mdss_dsi_sim_video {
+			status = "ok";
+		};
+	};
+
+	serial@f991f000 {
+		status = "ok";
+	};
+
+	serial@f995e000 {
+		status = "ok";
+	};
+};
+
+&jpeg_iommu {
+		qcom,iommu-ctx@fda6c000 {
+			interrupts = <0 69 0>;
+		};
+
+		qcom,iommu-ctx@fda6d000 {
+			interrupts = <0 70 0>;
+		};
+
+		qcom,iommu-ctx@fda6e000 {
+			interrupts = <0 71 0>;
+		};
+};
+
+&mdp_iommu {
+		qcom,iommu-ctx@fd930000 {
+			interrupts = <0 46 0>;
+		};
+
+		qcom,iommu-ctx@fd931000 {
+			interrupts = <0 47 0>;
+		};
+};
+
+&venus_iommu {
+		qcom,iommu-ctx@fdc8c000 {
+			interrupts = <0 43 0>;
+		};
+
+		qcom,iommu-ctx@fdc8d000 {
+			interrupts = <0 42 0>;
+		};
+
+		qcom,iommu-ctx@fdc8e000 {
+			interrupts = <0 41 0>;
+		};
+};
+
+&kgsl_iommu {
+		qcom,iommu-ctx@fdb18000 {
+			interrupts = <0 240 0>;
+		};
+
+		qcom,iommu-ctx@fdb19000 {
+			interrupts = <0 241 0>;
+		};
+};
+
+&vfe_iommu {
+		qcom,iommu-ctx@fda4c000 {
+			interrupts = <0 64 0>;
+		};
+
+		qcom,iommu-ctx@fda4d000 {
+			interrupts = <0 65 0>;
+		};
+
+		qcom,iommu-ctx@fda4e000 {
+			interrupts = <0 66 0>;
+		};
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index df3c520..dcd6e11 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -11,7 +11,7 @@
  */
 
 /include/ "skeleton.dtsi"
-/include/ "msm8974_pm.dtsi"
+/include/ "msm8974-pm.dtsi"
 /include/ "msm8974-iommu.dtsi"
 /include/ "msm8974-camera.dtsi"
 /include/ "msm8974-coresight.dtsi"
@@ -527,6 +527,57 @@
 					 <0x1e70008c>; /* LPG_CHAN12 */
 
 		qcom,pm8941@1 {
+			qcom,leds@d300 {
+				status = "okay";
+				qcom,flash_0 {
+					qcom,max-current = <1000>;
+					qcom,default-state = "off";
+					qcom,headroom = <0>;
+					qcom,duration = <1280>;
+					qcom,clamp-curr = <200>;
+					qcom,startup-dly = <1>;
+					qcom,safety-timer;
+					label = "flash";
+					linux,default-trigger =
+						"flash0_trigger";
+					qcom,id = <1>;
+					linux,name = "led:flash_0";
+					qcom,current = <625>;
+				};
+
+				qcom,flash_1 {
+					qcom,max-current = <1000>;
+					qcom,default-state = "off";
+					qcom,headroom = <0>;
+					qcom,duration = <1280>;
+					qcom,clamp-curr = <200>;
+					qcom,startup-dly = <1>;
+					qcom,safety-timer;
+					linux,default-trigger =
+						"flash1_trigger";
+					label = "flash";
+					qcom,id = <2>;
+					linux,name = "led:flash_1";
+					qcom,current = <625>;
+				};
+			};
+
+			qcom,leds@d400 {
+				status = "disabled";
+			};
+
+			qcom,leds@d500 {
+				status = "disabled";
+			};
+
+			qcom,leds@d600 {
+				status = "disabled";
+			};
+
+			qcom,leds@d700 {
+				status = "disabled";
+			};
+
 			qcom,leds@d800 {
 				status = "okay";
 				qcom,wled_0 {
@@ -535,7 +586,7 @@
 					linux,default-trigger = "bkl-trigger";
 					qcom,cs-out-en;
 					qcom,op-fdbck;
-					qcom,default-state = "on";
+					qcom,default-state = "off";
 					qcom,max-current = <25>;
 					qcom,ctrl-delay-us = <0>;
 					qcom,boost-curr-lim = <3>;
@@ -582,6 +633,7 @@
 			qcom,leds@e100 {
 				status = "disabled";
 			};
+
 		};
 	};
 
@@ -829,27 +881,17 @@
 		      <0xfd485000 0x400>,
 		      <0xfc820000 0x020>,
 		      <0xfc401680 0x004>,
-		      <0xfc980008 0x004>;
+		      <0x0d1fc000 0x4000>;
 		reg-names = "qdsp6_base", "halt_base", "rmb_base",
-			    "restart_reg", "clamp_reg";
+			    "restart_reg", "metadata_base";
 
+		interrupts = <0 24 1>;
 		vdd_mss-supply = <&pm8841_s3>;
 
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth = <1>;
 	};
 
-	qcom,mba@fc820000 {
-		compatible = "qcom,pil-mba";
-		reg = <0xfc820000 0x0020>,
-		      <0x0d1fc000 0x4000>;
-		reg-names = "rmb_base", "metadata_base";
-		interrupts = <0 24 1>;
-
-		qcom,firmware-name = "modem";
-		qcom,depends-on    = "mba";
-	};
-
 	qcom,pronto@fb21b000 {
 		compatible = "qcom,pil-pronto";
 		reg = <0xfb21b000 0x3000>,
@@ -1118,7 +1160,10 @@
                compatible = "qcom,msm-wdog-debug";
                reg = <0xfc401000 0x1000>;
         };
-
+        qcom,msm-mem-hole {
+                compatible = "qcom,msm-mem-hole";
+                qcom,memblock-remove = <0x8400000 0x7b00000>; /* Address and Size of Hole */
+        };
 };
 
 /include/ "msm-pm8x41-rpm-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 2f2518d..0ebeb9c 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -250,6 +250,12 @@
 		a5_cpu-supply = <&pm8019_l10_corner_ao>;
 		a5_mem-supply = <&pm8019_l12_ao>;
 	};
+
+	gdsc_usb_hsic: qcom,gdsc@fc400404 {
+		compatible = "qcom,gdsc";
+		reg = <0xfc400404 0x4>;
+		regulator-name = "gdsc_usb_hsic";
+	};
 };
 
 /include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index e4dd4fb..83a499b 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -69,6 +69,8 @@
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_STUB=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index b2ee503..98c1ede 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -50,6 +50,7 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL_LPASS_QDSP6V5=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_MSM_PIL_MBA=y
@@ -269,11 +270,14 @@
 CONFIG_GPIO_QPNP_PIN=y
 CONFIG_GPIO_QPNP_PIN_DEBUG=y
 CONFIG_POWER_SUPPLY=y
-# CONFIG_BATTERY_MSM is not set
+CONFIG_BATTERY_BQ28400=y
+CONFIG_QPNP_CHARGER=y
+CONFIG_QPNP_BMS=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_QPNP=y
 CONFIG_WCD9320_CODEC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_STUB=y
@@ -297,6 +301,7 @@
 CONFIG_MSM_CSI2_REGISTER=y
 CONFIG_MSM_ISPIF=y
 CONFIG_S5K3L1YX=y
+CONFIG_MSM_WFD=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
@@ -365,6 +370,7 @@
 CONFIG_USB_BAM=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index c49ad93..328a4dc 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -36,7 +36,6 @@
 CONFIG_EFI_PARTITION=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8974=y
-CONFIG_ARCH_MSM8226=y
 CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
@@ -272,10 +271,9 @@
 CONFIG_GPIO_QPNP_PIN=y
 CONFIG_GPIO_QPNP_PIN_DEBUG=y
 CONFIG_POWER_SUPPLY=y
-# CONFIG_BATTERY_MSM is not set
+CONFIG_BATTERY_BQ28400=y
 CONFIG_QPNP_CHARGER=y
 CONFIG_QPNP_BMS=y
-CONFIG_BATTERY_BQ28400=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_THERMAL=y
@@ -285,7 +283,6 @@
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_REGULATOR_QPNP=y
-CONFIG_QPNP_PWM=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
@@ -374,6 +371,7 @@
 CONFIG_USB_BAM=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU=y
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 42fef7c..938be62 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -268,12 +268,17 @@
 					__raw_readw(c)); __r; })
 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
 					__raw_readl(c)); __r; })
+#define readl_relaxed_no_log(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl_no_log(c)); __r; })
+
 
 #define writeb_relaxed(v,c)	((void)__raw_writeb(v,c))
 #define writew_relaxed(v,c)	((void)__raw_writew((__force u16) \
 					cpu_to_le16(v),c))
 #define writel_relaxed(v,c)	((void)__raw_writel((__force u32) \
 					cpu_to_le32(v),c))
+#define writel_relaxed_no_log(v, c)  ((void)__raw_writel_no_log((__force u32) \
+					cpu_to_le32(v), c))
 
 #define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
 #define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index b258707..6bd87de 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -264,6 +264,7 @@
 	select MSM_RPM_REGULATOR_SMD
 	select ARM_HAS_SG_CHAIN
 	select MSM_RUN_QUEUE_STATS
+	select MEMORY_HOLE_CARVEOUT
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
@@ -962,7 +963,7 @@
 	default "0x00000000" if ARCH_MSM8974
 	default "0x00000000" if ARCH_MPQ8092
 	default "0x00000000" if ARCH_MSM8226
-	default "0x80200000" if ARCH_MSM8910
+	default "0x00000000" if ARCH_MSM8910
 	default "0x10000000" if ARCH_FSM9XXX
 	default "0x00200000" if ARCH_MSM9625
 	default "0x00200000" if !MSM_STACKED_MEMORY
@@ -1981,18 +1982,14 @@
 	  ADSP if the processor encounters a fatal error.
 
 config MSM_PIL_MSS_QDSP6V5
-       tristate "MSS QDSP6v5 (Hexagon) Boot Support"
-       depends on MSM_PIL
-       help
-         Support for booting and shutting down QDSP6v5 (Hexagon) processors
-	 in modem subsystems.
-
-config MSM_PIL_MBA
-	tristate "Support for modem self-authentication"
-	depends on MSM_PIL_MSS_QDSP6V5 && MSM_SUBSYSTEM_RESTART
+	tristate "MSS QDSP6v5 (Hexagon) Boot Support"
+	depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
 	help
-	  Support for booting self-authenticating modems using the Modem Boot
-	  Authenticator.
+	  Support for booting and shutting down QDSP6v5 (Hexagon) processors
+	  in modem subsystems. If you would like to make or receive phone
+	  calls then say Y here.
+
+	  If unsure, say N.
 
 config MSM_PIL_RIVA
 	tristate "RIVA (WCNSS) Boot Support"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 11d2d2f..b9a16fa 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -84,7 +84,6 @@
 obj-$(CONFIG_MSM_PIL_MODEM_QDSP6V4) += pil-q6v4.o pil-q6v4-mss.o
 obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
 obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-q6v5-mss.o
-obj-$(CONFIG_MSM_PIL_MBA) += pil-mba.o
 obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
 obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
 obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
@@ -293,6 +292,7 @@
 obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
 obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o clock-mdss-8974.o
 obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
+obj-$(CONFIG_ARCH_MSM9625) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o
@@ -330,7 +330,7 @@
 endif
 obj-$(CONFIG_MSM_MPM_OF) += mpm-of.o
 obj-$(CONFIG_MSM_MPM) += mpm.o
-obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o
+obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
 obj-$(CONFIG_MSM_RPM_RBCPR_STATS_LOG) += rpm_rbcpr_stats.o
 obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
 obj-$(CONFIG_MSM_TZ_LOG) += tz_log.o
@@ -401,3 +401,5 @@
 endif
 obj-$(CONFIG_MSM_FIQ) += msm7k_fiq.o
 obj-$(CONFIG_MSM_FIQ) += msm7k_fiq_handler.o
+
+obj-$(CONFIG_MEMORY_HOLE_CARVEOUT) +=  msm_mem_hole.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index fa9ee54..cf1f401 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -66,4 +66,4 @@
    zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
 
 # MSM8910
-   zreladdr-$(CONFIG_ARCH_MSM8910)	:= 0x80208000
+   zreladdr-$(CONFIG_ARCH_MSM8910)	:= 0x00008000
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 7ba22f4..c475e2d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -193,6 +193,7 @@
 static struct sps_mem_buffer rx_desc_mem_buf;
 static struct sps_register_event tx_register_event;
 static struct sps_register_event rx_register_event;
+static bool satellite_mode;
 
 static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
 static int bam_mux_initialized;
@@ -2074,7 +2075,7 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
-	if (cpu_is_msm9615())
+	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	/* need to free on tear down */
 	ret = sps_register_bam_device(&a2_props, &h);
@@ -2246,7 +2247,7 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
-	if (cpu_is_msm9615())
+	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	ret = sps_register_bam_device(&a2_props, &h);
 	if (ret < 0) {
@@ -2374,10 +2375,14 @@
 			pr_err("%s: irq field missing\n", __func__);
 			return -ENODEV;
 		}
-		DBG("%s: base:%p size:%x irq:%d\n", __func__,
+		satellite_mode = of_property_read_bool(pdev->dev.of_node,
+						"qcom,satellite-mode");
+
+		DBG("%s: base:%p size:%x irq:%d satellite:%d\n", __func__,
 							a2_phys_base,
 							a2_phys_size,
-							a2_bam_irq);
+							a2_bam_irq,
+							satellite_mode);
 	} else { /* fallback to default init data */
 		a2_phys_base = (void *)(A2_PHYS_BASE);
 		a2_phys_size = A2_PHYS_SIZE;
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index cb03d4b..fc44b18 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -479,6 +479,12 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting gsbi6_spi_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct gpiomux_setting sx150x_suspended_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_8MA,
@@ -1514,6 +1520,33 @@
 	},
 };
 
+static struct msm_gpiomux_config mpq8064_gsbi6_spi_configs[] __initdata = {
+	{
+		.gpio      = 17,        /* GSBI6_0 SPI CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi6_spi_cfg,
+		},
+	},
+	{
+		.gpio      = 16,        /* GSBI6_1 SPI CS */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi6_spi_cfg,
+		},
+	},
+	{
+		.gpio      = 15,        /* GSBI6_2 SPI MISO */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi6_spi_cfg,
+		},
+	},
+	{
+		.gpio      = 14,        /* GSBI6_3 SPI_MOSI */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi6_spi_cfg,
+		},
+	},
+};
+
 void __init apq8064_init_gpiomux(void)
 {
 	int rc;
@@ -1630,10 +1663,14 @@
 		msm_gpiomux_install(apq8064_mhl_configs,
 				ARRAY_SIZE(apq8064_mhl_configs));
 
-	 if (machine_is_mpq8064_cdp())
+	if (machine_is_mpq8064_cdp()) {
 		msm_gpiomux_install(mpq8064_ir_configs,
 				ARRAY_SIZE(mpq8064_ir_configs));
 
+		msm_gpiomux_install(mpq8064_gsbi6_spi_configs,
+				ARRAY_SIZE(mpq8064_gsbi6_spi_configs));
+	}
+
 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
 	 msm_gpiomux_install(apq8064_sdc2_configs,
 			     ARRAY_SIZE(apq8064_sdc2_configs));
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index f35ae6b..5ebb010 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -226,7 +226,7 @@
 			.io_fraction = 0,
 		},
 		{
-			.gpu_freq = 325000000,
+			.gpu_freq = 320000000,
 			.bus_freq = 3,
 			.io_fraction = 33,
 		},
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 6a3e78e..c6bcb6b 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -42,6 +42,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach/mmc.h>
 #include <linux/platform_data/qcom_wcnss_device.h>
+#include <linux/ci-bridge-spi.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
@@ -2694,12 +2695,22 @@
 	&msm8064_device_vcap,
 #endif
 	&rc_input_loopback_pdev,
+	&mpq8064_device_qup_spi_gsbi6,
 };
 
 static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
 	.max_clock_speed = 1100000,
 };
 
+static struct msm_spi_platform_data mpq8064_qup_spi_gsbi6_pdata = {
+	.max_clock_speed = 1100000,
+};
+
+static struct ci_bridge_platform_data mpq8064_ci_bridge_pdata = {
+	.reset_pin = 260,
+	.interrupt_pin = 261,
+};
+
 #define KS8851_IRQ_GPIO		43
 
 static struct spi_board_info spi_board_info[] __initdata = {
@@ -2717,6 +2728,17 @@
 		.bus_num		= 0,
 		.chip_select		= 3,
 		.mode			= SPI_MODE_0,
+	}
+};
+
+static struct spi_board_info mpq8064_spi_board_info[] __initdata = {
+	{
+		.modalias		= "ci_bridge_spi",
+		.max_speed_hz		= 1000000,
+		.bus_num		= 1,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_0,
+		.platform_data		= &mpq8064_ci_bridge_pdata,
 	},
 };
 
@@ -3491,8 +3513,14 @@
 					msm_rpmrs_levels[0].latency_us;
 		enable_avc_i2c_bus();
 		msm_rotator_set_split_iommu_domain();
+
+		mpq8064_device_qup_spi_gsbi6.dev.platform_data =
+						&mpq8064_qup_spi_gsbi6_pdata;
+
 		platform_add_devices(mpq_devices, ARRAY_SIZE(mpq_devices));
 		mpq8064_pcie_init();
+		spi_register_board_info(mpq8064_spi_board_info,
+					ARRAY_SIZE(mpq8064_spi_board_info));
 	} else {
 		ethernet_init();
 		msm_rotator_set_split_iommu_domain();
diff --git a/arch/arm/mach-msm/board-8910.c b/arch/arm/mach-msm/board-8910.c
index 7039879..eaf146b 100644
--- a/arch/arm/mach-msm/board-8910.c
+++ b/arch/arm/mach-msm/board-8910.c
@@ -48,6 +48,9 @@
 	CLK_DUMMY("iface_clk", NULL, "f9824000.qcom,sdcc", OFF),
 	CLK_DUMMY("core_clk", NULL, "f9824000.qcom,sdcc", OFF),
 	CLK_DUMMY("bus_clk",  NULL, "f9824000.qcom,sdcc", OFF),
+	CLK_DUMMY("iface_clk", NULL, "f98a4000.qcom,sdcc", OFF),
+	CLK_DUMMY("core_clk", NULL, "f98a4000.qcom,sdcc", OFF),
+	CLK_DUMMY("bus_clk",  NULL, "f98a4000.qcom,sdcc", OFF),
 };
 
 struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index ce2531b..167923f 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2875,8 +2875,8 @@
 	/* Fixup data that needs to change based on GPU ID */
 	if (cpu_is_msm8960ab()) {
 		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
-		/* 8960PRO nominal clock rate is 325Mhz instead of 320Mhz */
-		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 325000000;
+		/* 8960PRO nominal clock rate is 320Mhz */
+		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 320000000;
 	} else {
 		kgsl_3d0_pdata->iommu_count = 1;
 		if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 19fb222..def9b76 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -501,7 +501,6 @@
 	OF_DEV_AUXDATA("qcom,pil-q6v5-lpass",   0xFE200000, \
 			"pil-q6v5-lpass", NULL),
 	OF_DEV_AUXDATA("qcom,pil-q6v5-mss", 0xFC880000, "pil-q6v5-mss", NULL),
-	OF_DEV_AUXDATA("qcom,pil-mba",     0xFC820000, "pil-mba", NULL),
 	OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
 			"pil_pronto", NULL),
 	OF_DEV_AUXDATA("arm,coresight-tmc", 0xFC322000, \
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index bcc9645..1c2d8a2 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -103,11 +103,12 @@
 	if (machine_is_msm7627a_qrd1())
 		gpio_bt_sys_rest_en = 114;
 	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
-				|| machine_is_msm8625_evt()
-				|| machine_is_qrd_skud_prime())
+				|| machine_is_msm8625_evt())
 		gpio_bt_sys_rest_en = 16;
 	if (machine_is_msm8625_qrd7())
 		gpio_bt_sys_rest_en = 88;
+	if (machine_is_qrd_skud_prime())
+		gpio_bt_sys_rest_en = 35;
 	if (machine_is_msm7627a_qrd3()) {
 		if (socinfo == 0x70002)
 			gpio_bt_sys_rest_en = 88;
@@ -976,9 +977,6 @@
 	int i, rc = 0;
 	struct device *dev;
 
-	if (machine_is_qrd_skud_prime())
-		return;
-
 	gpio_bt_config();
 
 	rc = i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 472cb68..3c417c3 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5307,7 +5307,7 @@
 	CLK_LOOKUP("core_clk",		gsbi4_qup_clk.c,	"qup_i2c.4"),
 	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	"spi_qsd.0"),
 	CLK_LOOKUP("core_clk",		gsbi5_qup_clk.c,	"qup_i2c.5"),
-	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi6_qup_clk.c,	"spi_qsd.1"),
 	CLK_LOOKUP("core_clk",		gsbi7_qup_clk.c,	""),
 	CLK_LOOKUP("core_clk",		pdm_clk.c,		""),
 	CLK_LOOKUP("mem_clk",		pmem_clk.c,		"msm_sps"),
@@ -5350,6 +5350,7 @@
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		"spi_qsd.0"),
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,		"qup_i2c.5"),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,	"msm_serial_hs.0"),
+	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,		"spi_qsd.1"),
 	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,	"msm_serial_hsl.0"),
 	CLK_LOOKUP("ref_clk",	tsif_ref_clk.c,	"msm_tspp.0"),
 	CLK_LOOKUP("iface_clk",		tsif_p_clk.c,		"msm_tspp.0"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 76b8abf..d080a379 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5022,7 +5022,6 @@
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"msm_otg"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-lpass"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-mss"),
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-mba"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"fb000000.qcom,wcnss-wlan"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil_pronto"),
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 3816b54..5c5b51e 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3101,7 +3101,7 @@
 	.c = {
 		.dbg_name = "pcm_clk",
 		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP1(LOW, 24580000),
+		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(pcm_clk.c),
 		.rate = ULONG_MAX,
 	},
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 127c9ab..fbfa036 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -373,6 +373,58 @@
 	.resource	= resources_qup_spi_gsbi5,
 };
 
+static struct resource resources_qup_spi_gsbi6[] = {
+	{
+		.name   = "spi_base",
+		.start  = MSM_GSBI6_QUP_PHYS,
+		.end    = MSM_GSBI6_QUP_PHYS + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "gsbi_base",
+		.start  = MSM_GSBI6_PHYS,
+		.end    = MSM_GSBI6_PHYS + 4 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "spi_irq_in",
+		.start  = GSBI6_QUP_IRQ,
+		.end    = GSBI6_QUP_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "spi_clk",
+		.start  = 17,
+		.end    = 17,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "spi_miso",
+		.start  = 15,
+		.end    = 15,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "spi_mosi",
+		.start  = 14,
+		.end    = 14,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "spi_cs",
+		.start  = 16,
+		.end    = 16,
+		.flags  = IORESOURCE_IO,
+	}
+};
+
+struct platform_device mpq8064_device_qup_spi_gsbi6 = {
+	.name		= "spi_qsd",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(resources_qup_spi_gsbi6),
+	.resource	= resources_qup_spi_gsbi6,
+};
+
 static struct resource resources_qup_i2c_gsbi5[] = {
 	{
 		.name	= "gsbi_qup_i2c_addr",
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 2c49b21..9aa771a 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1770,7 +1770,7 @@
 
 static struct msm_cpr_config msm_cpr_pdata = {
 	.ref_clk_khz = 19200,
-	.delay_us = 1000,
+	.delay_us = 25000,
 	.irq_line = 0,
 	.cpr_mode_data = msm_cpr_mode_data,
 	.tgt_count_div_N = 1,
@@ -1778,7 +1778,7 @@
 	.ceiling = 40,
 	.sw_vlevel = 20,
 	.up_threshold = 1,
-	.dn_threshold = 4,
+	.dn_threshold = 3,
 	.up_margin = 0,
 	.dn_margin = 0,
 	.max_nom_freq = 700800,
@@ -1848,11 +1848,11 @@
 	 * Ditto for a 1.0GHz part.
 	 */
 	if (msm8625_cpu_id() == MSM8625A) {
-		msm_cpr_pdata.max_quot += 100;
+		msm_cpr_pdata.max_quot += 30;
 		if (msm_cpr_pdata.max_quot > 1400)
 			msm_cpr_pdata.max_quot = 1400;
 	} else if (msm8625_cpu_id() == MSM8625) {
-		msm_cpr_pdata.max_quot += 120;
+		msm_cpr_pdata.max_quot += 50;
 		if (msm_cpr_pdata.max_quot > 1350)
 			msm_cpr_pdata.max_quot = 1350;
 	}
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 861f1d6..97adb35 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -416,6 +416,7 @@
 extern struct platform_device msm_device_vfe;
 extern struct platform_device msm_device_vpe;
 extern struct platform_device mpq8064_device_qup_i2c_gsbi5;
+extern struct platform_device mpq8064_device_qup_spi_gsbi6;
 
 extern struct platform_device msm8660_iommu_domain_device;
 extern struct platform_device msm8960_iommu_domain_device;
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 2455e93..9b04141 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -29,7 +29,8 @@
 	HDMI_SAMPLE_RATE_88_2KHZ,
 	HDMI_SAMPLE_RATE_96KHZ,
 	HDMI_SAMPLE_RATE_176_4KHZ,
-	HDMI_SAMPLE_RATE_192KHZ
+	HDMI_SAMPLE_RATE_192KHZ,
+	HDMI_SAMPLE_RATE_MAX
 };
 
 int hdmi_audio_enable(bool on , u32 fifo_water_mark);
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
index 296f222..4c06af4 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, The Linux Foundation. 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
@@ -165,4 +165,5 @@
 enum apr_subsys_state apr_get_q6_state(void);
 int apr_set_q6_state(enum apr_subsys_state state);
 void apr_set_subsys_state(void);
+const char *apr_get_lpass_subsys_name(void);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index 075d20f..b063b97 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -101,8 +101,7 @@
  * @init_data:		regulator constraints
  * @id:			regulator id; from enum rpm_vreg_id
  * @sleep_selectable:	flag which indicates that regulator should be accessable
- *			by external private API and that spinlocks should be
- *			used instead of mutex locks
+ *			by external private API
  * @system_uA:		current drawn from regulator not accounted for by any
  *			regulator framework consumer
  * @enable_time:	time in us taken to enable a regulator to the maximum
@@ -184,10 +183,8 @@
  * Returns 0 on success or errno.
  *
  * This function is used to vote for the voltage of a regulator without
- * using the regulator framework.  It is needed by consumers which hold spin
- * locks or have interrupts disabled because the regulator framework can sleep.
- * It is also needed by consumers which wish to only vote for active set
- * regulator voltage.
+ * using the regulator framework.  It is needed for consumers which wish to only
+ * vote for active set regulator voltage.
  *
  * If sleep_also == 0, then a sleep-set value of 0V will be voted for.
  *
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index a95e943..64190d2 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -70,6 +70,8 @@
 extern struct subsys_device *subsys_register(struct subsys_desc *desc);
 extern void subsys_unregister(struct subsys_device *dev);
 
+extern void subsys_default_online(struct subsys_device *dev);
+
 #else
 
 static inline int get_restart_level(void)
@@ -102,6 +104,8 @@
 
 static inline void subsys_unregister(struct subsys_device *dev) { }
 
+static inline void subsys_default_online(struct subsys_device *dev) { }
+
 #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
 
 #endif
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index 02978cf..8dd4bac 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -354,6 +354,7 @@
 		ret = PTR_ERR(charm_subsys);
 		goto fatal_err;
 	}
+	subsys_default_online(charm_subsys);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 58b26f2..b81832e 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -681,6 +681,7 @@
 		ret = PTR_ERR(mdm_subsys_dev);
 		goto fatal_err;
 	}
+	subsys_default_online(mdm_subsys_dev);
 
 	/* ERR_FATAL irq. */
 	irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_errfatal_gpio);
diff --git a/arch/arm/mach-msm/msm_mem_hole.c b/arch/arm/mach-msm/msm_mem_hole.c
new file mode 100644
index 0000000..736219b
--- /dev/null
+++ b/arch/arm/mach-msm/msm_mem_hole.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+/**
+ * This module exists for the express purpose of removing memory
+ * via the msm memory-remove mechanism (see
+ * Documentation/devicetree/bindings/arm/msm/memory-reserve.txt). Compiling
+ * this module into a kernel is essentially the means by which any
+ * nodes in the device tree with compatible =
+ * "qcom,msm-mem-hole" will be "activated", thus providing a
+ * convenient mechanism for enabling/disabling memory removal
+ * (qcom,memory-*).
+ */
+
+#include <linux/module.h>
+
+#define MSM_MEM_HOLE_COMPAT_STR	"qcom,msm-mem-hole"
+
+EXPORT_COMPAT(MSM_MEM_HOLE_COMPAT_STR);
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index e5892c3..37dec30 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -119,7 +119,7 @@
 	int hw_interconnect;
 } ocmem_client_table[OCMEM_CLIENT_MAX] = {
 	{OCMEM_GRAPHICS, PRIO_GFX, OCMEM_PERFORMANCE, OCMEM_PORT},
-	{OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_PORT},
+	{OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
 	{OCMEM_CAMERA, NO_PRIO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
 	{OCMEM_HP_AUDIO, PRIO_HP_AUDIO, OCMEM_PASSIVE, OCMEM_BLOCKED},
 	{OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
@@ -157,6 +157,16 @@
 		return 0;
 }
 
+static inline int is_iface_access(int id)
+{
+	return ocmem_client_table[id].hw_interconnect == OCMEM_OCMEMNOC ? 1 : 0;
+}
+
+static inline int is_remapped_access(int id)
+{
+	return ocmem_client_table[id].hw_interconnect == OCMEM_SYSNOC ? 1 : 0;
+}
+
 static inline int is_blocked(int id)
 {
 	return ocmem_client_table[id].hw_interconnect == OCMEM_BLOCKED ? 1 : 0;
@@ -223,9 +233,9 @@
 
 	switch (hw_interconnect) {
 	case OCMEM_PORT:
+	case OCMEM_OCMEMNOC:
 		ret_addr = phys_to_offset(addr);
 		break;
-	case OCMEM_OCMEMNOC:
 	case OCMEM_SYSNOC:
 		ret_addr = addr;
 		break;
@@ -244,9 +254,9 @@
 
 	switch (hw_interconnect) {
 	case OCMEM_PORT:
+	case OCMEM_OCMEMNOC:
 		ret_addr = offset_to_phys(addr);
 		break;
-	case OCMEM_OCMEMNOC:
 	case OCMEM_SYSNOC:
 		ret_addr = addr;
 		break;
@@ -588,16 +598,20 @@
 	if (rc < 0)
 		goto core_clock_fail;
 
-	rc = ocmem_enable_iface_clock();
 
-	if (rc < 0)
-		goto iface_clock_fail;
+	if (is_iface_access(req->owner)) {
+		rc = ocmem_enable_iface_clock();
 
-	rc = ocmem_enable_br_clock();
+		if (rc < 0)
+			goto iface_clock_fail;
+	}
 
-	if (rc < 0)
-		goto br_clock_fail;
+	if (is_remapped_access(req->owner)) {
+		rc = ocmem_enable_br_clock();
 
+		if (rc < 0)
+			goto br_clock_fail;
+	}
 
 	rc = ocmem_lock(req->owner, phys_to_offset(req->req_start), req->req_sz,
 							get_mode(req->owner));
@@ -622,9 +636,11 @@
 process_map_fail:
 	ocmem_unlock(req->owner, phys_to_offset(req->req_start), req->req_sz);
 lock_failed:
-	ocmem_disable_br_clock();
+	if (is_remapped_access(req->owner))
+		ocmem_disable_br_clock();
 br_clock_fail:
-	ocmem_disable_iface_clock();
+	if (is_iface_access(req->owner))
+		ocmem_disable_iface_clock();
 iface_clock_fail:
 	ocmem_disable_core_clock();
 core_clock_fail:
@@ -651,8 +667,10 @@
 		goto unlock_failed;
 	}
 
-	ocmem_disable_br_clock();
-	ocmem_disable_iface_clock();
+	if (is_remapped_access(req->owner))
+		ocmem_disable_br_clock();
+	if (is_iface_access(req->owner))
+		ocmem_disable_iface_clock();
 	ocmem_disable_core_clock();
 	pr_debug("ocmem: Unmapped request %p\n", req);
 	return 0;
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
deleted file mode 100644
index daafd1d..0000000
--- a/arch/arm/mach-msm/pil-mba.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (c) 2012, 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/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/ioport.h>
-#include <linux/elf.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/interrupt.h>
-
-#include <mach/subsystem_restart.h>
-#include <mach/msm_smsm.h>
-#include <mach/peripheral-loader.h>
-
-#include "peripheral-loader.h"
-#include "ramdump.h"
-
-#define RMB_MBA_COMMAND			0x08
-#define RMB_MBA_STATUS			0x0C
-#define RMB_PMI_META_DATA		0x10
-#define RMB_PMI_CODE_START		0x14
-#define RMB_PMI_CODE_LENGTH		0x18
-
-#define CMD_META_DATA_READY		0x1
-#define CMD_LOAD_READY			0x2
-
-#define STATUS_META_DATA_AUTH_SUCCESS	0x3
-#define STATUS_AUTH_COMPLETE		0x4
-
-#define PROXY_TIMEOUT_MS		10000
-#define POLL_INTERVAL_US		50
-
-#define MAX_SSR_REASON_LEN 81U
-
-static int modem_auth_timeout_ms = 10000;
-module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR);
-
-struct mba_data {
-	void __iomem *reg_base;
-	void __iomem *metadata_base;
-	unsigned long metadata_phys;
-	struct pil_device *pil;
-	struct pil_desc desc;
-	struct subsys_device *subsys;
-	struct subsys_desc subsys_desc;
-	struct clk *xo;
-	void *ramdump_dev;
-	void *smem_ramdump_dev;
-	bool crash_shutdown;
-	bool ignore_errors;
-	u32 img_length;
-};
-
-static int pil_mba_make_proxy_votes(struct pil_desc *pil)
-{
-	int ret;
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-
-	ret = clk_prepare_enable(drv->xo);
-	if (ret) {
-		dev_err(pil->dev, "Failed to enable XO\n");
-		return ret;
-	}
-	return 0;
-}
-
-static void pil_mba_remove_proxy_votes(struct pil_desc *pil)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	clk_disable_unprepare(drv->xo);
-}
-
-static int pil_mba_init_image(struct pil_desc *pil,
-			      const u8 *metadata, size_t size)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	s32 status;
-	int ret;
-
-	/* Copy metadata to assigned shared buffer location */
-	memcpy(drv->metadata_base, metadata, size);
-
-	/* Initialize length counter to 0 */
-	writel_relaxed(0, drv->reg_base + RMB_PMI_CODE_LENGTH);
-	drv->img_length = 0;
-
-	/* Pass address of meta-data to the MBA and perform authentication */
-	writel_relaxed(drv->metadata_phys, drv->reg_base + RMB_PMI_META_DATA);
-	writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
-	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
-		POLL_INTERVAL_US, modem_auth_timeout_ms * 1000);
-	if (ret) {
-		dev_err(pil->dev, "MBA authentication timed out\n");
-	} else if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d\n", status);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
-			       size_t size)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	s32 status;
-
-	/* Begin image authentication */
-	if (drv->img_length == 0) {
-		writel_relaxed(phy_addr, drv->reg_base + RMB_PMI_CODE_START);
-		writel_relaxed(CMD_LOAD_READY, drv->reg_base + RMB_MBA_COMMAND);
-	}
-	/* Increment length counter */
-	drv->img_length += size;
-	writel_relaxed(drv->img_length, drv->reg_base + RMB_PMI_CODE_LENGTH);
-
-	status = readl_relaxed(drv->reg_base + RMB_MBA_STATUS);
-	if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d\n", status);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int pil_mba_auth(struct pil_desc *pil)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	int ret;
-	s32 status;
-
-	/* Wait for all segments to be authenticated or an error to occur */
-	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-			status == STATUS_AUTH_COMPLETE || status < 0,
-			50, modem_auth_timeout_ms * 1000);
-	if (ret) {
-		dev_err(pil->dev, "MBA authentication timed out\n");
-	} else if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d\n", status);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int pil_mba_shutdown(struct pil_desc *pil)
-{
-	return 0;
-}
-
-static struct pil_reset_ops pil_mba_ops = {
-	.init_image = pil_mba_init_image,
-	.proxy_vote = pil_mba_make_proxy_votes,
-	.proxy_unvote = pil_mba_remove_proxy_votes,
-	.verify_blob = pil_mba_verify_blob,
-	.auth_and_reset = pil_mba_auth,
-	.shutdown = pil_mba_shutdown,
-};
-
-#define subsys_to_drv(d) container_of(d, struct mba_data, subsys_desc)
-
-static void log_modem_sfr(void)
-{
-	u32 size;
-	char *smem_reason, reason[MAX_SSR_REASON_LEN];
-
-	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
-	if (!smem_reason || !size) {
-		pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
-		return;
-	}
-	if (!smem_reason[0]) {
-		pr_err("modem subsystem failure reason: (unknown, empty string found).\n");
-		return;
-	}
-
-	strlcpy(reason, smem_reason, min(size, sizeof(reason)));
-	pr_err("modem subsystem failure reason: %s.\n", reason);
-
-	smem_reason[0] = '\0';
-	wmb();
-}
-
-static void restart_modem(struct mba_data *drv)
-{
-	log_modem_sfr();
-	drv->ignore_errors = true;
-	subsystem_restart_dev(drv->subsys);
-}
-
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
-{
-	struct mba_data *drv = data;
-
-	/* Ignore if we're the one that set SMSM_RESET */
-	if (drv->crash_shutdown)
-		return;
-
-	if (new_state & SMSM_RESET) {
-		pr_err("Probable fatal error on the modem.\n");
-		restart_modem(drv);
-	}
-}
-
-static int modem_shutdown(const struct subsys_desc *subsys)
-{
-	pil_force_shutdown("modem");
-	pil_force_shutdown("mba");
-	return 0;
-}
-
-static int modem_powerup(const struct subsys_desc *subsys)
-{
-	struct mba_data *drv = subsys_to_drv(subsys);
-	/*
-	 * At this time, the modem is shutdown. Therefore this function cannot
-	 * run concurrently with either the watchdog bite error handler or the
-	 * SMSM callback, making it safe to unset the flag below.
-	 */
-	drv->ignore_errors = 0;
-	pil_force_boot("mba");
-	pil_force_boot("modem");
-	return 0;
-}
-
-static void modem_crash_shutdown(const struct subsys_desc *subsys)
-{
-	struct mba_data *drv = subsys_to_drv(subsys);
-	drv->crash_shutdown = true;
-	smsm_reset_modem(SMSM_RESET);
-}
-
-static struct ramdump_segment modem_segments[] = {
-	{0x08400000, 0x0D100000 - 0x08400000},
-};
-
-static struct ramdump_segment smem_segments[] = {
-	{0x0FA00000, 0x0FC00000 - 0x0FA00000},
-};
-
-static int modem_ramdump(int enable, const struct subsys_desc *subsys)
-{
-	struct mba_data *drv = subsys_to_drv(subsys);
-	int ret;
-
-	if (!enable)
-		return 0;
-
-	pil_force_boot("mba");
-
-	ret = do_ramdump(drv->ramdump_dev, modem_segments,
-				ARRAY_SIZE(modem_segments));
-	if (ret < 0) {
-		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
-		goto out;
-	}
-
-	ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
-		ARRAY_SIZE(smem_segments));
-	if (ret < 0) {
-		pr_err("Unable to dump smem memory (rc = %d).\n", ret);
-		goto out;
-	}
-
-out:
-	pil_force_shutdown("mba");
-	return ret;
-}
-
-static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
-{
-	struct mba_data *drv = dev_id;
-	if (drv->ignore_errors)
-		return IRQ_HANDLED;
-	pr_err("Watchdog bite received from modem software!\n");
-	restart_modem(drv);
-	return IRQ_HANDLED;
-}
-
-static int mss_start(const struct subsys_desc *desc)
-{
-	void *ret;
-	struct mba_data *drv = subsys_to_drv(desc);
-
-	ret = pil_get(drv->desc.name);
-	if (IS_ERR(ret))
-		return PTR_ERR(ret);
-	return 0;
-}
-
-static void mss_stop(const struct subsys_desc *desc)
-{
-	struct mba_data *drv = subsys_to_drv(desc);
-	pil_put(drv->pil);
-}
-
-static int __devinit pil_mba_driver_probe(struct platform_device *pdev)
-{
-	struct mba_data *drv;
-	struct resource *res;
-	struct pil_desc *desc;
-	int ret, irq;
-
-	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
-	if (!drv)
-		return -ENOMEM;
-	platform_set_drvdata(pdev, drv);
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb_base");
-	if (!res)
-		return -EINVAL;
-	drv->reg_base = devm_ioremap(&pdev->dev, res->start,
-				     resource_size(res));
-	if (!drv->reg_base)
-		return -ENOMEM;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-					    "metadata_base");
-	if (res) {
-		drv->metadata_base = devm_ioremap(&pdev->dev, res->start,
-						  resource_size(res));
-		if (!drv->metadata_base)
-			return -ENOMEM;
-		drv->metadata_phys = res->start;
-	}
-
-	desc = &drv->desc;
-	ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
-				      &desc->name);
-	if (ret)
-		return ret;
-
-	of_property_read_string(pdev->dev.of_node, "qcom,depends-on",
-				      &desc->depends_on);
-
-	drv->xo = devm_clk_get(&pdev->dev, "xo");
-	if (IS_ERR(drv->xo))
-		return PTR_ERR(drv->xo);
-
-	desc->dev = &pdev->dev;
-	desc->ops = &pil_mba_ops;
-	desc->owner = THIS_MODULE;
-	desc->proxy_timeout = PROXY_TIMEOUT_MS;
-
-	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil))
-		return PTR_ERR(drv->pil);
-
-	drv->subsys_desc.name = desc->name;
-	drv->subsys_desc.dev = &pdev->dev;
-	drv->subsys_desc.owner = THIS_MODULE;
-	drv->subsys_desc.shutdown = modem_shutdown;
-	drv->subsys_desc.powerup = modem_powerup;
-	drv->subsys_desc.ramdump = modem_ramdump;
-	drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
-	drv->subsys_desc.start = mss_start;
-	drv->subsys_desc.stop = mss_stop;
-
-	drv->ramdump_dev = create_ramdump_device("modem");
-	if (!drv->ramdump_dev) {
-		pr_err("%s: Unable to create a modem ramdump device.\n",
-			__func__);
-		ret = -ENOMEM;
-		goto err_ramdump;
-	}
-
-	drv->smem_ramdump_dev = create_ramdump_device("smem-modem");
-	if (!drv->smem_ramdump_dev) {
-		pr_err("%s: Unable to create an smem ramdump device.\n",
-			__func__);
-		ret = -ENOMEM;
-		goto err_ramdump_smem;
-	}
-
-	drv->subsys = subsys_register(&drv->subsys_desc);
-	if (IS_ERR(drv->subsys)) {
-		goto err_subsys;
-		ret = PTR_ERR(drv->subsys);
-	}
-
-	ret = devm_request_irq(&pdev->dev, irq, modem_wdog_bite_irq,
-				IRQF_TRIGGER_RISING, "modem_wdog", drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to request watchdog IRQ.\n");
-		goto err_irq;
-	}
-
-	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
-		smsm_state_cb, drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to register SMSM callback!\n");
-		goto err_irq;
-	}
-
-	return 0;
-
-err_irq:
-	subsys_unregister(drv->subsys);
-err_subsys:
-	destroy_ramdump_device(drv->smem_ramdump_dev);
-err_ramdump_smem:
-	destroy_ramdump_device(drv->ramdump_dev);
-err_ramdump:
-	msm_pil_unregister(drv->pil);
-	return ret;
-}
-
-static int __devexit pil_mba_driver_exit(struct platform_device *pdev)
-{
-	struct mba_data *drv = platform_get_drvdata(pdev);
-	smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
-			smsm_state_cb, drv);
-	subsys_unregister(drv->subsys);
-	destroy_ramdump_device(drv->smem_ramdump_dev);
-	destroy_ramdump_device(drv->ramdump_dev);
-	msm_pil_unregister(drv->pil);
-	return 0;
-}
-
-static struct of_device_id mba_match_table[] = {
-	{ .compatible = "qcom,pil-mba" },
-	{}
-};
-
-struct platform_driver pil_mba_driver = {
-	.probe = pil_mba_driver_probe,
-	.remove = __devexit_p(pil_mba_driver_exit),
-	.driver = {
-		.name = "pil-mba",
-		.of_match_table = mba_match_table,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init pil_mba_init(void)
-{
-	return platform_driver_register(&pil_mba_driver);
-}
-module_init(pil_mba_init);
-
-static void __exit pil_mba_exit(void)
-{
-	platform_driver_unregister(&pil_mba_driver);
-}
-module_exit(pil_mba_exit);
-
-MODULE_DESCRIPTION("Support for modem boot using the Modem Boot Authenticator");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 8164d64..c32cf5c 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -348,6 +348,8 @@
 		ret = PTR_ERR(drv->subsys);
 		goto err_subsys;
 	}
+	if (!drv->loadable)
+		subsys_default_online(drv->subsys);
 
 	ret = devm_request_irq(&pdev->dev, q6->wdog_irq, lpass_wdog_bite_irq,
 			IRQF_TRIGGER_RISING, dev_name(&pdev->dev), drv);
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index fe8c3b1..aa59bbd 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -449,6 +449,8 @@
 		ret = PTR_ERR(drv->subsys);
 		goto err_subsys;
 	}
+	if (!drv->loadable)
+		subsys_default_online(drv->subsys);
 
 	ret = devm_request_irq(&pdev->dev, drv_fw->wdog_irq,
 			modem_wdog_bite_irq, IRQF_TRIGGER_RISING,
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index f3c731f..8a02251 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012, The Linux Foundation. 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
@@ -24,11 +24,16 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/regulator/consumer.h>
+#include <linux/interrupt.h>
 
+#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
 #include <mach/clk.h>
+#include <mach/msm_smsm.h>
 
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
+#include "ramdump.h"
 
 /* Q6 Register Offsets */
 #define QDSP6SS_RST_EVB			0x010
@@ -38,9 +43,6 @@
 #define MSS_MODEM_HALT_BASE		0x200
 #define MSS_NC_HALT_BASE		0x280
 
-/* MSS_CLAMP_IO Register Value */
-#define MSS_IO_UNCLAMP_ALL		0x40
-
 /* RMB Status Register Values */
 #define STATUS_PBL_SUCCESS		0x1
 #define STATUS_XPU_UNLOCKED		0x1
@@ -49,14 +51,47 @@
 /* PBL/MBA interface registers */
 #define RMB_MBA_IMAGE			0x00
 #define RMB_PBL_STATUS			0x04
+#define RMB_MBA_COMMAND			0x08
 #define RMB_MBA_STATUS			0x0C
+#define RMB_PMI_META_DATA		0x10
+#define RMB_PMI_CODE_START		0x14
+#define RMB_PMI_CODE_LENGTH		0x18
 
 #define PROXY_TIMEOUT_MS		10000
 #define POLL_INTERVAL_US		50
 
+#define CMD_META_DATA_READY		0x1
+#define CMD_LOAD_READY			0x2
+
+#define STATUS_META_DATA_AUTH_SUCCESS	0x3
+#define STATUS_AUTH_COMPLETE		0x4
+
+#define MAX_SSR_REASON_LEN 81U
+
+struct mba_data {
+	void __iomem *metadata_base;
+	void __iomem *rmb_base;
+	void __iomem *io_clamp_reg;
+	unsigned long metadata_phys;
+	struct pil_device *pil;
+	struct pil_desc desc;
+	struct subsys_device *subsys;
+	struct subsys_desc subsys_desc;
+	u32 img_length;
+	struct q6v5_data *q6;
+	int self_auth;
+	void *ramdump_dev;
+	void *smem_ramdump_dev;
+	bool crash_shutdown;
+	bool ignore_errors;
+};
+
 static int pbl_mba_boot_timeout_ms = 100;
 module_param(pbl_mba_boot_timeout_ms, int, S_IRUGO | S_IWUSR);
 
+static int modem_auth_timeout_ms = 10000;
+module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR);
+
 static int pil_mss_power_up(struct q6v5_data *drv)
 {
 	int ret;
@@ -108,11 +143,12 @@
 static int wait_for_mba_ready(struct q6v5_data *drv)
 {
 	struct device *dev = drv->desc.dev;
+	struct mba_data *mba = platform_get_drvdata(to_platform_device(dev));
 	int ret;
 	u32 status;
 
 	/* Wait for PBL completion. */
-	ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status,
+	ret = readl_poll_timeout(mba->rmb_base + RMB_PBL_STATUS, status,
 		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
 	if (ret) {
 		dev_err(dev, "PBL boot timed out\n");
@@ -124,7 +160,7 @@
 	}
 
 	/* Wait for MBA completion. */
-	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+	ret = readl_poll_timeout(mba->rmb_base + RMB_MBA_STATUS, status,
 		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
 	if (ret) {
 		dev_err(dev, "MBA boot timed out\n");
@@ -171,6 +207,8 @@
 static int pil_mss_reset(struct pil_desc *pil)
 {
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	struct platform_device *pdev = to_platform_device(pil->dev);
+	struct mba_data *mba = platform_get_drvdata(pdev);
 	int ret;
 
 	/* Deassert reset to subsystem and wait for propagation */
@@ -191,8 +229,8 @@
 		goto err_clks;
 
 	/* Program Image Address */
-	if (drv->self_auth) {
-		writel_relaxed(drv->start_addr, drv->rmb_base + RMB_MBA_IMAGE);
+	if (mba->self_auth) {
+		writel_relaxed(drv->start_addr, mba->rmb_base + RMB_MBA_IMAGE);
 		/* Ensure write to RMB base occurs before reset is released. */
 		mb();
 	} else {
@@ -200,15 +238,12 @@
 				drv->reg_base + QDSP6SS_RST_EVB);
 	}
 
-	/* De-assert MSS IO clamps */
-	writel_relaxed(MSS_IO_UNCLAMP_ALL, drv->io_clamp_reg);
-
 	ret = pil_q6v5_reset(pil);
 	if (ret)
 		goto err_q6v5_reset;
 
 	/* Wait for MBA to start. Check for PBL and MBA errors while waiting. */
-	if (drv->self_auth) {
+	if (mba->self_auth) {
 		ret = wait_for_mba_ready(drv);
 		if (ret)
 			goto err_auth;
@@ -236,22 +271,277 @@
 	.shutdown = pil_mss_shutdown,
 };
 
-static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
+static int pil_mba_make_proxy_votes(struct pil_desc *pil)
 {
-	struct q6v5_data *drv;
-	struct pil_desc *desc;
-	struct resource *res;
+	int ret;
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+
+	ret = clk_prepare_enable(drv->q6->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+	return 0;
+}
+
+static void pil_mba_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	clk_disable_unprepare(drv->q6->xo);
+}
+
+static int pil_mba_init_image(struct pil_desc *pil,
+			      const u8 *metadata, size_t size)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	s32 status;
 	int ret;
 
-	drv = pil_q6v5_init(pdev);
-	if (IS_ERR(drv))
-		return PTR_ERR(drv);
+	/* Copy metadata to assigned shared buffer location */
+	memcpy(drv->metadata_base, metadata, size);
+
+	/* Initialize length counter to 0 */
+	writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_LENGTH);
+	drv->img_length = 0;
+
+	/* Pass address of meta-data to the MBA and perform authentication */
+	writel_relaxed(drv->metadata_phys, drv->rmb_base + RMB_PMI_META_DATA);
+	writel_relaxed(CMD_META_DATA_READY, drv->rmb_base + RMB_MBA_COMMAND);
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
+		POLL_INTERVAL_US, modem_auth_timeout_ms * 1000);
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication of headers timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d for headers\n",
+				status);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
+			       size_t size)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	s32 status;
+
+	/* Begin image authentication */
+	if (drv->img_length == 0) {
+		writel_relaxed(phy_addr, drv->rmb_base + RMB_PMI_CODE_START);
+		writel_relaxed(CMD_LOAD_READY, drv->rmb_base + RMB_MBA_COMMAND);
+	}
+	/* Increment length counter */
+	drv->img_length += size;
+	writel_relaxed(drv->img_length, drv->rmb_base + RMB_PMI_CODE_LENGTH);
+
+	status = readl_relaxed(drv->rmb_base + RMB_MBA_STATUS);
+	if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int pil_mba_auth(struct pil_desc *pil)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+	s32 status;
+
+	/* Wait for all segments to be authenticated or an error to occur */
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+			status == STATUS_AUTH_COMPLETE || status < 0,
+			50, modem_auth_timeout_ms * 1000);
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication of image timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d for image\n", status);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int pil_mba_shutdown(struct pil_desc *pil)
+{
+	return 0;
+}
+
+static struct pil_reset_ops pil_mba_ops = {
+	.init_image = pil_mba_init_image,
+	.proxy_vote = pil_mba_make_proxy_votes,
+	.proxy_unvote = pil_mba_remove_proxy_votes,
+	.verify_blob = pil_mba_verify_blob,
+	.auth_and_reset = pil_mba_auth,
+	.shutdown = pil_mba_shutdown,
+};
+
+#define subsys_to_drv(d) container_of(d, struct mba_data, subsys_desc)
+
+static void log_modem_sfr(void)
+{
+	u32 size;
+	char *smem_reason, reason[MAX_SSR_REASON_LEN];
+
+	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+	if (!smem_reason || !size) {
+		pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
+		return;
+	}
+	if (!smem_reason[0]) {
+		pr_err("modem subsystem failure reason: (unknown, empty string found).\n");
+		return;
+	}
+
+	strlcpy(reason, smem_reason, min(size, sizeof(reason)));
+	pr_err("modem subsystem failure reason: %s.\n", reason);
+
+	smem_reason[0] = '\0';
+	wmb();
+}
+
+static void restart_modem(struct mba_data *drv)
+{
+	log_modem_sfr();
+	drv->ignore_errors = true;
+	subsystem_restart_dev(drv->subsys);
+}
+
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+{
+	struct mba_data *drv = data;
+
+	/* Ignore if we're the one that set SMSM_RESET */
+	if (drv->crash_shutdown)
+		return;
+
+	if (new_state & SMSM_RESET) {
+		pr_err("Probable fatal error on the modem.\n");
+		restart_modem(drv);
+	}
+}
+
+static int modem_shutdown(const struct subsys_desc *subsys)
+{
+	pil_force_shutdown("modem");
+	pil_force_shutdown("mba");
+	return 0;
+}
+
+static int modem_powerup(const struct subsys_desc *subsys)
+{
+	struct mba_data *drv = subsys_to_drv(subsys);
+	/*
+	 * At this time, the modem is shutdown. Therefore this function cannot
+	 * run concurrently with either the watchdog bite error handler or the
+	 * SMSM callback, making it safe to unset the flag below.
+	 */
+	drv->ignore_errors = false;
+	pil_force_boot("mba");
+	pil_force_boot("modem");
+	return 0;
+}
+
+static void modem_crash_shutdown(const struct subsys_desc *subsys)
+{
+	struct mba_data *drv = subsys_to_drv(subsys);
+	drv->crash_shutdown = true;
+	smsm_reset_modem(SMSM_RESET);
+}
+
+static struct ramdump_segment modem_segments[] = {
+	{0x08400000, 0x0D100000 - 0x08400000},
+};
+
+static struct ramdump_segment smem_segments[] = {
+	{0x0FA00000, 0x0FC00000 - 0x0FA00000},
+};
+
+static int modem_ramdump(int enable, const struct subsys_desc *subsys)
+{
+	struct mba_data *drv = subsys_to_drv(subsys);
+	int ret;
+
+	if (!enable)
+		return 0;
+
+	pil_force_boot("mba");
+
+	ret = do_ramdump(drv->ramdump_dev, modem_segments,
+				ARRAY_SIZE(modem_segments));
+	if (ret < 0) {
+		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
+		goto out;
+	}
+
+	ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
+		ARRAY_SIZE(smem_segments));
+	if (ret < 0) {
+		pr_err("Unable to dump smem memory (rc = %d).\n", ret);
+		goto out;
+	}
+
+out:
+	pil_force_shutdown("mba");
+	return ret;
+}
+
+static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
+{
+	struct mba_data *drv = dev_id;
+	if (drv->ignore_errors)
+		return IRQ_HANDLED;
+	pr_err("Watchdog bite received from modem software!\n");
+	restart_modem(drv);
+	return IRQ_HANDLED;
+}
+
+static int mss_start(const struct subsys_desc *desc)
+{
+	void *ret;
+	struct mba_data *drv = subsys_to_drv(desc);
+
+	ret = pil_get(drv->desc.name);
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+	return 0;
+}
+
+static void mss_stop(const struct subsys_desc *desc)
+{
+	struct mba_data *drv = subsys_to_drv(desc);
+	pil_put(drv->pil);
+}
+
+static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
+{
+	struct mba_data *drv;
+	struct q6v5_data *q6;
+	struct pil_desc *q6_desc, *mba_desc;
+	struct resource *res;
+	int ret, irq;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
 	platform_set_drvdata(pdev, drv);
 
-	desc = &drv->desc;
-	desc->ops = &pil_mss_ops;
-	desc->owner = THIS_MODULE;
-	desc->proxy_timeout = PROXY_TIMEOUT_MS;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	q6 = pil_q6v5_init(pdev);
+	if (IS_ERR(q6))
+		return PTR_ERR(q6);
+	drv->q6 = q6;
+
+	q6_desc = &q6->desc;
+	q6_desc->ops = &pil_mss_ops;
+	q6_desc->owner = THIS_MODULE;
+	q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
 
 	of_property_read_u32(pdev->dev.of_node, "qcom,pil-self-auth",
 			     &drv->self_auth);
@@ -262,57 +552,138 @@
 					     resource_size(res));
 		if (!drv->rmb_base)
 			return -ENOMEM;
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					    "metadata_base");
+		if (res) {
+			drv->metadata_base = devm_ioremap(&pdev->dev,
+						res->start, resource_size(res));
+			if (!drv->metadata_base)
+				return -ENOMEM;
+			drv->metadata_phys = res->start;
+		}
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
-	drv->restart_reg = devm_ioremap(&pdev->dev, res->start,
+	q6->restart_reg = devm_ioremap(&pdev->dev, res->start,
 					resource_size(res));
-	if (!drv->restart_reg)
+	if (!q6->restart_reg)
 		return -ENOMEM;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clamp_reg");
-	drv->io_clamp_reg = devm_ioremap(&pdev->dev, res->start,
-					resource_size(res));
-	if (!drv->io_clamp_reg)
-		return -ENOMEM;
+	q6->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
+	if (IS_ERR(q6->vreg))
+		return PTR_ERR(q6->vreg);
 
-	drv->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
-	if (IS_ERR(drv->vreg))
-		return PTR_ERR(drv->vreg);
-
-	ret = regulator_set_voltage(drv->vreg, 1050000, 1050000);
+	ret = regulator_set_voltage(q6->vreg, 1050000, 1050000);
 	if (ret)
 		dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
 
-	ret = regulator_set_optimum_mode(drv->vreg, 100000);
+	ret = regulator_set_optimum_mode(q6->vreg, 100000);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to set regulator's mode.\n");
 		return ret;
 	}
 
-	drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
-	if (IS_ERR(drv->ahb_clk))
-		return PTR_ERR(drv->ahb_clk);
+	q6->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+	if (IS_ERR(q6->ahb_clk))
+		return PTR_ERR(q6->ahb_clk);
 
-	drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
-	if (IS_ERR(drv->axi_clk))
-		return PTR_ERR(drv->axi_clk);
+	q6->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+	if (IS_ERR(q6->axi_clk))
+		return PTR_ERR(q6->axi_clk);
 
-	drv->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
-	if (IS_ERR(drv->rom_clk))
-		return PTR_ERR(drv->rom_clk);
+	q6->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
+	if (IS_ERR(q6->rom_clk))
+		return PTR_ERR(q6->rom_clk);
 
-	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil))
-		return PTR_ERR(drv->pil);
+	q6->pil = msm_pil_register(q6_desc);
+	if (IS_ERR(q6->pil))
+		return PTR_ERR(q6->pil);
+
+	mba_desc = &drv->desc;
+	mba_desc->name = "modem";
+	mba_desc->depends_on = "mba";
+	mba_desc->dev = &pdev->dev;
+	mba_desc->ops = &pil_mba_ops;
+	mba_desc->owner = THIS_MODULE;
+	mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
+
+	drv->pil = msm_pil_register(mba_desc);
+	if (IS_ERR(drv->pil)) {
+		ret = PTR_ERR(drv->pil);
+		goto err_mba_desc;
+	}
+
+	drv->subsys_desc.name = "modem";
+	drv->subsys_desc.dev = &pdev->dev;
+	drv->subsys_desc.owner = THIS_MODULE;
+	drv->subsys_desc.shutdown = modem_shutdown;
+	drv->subsys_desc.powerup = modem_powerup;
+	drv->subsys_desc.ramdump = modem_ramdump;
+	drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
+	drv->subsys_desc.start = mss_start;
+	drv->subsys_desc.stop = mss_stop;
+
+	drv->ramdump_dev = create_ramdump_device("modem");
+	if (!drv->ramdump_dev) {
+		pr_err("%s: Unable to create a modem ramdump device.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_ramdump;
+	}
+
+	drv->smem_ramdump_dev = create_ramdump_device("smem-modem");
+	if (!drv->smem_ramdump_dev) {
+		pr_err("%s: Unable to create an smem ramdump device.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_ramdump_smem;
+	}
+
+	drv->subsys = subsys_register(&drv->subsys_desc);
+	if (IS_ERR(drv->subsys)) {
+		ret = PTR_ERR(drv->subsys);
+		goto err_subsys;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, modem_wdog_bite_irq,
+				IRQF_TRIGGER_RISING, "modem_wdog", drv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to request watchdog IRQ.\n");
+		goto err_irq;
+	}
+
+	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+		smsm_state_cb, drv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to register SMSM callback!\n");
+		goto err_irq;
+	}
 
 	return 0;
+
+err_irq:
+	subsys_unregister(drv->subsys);
+err_subsys:
+	destroy_ramdump_device(drv->smem_ramdump_dev);
+err_ramdump_smem:
+	destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+	msm_pil_unregister(drv->pil);
+err_mba_desc:
+	msm_pil_unregister(q6->pil);
+	return ret;
 }
 
 static int __devexit pil_mss_driver_exit(struct platform_device *pdev)
 {
-	struct q6v5_data *drv = platform_get_drvdata(pdev);
+	struct mba_data *drv = platform_get_drvdata(pdev);
+	smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
+			smsm_state_cb, drv);
+	subsys_unregister(drv->subsys);
+	destroy_ramdump_device(drv->smem_ramdump_dev);
+	destroy_ramdump_device(drv->ramdump_dev);
 	msm_pil_unregister(drv->pil);
+	msm_pil_unregister(drv->q6->pil);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index f176d2d..340b5e3 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012, The Linux Foundation. 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
@@ -29,13 +29,10 @@
 	struct clk *reg_clk;	/* CPU access registers */
 	struct clk *rom_clk;	/* Boot ROM */
 	void __iomem *axi_halt_base;
-	void __iomem *rmb_base;
 	void __iomem *restart_reg;
-	void __iomem *io_clamp_reg;
 	unsigned long start_addr;
 	struct regulator *vreg;
 	bool is_booted;
-	int self_auth;
 	struct pil_device *pil;
 	struct pil_desc desc;
 };
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 5f05f98..0933d20 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -103,8 +103,7 @@
 	if (!base_ptr)
 		return -ENODEV;
 
-	if (machine_is_msm8974_sim() || machine_is_mpq8092_sim() ||
-	    machine_is_msm8226_sim()) {
+	if (machine_is_msm8974_sim() || machine_is_mpq8092_sim()) {
 		writel_relaxed(0x800, base_ptr+0x04);
 		writel_relaxed(0x3FFF, base_ptr+0x14);
 	}
@@ -179,8 +178,7 @@
 	if (cpu_is_msm8x60())
 		return scorpion_release_secondary();
 
-	if (machine_is_msm8974_sim() || machine_is_mpq8092_sim() ||
-	    machine_is_msm8226_sim())
+	if (machine_is_msm8974_sim() || machine_is_mpq8092_sim())
 		return krait_release_secondary_sim(0xf9088000, cpu);
 
 	if (soc_class_is_msm8960() || soc_class_is_msm8930() ||
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 0f17a0b..66d6bda 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -27,4 +27,3 @@
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
-obj-m += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 8ac1fea..d494069 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -231,8 +231,11 @@
 			apr_set_q6_state(APR_SUBSYS_LOADED);
 			pr_debug("APR: Image is loaded, stated\n");
 		}
-	} else
+	} else if (apr_get_q6_state() == APR_SUBSYS_LOADED) {
+		pr_debug("APR: q6 image already loaded\n");
+	} else {
 		pr_debug("APR: cannot load state %d\n", apr_get_q6_state());
+	}
 	mutex_unlock(&q6.lock);
 	return rc;
 }
@@ -658,8 +661,8 @@
 		pr_debug("L-notify: Bootup started\n");
 		break;
 	case SUBSYS_AFTER_POWERUP:
-		if (apr_cmpxchg_q6_state(APR_SUBSYS_DOWN, APR_SUBSYS_UP) ==
-					     APR_SUBSYS_DOWN)
+		if (apr_cmpxchg_q6_state(APR_SUBSYS_DOWN,
+				APR_SUBSYS_LOADED) == APR_SUBSYS_DOWN)
 			wake_up(&dsp_wait);
 		pr_debug("L-Notify: Bootup Completed\n");
 		break;
@@ -703,7 +706,7 @@
 	init_waitqueue_head(&dsp_wait);
 	init_waitqueue_head(&modem_wait);
 	subsys_notif_register_notifier("modem", &mnb);
-	subsys_notif_register_notifier("lpass", &lnb);
+	subsys_notif_register_notifier(apr_get_lpass_subsys_name(), &lnb);
 	return ret;
 }
 late_initcall(apr_late_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/apr_v1.c b/arch/arm/mach-msm/qdsp6v2/apr_v1.c
index 9535968..011a73b 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr_v1.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr_v1.c
@@ -21,6 +21,8 @@
 #include <mach/qdsp6v2/dsp_debug.h>
 #include <mach/peripheral-loader.h>
 
+static const char *lpass_subsys_name = "lpass";
+
 struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn,
 			     uint32_t src_port, void *priv)
 {
@@ -131,3 +133,8 @@
 	apr_set_q6_state(APR_SUBSYS_UP);
 	apr_set_modem_state(APR_SUBSYS_UP);
 }
+
+const char *apr_get_lpass_subsys_name(void)
+{
+	return lpass_subsys_name;
+}
diff --git a/arch/arm/mach-msm/qdsp6v2/apr_v2.c b/arch/arm/mach-msm/qdsp6v2/apr_v2.c
index 1ef189f..ed494e4 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr_v2.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr_v2.c
@@ -19,6 +19,8 @@
 #include <mach/qdsp6v2/apr_tal.h>
 #include <mach/qdsp6v2/dsp_debug.h>
 
+static const char *lpass_subsys_name = "adsp";
+
 struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn,
 			     uint32_t src_port, void *priv)
 {
@@ -48,7 +50,7 @@
 			pr_err("%s: adsp not up\n", __func__);
 			return NULL;
 		}
-		pr_info("%s: Lpass Up\n", __func__);
+		pr_info("%s: adsp Up\n", __func__);
 	} else if ((dest_id == APR_DEST_MODEM) &&
 		   (apr_get_modem_state() == APR_SUBSYS_DOWN)) {
 		pr_info("%s: Wait for modem to bootup\n", __func__);
@@ -125,3 +127,8 @@
 	apr_set_q6_state(APR_SUBSYS_DOWN);
 	apr_set_modem_state(APR_SUBSYS_UP);
 }
+
+const char *apr_get_lpass_subsys_name(void)
+{
+	return lpass_subsys_name;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 01543a2..4e5281d 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/wakelock.h>
@@ -299,12 +298,9 @@
 }
 
 static bool requires_tcxo_workaround;
-static bool tcxo_workaround_noirq;
 static struct clk *tcxo_handle;
 static struct wake_lock tcxo_wake_lock;
 static DEFINE_MUTEX(tcxo_mutex);
-/* Spin lock needed for sleep-selectable regulators. */
-static DEFINE_SPINLOCK(tcxo_noirq_lock);
 static bool tcxo_is_enabled;
 /*
  * TCXO must be kept on for at least the duration of its warmup (4 ms);
@@ -314,19 +310,10 @@
 
 static void tcxo_get_handle(void)
 {
-	int rc;
-
 	if (!tcxo_handle) {
 		tcxo_handle = clk_get_sys("rpm-regulator", "vref_buff");
-		if (IS_ERR(tcxo_handle)) {
+		if (IS_ERR(tcxo_handle))
 			tcxo_handle = NULL;
-		} else {
-			rc = clk_prepare(tcxo_handle);
-			if (rc) {
-				clk_put(tcxo_handle);
-				tcxo_handle = NULL;
-			}
-		}
 	}
 }
 
@@ -342,7 +329,7 @@
 	int rc;
 
 	if (tcxo_handle && !tcxo_is_enabled) {
-		rc = clk_enable(tcxo_handle);
+		rc = clk_prepare_enable(tcxo_handle);
 		if (!rc) {
 			tcxo_is_enabled = true;
 			wake_lock(&tcxo_wake_lock);
@@ -355,21 +342,13 @@
 
 static void tcxo_delayed_disable_work(struct work_struct *work)
 {
-	unsigned long flags = 0;
+	mutex_lock(&tcxo_mutex);
 
-	if (tcxo_workaround_noirq)
-		spin_lock_irqsave(&tcxo_noirq_lock, flags);
-	else
-		mutex_lock(&tcxo_mutex);
-
-	clk_disable(tcxo_handle);
+	clk_disable_unprepare(tcxo_handle);
 	tcxo_is_enabled = false;
 	wake_unlock(&tcxo_wake_lock);
 
-	if (tcxo_workaround_noirq)
-		spin_unlock_irqrestore(&tcxo_noirq_lock, flags);
-	else
-		mutex_unlock(&tcxo_mutex);
+	mutex_unlock(&tcxo_mutex);
 }
 
 static DECLARE_DELAYED_WORK(tcxo_disable_work, tcxo_delayed_disable_work);
@@ -387,8 +366,8 @@
 				msecs_to_jiffies(TCXO_WARMUP_TIME_MS) + 1);
 }
 
-/* Spin lock needed for sleep-selectable regulators. */
-static DEFINE_SPINLOCK(rpm_noirq_lock);
+/* Mutex lock needed for sleep-selectable regulators. */
+static DEFINE_MUTEX(rpm_sleep_sel_lock);
 
 static int voltage_from_req(struct vreg *vreg)
 {
@@ -421,7 +400,6 @@
 {
 	struct msm_rpm_iv_pair *prev_req;
 	int rc = 0, max_uV_vote = 0;
-	unsigned long flags = 0;
 	bool tcxo_enabled = false;
 	bool voltage_increased = false;
 	unsigned prev0, prev1;
@@ -470,17 +448,19 @@
 		if (requires_tcxo_workaround && vreg->requires_cxo
 		    && (set == MSM_RPM_CTX_SET_0)
 		    && (GET_PART(vreg, uV) > GET_PART_PREV_ACT(vreg, uV))) {
+			mutex_lock(&tcxo_mutex);
+			if (!tcxo_handle)
+				tcxo_get_handle();
 			voltage_increased = true;
-			spin_lock_irqsave(&tcxo_noirq_lock, flags);
 			tcxo_enabled = tcxo_enable();
 		}
 
-		rc = msm_rpmrs_set_noirq(set, vreg->req, cnt);
+		rc = msm_rpmrs_set(set, vreg->req, cnt);
 		if (rc) {
 			vreg->req[0].value = prev0;
 			vreg->req[1].value = prev1;
 
-			vreg_err(vreg, "msm_rpmrs_set_noirq failed - "
+			vreg_err(vreg, "msm_rpmrs_set failed - "
 				"set=%s, id=%d, rc=%d\n",
 				(set == MSM_RPM_CTX_SET_0 ? "active" : "sleep"),
 				vreg->req[0].id, rc);
@@ -502,7 +482,7 @@
 		if (voltage_increased) {
 			if (tcxo_enabled)
 				tcxo_delayed_disable();
-			spin_unlock_irqrestore(&tcxo_noirq_lock, flags);
+			mutex_unlock(&tcxo_mutex);
 		}
 	} else if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_DUPLICATE) {
 		rpm_regulator_duplicate(vreg, set, cnt);
@@ -511,19 +491,18 @@
 	return rc;
 }
 
-static int vreg_set_noirq(struct vreg *vreg, enum rpm_vreg_voter voter,
+static int vreg_set_sleep_sel(struct vreg *vreg, enum rpm_vreg_voter voter,
 			  int sleep, unsigned mask0, unsigned val0,
 			  unsigned mask1, unsigned val1, unsigned cnt,
 			  int update_voltage)
 {
 	unsigned int s_mask[2] = {mask0, mask1}, s_val[2] = {val0, val1};
-	unsigned long flags;
 	int rc;
 
 	if (voter < 0 || voter >= RPM_VREG_VOTER_COUNT)
 		return -EINVAL;
 
-	spin_lock_irqsave(&rpm_noirq_lock, flags);
+	mutex_lock(&rpm_sleep_sel_lock);
 
 	/*
 	 * Send sleep set request first so that subsequent set_mode, etc calls
@@ -559,7 +538,7 @@
 	rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_0, mask0, val0,
 					mask1, val1, cnt, update_voltage);
 
-	spin_unlock_irqrestore(&rpm_noirq_lock, flags);
+	mutex_unlock(&rpm_sleep_sel_lock);
 
 	return rc;
 }
@@ -575,10 +554,8 @@
  * Returns 0 on success or errno.
  *
  * This function is used to vote for the voltage of a regulator without
- * using the regulator framework.  It is needed by consumers which hold spin
- * locks or have interrupts disabled because the regulator framework can sleep.
- * It is also needed by consumers which wish to only vote for active set
- * regulator voltage.
+ * using the regulator framework.  It is needed for consumers which wish to only
+ * vote for active set regulator voltage.
  *
  * If sleep_also == 0, then a sleep-set value of 0V will be voted for.
  *
@@ -693,10 +670,10 @@
 		    = vreg->part->enable_state.mask;
 	}
 
-	rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],
-			    val[1], vreg->part->request_len, 1);
+	rc = vreg_set_sleep_sel(vreg, voter, sleep_also, mask[0], val[0],
+				mask[1], val[1], vreg->part->request_len, 1);
 	if (rc)
-		vreg_err(vreg, "vreg_set_noirq failed, rc=%d\n", rc);
+		vreg_err(vreg, "vreg_set_sleep_sel failed, rc=%d\n", rc);
 
 	return rc;
 }
@@ -743,10 +720,10 @@
 	val[vreg->part->freq.word] = freq << vreg->part->freq.shift;
 	mask[vreg->part->freq.word] = vreg->part->freq.mask;
 
-	rc = vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1, mask[0],
+	rc = vreg_set_sleep_sel(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1, mask[0],
 			   val[0], mask[1], val[1], vreg->part->request_len, 0);
 	if (rc)
-		vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
+		vreg_err(vreg, "vreg_set_sleep_sel failed, rc=%d\n", rc);
 
 	return rc;
 }
@@ -1018,10 +995,8 @@
 static int vreg_store(struct vreg *vreg, unsigned mask0, unsigned val0,
 		unsigned mask1, unsigned val1)
 {
-	unsigned long flags = 0;
-
 	if (vreg->pdata.sleep_selectable)
-		spin_lock_irqsave(&rpm_noirq_lock, flags);
+		mutex_lock(&rpm_sleep_sel_lock);
 
 	vreg->req[0].value &= ~mask0;
 	vreg->req[0].value |= val0 & mask0;
@@ -1030,7 +1005,7 @@
 	vreg->req[1].value |= val1 & mask1;
 
 	if (vreg->pdata.sleep_selectable)
-		spin_unlock_irqrestore(&rpm_noirq_lock, flags);
+		mutex_unlock(&rpm_sleep_sel_lock);
 
 	return 0;
 }
@@ -1039,7 +1014,6 @@
 		unsigned mask1, unsigned val1, unsigned cnt)
 {
 	unsigned prev0 = 0, prev1 = 0;
-	unsigned long flags = 0;
 	bool tcxo_enabled = false;
 	bool voltage_increased = false;
 	int rc;
@@ -1049,7 +1023,7 @@
 	 * just the active set values.
 	 */
 	if (vreg->pdata.sleep_selectable)
-		return vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1,
+		return vreg_set_sleep_sel(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1,
 					mask0, val0, mask1, val1, cnt, 1);
 
 	prev0 = vreg->req[0].value;
@@ -1071,21 +1045,14 @@
 	/* Enable CXO clock if necessary for TCXO workaround. */
 	if (requires_tcxo_workaround && vreg->requires_cxo
 	    && (GET_PART(vreg, uV) > GET_PART_PREV_ACT(vreg, uV))) {
+		mutex_lock(&tcxo_mutex);
 		if (!tcxo_handle)
 			tcxo_get_handle();
-		if (tcxo_workaround_noirq)
-			spin_lock_irqsave(&tcxo_noirq_lock, flags);
-		else
-			mutex_lock(&tcxo_mutex);
-
 		voltage_increased = true;
 		tcxo_enabled = tcxo_enable();
 	}
 
-	if (voltage_increased && tcxo_workaround_noirq)
-		rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, vreg->req, cnt);
-	else
-		rc = msm_rpm_set(MSM_RPM_CTX_SET_0, vreg->req, cnt);
+	rc = msm_rpm_set(MSM_RPM_CTX_SET_0, vreg->req, cnt);
 
 	if (rc) {
 		vreg->req[0].value = prev0;
@@ -1107,11 +1074,7 @@
 	if (voltage_increased) {
 		if (tcxo_enabled)
 			tcxo_delayed_disable();
-
-		if (tcxo_workaround_noirq)
-			spin_unlock_irqrestore(&tcxo_noirq_lock, flags);
-		else
-			mutex_unlock(&tcxo_mutex);
+		mutex_unlock(&tcxo_mutex);
 	}
 
 	return rc;
@@ -1794,7 +1757,6 @@
 	struct rpm_regulator_platform_data *platform_data;
 	static struct rpm_regulator_consumer_mapping *prev_consumer_map;
 	static int prev_consumer_map_len;
-	struct vreg *vreg;
 	int rc = 0;
 	int i, id;
 
@@ -1880,18 +1842,6 @@
 				"rpm_regulator_tcxo");
 	}
 
-	if (requires_tcxo_workaround && !tcxo_workaround_noirq) {
-		for (i = 0; i < platform_data->num_regulators; i++) {
-			vreg = rpm_vreg_get_vreg(
-					platform_data->init_data[i].id);
-			if (vreg && vreg->requires_cxo
-			    && platform_data->init_data[i].sleep_selectable) {
-				tcxo_workaround_noirq = true;
-				break;
-			}
-		}
-	}
-
 	/* Initialize all of the regulators listed in the platform data. */
 	for (i = 0; i < platform_data->num_regulators; i++) {
 		rc = rpm_vreg_init_regulator(&platform_data->init_data[i],
diff --git a/arch/arm/mach-msm/rpm_master_stat.c b/arch/arm/mach-msm/rpm_master_stat.c
new file mode 100644
index 0000000..4dcf5eb
--- /dev/null
+++ b/arch/arm/mach-msm/rpm_master_stat.c
@@ -0,0 +1,247 @@
+/* Copyright (c) 2012, The Linux Foundation. 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/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+
+#include <mach/msm_iomap.h>
+#include "rpm_stats.h"
+#define MSG_RAM_SIZE_PER_MASTER	32
+
+enum {
+	NUMSHUTDOWNS,
+	ACTIVECORES,
+	MASTER_ID_MAX,
+};
+
+static char *msm_rpm_master_stats_id_labels[MASTER_ID_MAX] = {
+	[NUMSHUTDOWNS] = "num_shutdowns",
+	[ACTIVECORES] = "active_cores",
+};
+
+
+struct msm_rpm_master_stats {
+	unsigned long numshutdowns;
+	unsigned long active_cores;
+};
+
+struct msm_rpm_master_stats_private_data {
+	void __iomem *reg_base;
+	u32 len;
+	char **master_names;
+	u32 nomasters;
+	char buf[256];
+	struct msm_rpm_master_stats_platform_data *platform_data;
+};
+
+static int msm_rpm_master_stats_file_close(struct inode *inode,
+		struct file *file)
+{
+	struct msm_rpm_master_stats_private_data *private = file->private_data;
+
+	if (private->reg_base)
+		iounmap(private->reg_base);
+	kfree(file->private_data);
+
+	return 0;
+}
+
+static int msm_rpm_master_copy_stats(
+		struct msm_rpm_master_stats_private_data *pdata)
+{
+	struct msm_rpm_master_stats record;
+	static int nomasters;
+	int count;
+	static DEFINE_MUTEX(msm_rpm_master_stats_mutex);
+	int j = 0;
+
+	mutex_lock(&msm_rpm_master_stats_mutex);
+	/*
+	 * iterrate possible nomasters times.
+	 * 8960, 8064 have 5 masters.
+	 * 8930 has 4 masters.
+	 * 9x15 has 3 masters.
+	 */
+	if (nomasters > pdata->nomasters - 1) {
+		nomasters = 0;
+		mutex_unlock(&msm_rpm_master_stats_mutex);
+		return 0;
+	}
+
+	record.numshutdowns = readl_relaxed(pdata->reg_base +
+			(nomasters * MSG_RAM_SIZE_PER_MASTER));
+	record.active_cores = readl_relaxed(pdata->reg_base +
+				(nomasters * MSG_RAM_SIZE_PER_MASTER + 4));
+
+	count = snprintf(pdata->buf, sizeof(pdata->buf),
+		"%s\n\t%s:%lu\n\t%s:%lu\n",
+		pdata->master_names[nomasters],
+		msm_rpm_master_stats_id_labels[0],
+		record.numshutdowns,
+		msm_rpm_master_stats_id_labels[1],
+		record.active_cores);
+
+	j = find_first_bit(&record.active_cores, BITS_PER_LONG);
+	while (j < BITS_PER_LONG) {
+		count += snprintf(pdata->buf + count,
+			sizeof(pdata->buf) - count,
+			"\t\tcore%d\n", j);
+		j = find_next_bit(&record.active_cores,
+				BITS_PER_LONG, j + 1);
+	}
+
+
+	nomasters++;
+	mutex_unlock(&msm_rpm_master_stats_mutex);
+	return count;
+}
+
+static int msm_rpm_master_stats_file_read(struct file *file, char __user *bufu,
+				  size_t count, loff_t *ppos)
+{
+	struct msm_rpm_master_stats_private_data *prvdata;
+	struct msm_rpm_master_stats_platform_data *pdata;
+
+	prvdata = file->private_data;
+	if (!prvdata)
+		return -EINVAL;
+
+	pdata = prvdata->platform_data;
+	if (!pdata)
+		return -EINVAL;
+
+	if (!bufu || count < 0)
+		return -EINVAL;
+
+	if ((*ppos <= pdata->phys_size)) {
+		prvdata->len = msm_rpm_master_copy_stats(prvdata);
+		*ppos = 0;
+	}
+
+	return simple_read_from_buffer(bufu, count, ppos,
+			prvdata->buf, prvdata->len);
+}
+
+static int msm_rpm_master_stats_file_open(struct inode *inode,
+		struct file *file)
+{
+	struct msm_rpm_master_stats_private_data *prvdata;
+	struct msm_rpm_master_stats_platform_data *pdata;
+
+	pdata = inode->i_private;
+
+	file->private_data =
+		kmalloc(sizeof(struct msm_rpm_master_stats_private_data),
+			GFP_KERNEL);
+
+	if (!file->private_data)
+		return -ENOMEM;
+	prvdata = file->private_data;
+
+	prvdata->reg_base = ioremap(pdata->phys_addr_base,
+		pdata->phys_size);
+	if (!prvdata->reg_base) {
+		kfree(file->private_data);
+		prvdata = NULL;
+		pr_err("%s: ERROR could not ioremap start=%p, len=%u\n",
+			__func__, (void *)pdata->phys_addr_base,
+			pdata->phys_size);
+		return -EBUSY;
+	}
+
+	prvdata->len = 0;
+	prvdata->nomasters = pdata->nomasters;
+	prvdata->master_names = pdata->masters;
+	prvdata->platform_data = pdata;
+	return 0;
+}
+
+static const struct file_operations msm_rpm_master_stats_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = msm_rpm_master_stats_file_open,
+	.read	  = msm_rpm_master_stats_file_read,
+	.release  = msm_rpm_master_stats_file_close,
+	.llseek   = no_llseek,
+};
+
+static  int __devinit msm_rpm_master_stats_probe(struct platform_device *pdev)
+{
+	struct dentry *dent;
+	struct msm_rpm_master_stats_platform_data *pdata;
+	struct resource *res;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pdata->phys_addr_base = res->start;
+	pdata->phys_size = resource_size(res);
+
+	dent = debugfs_create_file("rpm_master_stats", S_IRUGO, NULL,
+			pdev->dev.platform_data, &msm_rpm_master_stats_fops);
+
+	if (!dent) {
+		pr_err("%s: ERROR debugfs_create_file failed\n", __func__);
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, dent);
+	return 0;
+}
+
+static int __devexit msm_rpm_master_stats_remove(struct platform_device *pdev)
+{
+	struct dentry *dent;
+
+	dent = platform_get_drvdata(pdev);
+	debugfs_remove(dent);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver msm_rpm_master_stats_driver = {
+	.probe	= msm_rpm_master_stats_probe,
+	.remove = __devexit_p(msm_rpm_master_stats_remove),
+	.driver = {
+		.name = "msm_rpm_master_stat",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_rpm_master_stats_init(void)
+{
+	return platform_driver_register(&msm_rpm_master_stats_driver);
+}
+
+static void __exit msm_rpm_master_stats_exit(void)
+{
+	platform_driver_unregister(&msm_rpm_master_stats_driver);
+}
+
+module_init(msm_rpm_master_stats_init);
+module_exit(msm_rpm_master_stats_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM RPM Master Statistics driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:msm_master_stat_log");
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 43436e5..55ae2f8 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -204,11 +204,7 @@
 		}
 	}
 
-	/* TODO : Remove once bus scaling driver is in place */
-	if (!cpu_is_msm8226())
-		scm_perf_client = msm_bus_scale_register_client(
-				&scm_pas_bus_pdata);
-
+	scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
 	if (!scm_perf_client)
 		pr_warn("unable to register bus client\n");
 
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index e5cc4ec..8951cfe 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -178,6 +178,20 @@
 	spin_unlock_irqrestore(&subsys->track.s_lock, flags);
 }
 
+/**
+ * subsytem_default_online() - Mark a subsystem as online by default
+ * @dev: subsystem to mark as online
+ *
+ * Marks a subsystem as "online" without increasing the reference count
+ * on the subsystem. This is typically used by subsystems that are already
+ * online when the kernel boots up.
+ */
+void subsys_default_online(struct subsys_device *dev)
+{
+	subsys_set_state(dev, SUBSYS_ONLINE);
+}
+EXPORT_SYMBOL(subsys_default_online);
+
 static struct device_attribute subsys_attrs[] = {
 	__ATTR_RO(name),
 	__ATTR_RO(state),
@@ -671,6 +685,18 @@
 	}
 
 	name = dev->desc->name;
+
+	/*
+	 * If a system reboot/shutdown is underway, ignore subsystem errors.
+	 * However, print a message so that we know that a subsystem behaved
+	 * unexpectedly here.
+	 */
+	if (system_state == SYSTEM_RESTART
+		|| system_state == SYSTEM_POWER_OFF) {
+		pr_err("%s crashed during a system poweroff/shutdown.\n", name);
+		return -EBUSY;
+	}
+
 	pr_info("Restart sequence requested for %s, restart_level = %d.\n",
 		name, restart_level);
 
diff --git a/arch/arm/mach-msm/sysmon.c b/arch/arm/mach-msm/sysmon.c
index 02ba5ea..112daca 100644
--- a/arch/arm/mach-msm/sysmon.c
+++ b/arch/arm/mach-msm/sysmon.c
@@ -43,6 +43,7 @@
 	struct completion	resp_ready;
 	char			rx_buf[RX_BUF_SIZE];
 	enum transports		transport;
+	struct device		*dev;
 };
 
 static struct sysmon_subsys subsys[SYSMON_NUM_SS] = {
@@ -138,6 +139,9 @@
 	char tx_buf[TX_BUF_SIZE];
 	int ret;
 
+	if (ss->dev == NULL)
+		return -ENODEV;
+
 	if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS ||
 	    notif < 0 || notif >= SUBSYS_NOTIF_TYPE_COUNT ||
 	    event_ss == NULL)
@@ -178,6 +182,9 @@
 	size_t prefix_len = ARRAY_SIZE(expect) - 1;
 	int ret;
 
+	if (ss->dev == NULL)
+		return -ENODEV;
+
 	if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS)
 		return -EINVAL;
 
@@ -214,6 +221,9 @@
 	size_t prefix_len = ARRAY_SIZE(expect) - 1;
 	int ret;
 
+	if (ss->dev == NULL)
+		return -ENODEV;
+
 	if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS ||
 	    buf == NULL || len == 0)
 		return -EINVAL;
@@ -293,6 +303,7 @@
 	default:
 		return -EINVAL;
 	}
+	ss->dev = &pdev->dev;
 
 	return 0;
 }
@@ -301,6 +312,9 @@
 {
 	struct sysmon_subsys *ss = &subsys[pdev->id];
 
+	ss->dev = NULL;
+
+	mutex_lock(&ss->lock);
 	switch (ss->transport) {
 	case TRANSPORT_SMD:
 		smd_close(ss->chan);
@@ -309,6 +323,7 @@
 		hsic_sysmon_close(HSIC_SYSMON_DEV_EXT_MODEM);
 		break;
 	}
+	mutex_unlock(&ss->lock);
 
 	return 0;
 }
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 00a07a0..0b3ffef 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -649,6 +649,16 @@
           block.  Or some systems may want the iMem to be dedicated to a
           different function.
 
+config MSM_ADSPRPC
+        tristate "Qualcomm ADSP RPC driver"
+        depends on MSM_AUDIO_QDSP6 || MSM_AUDIO_QDSP6V2
+        default m
+        help
+          Provides a communication mechanism that allows for clients to
+          make remote method invocations across processor boundary to
+          applications DSP processor. Say M if you want to enable this
+          module.
+
 config MMC_GENERIC_CSDIO
 	tristate "Generic sdio driver"
 	default n
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c38c26c..8032f0b 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -66,4 +66,5 @@
 obj-$(CONFIG_TILE_SROM)		+= tile-srom.o
 obj-$(CONFIG_MSM_ROTATOR)	+= msm_rotator.o
 obj-$(CONFIG_MMC_GENERIC_CSDIO)	+= csdio.o
-obj-$(CONFIG_DIAG_CHAR)		+= diag/
\ No newline at end of file
+obj-$(CONFIG_DIAG_CHAR)		+= diag/
+obj-$(CONFIG_MSM_ADSPRPC)       += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/drivers/char/adsprpc.c
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.c
rename to drivers/char/adsprpc.c
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.h b/drivers/char/adsprpc.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.h
rename to drivers/char/adsprpc.h
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
rename to drivers/char/adsprpc_shared.h
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 7c0c0b9..5cd5ce9 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -35,6 +35,8 @@
 unsigned int dci_max_clients = 10;
 unsigned char dci_cumulative_log_mask[DCI_LOG_MASK_SIZE];
 unsigned char dci_cumulative_event_mask[DCI_EVENT_MASK_SIZE];
+struct mutex dci_log_mask_mutex;
+struct mutex dci_event_mask_mutex;
 
 #define DCI_CHK_CAPACITY(entry, new_data_len)				\
 ((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0)	\
@@ -91,14 +93,15 @@
 			read_bytes += 5 + dci_pkt_len;
 			buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
 		}
-		driver->in_busy_dci = 1;
 		/* wake up all sleeping DCI clients which have some data */
 		for (i = 0; i < MAX_DCI_CLIENTS; i++)
 			if (driver->dci_client_tbl[i].client &&
-					 driver->dci_client_tbl[i].data_len)
+				driver->dci_client_tbl[i].data_len) {
+				driver->in_busy_dci = 1;
 				diag_update_sleeping_process(
 					driver->dci_client_tbl[i].client->tgid,
 						 DCI_DATA_TYPE);
+			}
 	}
 }
 
@@ -224,6 +227,8 @@
 							dropped_events++;
 						return;
 					}
+					driver->dci_client_tbl[i].
+							received_events++;
 					*(int *)(entry->dci_data+
 					entry->data_len) = DCI_EVENT_TYPE;
 					memcpy(entry->dci_data+
@@ -281,6 +286,7 @@
 								dropped_logs++;
 						return;
 				}
+				driver->dci_client_tbl[i].received_logs++;
 				*(int *)(entry->dci_data+entry->data_len) =
 								DCI_LOG_TYPE;
 				memcpy(entry->dci_data+entry->data_len+4, buf+4,
@@ -378,14 +384,6 @@
 		}
 	}
 	mutex_lock(&driver->dci_mutex);
-	if (new_dci_client)
-		driver->num_dci_client++;
-	if (driver->num_dci_client > MAX_DCI_CLIENTS) {
-		pr_info("diag: Max DCI Client limit reached\n");
-		driver->num_dci_client--;
-		mutex_unlock(&driver->dci_mutex);
-		return ret;
-	}
 	/* Make an entry in kernel DCI table */
 	driver->dci_tag++;
 	for (i = 0; i < dci_max_reg; i++) {
@@ -483,7 +481,7 @@
 		temp += 4;
 
 		head_log_mask_ptr = driver->dci_client_tbl[i].dci_log_mask;
-		pr_info("diag: head of dci log mask %p\n", head_log_mask_ptr);
+		pr_debug("diag: head of dci log mask %p\n", head_log_mask_ptr);
 		count = 0; /* iterator for extracting log codes */
 		while (count < num_codes) {
 			log_code = *(uint16_t *)temp;
@@ -500,11 +498,11 @@
 			while (log_mask_ptr) {
 				if (*log_mask_ptr == equip_id) {
 					found = 1;
-					pr_info("diag: find equip id = %x at %p\n",
+					pr_debug("diag: find equip id = %x at %p\n",
 						 equip_id, log_mask_ptr);
 					break;
 				} else {
-					pr_info("diag: did not find equip id = %x at %p\n",
+					pr_debug("diag: did not find equip id = %x at %p\n",
 						 equip_id, log_mask_ptr);
 					log_mask_ptr += 514;
 				}
@@ -583,9 +581,11 @@
 	uint8_t *update_ptr = dci_cumulative_event_mask;
 	uint8_t *event_mask_ptr;
 
+	mutex_lock(&dci_event_mask_mutex);
 	event_mask_ptr = driver->dci_client_tbl[client_index].dci_event_mask;
 	for (i = 0; i < DCI_EVENT_MASK_SIZE; i++)
 		*(update_ptr+i) |= *(event_mask_ptr+i);
+	mutex_unlock(&dci_event_mask_mutex);
 }
 
 void diag_send_dci_event_mask(smd_channel_t *ch)
@@ -631,6 +631,7 @@
 	uint8_t *log_mask_ptr =
 	driver->dci_client_tbl[client_index].dci_log_mask;
 
+	mutex_lock(&dci_log_mask_mutex);
 	*update_ptr = 0; /* add first equip id */
 	/* skip the first equip id */
 	update_ptr++; log_mask_ptr++;
@@ -644,6 +645,7 @@
 		update_ptr++;
 		log_mask_ptr++;
 	}
+	mutex_unlock(&dci_log_mask_mutex);
 }
 
 void diag_send_dci_log_mask(smd_channel_t *ch)
@@ -743,6 +745,8 @@
 	driver->num_dci_client = 0;
 	driver->in_busy_dci = 0;
 	mutex_init(&driver->dci_mutex);
+	mutex_init(&dci_log_mask_mutex);
+	mutex_init(&dci_event_mask_mutex);
 	if (driver->buf_in_dci == NULL) {
 		driver->buf_in_dci = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_dci == NULL)
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 97a285c..afcabcc 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -53,6 +53,17 @@
 	int total_capacity;
 	int dropped_logs;
 	int dropped_events;
+	int received_logs;
+	int received_events;
+};
+
+/* This is used for DCI health stats */
+struct diag_dci_health_stats {
+	int dropped_logs;
+	int dropped_events;
+	int received_logs;
+	int received_events;
+	int reset_status;
 };
 
 enum {
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 8a7ae9f..92efd94 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -246,17 +246,23 @@
 	int i = 0;
 	struct diagchar_priv *diagpriv_data = file->private_data;
 
+	pr_debug("diag: process exit %s\n", current->comm);
 	if (!(file->private_data)) {
 		pr_alert("diag: Invalid file pointer");
 		return -ENOMEM;
 	}
-
-	/* clean up any DCI registrations for this client
+	/* clean up any DCI registrations, if this is a DCI client
 	* This will specially help in case of ungraceful exit of any DCI client
 	* This call will remove any pending registrations of such client
 	*/
-	diagchar_ioctl(NULL, DIAG_IOCTL_DCI_DEINIT, 0);
-
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		if (driver->dci_client_tbl[i].client &&
+			driver->dci_client_tbl[i].client->tgid ==
+							 current->tgid) {
+			diagchar_ioctl(NULL, DIAG_IOCTL_DCI_DEINIT, 0);
+			break;
+		}
+	}
 	/* If the exiting process is the socket process */
 	if (driver->socket_process &&
 		(driver->socket_process->tgid == current->tgid)) {
@@ -381,7 +387,9 @@
 	int success = -1;
 	void *temp_buf;
 	uint16_t support_list = 0;
-	struct diag_dci_client_tbl *notify_params;
+	struct diag_dci_client_tbl *params =
+		kzalloc(sizeof(struct diag_dci_client_tbl), GFP_KERNEL);
+	struct diag_dci_health_stats stats;
 	int status;
 
 	if (iocmd == DIAG_IOCTL_COMMAND_REG) {
@@ -455,8 +463,12 @@
 			return DIAG_DCI_NO_REG;
 		if (driver->num_dci_client >= MAX_DCI_CLIENTS)
 			return DIAG_DCI_NO_REG;
-		notify_params = (struct diag_dci_client_tbl *) ioarg;
+		if (copy_from_user(params, (void *)ioarg,
+				 sizeof(struct diag_dci_client_tbl)))
+			return -EFAULT;
 		mutex_lock(&driver->dci_mutex);
+		if (!(driver->num_dci_client))
+			driver->in_busy_dci = 0;
 		driver->num_dci_client++;
 		pr_debug("diag: id = %d\n", driver->dci_client_id);
 		driver->dci_client_id++;
@@ -464,9 +476,9 @@
 			if (driver->dci_client_tbl[i].client == NULL) {
 				driver->dci_client_tbl[i].client = current;
 				driver->dci_client_tbl[i].list =
-							 notify_params->list;
+							 params->list;
 				driver->dci_client_tbl[i].signal_type =
-					 notify_params->signal_type;
+					 params->signal_type;
 				create_dci_log_mask_tbl(driver->
 					dci_client_tbl[i].dci_log_mask);
 				create_dci_event_mask_tbl(driver->
@@ -478,6 +490,8 @@
 								 IN_BUF_SIZE;
 				driver->dci_client_tbl[i].dropped_logs = 0;
 				driver->dci_client_tbl[i].dropped_events = 0;
+				driver->dci_client_tbl[i].received_logs = 0;
+				driver->dci_client_tbl[i].received_events = 0;
 				break;
 			}
 		}
@@ -487,32 +501,52 @@
 		success = -1;
 		/* Delete this process from DCI table */
 		mutex_lock(&driver->dci_mutex);
-		for (i = 0; i < dci_max_reg; i++) {
-			if (driver->req_tracking_tbl[i].pid == current->tgid) {
-				pr_debug("diag: delete %d\n", current->tgid);
+		for (i = 0; i < dci_max_reg; i++)
+			if (driver->req_tracking_tbl[i].pid == current->tgid)
 				driver->req_tracking_tbl[i].pid = 0;
-				success = i;
-			}
-		}
 		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
-			if (driver->dci_client_tbl[i].client == current) {
+			if (driver->dci_client_tbl[i].client &&
+			driver->dci_client_tbl[i].client->tgid ==
+							 current->tgid) {
 				driver->dci_client_tbl[i].client = NULL;
+				success = i;
 				break;
 			}
 		}
-		/* if any registrations were deleted successfully OR a valid
-		   client_id was sent in DEINIT call , then its DCI client */
-		if (success >= 0 || ioarg)
+		if (success >= 0)
 			driver->num_dci_client--;
-		driver->num_dci_client--;
 		mutex_unlock(&driver->dci_mutex);
-		pr_debug("diag: complete deleting registrations\n");
 		return success;
 	} else if (iocmd == DIAG_IOCTL_DCI_SUPPORT) {
 		if (driver->ch_dci)
 			support_list = support_list | DIAG_CON_MPSS;
 		*(uint16_t *)ioarg = support_list;
 		return DIAG_DCI_NO_ERROR;
+	} else if (iocmd == DIAG_IOCTL_DCI_HEALTH_STATS) {
+		if (copy_from_user(&stats, (void *)ioarg,
+				 sizeof(struct diag_dci_health_stats)))
+			return -EFAULT;
+		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+			params = &(driver->dci_client_tbl[i]);
+			if (params->client &&
+				params->client->tgid == current->tgid) {
+				stats.dropped_logs = params->dropped_logs;
+				stats.dropped_events = params->dropped_events;
+				stats.received_logs = params->received_logs;
+				stats.received_events = params->received_events;
+				if (stats.reset_status) {
+					params->dropped_logs = 0;
+					params->dropped_events = 0;
+					params->received_logs = 0;
+					params->received_events = 0;
+				}
+				break;
+			}
+		}
+		if (copy_to_user((void *)ioarg, &stats,
+				   sizeof(struct diag_dci_health_stats)))
+			return -EFAULT;
+		return DIAG_DCI_NO_ERROR;
 	} else if (iocmd == DIAG_IOCTL_LSM_DEINIT) {
 		for (i = 0; i < driver->num_clients; i++)
 			if (driver->client_map[i].pid == current->tgid)
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index e9ac904..1f6bd1d 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -86,7 +86,7 @@
 	CSR_UNLOCK(drvdata);
 
 	usbbamctrl = csr_readl(drvdata, CSR_USBBAMCTRL);
-	usbbamctrl = (usbbamctrl & ~0x3) | BLKSIZE_256;
+	usbbamctrl = (usbbamctrl & ~0x3) | BLKSIZE_2048;
 	csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
 
 	usbflshctrl = csr_readl(drvdata, CSR_USBFLSHCTRL);
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 7fe47ee..20f84d6 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. 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
@@ -24,6 +24,7 @@
 #include <linux/sched.h>
 #include <linux/rwsem.h>
 #include <linux/uaccess.h>
+#include <linux/memblock.h>
 #include <mach/ion.h>
 #include <mach/msm_memtypes.h>
 #include "../ion_priv.h"
@@ -88,6 +89,16 @@
 		.name	= ION_AUDIO_HEAP_NAME,
 	},
 	{
+		.id	= ION_PIL1_HEAP_ID,
+		.type	= ION_HEAP_TYPE_CARVEOUT,
+		.name	= ION_PIL1_HEAP_NAME,
+	},
+	{
+		.id	= ION_PIL2_HEAP_ID,
+		.type	= ION_HEAP_TYPE_CARVEOUT,
+		.name	= ION_PIL2_HEAP_NAME,
+	},
+	{
 		.id	= ION_CP_WB_HEAP_ID,
 		.type	= ION_HEAP_TYPE_CP,
 		.name	= ION_WB_HEAP_NAME,
@@ -458,6 +469,7 @@
 {
 	unsigned int val;
 	int ret = 0;
+	u32 out_values[2];
 	const char *memory_name_prop;
 
 	ret = of_property_read_u32(node, "qcom,memory-reservation-size", &val);
@@ -481,12 +493,29 @@
 			ret = -EINVAL;
 		}
 	} else {
-		ret = 0;
+		ret = of_property_read_u32_array(node, "qcom,memory-fixed",
+								out_values, 2);
+		if (!ret)
+			heap->size = out_values[1];
+		else
+			ret = 0;
 	}
 out:
 	return ret;
 }
 
+static void msm_ion_get_heap_base(struct device_node *node,
+				 struct ion_platform_heap *heap)
+{
+	u32 out_values[2];
+	int ret = 0;
+
+	ret = of_property_read_u32_array(node, "qcom,memory-fixed",
+							out_values, 2);
+	if (!ret)
+		heap->base = out_values[0];
+	return;
+}
 
 static void msm_ion_get_heap_adjacent(struct device_node *node,
 				      struct ion_platform_heap *heap)
@@ -560,6 +589,7 @@
 		if (ret)
 			goto free_heaps;
 
+		msm_ion_get_heap_base(node, &pdata->heaps[idx]);
 		msm_ion_get_heap_align(node, &pdata->heaps[idx]);
 
 		ret = msm_ion_get_heap_size(node, &pdata->heaps[idx]);
@@ -734,6 +764,19 @@
 	if (pdata_needs_to_be_freed)
 		free_pdata(pdata);
 
+	/* Check if each heap has been removed from the memblock */
+	for (i = 0; i < num_heaps; i++) {
+		struct ion_platform_heap *heap_data = &pdata->heaps[i];
+		if (!heap_data->base)
+			continue;
+		err = memblock_overlaps_memory(heap_data->base,
+						heap_data->size);
+		if (err) {
+			panic("ION heap %s not removed from memblock\n",
+							heap_data->name);
+		}
+	}
+
 	check_for_heap_overlap(pdata->heaps, num_heaps);
 	platform_set_drvdata(pdev, idev);
 	return 0;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1b1f0ac..b8adbe67 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -333,14 +333,19 @@
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 
-	if (context == NULL)
-		return NULL;
+	if (context == NULL) {
+		KGSL_DRV_INFO(dev_priv->device, "kzalloc(%d) failed\n",
+				sizeof(*context));
+		return ERR_PTR(-ENOMEM);
+	}
 
 	while (1) {
 		if (idr_pre_get(&dev_priv->device->context_idr,
 				GFP_KERNEL) == 0) {
-			kfree(context);
-			return NULL;
+			KGSL_DRV_INFO(dev_priv->device,
+					"idr_pre_get: ENOMEM\n");
+			ret = -ENOMEM;
+			goto func_end;
 		}
 
 		ret = idr_get_new_above(&dev_priv->device->context_idr,
@@ -350,10 +355,8 @@
 			break;
 	}
 
-	if (ret) {
-		kfree(context);
-		return NULL;
-	}
+	if (ret)
+		goto func_end;
 
 	/* MAX - 1, there is one memdesc in memstore for device info */
 	if (id >= KGSL_MEMSTORE_MAX) {
@@ -361,18 +364,24 @@
 				"ctxts due to memstore limitation\n",
 				KGSL_MEMSTORE_MAX);
 		idr_remove(&dev_priv->device->context_idr, id);
-		kfree(context);
-		return NULL;
+		ret = -ENOSPC;
+		goto func_end;
 	}
 
 	kref_init(&context->refcount);
 	context->id = id;
 	context->dev_priv = dev_priv;
 
-	if (kgsl_sync_timeline_create(context)) {
+	ret = kgsl_sync_timeline_create(context);
+	if (ret) {
 		idr_remove(&dev_priv->device->context_idr, id);
+		goto func_end;
+	}
+
+func_end:
+	if (ret) {
 		kfree(context);
-		return NULL;
+		return ERR_PTR(ret);
 	}
 
 	return context;
@@ -1283,8 +1292,8 @@
 
 	context = kgsl_create_context(dev_priv);
 
-	if (context == NULL) {
-		result = -ENOMEM;
+	if (IS_ERR(context)) {
+		result = PTR_ERR(context);
 		goto done;
 	}
 
@@ -1298,7 +1307,7 @@
 	trace_kgsl_context_create(dev_priv->device, context, param->flags);
 	param->drawctxt_id = context->id;
 done:
-	if (result && context)
+	if (result && !IS_ERR(context))
 		kgsl_context_detach(context);
 
 	return result;
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 0a85b93..10c5a17 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -672,9 +672,9 @@
 		qpnp_adc_attr.index = iadc->adc->adc_channels[i].channel_num;
 		qpnp_adc_attr.dev_attr.attr.name =
 						iadc->adc->adc_channels[i].name;
-		sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
 		memcpy(&iadc->sens_attr[i], &qpnp_adc_attr,
 						sizeof(qpnp_adc_attr));
+		sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
 		rc = device_create_file(&spmi->dev,
 				&iadc->sens_attr[i].dev_attr);
 		if (rc) {
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 5690c88..5eef34f 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -714,9 +714,9 @@
 		qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
 		qpnp_adc_attr.dev_attr.attr.name =
 						vadc->adc->adc_channels[i].name;
-		sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
 		memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
 						sizeof(qpnp_adc_attr));
+		sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
 		rc = device_create_file(&spmi->dev,
 				&vadc->sens_attr[i].dev_attr);
 		if (rc) {
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 696c9f9..ba122bb 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -75,6 +75,56 @@
 #define WLED_CTRL_DLY_DEFAULT		0x00
 #define WLED_SWITCH_FREQ_DEFAULT	0x02
 
+#define FLASH_SAFETY_TIMER(base)	(base + 0x40)
+#define FLASH_MAX_CURR(base)		(base + 0x41)
+#define FLASH_LED_0_CURR(base)		(base + 0x42)
+#define FLASH_LED_1_CURR(base)		(base + 0x43)
+#define FLASH_CLAMP_CURR(base)		(base + 0x44)
+#define FLASH_LED_TMR_CTRL(base)	(base + 0x48)
+#define FLASH_HEADROOM(base)		(base + 0x49)
+#define FLASH_STARTUP_DELAY(base)	(base + 0x4B)
+#define FLASH_MASK_ENABLE(base)		(base + 0x4C)
+#define FLASH_VREG_OK_FORCE(base)	(base + 0x4F)
+#define FLASH_ENABLE_CONTROL(base)	(base + 0x46)
+#define FLASH_LED_STROBE_CTRL(base)	(base + 0x47)
+
+#define FLASH_MAX_LEVEL			0x4F
+#define	FLASH_NO_MASK			0x00
+
+#define FLASH_MASK_1			0x20
+#define FLASH_MASK_REG_MASK		0xE0
+#define FLASH_HEADROOM_MASK		0x03
+#define FLASH_SAFETY_TIMER_MASK		0x7F
+#define FLASH_CURRENT_MASK		0xFF
+#define FLASH_TMR_MASK			0x03
+#define FLASH_TMR_WATCHDOG		0x03
+#define FLASH_TMR_SAFETY		0x00
+
+#define FLASH_HW_VREG_OK		0x80
+#define FLASH_VREG_MASK			0xC0
+
+#define FLASH_STARTUP_DLY_MASK		0x02
+
+#define FLASH_ENABLE_ALL		0xE0
+#define FLASH_ENABLE_MODULE		0x80
+#define FLASH_ENABLE_MODULE_MASK	0x80
+#define FLASH_DISABLE_ALL		0x00
+#define FLASH_ENABLE_MASK		0x60
+#define FLASH_ENABLE_LED_0		0x40
+#define FLASH_ENABLE_LED_1		0x20
+#define FLASH_INIT_MASK			0xE0
+
+#define FLASH_STROBE_ALL		0xC0
+#define FLASH_STROBE_MASK		0xC0
+#define FLASH_LED_0_OUTPUT		0x80
+#define FLASH_LED_1_OUTPUT		0x40
+
+#define FLASH_CURRENT_PRGM_MIN		1
+#define FLASH_CURRENT_PRGM_SHIFT	1
+
+#define FLASH_DURATION_200ms		0x13
+#define FLASH_CLAMP_200mA		0x0F
+
 #define LED_TRIGGER_DEFAULT		"none"
 
 /**
@@ -82,7 +132,10 @@
  * @QPNP_ID_WLED - White led backlight
  */
 enum qpnp_leds {
-	QPNP_ID_WLED,
+	QPNP_ID_WLED = 0,
+	QPNP_ID_FLASH1_LED0,
+	QPNP_ID_FLASH1_LED1,
+	QPNP_ID_MAX,
 };
 
 /* current boost limit */
@@ -113,6 +166,20 @@
 	WLED_3200kHz,
 };
 
+enum flash_headroom {
+	HEADROOM_250mV = 0,
+	HEADROOM_300mV,
+	HEADROOM_400mV,
+	HEADROOM_500mV,
+};
+
+enum flash_startup_dly {
+	DELAY_10us = 0,
+	DELAY_32us,
+	DELAY_64us,
+	DELAY_128us,
+};
+
 static u8 wled_debug_regs[] = {
 	/* common registers */
 	0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4f,
@@ -125,6 +192,12 @@
 	0x80, 0x81, 0x82, 0x83, 0x86,
 };
 
+static u8 flash_debug_regs[] = {
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x48, 0x49, 0x4b, 0x4c,
+	0x4f, 0x46, 0x47,
+};
+
+
 /**
  *  wled_config_data - wled configuration data
  *  @num_strings - number of wled strings supported
@@ -149,6 +222,32 @@
 };
 
 /**
+ *  flash_config_data - flash configuration data
+ *  @current_prgm - current to be programmed, scaled by max level
+ *  @clamp_curr - clamp current to use
+ *  @headroom - headroom value to use
+ *  @duration - duration of the flash
+ *  @enable_module - enable address for particular flash
+ *  @trigger_flash - trigger flash
+ *  @startup_dly - startup delay for flash
+ *  @current_addr - address to write for current
+ *  @second_addr - address of secondary flash to be written
+ *  @safety_timer - enable safety timer or watchdog timer
+ */
+struct flash_config_data {
+	u8	current_prgm;
+	u8	clamp_curr;
+	u8	headroom;
+	u8	duration;
+	u8	enable_module;
+	u8	trigger_flash;
+	u8	startup_dly;
+	u16	current_addr;
+	u16	second_addr;
+	bool	safety_timer;
+};
+
+/**
  * struct qpnp_led_data - internal led data structure
  * @led_classdev - led class device
  * @id - led index
@@ -168,6 +267,7 @@
 	u8			num_leds;
 	spinlock_t		lock;
 	struct wled_config_data *wled_cfg;
+	struct flash_config_data	*flash_cfg;
 	int			max_current;
 	bool			default_on;
 };
@@ -289,6 +389,78 @@
 	return 0;
 }
 
+static int qpnp_flash_set(struct qpnp_led_data *led)
+{
+	int rc;
+	int val = led->cdev.brightness;
+
+	led->flash_cfg->current_prgm = (val * FLASH_MAX_LEVEL /
+						led->max_current);
+
+	led->flash_cfg->current_prgm =
+		led->flash_cfg->current_prgm >> FLASH_CURRENT_PRGM_SHIFT;
+	if (!led->flash_cfg->current_prgm)
+		led->flash_cfg->current_prgm = FLASH_CURRENT_PRGM_MIN;
+
+	/* Set led current */
+	if (val > 0) {
+		rc = qpnp_led_masked_write(led, led->flash_cfg->current_addr,
+			FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Current reg write failed(%d)\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_led_masked_write(led, led->flash_cfg->second_addr,
+			FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Current reg write failed(%d)\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
+			FLASH_ENABLE_MASK,
+			FLASH_ENABLE_ALL);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Enable reg write failed(%d)\n", rc);
+			return rc;
+		}
+		rc = qpnp_led_masked_write(led,
+			FLASH_LED_STROBE_CTRL(led->base),
+			FLASH_STROBE_MASK, FLASH_STROBE_ALL);
+
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"LED %d flash write failed(%d)\n", led->id, rc);
+			return rc;
+		}
+	} else {
+		rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
+			FLASH_ENABLE_MASK,
+			FLASH_DISABLE_ALL);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Enable reg write failed(%d)\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_led_masked_write(led,
+			FLASH_LED_STROBE_CTRL(led->base),
+			FLASH_STROBE_MASK,
+			FLASH_DISABLE_ALL);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"LED %d flash write failed(%d)\n", led->id, rc);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 static void qpnp_led_set(struct led_classdev *led_cdev,
 				enum led_brightness value)
 {
@@ -311,6 +483,13 @@
 			dev_err(&led->spmi_dev->dev,
 				"WLED set brightness failed (%d)\n", rc);
 		break;
+	case QPNP_ID_FLASH1_LED0:
+	case QPNP_ID_FLASH1_LED1:
+		rc = qpnp_flash_set(led);
+		if (rc < 0)
+			dev_err(&led->spmi_dev->dev,
+				"FLASH set brightness failed (%d)\n", rc);
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		break;
@@ -324,6 +503,10 @@
 	case QPNP_ID_WLED:
 		led->cdev.max_brightness = WLED_MAX_LEVEL;
 		break;
+	case QPNP_ID_FLASH1_LED0:
+	case QPNP_ID_FLASH1_LED1:
+		led->cdev.max_brightness = led->max_current;
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		return -EINVAL;
@@ -471,6 +654,121 @@
 	return 0;
 }
 
+static int __devinit qpnp_flash_init(struct qpnp_led_data *led)
+{
+	int rc;
+
+	rc = qpnp_led_masked_write(led,
+		FLASH_LED_STROBE_CTRL(led->base),
+		FLASH_STROBE_MASK, FLASH_DISABLE_ALL);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"LED %d flash write failed(%d)\n", led->id, rc);
+		return rc;
+	}
+	rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
+		FLASH_INIT_MASK, FLASH_ENABLE_MODULE);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Enable reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	/* Set flash safety timer */
+	rc = qpnp_led_masked_write(led, FLASH_SAFETY_TIMER(led->base),
+		FLASH_SAFETY_TIMER_MASK, led->flash_cfg->duration);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Safety timer reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	/* Set max current */
+	rc = qpnp_led_masked_write(led, FLASH_MAX_CURR(led->base),
+		FLASH_CURRENT_MASK, FLASH_MAX_LEVEL);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Max current reg write failed(%d)\n", rc);
+		return rc;
+	}
+	/* Set clamp current */
+	rc = qpnp_led_masked_write(led, FLASH_CLAMP_CURR(led->base),
+		FLASH_CURRENT_MASK, led->flash_cfg->clamp_curr);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Clamp current reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	/* Set timer control - safety or watchdog */
+	if (led->flash_cfg->safety_timer)
+		rc = qpnp_led_masked_write(led, FLASH_LED_TMR_CTRL(led->base),
+			FLASH_TMR_MASK, FLASH_TMR_SAFETY);
+	else
+		rc = qpnp_led_masked_write(led, FLASH_LED_TMR_CTRL(led->base),
+			FLASH_TMR_MASK, FLASH_TMR_WATCHDOG);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"LED timer ctrl reg write failed(%d)\n", rc);
+		return rc;
+	}
+	/* Set headroom */
+	rc = qpnp_led_masked_write(led, FLASH_HEADROOM(led->base),
+		FLASH_HEADROOM_MASK, led->flash_cfg->headroom);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Headroom reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	/* Set mask enable */
+	rc = qpnp_led_masked_write(led, FLASH_MASK_ENABLE(led->base),
+		FLASH_MASK_REG_MASK, FLASH_MASK_1);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Mask enable reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	/* Set startup delay */
+	rc = qpnp_led_masked_write(led, FLASH_STARTUP_DELAY(led->base),
+		FLASH_STARTUP_DLY_MASK, led->flash_cfg->startup_dly);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Startup delay reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_led_masked_write(led, FLASH_VREG_OK_FORCE(led->base),
+		FLASH_VREG_MASK, FLASH_HW_VREG_OK);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Vreg OK reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	/* Set led current and enable module */
+	rc = qpnp_led_masked_write(led, led->flash_cfg->current_addr,
+		FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Current reg write failed(%d)\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
+		FLASH_ENABLE_MODULE_MASK, FLASH_ENABLE_MODULE);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Enable reg write failed(%d)\n", rc);
+		return rc;
+	}
+	/* dump flash registers */
+	qpnp_dump_regs(led, flash_debug_regs, ARRAY_SIZE(flash_debug_regs));
+
+	return 0;
+}
+
 static int __devinit qpnp_led_initialize(struct qpnp_led_data *led)
 {
 	int rc;
@@ -482,6 +780,13 @@
 			dev_err(&led->spmi_dev->dev,
 				"WLED initialize failed(%d)\n", rc);
 		break;
+	case QPNP_ID_FLASH1_LED0:
+	case QPNP_ID_FLASH1_LED1:
+		rc = qpnp_flash_init(led);
+		if (rc)
+			dev_err(&led->spmi_dev->dev,
+				"FLASH initialize failed(%d)\n", rc);
+		break;
 	default:
 		dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
 		rc = -EINVAL;
@@ -586,6 +891,80 @@
 	return 0;
 }
 
+static int __devinit qpnp_get_config_flash(struct qpnp_led_data *led,
+				struct device_node *node)
+{
+	int rc;
+	u32 val;
+
+	led->flash_cfg = devm_kzalloc(&led->spmi_dev->dev,
+				sizeof(struct flash_config_data), GFP_KERNEL);
+	if (!led->flash_cfg) {
+		dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	if (led->id == QPNP_ID_FLASH1_LED0) {
+		led->flash_cfg->enable_module = FLASH_ENABLE_ALL;
+		led->flash_cfg->current_addr = FLASH_LED_0_CURR(led->base);
+		led->flash_cfg->second_addr = FLASH_LED_1_CURR(led->base);
+		led->flash_cfg->trigger_flash = FLASH_LED_0_OUTPUT;
+	} else if (led->id == QPNP_ID_FLASH1_LED1) {
+		led->flash_cfg->enable_module = FLASH_ENABLE_ALL;
+		led->flash_cfg->current_addr = FLASH_LED_1_CURR(led->base);
+		led->flash_cfg->second_addr = FLASH_LED_0_CURR(led->base);
+		led->flash_cfg->trigger_flash = FLASH_LED_1_OUTPUT;
+	} else {
+		dev_err(&led->spmi_dev->dev, "Unknown flash LED name given\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(node, "qcom,current", &val);
+	if (!rc)
+		led->flash_cfg->current_prgm = (val *
+				FLASH_MAX_LEVEL / led->max_current);
+	else
+		return -EINVAL;
+
+	rc = of_property_read_u32(node, "qcom,headroom", &val);
+	if (!rc)
+		led->flash_cfg->headroom = (u8) val;
+	else if (rc == -EINVAL)
+		led->flash_cfg->headroom = HEADROOM_300mV;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,duration", &val);
+	if (!rc)
+		led->flash_cfg->duration = (((u8) val) - 10) / 10;
+	else if (rc == -EINVAL)
+		led->flash_cfg->duration = FLASH_DURATION_200ms;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,clamp-curr", &val);
+	if (!rc)
+		led->flash_cfg->clamp_curr = (val *
+				FLASH_MAX_LEVEL / led->max_current);
+	else if (rc == -EINVAL)
+		led->flash_cfg->clamp_curr = FLASH_CLAMP_200mA;
+	else
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,startup-dly", &val);
+	if (!rc)
+		led->flash_cfg->startup_dly = (u8) val;
+	else if (rc == -EINVAL)
+		led->flash_cfg->startup_dly = DELAY_32us;
+	else
+		return rc;
+
+	led->flash_cfg->safety_timer =
+		of_property_read_bool(node, "qcom,safety-timer");
+
+	return 0;
+}
+
 static int __devinit qpnp_leds_probe(struct spmi_device *spmi)
 {
 	struct qpnp_led_data *led;
@@ -673,6 +1052,14 @@
 					"Unable to read wled config data\n");
 				return rc;
 			}
+		} else if (strncmp(led_label, "flash", sizeof("flash"))
+				== 0) {
+			rc = qpnp_get_config_flash(led, temp);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev,
+					"Unable to read flash config data\n");
+				return rc;
+			}
 		} else {
 			dev_err(&led->spmi_dev->dev, "No LED matching label\n");
 			return -EINVAL;
@@ -751,3 +1138,4 @@
 MODULE_DESCRIPTION("QPNP LEDs driver");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("leds:leds-qpnp");
+
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index eb0cd8a..80fdac5 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -777,6 +777,11 @@
 		goto exit;
 	}
 	for (i = 0; i < b->length; ++i) {
+		if (EXTRADATA_IDX(b->length) &&
+			(i == EXTRADATA_IDX(b->length)) &&
+			!b->m.planes[i].length) {
+			continue;
+		}
 		temp = get_registered_buf(&v4l2_inst->registered_bufs,
 				b->m.planes[i].reserved[0],
 				b->m.planes[i].reserved[1],
@@ -850,6 +855,12 @@
 	vidc_inst = get_vidc_inst(file, fh);
 	v4l2_inst = get_v4l2_inst(file, fh);
 	for (i = 0; i < b->length; ++i) {
+		if (EXTRADATA_IDX(b->length) &&
+			(i == EXTRADATA_IDX(b->length)) &&
+			!b->m.planes[i].length) {
+			b->m.planes[i].m.userptr = 0;
+			continue;
+		}
 		binfo = get_registered_buf(&v4l2_inst->registered_bufs,
 				b->m.planes[i].reserved[0],
 				b->m.planes[i].reserved[1],
@@ -902,6 +913,11 @@
 		goto fail_dq_buf;
 	}
 	for (i = 0; i < b->length; i++) {
+		if (EXTRADATA_IDX(b->length) &&
+				(i == EXTRADATA_IDX(b->length)) &&
+				!b->m.planes[i].m.userptr) {
+			continue;
+		}
 		b->m.planes[i].m.userptr = device_to_uvaddr(
 				&v4l2_inst->registered_bufs,
 				b->m.planes[i].m.userptr);
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 3afc496..b476e39 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -346,7 +346,8 @@
 			buffer_info.align_device_addr =
 				b->m.planes[0].m.userptr;
 			extra_idx = EXTRADATA_IDX(b->length);
-			if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+			if (extra_idx && (extra_idx < VIDEO_MAX_PLANES) &&
+				b->m.planes[extra_idx].m.userptr) {
 				buffer_info.extradata_addr =
 					b->m.planes[extra_idx].m.userptr;
 				dprintk(VIDC_DBG,
@@ -354,6 +355,9 @@
 				b->m.planes[extra_idx].m.userptr);
 				buffer_info.extradata_size =
 					b->m.planes[extra_idx].length;
+			} else {
+				buffer_info.extradata_addr = 0;
+				buffer_info.extradata_size = 0;
 			}
 			rc = vidc_hal_session_set_buffers((void *)inst->session,
 					&buffer_info);
@@ -409,9 +413,13 @@
 			buffer_info.align_device_addr =
 				 b->m.planes[0].m.userptr;
 			extra_idx = EXTRADATA_IDX(b->length);
-			if (extra_idx && (extra_idx < VIDEO_MAX_PLANES))
+			if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)
+				&& b->m.planes[extra_idx].m.userptr)
 				buffer_info.extradata_addr =
 					b->m.planes[extra_idx].m.userptr;
+			else
+				buffer_info.extradata_addr = 0;
+
 			rc = vidc_hal_session_release_buffers(
 					(void *)inst->session, &buffer_info);
 			if (rc)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 038f03e..56bcf65 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1551,7 +1551,8 @@
 			frame_data.buffer_type = HAL_BUFFER_OUTPUT;
 			extra_idx =
 			EXTRADATA_IDX(inst->fmts[CAPTURE_PORT]->num_planes);
-			if (extra_idx)
+			if (extra_idx && (extra_idx < VIDEO_MAX_PLANES) &&
+				vb->v4l2_planes[extra_idx].m.userptr)
 				frame_data.extradata_addr =
 					vb->v4l2_planes[extra_idx].m.userptr;
 			dprintk(VIDC_DBG,
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 72a3f3b..51a798f 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -82,7 +82,7 @@
 
 static int vcap_reg_powerup(struct vcap_dev *dev)
 {
-	dev->fs_vcap = regulator_get(NULL, "fs_vcap");
+	dev->fs_vcap = regulator_get(dev->ddev, "fs_vcap");
 	if (IS_ERR(dev->fs_vcap)) {
 		pr_err("%s: Regulator FS_VCAP get failed %ld\n", __func__,
 			PTR_ERR(dev->fs_vcap));
diff --git a/drivers/mfd/marimba-core.c b/drivers/mfd/marimba-core.c
index b7d38cd..26f3ece 100644
--- a/drivers/mfd/marimba-core.c
+++ b/drivers/mfd/marimba-core.c
@@ -173,13 +173,14 @@
 	u8 data[num_bytes + 1];
 	u8 mask_value[num_bytes];
 
+	memset(mask_value, 0, sizeof(mask_value));
+
 	marimba = &marimba_modules[marimba->mod_id];
 	if (marimba == NULL) {
 		pr_err("%s: Unable to access Marimba core\n", __func__);
 		return -ENODEV;
 	}
 
-
 	mutex_lock(&marimba->xfer_lock);
 
 	for (i = 0; i < num_bytes; i++)
@@ -619,7 +620,7 @@
 static int __devinit marimba_dbg_init(int adie_type)
 {
 	struct adie_dbg_device *dbgdev;
-	struct dentry *dent;
+	struct dentry *dent = NULL;
 	struct dentry *temp;
 
 	dbgdev = kzalloc(sizeof *dbgdev, GFP_KERNEL);
diff --git a/drivers/mfd/pm8xxx-spk.c b/drivers/mfd/pm8xxx-spk.c
index 8ba7372..4366717 100644
--- a/drivers/mfd/pm8xxx-spk.c
+++ b/drivers/mfd/pm8xxx-spk.c
@@ -118,8 +118,6 @@
 	}
 
 	val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
-	if (val < 0)
-		return val;
 	val |= mute << 2;
 	ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
 	return ret;
@@ -137,8 +135,6 @@
 	}
 
 	val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
-	if (val < 0)
-		return val;
 	val = (gain << 4) | (val & 0xF);
 	ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
 	if (!ret) {
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index a8e40f7..1f7b67a 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -550,6 +550,13 @@
 	}
 
 	wcd9xxx->num_of_supplies = 0;
+
+	if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
+		pr_err("%s: Array Size out of bound\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
 		if (pdata->regulator[i].name) {
 			wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 7d1fdf0..23e0fcc 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -56,6 +56,12 @@
 	struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
 	int i;
 
+	if (ARRAY_SIZE(wcd9xxx->irq_masks_cur) > WCD9XXX_NUM_IRQ_REGS ||
+		ARRAY_SIZE(wcd9xxx->irq_masks_cache) > WCD9XXX_NUM_IRQ_REGS) {
+			pr_err("%s: Array Size out of bound\n", __func__);
+			 return;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(wcd9xxx->irq_masks_cur); i++) {
 		/* If there's been a change in the mask write it back
 		 * to the hardware.
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 3c28447..6ab3a66 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -578,6 +578,17 @@
 	processing of MPEG transport streams from the main processor.
 	This can also be compiled as a loadable module.
 
+config CI_BRIDGE_SPI
+	depends on SPI_QUP
+	tristate "CI Bridge SPI Driver Support"
+	---help---
+	This driver provides a simple SPI read/write interface to
+	an external CI bridge. It implements a character device
+	driver interface which allows making SPI transactions
+	using the Linux SPI framework.
+
+	To compile this driver as module, choose M here.
+
 config HAPTIC_ISA1200
 	tristate "ISA1200 haptic support"
 	depends on I2C
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index be3d0a0..e92e119 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -61,6 +61,7 @@
 msm_tsif-objs := tsif.o
 obj-$(CONFIG_TSIF_CHRDEV) += tsif_chrdev.o
 obj-$(CONFIG_TSPP) += tspp.o
+obj-$(CONFIG_CI_BRIDGE_SPI) += ci-bridge-spi.o
 obj-$(CONFIG_HAPTIC_ISA1200)		+= isa1200.o
 obj-$(CONFIG_PMIC8058_PWM) += pmic8058-pwm.o
 obj-$(CONFIG_PMIC8XXX_VIBRATOR) += pm8xxx-vibrator.o
diff --git a/drivers/misc/ci-bridge-spi.c b/drivers/misc/ci-bridge-spi.c
new file mode 100644
index 0000000..368bef7
--- /dev/null
+++ b/drivers/misc/ci-bridge-spi.c
@@ -0,0 +1,428 @@
+/* Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+
+/* This driver implements a simple SPI read/write interface to access
+ * an external device over SPI.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <linux/ci-bridge-spi.h>
+
+#define CI_MAX_BUFFER_SIZE	(64 * 1024)
+
+struct ci_bridge {
+	dev_t ci_bridge_dev;
+	struct cdev cdev;
+	struct class *bridge_class;
+	struct device *bridge_dev;
+	char *write_buffer;
+	char *read_buffer;
+	struct mutex lock;
+	struct spi_device *spi;
+	unsigned int gpio_reset_pin;
+	unsigned int gpio_interrupt_pin;
+	int num_opened;
+
+};
+
+static struct ci_bridge ci;
+
+static int __devinit ci_bridge_spi_probe(struct spi_device *spi)
+{
+	int ret;
+	struct ci_bridge_platform_data *pdata;
+
+	if (spi->dev.platform_data == NULL) {
+		pr_err("%s: platform data is missing\n", __func__);
+		return -EINVAL;
+	}
+
+	ci.spi = spi;
+	ci.num_opened = 0;
+	mutex_init(&ci.lock);
+	spi_set_drvdata(spi, &ci);
+	pdata = spi->dev.platform_data;
+	ci.gpio_reset_pin = pdata->reset_pin;
+	ci.gpio_interrupt_pin = pdata->interrupt_pin;
+
+	ret = gpio_request(ci.gpio_reset_pin, "ci_bridge_spi");
+	if (ret) {
+		pr_err("%s: GPIO request for pin number %u failed\n",
+			   __func__, ci.gpio_reset_pin);
+		return ret;
+	}
+	ret = gpio_direction_output(ci.gpio_reset_pin, 1);
+	if (ret) {
+		pr_err("%s: unable to set GPIO direction, err=%d\n",
+			  __func__, ret);
+		goto err_free_reset_pin;
+	}
+
+	ret = gpio_request(ci.gpio_interrupt_pin, "ci_bridge_spi");
+	if (ret) {
+		pr_err("%s: GPIO request for pin number %u failed\n",
+			   __func__, ci.gpio_interrupt_pin);
+		goto err_free_reset_pin;
+	}
+	ret = gpio_direction_input(ci.gpio_interrupt_pin);
+	if (ret) {
+		pr_err("%s: unable to set GPIO direction, err=%d\n",
+			   __func__, ret);
+		goto err_free_int_pin;
+	}
+
+	return 0;
+
+err_free_int_pin:
+	gpio_free(ci.gpio_interrupt_pin);
+err_free_reset_pin:
+	gpio_free(ci.gpio_reset_pin);
+
+	return ret;
+}
+
+static int __devexit ci_bridge_spi_remove(struct spi_device *spi)
+{
+	struct ci_bridge *bridge = spi_get_drvdata(spi);
+
+	spi_set_drvdata(bridge->spi, NULL);
+	bridge->spi = NULL;
+	mutex_destroy(&ci.lock);
+
+	gpio_free(ci.gpio_reset_pin);
+	gpio_free(ci.gpio_interrupt_pin);
+
+	return 0;
+}
+
+static struct spi_driver ci_bridge_driver = {
+	.driver = {
+		.name = "ci_bridge_spi",
+		.owner = THIS_MODULE,
+	},
+	.probe = ci_bridge_spi_probe,
+	.remove = __devexit_p(ci_bridge_spi_remove),
+};
+
+static void ci_bridge_spi_completion_cb(void *arg)
+{
+	complete(arg);
+}
+
+static ssize_t ci_bridge_spi_read(struct file *filp,
+				char __user *buf,
+				size_t count,
+				loff_t *f_pos)
+{
+	int ret = 0;
+	unsigned long not_copied = 0;
+	struct spi_transfer spi_transfer;
+	struct spi_message spi_message;
+	DECLARE_COMPLETION_ONSTACK(context);
+	struct ci_bridge *bridge = filp->private_data;
+
+	if ((bridge == NULL) || (bridge->spi == NULL))
+		return -ENODEV;
+
+	if (count > CI_MAX_BUFFER_SIZE)
+		return -EMSGSIZE;
+
+	memset(&spi_transfer, 0, sizeof(struct spi_transfer));
+	memset(&spi_message, 0, sizeof(struct spi_message));
+
+	mutex_lock(&bridge->lock);
+
+	spi_transfer.rx_buf = bridge->read_buffer;
+	spi_transfer.len =  count;
+	spi_message_init(&spi_message);
+	spi_message_add_tail(&spi_transfer, &spi_message);
+	spi_message.complete = ci_bridge_spi_completion_cb;
+	spi_message.context = &context;
+
+	/* must use spi_async in a context that may sleep */
+	ret = spi_async(bridge->spi, &spi_message);
+	if (ret == 0) {
+		wait_for_completion(&context);
+
+		if (spi_message.status == 0) {
+			/* spi_message.actual_length should contain the number
+			 * of bytes actually read and should update ret to be
+			 * the actual length, but since our driver doesn't
+			 * support this, assume all count bytes were read.
+			 */
+			ret = count;
+		}
+
+		if (ret > 0) {
+			not_copied =
+				copy_to_user(buf, bridge->read_buffer, ret);
+			if (not_copied == ret)
+				ret = -EFAULT;
+			else
+				ret -= not_copied;
+		}
+	} else {
+		pr_err("%s: Error calling spi_async, ret = %d\n",
+			__func__, ret);
+	}
+
+	mutex_unlock(&bridge->lock);
+
+	return ret;
+}
+
+static ssize_t ci_bridge_spi_write(struct file *filp,
+				const char __user *buf,
+				size_t count,
+				loff_t *f_pos)
+{
+	int ret = 0;
+	unsigned long not_copied = 0;
+	struct spi_transfer spi_transfer;
+	struct spi_message spi_message;
+	DECLARE_COMPLETION_ONSTACK(context);
+	struct ci_bridge *bridge = filp->private_data;
+
+	if ((bridge == NULL) || (bridge->spi == NULL))
+		return -ENODEV;
+
+	if (count > CI_MAX_BUFFER_SIZE)
+		return -EMSGSIZE;
+
+	memset(&spi_transfer, 0, sizeof(struct spi_transfer));
+	memset(&spi_message, 0, sizeof(struct spi_message));
+
+	mutex_lock(&bridge->lock);
+	/* copy user data to our SPI Tx buffer */
+	not_copied = copy_from_user(bridge->write_buffer, buf, count);
+	if (not_copied != 0) {
+		ret = -EFAULT;
+	} else {
+		spi_transfer.tx_buf = bridge->write_buffer;
+		spi_transfer.len = count;
+
+		spi_message_init(&spi_message);
+		spi_message_add_tail(&spi_transfer, &spi_message);
+		spi_message.complete = ci_bridge_spi_completion_cb;
+		spi_message.context = &context;
+
+		/* must use spi_async in a context that may sleep */
+		ret = spi_async(bridge->spi, &spi_message);
+		if (ret == 0) {
+			wait_for_completion(&context);
+			/* update ret to contain
+			 * the number of bytes actually written
+			 */
+			if (spi_message.status == 0)
+				ret = spi_transfer.len;
+			else
+				pr_err("%s: SPI transfer error, spi_message.status = %d\n",
+					__func__, spi_message.status);
+		} else {
+			pr_err("%s: Error calling spi_async, ret = %d\n",
+				__func__, ret);
+		}
+	}
+	mutex_unlock(&bridge->lock);
+
+	return ret;
+}
+
+static int ci_bridge_spi_open(struct inode *inode, struct file *filp)
+{
+	/* forbid opening more then one instance at a time,
+	   parallel execution can still be problematic */
+	if (ci.num_opened != 0)
+		return -EBUSY;
+
+	/* allocate write buffer */
+	ci.write_buffer =
+		kzalloc((CI_MAX_BUFFER_SIZE * sizeof(char)), GFP_KERNEL);
+	if (ci.write_buffer == NULL) {
+		pr_err("%s: Error allocating memory for write buffer\n",
+			__func__);
+		return -ENOMEM;
+	}
+	/* allocate read buffer */
+	ci.read_buffer =
+		kzalloc((CI_MAX_BUFFER_SIZE * sizeof(char)), GFP_KERNEL);
+	if (ci.read_buffer == NULL) {
+		pr_err("%s: Error allocating memory for read buffer\n",
+			__func__);
+		kfree(ci.write_buffer);
+		return -ENOMEM;
+	}
+	/* device is non-seekable */
+	nonseekable_open(inode, filp);
+
+	filp->private_data = &ci;
+	ci.num_opened = 1;
+
+	return 0;
+}
+
+static int ci_bridge_ioctl_get_int(void *arg)
+{
+	int state;
+
+	if (arg == NULL)
+		return -EINVAL;
+
+	state = gpio_get_value_cansleep(ci.gpio_interrupt_pin);
+	if (copy_to_user(arg, &state, sizeof(state)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int ci_bridge_ioctl_reset(unsigned long arg)
+{
+	if ((arg != 0) && (arg != 1))
+		return -EINVAL;
+
+	gpio_set_value_cansleep(ci.gpio_reset_pin, arg);
+
+	return 0;
+}
+
+static long ci_bridge_spi_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+
+	case CI_BRIDGE_IOCTL_RESET:
+		ret = ci_bridge_ioctl_reset(arg);
+		break;
+
+	case CI_BRIDGE_IOCTL_GET_INT_STATE:
+		ret = ci_bridge_ioctl_get_int((void *) arg);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int ci_bridge_spi_release(struct inode *inode, struct file *filp)
+{
+	struct ci_bridge *bridge = filp->private_data;
+
+	if ((bridge == NULL) || (bridge->spi == NULL))
+		return -ENODEV;
+
+	kfree(bridge->write_buffer);
+	kfree(bridge->read_buffer);
+	filp->private_data = NULL;
+	ci.num_opened = 0;
+
+	return 0;
+}
+
+static const struct file_operations ci_bridge_spi_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ci_bridge_spi_read,
+	.write   = ci_bridge_spi_write,
+	.open    = ci_bridge_spi_open,
+	.unlocked_ioctl = ci_bridge_spi_ioctl,
+	.release = ci_bridge_spi_release,
+	.llseek  = no_llseek,
+};
+
+static int __init ci_bridge_init(void)
+{
+	int ret = 0;
+
+	ret = alloc_chrdev_region(&ci.ci_bridge_dev, 0, 1, "ci_bridge_spi");
+	if (ret != 0)
+		return ret;
+
+	ci.bridge_class = class_create(THIS_MODULE, "ci_bridge_spi");
+	if (IS_ERR(ci.bridge_class)) {
+		ret = PTR_ERR(ci.bridge_class);
+		pr_err("Error creating ci.bridge_class: %d\n", ret);
+		goto free_region;
+	}
+
+	cdev_init(&ci.cdev, &ci_bridge_spi_fops);
+	ci.cdev.owner = THIS_MODULE;
+	ret = cdev_add(&ci.cdev, ci.ci_bridge_dev, 1);
+	if (ret != 0) {
+		pr_err("Error calling cdev_add: %d\n", ret);
+		goto class_destroy;
+	}
+
+
+	ci.bridge_dev = device_create(ci.bridge_class, NULL, ci.cdev.dev,
+				     &ci, "ci_bridge_spi0");
+	if (IS_ERR(ci.bridge_dev)) {
+		ret = PTR_ERR(ci.bridge_dev);
+		pr_err("device_create failed: %d\n", ret);
+		goto del_cdev;
+	}
+
+	ret = spi_register_driver(&ci_bridge_driver);
+	if (ret != 0) {
+		pr_err("Error registering spi driver: %d\n", ret);
+		goto device_destroy;
+	}
+
+	/* successful return */
+	return 0;
+
+device_destroy:
+	device_destroy(ci.bridge_class, ci.ci_bridge_dev);
+
+del_cdev:
+	cdev_del(&ci.cdev);
+
+class_destroy:
+	class_destroy(ci.bridge_class);
+
+free_region:
+	unregister_chrdev_region(ci.ci_bridge_dev, 1);
+
+	return ret;
+}
+
+static void __exit ci_bridge_exit(void)
+{
+	spi_unregister_driver(&ci_bridge_driver);
+	device_destroy(ci.bridge_class, ci.ci_bridge_dev);
+	cdev_del(&ci.cdev);
+	class_destroy(ci.bridge_class);
+	unregister_chrdev_region(ci.ci_bridge_dev, 1);
+}
+
+module_init(ci_bridge_init);
+module_exit(ci_bridge_exit);
+
+MODULE_DESCRIPTION("CI Bridge SPI Driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 12f896e..8cb903a 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1,6 +1,6 @@
 
 
-/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
+/*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
  *
  * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
  *
@@ -32,6 +32,8 @@
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/qseecom.h>
+#include <linux/elf.h>
+#include <linux/firmware.h>
 #include <linux/freezer.h>
 #include <mach/board.h>
 #include <mach/msm_bus.h>
@@ -40,6 +42,7 @@
 #include <mach/peripheral-loader.h>
 #include <mach/socinfo.h>
 #include "qseecom_legacy.h"
+#include "qseecom_kernel.h"
 
 #define QSEECOM_DEV			"qseecom"
 #define QSEOS_VERSION_13		0x13
@@ -168,6 +171,11 @@
 	u32  ref_cnt;
 };
 
+struct qseecom_registered_kclient_list {
+	struct list_head list;
+	struct qseecom_handle *handle;
+};
+
 struct qseecom_control {
 	struct ion_client *ion_clnt;		/* Ion client */
 	struct list_head  registered_listener_list_head;
@@ -176,6 +184,9 @@
 	struct list_head  registered_app_list_head;
 	spinlock_t        registered_app_list_lock;
 
+	struct list_head   registered_kclient_list_head;
+	spinlock_t        registered_kclient_list_lock;
+
 	wait_queue_head_t send_resp_wq;
 	int               send_resp_flag;
 
@@ -642,7 +653,6 @@
 	ion_phys_addr_t pa = 0;
 	uint32_t len;
 	struct qseecom_command_scm_resp resp;
-	struct qseecom_check_app_ireq req;
 	struct qseecom_load_app_ireq load_req;
 
 	/* Copy the relevant information needed for loading the image */
@@ -657,11 +667,8 @@
 	if (ret)
 		pr_warning("Unable to vote for SFPB clock");
 
-	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
-	memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
-
 	pr_warn("App (%s) does not exist, loading apps for first time\n",
-			(char *)(req.app_name));
+			(char *)(load_img_req.img_name));
 	/* Get the handle of the shared fd */
 	ihandle = ion_import_dma_buf(qseecom.ion_clnt,
 					load_img_req.ifd_data_fd);
@@ -675,6 +682,7 @@
 	ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len);
 
 	/* Populate the structure for sending scm call to load image */
+	memcpy(load_req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
 	load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
 	load_req.mdt_len = load_img_req.mdt_len;
 	load_req.img_len = load_img_req.img_len;
@@ -738,7 +746,7 @@
 	spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags);
 
 	pr_warn("App with id %d (%s) now loaded\n", app_id,
-		(char *)(req.app_name));
+		(char *)(load_img_req.img_name));
 
 	data->client.app_id = app_id;
 	load_img_req.app_id = app_id;
@@ -1171,6 +1179,394 @@
 	return ret;
 }
 
+static bool __qseecom_is_fw_image_valid(const struct firmware *fw_entry)
+{
+	struct elf32_hdr *ehdr;
+
+	if (fw_entry->size < sizeof(*ehdr)) {
+		pr_err("%s: Not big enough to be an elf header\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+	ehdr = (struct elf32_hdr *)fw_entry->data;
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		pr_err("%s: Not an elf header\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+
+	if (ehdr->e_phnum == 0) {
+		pr_err("%s: No loadable segments\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+	if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
+	    sizeof(struct elf32_hdr) > fw_entry->size) {
+		pr_err("%s: Program headers not within mdt\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+	return true;
+}
+
+static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size)
+{
+	int ret = -1;
+	int i = 0, rc = 0;
+	const struct firmware *fw_entry = NULL;
+	struct elf32_phdr *phdr;
+	char fw_name[MAX_APP_NAME_SIZE];
+	struct elf32_hdr *ehdr;
+	int num_images = 0;
+
+	snprintf(fw_name, sizeof(fw_name), "%s.mdt", appname);
+	rc = request_firmware(&fw_entry, fw_name,  qseecom.pdev);
+	if (rc) {
+		pr_err("error with request_firmware\n");
+		ret = -EIO;
+		goto err;
+	}
+	if (!__qseecom_is_fw_image_valid(fw_entry)) {
+		ret = -EIO;
+		goto err;
+	}
+	*fw_size = fw_entry->size;
+	phdr = (struct elf32_phdr *)(fw_entry->data + sizeof(struct elf32_hdr));
+	ehdr = (struct elf32_hdr *)fw_entry->data;
+	num_images = ehdr->e_phnum;
+	release_firmware(fw_entry);
+	for (i = 0; i < num_images; i++, phdr++) {
+		memset(fw_name, 0, sizeof(fw_name));
+		snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i);
+		ret = request_firmware(&fw_entry, fw_name, qseecom.pdev);
+		if (ret)
+			goto err;
+		*fw_size += fw_entry->size;
+		release_firmware(fw_entry);
+	}
+	return ret;
+err:
+	if (fw_entry)
+		release_firmware(fw_entry);
+	*fw_size = 0;
+	return ret;
+}
+
+static int __qseecom_get_fw_data(char *appname, u8 *img_data,
+					struct qseecom_load_app_ireq *load_req)
+{
+	int ret = -1;
+	int i = 0, rc = 0;
+	const struct firmware *fw_entry = NULL;
+	char fw_name[MAX_APP_NAME_SIZE];
+	u8 *img_data_ptr = img_data;
+	struct elf32_hdr *ehdr;
+	int num_images = 0;
+
+	snprintf(fw_name, sizeof(fw_name), "%s.mdt", appname);
+	rc = request_firmware(&fw_entry, fw_name,  qseecom.pdev);
+	if (rc) {
+		ret = -EIO;
+		goto err;
+	}
+	load_req->img_len = fw_entry->size;
+	memcpy(img_data_ptr, fw_entry->data, fw_entry->size);
+	img_data_ptr = img_data_ptr + fw_entry->size;
+	load_req->mdt_len = fw_entry->size; /*Get MDT LEN*/
+	ehdr = (struct elf32_hdr *)fw_entry->data;
+	num_images = ehdr->e_phnum;
+	release_firmware(fw_entry);
+	for (i = 0; i < num_images; i++) {
+		snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i);
+		ret = request_firmware(&fw_entry, fw_name,  qseecom.pdev);
+		if (ret) {
+			pr_err("Failed to locate blob %s\n", fw_name);
+			goto err;
+		}
+		memcpy(img_data_ptr, fw_entry->data, fw_entry->size);
+		img_data_ptr = img_data_ptr + fw_entry->size;
+		load_req->img_len += fw_entry->size;
+		release_firmware(fw_entry);
+	}
+	load_req->phy_addr = virt_to_phys(img_data);
+	return ret;
+err:
+	release_firmware(fw_entry);
+	return ret;
+}
+
+static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname)
+{
+	int ret = -1;
+	uint32_t fw_size = 0;
+	struct qseecom_load_app_ireq load_req = {0, 0, 0, 0};
+	struct qseecom_command_scm_resp resp;
+	u8 *img_data = NULL;
+
+	if (__qseecom_get_fw_size(appname, &fw_size))
+		return -EIO;
+
+	img_data = kzalloc(fw_size, GFP_KERNEL);
+	if (!img_data) {
+		pr_err("Failied to allocate memory for copying image data\n");
+		return -ENOMEM;
+	}
+	ret = __qseecom_get_fw_data(appname, img_data, &load_req);
+	if (ret) {
+		kzfree(img_data);
+		return -EIO;
+	}
+
+	/* Populate the remaining parameters */
+	load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
+	memcpy(load_req.app_name, appname, MAX_APP_NAME_SIZE);
+	/* SCM_CALL to load the image */
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,	&load_req,
+			sizeof(struct qseecom_load_app_ireq),
+			&resp, sizeof(resp));
+	kzfree(img_data);
+	if (ret) {
+		pr_err("scm_call to load failed : ret %d\n", ret);
+		return -EIO;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		ret = resp.data;
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret)
+			pr_err("process_incomplete_cmd FAILED\n");
+		else
+			ret = resp.data;
+		break;
+	case QSEOS_RESULT_FAILURE:
+		pr_err("scm call failed with response QSEOS_RESULT FAILURE\n");
+		break;
+	default:
+		pr_err("scm call return unknown response %d\n", resp.result);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+int qseecom_start_app(struct qseecom_handle **handle,
+						char *app_name, uint32_t size)
+{
+	int32_t ret;
+	unsigned long flags = 0;
+	struct qseecom_dev_handle *data = NULL;
+	struct qseecom_check_app_ireq app_ireq;
+	struct qseecom_registered_app_list *entry = NULL;
+	struct qseecom_registered_kclient_list *kclient_entry = NULL;
+	bool found_app = false;
+	uint32_t len;
+	ion_phys_addr_t pa;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		pr_err("This functionality is UNSUPPORTED in version 1.3\n");
+		return -EINVAL;
+	}
+
+	*handle = kzalloc(sizeof(struct qseecom_handle), GFP_KERNEL);
+	if (!(*handle)) {
+		pr_err("failed to allocate memory for kernel client handle\n");
+		return -ENOMEM;
+	}
+
+	app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+	memcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
+	ret = __qseecom_check_app_exists(app_ireq);
+	if (ret < 0)
+		return -EINVAL;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		pr_err("kmalloc failed\n");
+		if (ret == 0) {
+			kfree(*handle);
+			*handle = NULL;
+		}
+		return -ENOMEM;
+	}
+	data->abort = 0;
+	data->service = false;
+	data->released = false;
+	data->client.app_id = ret;
+	data->client.sb_length = size;
+	data->client.user_virt_sb_base = 0;
+	data->client.ihandle = NULL;
+
+	init_waitqueue_head(&data->abort_wq);
+	atomic_set(&data->ioctl_count, 0);
+
+	data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096,
+				ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL(data->client.ihandle)) {
+		pr_err("Ion client could not retrieve the handle\n");
+		kfree(data);
+		kfree(*handle);
+		*handle = NULL;
+		return -EINVAL;
+	}
+
+	if (ret > 0) {
+		pr_warn("App id %d for [%s] app exists\n", ret,
+			(char *)app_ireq.app_name);
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+		list_for_each_entry(entry,
+				&qseecom.registered_app_list_head, list){
+			if (entry->app_id == ret) {
+				entry->ref_cnt++;
+				found_app = true;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(
+				&qseecom.registered_app_list_lock, flags);
+		if (!found_app)
+			pr_warn("App_id %d [%s] was loaded but not registered\n",
+					ret, (char *)app_ireq.app_name);
+	} else {
+		/* load the app and get the app_id  */
+		pr_debug("%s: Loading app for the first time'\n",
+				qseecom.pdev->init_name);
+		mutex_lock(&app_access_lock);
+		ret = __qseecom_load_fw(data, app_name);
+		mutex_unlock(&app_access_lock);
+
+		if (ret < 0) {
+			kfree(*handle);
+			*handle = NULL;
+			return ret;
+		}
+		data->client.app_id = ret;
+	}
+	if (!found_app) {
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+		if (!entry) {
+			pr_err("kmalloc failed\n");
+			return -ENOMEM;
+		}
+		entry->app_id = ret;
+		entry->ref_cnt = 1;
+
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+		list_add_tail(&entry->list, &qseecom.registered_app_list_head);
+		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+									flags);
+	}
+
+	/* Get the physical address of the ION BUF */
+	ret = ion_phys(qseecom.ion_clnt, data->client.ihandle, &pa, &len);
+	/* Populate the structure for sending scm call to load image */
+	data->client.sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
+							data->client.ihandle);
+	data->client.sb_phys = pa;
+	(*handle)->dev = (void *)data;
+	(*handle)->sbuf = (unsigned char *)data->client.sb_virt;
+	(*handle)->sbuf_len = data->client.sb_length;
+
+	kclient_entry = kzalloc(sizeof(*kclient_entry), GFP_KERNEL);
+	if (!kclient_entry) {
+		pr_err("kmalloc failed\n");
+		return -ENOMEM;
+	}
+	kclient_entry->handle = *handle;
+
+	spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+	list_add_tail(&kclient_entry->list,
+			&qseecom.registered_kclient_list_head);
+	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(qseecom_start_app);
+
+int qseecom_shutdown_app(struct qseecom_handle **handle)
+{
+	int ret = -EINVAL;
+	struct qseecom_dev_handle *data =
+			(struct qseecom_dev_handle *) ((*handle)->dev);
+	struct qseecom_registered_kclient_list *kclient = NULL;
+	unsigned long flags = 0;
+	bool found_handle = false;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		pr_err("This functionality is UNSUPPORTED in version 1.3\n");
+		return -EINVAL;
+	}
+	if (*handle == NULL) {
+		pr_err("Handle is not initialized\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+	list_for_each_entry(kclient, &qseecom.registered_kclient_list_head,
+				list) {
+		if (kclient->handle == (*handle)) {
+			list_del(&kclient->list);
+			found_handle = true;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+	if (!found_handle)
+		pr_err("Unable to find the handle, exiting\n");
+	else
+		ret = qseecom_unload_app(data);
+	if (ret == 0) {
+		kzfree(data);
+		kzfree(*handle);
+		kzfree(kclient);
+		*handle = NULL;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(qseecom_shutdown_app);
+
+int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
+			uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len)
+{
+	int ret = 0;
+	struct qseecom_send_cmd_req req = {0, 0, 0, 0};
+	struct qseecom_dev_handle *data;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		pr_err("This functionality is UNSUPPORTED in version 1.3\n");
+		return -EINVAL;
+	}
+
+	if (handle == NULL) {
+		pr_err("Handle is not initialized\n");
+		return -EINVAL;
+	}
+	data = handle->dev;
+
+	req.cmd_req_len = sbuf_len;
+	req.resp_len = rbuf_len;
+	req.cmd_req_buf = send_buf;
+	req.resp_buf = resp_buf;
+
+	mutex_lock(&app_access_lock);
+	atomic_inc(&data->ioctl_count);
+
+	ret = __qseecom_send_cmd(data, &req);
+
+	atomic_dec(&data->ioctl_count);
+	mutex_unlock(&app_access_lock);
+
+	if (ret)
+		return ret;
+
+	pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
+			req.resp_len, req.resp_buf);
+	return ret;
+}
+EXPORT_SYMBOL(qseecom_send_command);
+
 static int qseecom_send_resp(void)
 {
 	qseecom.send_resp_flag = 1;
@@ -1871,7 +2267,7 @@
 	int ret;
 	struct device *class_dev;
 	char qsee_not_legacy = 0;
-	struct msm_bus_scale_pdata *qseecom_platform_support;
+	struct msm_bus_scale_pdata *qseecom_platform_support = NULL;
 	uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
 
 	qsee_bw_count = 0;
@@ -1911,6 +2307,8 @@
 	spin_lock_init(&qseecom.registered_listener_list_lock);
 	INIT_LIST_HEAD(&qseecom.registered_app_list_head);
 	spin_lock_init(&qseecom.registered_app_list_lock);
+	INIT_LIST_HEAD(&qseecom.registered_kclient_list_head);
+	spin_lock_init(&qseecom.registered_kclient_list_lock);
 	init_waitqueue_head(&qseecom.send_resp_wq);
 	qseecom.send_resp_flag = 0;
 
@@ -1930,7 +2328,7 @@
 
 	qseecom.pdev = class_dev;
 	/* Create ION msm client */
-	qseecom.ion_clnt = msm_ion_client_create(0x03, "qseecom-kernel");
+	qseecom.ion_clnt = msm_ion_client_create(-1, "qseecom-kernel");
 	if (qseecom.ion_clnt == NULL) {
 		pr_err("Ion client cannot be created\n");
 		rc = -ENOMEM;
@@ -1966,9 +2364,60 @@
 
 static int __devinit qseecom_remove(struct platform_device *pdev)
 {
+	struct qseecom_registered_kclient_list *kclient = NULL;
+	unsigned long flags = 0;
+	int ret = 0;
+
 	if (pdev->dev.platform_data != NULL)
 		msm_bus_scale_unregister_client(qsee_perf_client);
-	return 0;
+
+	spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+	kclient = list_entry((&qseecom.registered_kclient_list_head)->next,
+		struct qseecom_registered_kclient_list, list);
+	if (list_empty(&kclient->list)) {
+		spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock,
+			flags);
+		return 0;
+	}
+	list_for_each_entry(kclient, &qseecom.registered_kclient_list_head,
+				list) {
+			if (kclient)
+				list_del(&kclient->list);
+			break;
+	}
+	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+
+
+	while (kclient->handle != NULL) {
+		ret = qseecom_unload_app(kclient->handle->dev);
+		if (ret == 0) {
+			kzfree(kclient->handle->dev);
+			kzfree(kclient->handle);
+			kzfree(kclient);
+		}
+		spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+		kclient = list_entry(
+				(&qseecom.registered_kclient_list_head)->next,
+				struct qseecom_registered_kclient_list, list);
+		if (list_empty(&kclient->list)) {
+			spin_unlock_irqrestore(
+				&qseecom.registered_kclient_list_lock, flags);
+			return 0;
+		}
+		list_for_each_entry(kclient,
+				&qseecom.registered_kclient_list_head, list) {
+			if (kclient)
+				list_del(&kclient->list);
+			break;
+		}
+		spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock,
+				flags);
+		if (!kclient) {
+			ret = 0;
+			break;
+		}
+	}
+	return ret;
 };
 
 static struct of_device_id qseecom_match[] = {
diff --git a/drivers/misc/qseecom_kernel.h b/drivers/misc/qseecom_kernel.h
new file mode 100644
index 0000000..bfa5709
--- /dev/null
+++ b/drivers/misc/qseecom_kernel.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2012, The Linux Foundation. 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 __QSEECOM_KERNEL_H_
+#define __QSEECOM_KERNEL_H_
+
+#include <linux/types.h>
+/*
+ * struct qseecom_handle -
+ *      Handle to the qseecom device for kernel clients
+ * @sbuf - shared buffer pointer
+ * @sbbuf_len - shared buffer size
+ */
+struct qseecom_handle {
+	void *dev; /* in/out */
+	unsigned char *sbuf; /* in/out */
+	uint32_t sbuf_len; /* in/out */
+};
+
+int qseecom_start_app(struct qseecom_handle **handle,
+						char *app_name, uint32_t size);
+int qseecom_shutdown_app(struct qseecom_handle **handle);
+int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
+			uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len);
+
+
+#endif /* __QSEECOM_KERNEL_H_ */
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 254672f..fe41cdd 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1737,6 +1737,7 @@
 	brq->data.blksz = 512;
 	brq->data.blocks = mqrq->packed_blocks + 1;
 	brq->data.flags |= MMC_DATA_WRITE;
+	brq->data.fault_injected = false;
 
 	brq->stop.opcode = MMC_STOP_TRANSMISSION;
 	brq->stop.arg = 0;
@@ -2360,7 +2361,7 @@
 	ret = device_create_file(disk_to_dev(md->disk),
 				 &md->num_wr_reqs_to_start_packing);
 	if (ret)
-		goto power_ro_lock_fail;
+		goto num_wr_reqs_to_start_packing_fail;
 
 	md->min_sectors_to_check_bkops_status.show =
 		min_sectors_to_check_bkops_status_show;
@@ -2373,14 +2374,19 @@
 	ret = device_create_file(disk_to_dev(md->disk),
 				 &md->min_sectors_to_check_bkops_status);
 	if (ret)
-		goto power_ro_lock_fail;
+		goto min_sectors_to_check_bkops_status_fails;
 
 	return ret;
 
+min_sectors_to_check_bkops_status_fails:
+	device_remove_file(disk_to_dev(md->disk),
+			   &md->num_wr_reqs_to_start_packing);
+num_wr_reqs_to_start_packing_fail:
+	device_remove_file(disk_to_dev(md->disk), &md->power_ro_lock);
 power_ro_lock_fail:
-		device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+	device_remove_file(disk_to_dev(md->disk), &md->force_ro);
 force_ro_fail:
-		del_gendisk(md->disk);
+	del_gendisk(md->disk);
 
 	return ret;
 }
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index cc91646..8897f18a 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -201,11 +201,12 @@
 	if (!mq->queue)
 		return -ENOMEM;
 
+	memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur));
+	memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev));
+
 	INIT_LIST_HEAD(&mqrq_cur->packed_list);
 	INIT_LIST_HEAD(&mqrq_prev->packed_list);
 
-	memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur));
-	memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev));
 	mq->mqrq_cur = mqrq_cur;
 	mq->mqrq_prev = mqrq_prev;
 	mq->queue->queuedata = mq;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 72f4a5c..49bbe09 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -213,9 +213,9 @@
 #endif /* CONFIG_MMC_MSM_SPS_SUPPORT */
 
 /**
- * Apply soft reset to all SDCC BAM pipes
+ * Apply reset
  *
- * This function applies soft reset to SDCC BAM pipe.
+ * This function resets SPS BAM and DML cores.
  *
  * This function should be called to recover from error
  * conditions encountered during CMD/DATA tranfsers with card.
@@ -223,43 +223,64 @@
  * @host - Pointer to driver's host structure
  *
  */
-static void msmsdcc_sps_pipes_reset_and_restore(struct msmsdcc_host *host)
+static int msmsdcc_bam_dml_reset_and_restore(struct msmsdcc_host *host)
 {
 	int rc;
 
+	/* Reset and init DML */
+	rc = msmsdcc_dml_init(host);
+	if (rc) {
+		pr_err("%s: msmsdcc_dml_init error=%d\n",
+				mmc_hostname(host->mmc), rc);
+		goto out;
+	}
+
 	/* Reset all SDCC BAM pipes */
 	rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
-	if (rc)
-		pr_err("%s:msmsdcc_sps_reset_ep(prod) error=%d\n",
+	if (rc) {
+		pr_err("%s: msmsdcc_sps_reset_ep(prod) error=%d\n",
 				mmc_hostname(host->mmc), rc);
-	rc = msmsdcc_sps_reset_ep(host, &host->sps.cons);
-	if (rc)
-		pr_err("%s:msmsdcc_sps_reset_ep(cons) error=%d\n",
-				mmc_hostname(host->mmc), rc);
+		goto out;
+	}
 
-	if (host->sps.reset_device) {
-		rc = sps_device_reset(host->sps.bam_handle);
-		if (rc)
-			pr_err("%s: sps_device_reset error=%d\n",
+	rc = msmsdcc_sps_reset_ep(host, &host->sps.cons);
+	if (rc) {
+		pr_err("%s: msmsdcc_sps_reset_ep(cons) error=%d\n",
 				mmc_hostname(host->mmc), rc);
-		host->sps.reset_device = false;
+		goto out;
+	}
+
+	/* Reset BAM */
+	rc = sps_device_reset(host->sps.bam_handle);
+	if (rc) {
+		pr_err("%s: sps_device_reset error=%d\n",
+				mmc_hostname(host->mmc), rc);
+		goto out;
 	}
 
 	/* Restore all BAM pipes connections */
 	rc = msmsdcc_sps_restore_ep(host, &host->sps.prod);
-	if (rc)
-		pr_err("%s:msmsdcc_sps_restore_ep(prod) error=%d\n",
+	if (rc) {
+		pr_err("%s: msmsdcc_sps_restore_ep(prod) error=%d\n",
 				mmc_hostname(host->mmc), rc);
+		goto out;
+	}
+
 	rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
 	if (rc)
-		pr_err("%s:msmsdcc_sps_restore_ep(cons) error=%d\n",
+		pr_err("%s: msmsdcc_sps_restore_ep(cons) error=%d\n",
 				mmc_hostname(host->mmc), rc);
+	else
+		host->sps.reset_bam = false;
+
+out:
+	return rc;
 }
 
 /**
  * Apply soft reset
  *
- * This function applies soft reset to SDCC core and DML core.
+ * This function applies soft reset to SDCC core.
  *
  * This function should be called to recover from error
  * conditions encountered with CMD/DATA tranfsers with card.
@@ -277,6 +298,11 @@
 	 */
 	if (is_sw_reset_save_config(host)) {
 		ktime_t start;
+		uint32_t dll_config = 0;
+
+
+		if (is_sw_reset_save_config_broken(host))
+			dll_config = readl_relaxed(host->base + MCI_DLL_CONFIG);
 
 		writel_relaxed(readl_relaxed(host->base + MMCIPOWER)
 				| MCI_SW_RST_CFG, host->base + MMCIPOWER);
@@ -296,6 +322,11 @@
 				BUG();
 			}
 		}
+
+		if (is_sw_reset_save_config_broken(host)) {
+			writel_relaxed(dll_config, host->base + MCI_DLL_CONFIG);
+			mb();
+		}
 	} else {
 		writel_relaxed(0, host->base + MMCICOMMAND);
 		msmsdcc_sync_reg_wr(host);
@@ -354,25 +385,25 @@
 static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
 {
 	if (is_soft_reset(host)) {
-		if (is_sps_mode(host)) {
-			/* Reset DML first */
-			msmsdcc_dml_reset(host);
+		if (is_sps_mode(host))
 			/*
-			 * delay the SPS pipe reset in thread context as
+			 * delay the SPS BAM reset in thread context as
 			 * sps_connect/sps_disconnect APIs can be called
 			 * only from non-atomic context.
 			 */
-			host->sps.pipe_reset_pending = true;
-		}
-		mb();
+			host->sps.reset_bam = true;
+
 		msmsdcc_soft_reset(host);
 
 		pr_debug("%s: Applied soft reset to Controller\n",
 				mmc_hostname(host->mmc));
-
-		if (is_sps_mode(host))
-			msmsdcc_dml_init(host);
 	} else {
+		/*
+		 * When there is a requirement to use this hard reset,
+		 * BAM needs to be reconfigured as well by calling
+		 * msmsdcc_sps_exit and msmsdcc_sps_init.
+		 */
+
 		/* Give Clock reset (hard reset) to controller */
 		u32	mci_clk = 0;
 		u32	mci_mask0 = 0;
@@ -2086,6 +2117,7 @@
 {
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long		flags;
+	int retries = 5;
 
 	/*
 	 * Get the SDIO AL client out of LPM.
@@ -2094,10 +2126,14 @@
 	if (host->plat->is_sdio_al_client)
 		msmsdcc_sdio_al_lpm(mmc, false);
 
-	/* check if sps pipe reset is pending? */
-	if (is_sps_mode(host) && host->sps.pipe_reset_pending) {
-		msmsdcc_sps_pipes_reset_and_restore(host);
-		host->sps.pipe_reset_pending = false;
+	/* check if sps bam needs to be reset */
+	if (is_sps_mode(host) && host->sps.reset_bam) {
+		while (retries) {
+			if (!msmsdcc_bam_dml_reset_and_restore(host))
+				break;
+			pr_err("%s: msmsdcc_bam_dml_reset_and_restore returned error. %d attempts left.\n",
+					mmc_hostname(host->mmc), --retries);
+		}
 	}
 
 	spin_lock_irqsave(&host->lock, flags);
@@ -2118,8 +2154,9 @@
 	/*
 	 * Don't start the request if SDCC is not in proper state to handle it
 	 */
-	if (!host->pwr || !atomic_read(&host->clks_on)
-			|| host->sdcc_irq_disabled) {
+	if (!host->pwr || !atomic_read(&host->clks_on) ||
+			host->sdcc_irq_disabled ||
+			host->sps.reset_bam) {
 		WARN(1, "%s: %s: SDCC is in bad state. don't process"
 		     " new request (CMD%d)\n", mmc_hostname(host->mmc),
 		     __func__, mrq->cmd->opcode);
@@ -4599,11 +4636,8 @@
 	BUG_ON(!is_sps_mode(host));
 
 	if (sps_cb_case == SPS_CALLBACK_BAM_ERROR_IRQ) {
-		/**
-		 * Reset the all endpoints along with reseting the sps device.
-		 */
-		host->sps.pipe_reset_pending = true;
-		host->sps.reset_device = true;
+		/* Reset all endpoints along with resetting bam. */
+		host->sps.reset_bam = true;
 
 		pr_err("%s: BAM Global ERROR IRQ happened\n",
 			mmc_hostname(host->mmc));
@@ -5019,6 +5053,10 @@
 			host->curr.data_xfered, host->curr.xfer_remain);
 	}
 
+	if (host->sps.reset_bam)
+		pr_err("%s: SPS BAM reset failed: sps reset_bam=%d\n",
+			mmc_hostname(host->mmc), host->sps.reset_bam);
+
 	pr_err("%s: got_dataend=%d, prog_enable=%d,"
 		" wait_for_auto_prog_done=%d, got_auto_prog_done=%d,"
 		" req_tout_ms=%d\n", mmc_hostname(host->mmc),
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index c66d1a5..af5498e 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -2,7 +2,7 @@
  *  linux/drivers/mmc/host/msmsdcc.h - QCT MSM7K SDC Controller
  *
  *  Copyright (C) 2008 Google, All Rights Reserved.
- *  Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2009-2012, The Linux Foundation. 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 as
@@ -321,8 +321,7 @@
 	unsigned int			dest_pipe_index;
 	unsigned int			busy;
 	unsigned int			xfer_req_cnt;
-	bool				pipe_reset_pending;
-	bool				reset_device;
+	bool				reset_bam;
 	struct tasklet_struct		tlet;
 };
 
@@ -446,6 +445,7 @@
 #define MSMSDCC_IO_PAD_PWR_SWITCH	(1 << 8)
 #define MSMSDCC_AUTO_CMD19	(1 << 9)
 #define MSMSDCC_AUTO_CMD21	(1 << 10)
+#define MSMSDCC_SW_RST_CFG_BROKEN	(1 << 11)
 
 #define set_hw_caps(h, val)		((h)->hw_caps |= val)
 #define is_sps_mode(h)			((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -459,6 +459,8 @@
 #define is_io_pad_pwr_switch(h)	((h)->hw_caps & MSMSDCC_IO_PAD_PWR_SWITCH)
 #define is_auto_cmd19(h)		((h)->hw_caps & MSMSDCC_AUTO_CMD19)
 #define is_auto_cmd21(h)		((h)->hw_caps & MSMSDCC_AUTO_CMD21)
+#define is_sw_reset_save_config_broken(h) \
+				((h)->hw_caps & MSMSDCC_SW_RST_CFG_BROKEN)
 
 /* Set controller capabilities based on version */
 static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -490,7 +492,11 @@
 		host->hw_caps |= MSMSDCC_AUTO_CMD21;
 
 	if (step >= 0x2b) /* SDCC v4 2.1.0 and greater */
-		host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_AUTO_CMD21;
+		host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG |
+					MSMSDCC_AUTO_CMD21;
+
+	if (step == 0x2b)
+		host->hw_caps |= MSMSDCC_SW_RST_CFG_BROKEN;
 }
 
 int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/power/bq28400_battery.c b/drivers/power/bq28400_battery.c
index 39d52cb..47fced1 100644
--- a/drivers/power/bq28400_battery.c
+++ b/drivers/power/bq28400_battery.c
@@ -818,6 +818,11 @@
 		return -EIO;
 	}
 
+	if (bq28400_read_reg(client, SBS_BATTERY_STATUS) < 0) {
+		pr_err("Device doesn't exist.\n");
+		return -ENODEV;
+	}
+
 	bq28400_dev = kzalloc(sizeof(*bq28400_dev), GFP_KERNEL);
 	if (!bq28400_dev) {
 		pr_err(" alloc fail.\n");
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 23903df..60eee64 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -856,6 +856,22 @@
 	*val = cc_uah;
 }
 
+int pm8921_bms_cc_uah(int *cc_uah)
+{
+	int cc;
+
+	*cc_uah = 0;
+
+	if (!the_chip)
+		return -EINVAL;
+
+	read_cc(the_chip, &cc);
+	calculate_cc_uah(the_chip, cc, cc_uah);
+
+	return 0;
+}
+EXPORT_SYMBOL(pm8921_bms_cc_uah);
+
 static int calculate_termination_uuc(struct pm8921_bms_chip *chip,
 				 int batt_temp, int chargecycles,
 				int fcc_uah, int i_ma,
@@ -1398,7 +1414,7 @@
 						(s64)fcc_uah - uuc_uah);
 	soc_est = bound_soc(soc_est);
 
-	if (ibat_ua < 0) {
+	if (ibat_ua < 0 && pm8921_is_batfet_closed()) {
 		soc = charging_adjustments(chip, soc, vbat_uv, ibat_ua,
 				batt_temp, chargecycles,
 				fcc_uah, cc_uah, uuc_uah);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index cf34df5..8a36d6c 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1354,6 +1354,7 @@
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
 };
 
 static int get_prop_battery_uvolts(struct pm8921_chg_chip *chip)
@@ -1489,6 +1490,20 @@
 	return rc;
 }
 
+static int get_prop_batt_charge_now(struct pm8921_chg_chip *chip)
+{
+	int rc;
+	int cc_uah;
+
+	rc = pm8921_bms_cc_uah(&cc_uah);
+
+	if (rc == 0)
+		return cc_uah;
+
+	pr_err("unable to get batt fcc rc = %d\n", rc);
+	return rc;
+}
+
 static int get_prop_batt_health(struct pm8921_chg_chip *chip)
 {
 	int temp;
@@ -1627,6 +1642,9 @@
 	case POWER_SUPPLY_PROP_ENERGY_FULL:
 		val->intval = get_prop_batt_fcc(chip) * 1000;
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = get_prop_batt_charge_now(chip);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1693,7 +1711,7 @@
 		}
 
 		/* Check if IUSB_FINE_RES is available */
-		if ((usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
+		while ((usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
 				&& !the_chip->iusb_fine_res)
 			i--;
 		if (i < 0)
@@ -4339,6 +4357,11 @@
 						vin_collapse_check_worker);
 	INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
 
+	INIT_WORK(&chip->bms_notify.work, bms_notify);
+	INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
+
+	INIT_DELAYED_WORK(&chip->update_heartbeat_work, update_heartbeat);
+
 	rc = request_irqs(chip, pdev);
 	if (rc) {
 		pr_err("couldn't register interrupts rc=%d\n", rc);
@@ -4375,19 +4398,13 @@
 	}
 	create_debugfs_entries(chip);
 
-	INIT_WORK(&chip->bms_notify.work, bms_notify);
-	INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
-
 	/* determine what state the charger is in */
 	determine_initial_state(chip);
 
-	if (chip->update_time) {
-		INIT_DELAYED_WORK(&chip->update_heartbeat_work,
-							update_heartbeat);
+	if (chip->update_time)
 		schedule_delayed_work(&chip->update_heartbeat_work,
 				      round_jiffies_relative(msecs_to_jiffies
 							(chip->update_time)));
-	}
 	return 0;
 
 free_irq:
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index 7966a79..14e5b60 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -56,6 +56,7 @@
 	struct usb_request *rx_req;
 	int rx_done;
 	bool notify_close;
+	bool close_notified;
 };
 
 static struct usb_interface_descriptor adb_interface_desc = {
@@ -424,8 +425,10 @@
 	/* clear the error latch */
 	atomic_set(&_adb_dev->error, 0);
 
-	if (_adb_dev->notify_close)
+	if (_adb_dev->close_notified) {
+		_adb_dev->close_notified = false;
 		adb_ready_callback();
+	}
 
 	_adb_dev->notify_close = true;
 	return 0;
@@ -443,8 +446,10 @@
 	 * undesired.  We want to force bus reset only for certain
 	 * commands like "adb root" and "adb usb".
 	 */
-	if (_adb_dev->notify_close)
+	if (_adb_dev->notify_close) {
 		adb_closed_callback();
+		_adb_dev->close_notified = true;
+	}
 
 	adb_unlock(&_adb_dev->open_excl);
 	return 0;
@@ -625,7 +630,9 @@
 	atomic_set(&dev->open_excl, 0);
 	atomic_set(&dev->read_excl, 0);
 	atomic_set(&dev->write_excl, 0);
-	dev->notify_close = true;
+
+	/* config is disabled by default if adb is present. */
+	dev->close_notified = true;
 
 	INIT_LIST_HEAD(&dev->tx_idle);
 
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 12f70c3..c61591a 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -178,12 +178,15 @@
 static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
 {
 	int i;
+	size_t align;
+
+	align = ((ehci->pool_64_bit_align) ? 64 : 32);
 
 	/* QTDs for control/bulk/intr transfers */
 	ehci->qtd_pool = dma_pool_create ("ehci_qtd",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_qtd),
-			32 /* byte alignment (for hw parts) */,
+			align /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
 	if (!ehci->qtd_pool) {
 		goto fail;
@@ -193,7 +196,7 @@
 	ehci->qh_pool = dma_pool_create ("ehci_qh",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof(struct ehci_qh_hw),
-			32 /* byte alignment (for hw parts) */,
+			align /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
 	if (!ehci->qh_pool) {
 		goto fail;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index d238b4e2..07a232a 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -30,6 +30,7 @@
 
 	hcd->has_tt = pdata->has_tt;
 	ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+	ehci->pool_64_bit_align = pdata->pool_64_bit_align;
 	ehci->big_endian_desc = pdata->big_endian_desc;
 	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index f8b884a..cd17421 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -166,6 +166,7 @@
 	unsigned		has_hostpc:1;
 	unsigned		has_lpm:1;  /* support link power management */
 	unsigned		has_ppcd:1; /* support per-port change bits */
+	unsigned		pool_64_bit_align:1; /* for 64 bit alignment */
 	u8			sbrn;		/* packed release number */
 
 	/* irq statistics */
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 1bd697e..04da6f5 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1777,6 +1777,7 @@
 	struct mdp4_overlay_pipe *bspipe;
 	int ptype, pnum, pndx, mixer;
 	int format, alpha_enable, alpha;
+	struct mdp4_iommu_pipe_info iom;
 
 	if (pipe->pipe_type != OVERLAY_TYPE_BF)
 		return;
@@ -1791,6 +1792,7 @@
 		return;
 	}
 
+	iom = bspipe->iommu;
 	ptype = bspipe->pipe_type;
 	pnum = bspipe->pipe_num;
 	pndx = bspipe->pipe_ndx;
@@ -1804,6 +1806,7 @@
 	bspipe->src_format = format;
 	bspipe->alpha_enable = alpha_enable;
 	bspipe->alpha = alpha;
+	bspipe->iommu = iom;
 
 	bspipe->pipe_used++;	/* mark base layer pipe used */
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index a83c340..5551c9d 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -1073,7 +1073,7 @@
 	uint8 *buf;
 	unsigned int buf_offset;
 	int bpp;
-	int cndx = 0;
+	int cnt, cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 
@@ -1104,12 +1104,14 @@
 
 	mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
-	mdp4_dsi_video_pipe_commit(cndx, 0);
 
-	if (pipe->ov_blt_addr)
-		mdp4_dsi_video_wait4ov(cndx);
-	else
-		mdp4_dsi_video_wait4dmap(cndx);
+	cnt = mdp4_dsi_video_pipe_commit(cndx, 0);
+	if (cnt) {
+		if (pipe->ov_blt_addr)
+			mdp4_dsi_video_wait4ov(cndx);
+		else
+			mdp4_dsi_video_wait4dmap(cndx);
+	}
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 67690cf..e71f49f 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -1114,6 +1114,7 @@
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	int wait = 0;
 
 	mutex_lock(&mfd->dma->ov_mutex);
 	if (!mfd->panel_power_on) {
@@ -1145,8 +1146,12 @@
 		mdp4_dtv_pipe_queue(0, pipe);
 	}
 	mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
+
+	if (hdmi_prim_display)
+		wait = 1;
+
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
-	mdp4_dtv_pipe_commit(cndx, 0);
+	mdp4_dtv_pipe_commit(cndx, wait);
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 9e0c411..df5c262 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -961,7 +961,7 @@
 	uint8 *buf;
 	unsigned int buf_offset;
 	int bpp;
-	int cndx = 0;
+	int cnt, cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 
@@ -993,13 +993,13 @@
 
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 
-
-	mdp4_lcdc_pipe_commit(cndx, 0);
-
-	if (pipe->ov_blt_addr)
-		mdp4_lcdc_wait4ov(cndx);
-	else
-		mdp4_lcdc_wait4dmap(cndx);
+	cnt = mdp4_lcdc_pipe_commit(cndx, 0);
+	if (cnt) {
+		if (pipe->ov_blt_addr)
+			mdp4_lcdc_wait4ov(cndx);
+		else
+			mdp4_lcdc_wait4dmap(cndx);
+	}
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index c2d5f28..d53240f 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -18,6 +18,7 @@
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
 #include <linux/types.h>
+#include <mach/msm_hdmi_audio.h>
 
 #define REG_DUMP 0
 
@@ -40,6 +41,17 @@
 	((d & 0xff) + ((d >> 8) & 0xff) +	\
 	((d >> 16) & 0xff) + ((d >> 24) & 0xff))
 
+/* parameters for clock regeneration */
+struct hdmi_tx_audio_acr {
+	u32 n;
+	u32 cts;
+};
+
+struct hdmi_tx_audio_acr_arry {
+	u32 pclk;
+	struct hdmi_tx_audio_acr lut[HDMI_SAMPLE_RATE_MAX];
+};
+
 static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
 
@@ -90,6 +102,27 @@
 	 0x07,	0x07,	0x07,	0x07,	0x02, 0x02, 0x02}  /*12*/
 };
 
+/* Audio constants lookup table for hdmi_tx_audio_acr_setup */
+/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
+static const struct hdmi_tx_audio_acr_arry hdmi_tx_audio_acr_lut[] = {
+	/*  25.200MHz  */
+	{25200, {{4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
+		{12288, 25200}, {25088, 28000}, {24576, 25200} } },
+	/*  27.000MHz  */
+	{27000, {{4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
+		{12288, 27000}, {25088, 30000}, {24576, 27000} } },
+	/*  27.027MHz */
+	{27030, {{4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
+		{12288, 27027}, {25088, 30030}, {24576, 27027} } },
+	/*  74.250MHz */
+	{74250, {{4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
+		{12288, 74250}, {25088, 82500}, {24576, 74250} } },
+	/* 148.500MHz */
+	{148500, {{4096, 148500}, {6272, 165000}, {6144, 148500},
+		{12544, 165000}, {12288, 148500}, {25088, 165000},
+		{24576, 148500} } },
+};
+
 const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
 {
 	switch (module) {
@@ -335,8 +368,8 @@
 
 static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
-	struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
-	return !(DSS_REG_R_ND(io, HDMI_CTRL) & BIT(1));
+	return hdmi_edid_get_sink_mode(
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
 } /* hdmi_tx_is_dvi_mode */
 
 static int hdmi_tx_init_panel_info(uint32_t resolution,
@@ -1275,6 +1308,335 @@
 	DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL0, 0x7F);
 } /* hdmi_tx_powerdown_phy */
 
+static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
+	bool enabled, int num_of_channels)
+{
+	/* Read first before writing */
+	u32 acr_pck_ctrl_reg;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	acr_pck_ctrl_reg = DSS_REG_R(io, HDMI_ACR_PKT_CTRL);
+
+	if (enabled) {
+		const struct hdmi_disp_mode_timing_type *timing =
+			hdmi_get_supported_mode(hdmi_ctrl->video_resolution);
+		const struct hdmi_tx_audio_acr_arry *audio_acr =
+			&hdmi_tx_audio_acr_lut[0];
+		const int lut_size = sizeof(hdmi_tx_audio_acr_lut)
+			/ sizeof(*hdmi_tx_audio_acr_lut);
+		u32 i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
+
+		if (timing == NULL) {
+			DEV_WARN("%s: video format %d not supported\n",
+				__func__, hdmi_ctrl->video_resolution);
+			return -EPERM;
+		}
+
+		for (i = 0; i < lut_size;
+			audio_acr = &hdmi_tx_audio_acr_lut[++i]) {
+			if (audio_acr->pclk == timing->pixel_freq)
+				break;
+		}
+		if (i >= lut_size) {
+			DEV_WARN("%s: pixel clk %d not supported\n", __func__,
+				timing->pixel_freq);
+			return -EPERM;
+		}
+
+		n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
+		cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
+		layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+
+		if (
+		(HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+			multiplier = 4;
+			n >>= 2; /* divide N by 4 and use multiplier */
+		} else if (
+		(HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+			multiplier = 2;
+			n >>= 1; /* divide N by 2 and use multiplier */
+		} else {
+			multiplier = 1;
+		}
+		DEV_DBG("%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
+			layout);
+
+		/* AUDIO_PRIORITY | SOURCE */
+		acr_pck_ctrl_reg |= 0x80000100;
+		/* N_MULTIPLE(multiplier) */
+		acr_pck_ctrl_reg |= (multiplier & 7) << 16;
+
+		if ((HDMI_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+			/* SELECT(3) */
+			acr_pck_ctrl_reg |= 3 << 4;
+			/* CTS_48 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_48_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_48_1, n);
+		} else if (
+		(HDMI_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+			/* SELECT(2) */
+			acr_pck_ctrl_reg |= 2 << 4;
+			/* CTS_44 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_44_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_44_1, n);
+		} else {	/* default to 32k */
+			/* SELECT(1) */
+			acr_pck_ctrl_reg |= 1 << 4;
+			/* CTS_32 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_32_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_32_1, n);
+		}
+		/* Payload layout depends on number of audio channels */
+		/* LAYOUT_SEL(layout) */
+		aud_pck_ctrl_2_reg = 1 | (layout << 1);
+		/* override | layout */
+		DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+		/* SEND | CONT */
+		acr_pck_ctrl_reg |= 0x00000003;
+	} else {
+		/* ~(SEND | CONT) */
+		acr_pck_ctrl_reg &= ~0x00000003;
+	}
+	DSS_REG_W(io, HDMI_ACR_PKT_CTRL, acr_pck_ctrl_reg);
+
+	return 0;
+} /* hdmi_tx_audio_acr_setup */
+
+static int hdmi_tx_audio_info_setup(void *priv_d, bool enabled,
+	u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+	bool down_mix)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)priv_d;
+	struct dss_io_data *io = NULL;
+
+	u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+	u32 check_sum, audio_info_0_reg, audio_info_1_reg;
+	u32 audio_info_ctrl_reg;
+	u32 aud_pck_ctrl_2_reg;
+	u32 layout;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+	aud_pck_ctrl_2_reg = 1 | (layout << 1);
+	DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+	/*
+	 * Please see table 20 Audio InfoFrame in HDMI spec
+	 * FL  = front left
+	 * FC  = front Center
+	 * FR  = front right
+	 * FLC = front left center
+	 * FRC = front right center
+	 * RL  = rear left
+	 * RC  = rear center
+	 * RR  = rear right
+	 * RLC = rear left center
+	 * RRC = rear right center
+	 * LFE = low frequency effect
+	 */
+
+	/* Read first then write because it is bundled with other controls */
+	audio_info_ctrl_reg = DSS_REG_R(io, HDMI_INFOFRAME_CTRL0);
+
+	if (enabled) {
+		switch (num_of_channels) {
+		case MSM_HDMI_AUDIO_CHANNEL_2:
+			channel_allocation = 0;	/* Default to FR, FL */
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_4:
+			channel_count = 3;
+			/* FC, LFE, FR, FL */
+			channel_allocation = 0x3;
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_6:
+			channel_count = 5;
+			/* RR, RL, FC, LFE, FR, FL */
+			channel_allocation = 0xB;
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_8:
+			channel_count = 7;
+			/* FRC, FLC, RR, RL, FC, LFE, FR, FL */
+			channel_allocation = 0x1f;
+			break;
+		default:
+			DEV_ERR("%s: Unsupported num_of_channels = %u\n",
+				__func__, num_of_channels);
+			return -EINVAL;
+		}
+
+		/* Program the Channel-Speaker allocation */
+		audio_info_1_reg = 0;
+		/* CA(channel_allocation) */
+		audio_info_1_reg |= channel_allocation & 0xff;
+		/* Program the Level shifter */
+		audio_info_1_reg |= (level_shift << 11) & 0x00007800;
+		/* Program the Down-mix Inhibit Flag */
+		audio_info_1_reg |= (down_mix << 15) & 0x00008000;
+
+		DSS_REG_W(io, HDMI_AUDIO_INFO1, audio_info_1_reg);
+
+		/*
+		 * Calculate CheckSum: Sum of all the bytes in the
+		 * Audio Info Packet (See table 8.4 in HDMI spec)
+		 */
+		check_sum = 0;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
+		check_sum += 0x84;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
+		check_sum += 1;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
+		check_sum += 0x0A;
+		check_sum += channel_count;
+		check_sum += channel_allocation;
+		/* See Table 8.5 in HDMI spec */
+		check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
+		check_sum &= 0xFF;
+		check_sum = (u8) (256 - check_sum);
+
+		audio_info_0_reg = 0;
+		/* CHECKSUM(check_sum) */
+		audio_info_0_reg |= check_sum & 0xff;
+		/* CC(channel_count) */
+		audio_info_0_reg |= (channel_count << 8) & 0x00000700;
+
+		DSS_REG_W(io, HDMI_AUDIO_INFO0, audio_info_0_reg);
+
+		/*
+		 * Set these flags
+		 * AUDIO_INFO_UPDATE |
+		 * AUDIO_INFO_SOURCE |
+		 * AUDIO_INFO_CONT   |
+		 * AUDIO_INFO_SEND
+		 */
+		audio_info_ctrl_reg |= 0x000000F0;
+	} else {
+		/*Clear these flags
+		 * ~(AUDIO_INFO_UPDATE |
+		 *   AUDIO_INFO_SOURCE |
+		 *   AUDIO_INFO_CONT   |
+		 *   AUDIO_INFO_SEND)
+		 */
+		audio_info_ctrl_reg &= ~0x000000F0;
+	}
+	DSS_REG_W(io, HDMI_INFOFRAME_CTRL0, audio_info_ctrl_reg);
+
+	dss_reg_dump(io->base, io->len, "HDMI-AUDIO-ON: ", REG_DUMP);
+
+	return 0;
+} /* hdmi_tx_audio_info_setup */
+
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc = 0;
+	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+	if (rc) {
+		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = hdmi_tx_audio_info_setup(hdmi_ctrl, true, channels, 0, 0, false);
+	if (rc) {
+		DEV_ERR("%s: hdmi_tx_audio_info_setup failed. rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	DEV_INFO("HDMI Audio: Enabled\n");
+
+	return 0;
+} /* hdmi_tx_audio_setup */
+
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int i;
+	u32 audio_pkt_ctrl, audio_cfg;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return;
+	}
+
+	/* Number of wait iterations */
+	i = 10;
+	do {
+		audio_pkt_ctrl = DSS_REG_R_ND(io, HDMI_AUDIO_PKT_CTRL);
+		audio_cfg = DSS_REG_R_ND(io, HDMI_AUDIO_CFG);
+		DEV_DBG("%s: i=%d, AUDIO PACKET=%08x, AUDIO CFG=%08x",
+			__func__, i, audio_pkt_ctrl, audio_cfg);
+		msleep(20);
+	} while (((audio_pkt_ctrl & BIT(0)) || (audio_cfg & BIT(0))) && i--);
+
+	if (hdmi_tx_audio_info_setup(hdmi_ctrl, false, 0, 0, 0, false))
+		DEV_ERR("%s: hdmi_tx_audio_info_setup failed.\n", __func__);
+
+	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
+
+	DEV_INFO("HDMI Audio: Disabled\n");
+} /* hdmi_tx_audio_off */
+
 static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
@@ -1290,8 +1652,6 @@
 		return -EINVAL;
 	}
 
-	/* todo: Audio */
-
 	hdmi_tx_set_mode(hdmi_ctrl, false);
 	hdmi_tx_init_phy(hdmi_ctrl);
 	DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
@@ -1299,7 +1659,21 @@
 	hdmi_tx_set_mode(hdmi_ctrl, true);
 
 	hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution);
-	/* todo: Audio */
+
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+		rc = hdmi_tx_audio_setup(hdmi_ctrl);
+		if (rc) {
+			DEV_ERR("%s: hdmi_msm_audio_setup failed. rc=%d\n",
+				__func__, rc);
+			hdmi_tx_set_mode(hdmi_ctrl, false);
+			return rc;
+		}
+
+		switch_set_state(&hdmi_ctrl->audio_sdev, 1);
+		DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+			hdmi_ctrl->audio_sdev.state);
+	}
+
 	hdmi_tx_set_avi_infoframe(hdmi_ctrl);
 	/* todo: CONFIG_FB_MSM_HDMI_3D */
 	hdmi_tx_set_spd_infoframe(hdmi_ctrl);
@@ -1324,8 +1698,16 @@
 		return -EINVAL;
 	}
 
-	DEV_INFO("%s: power: OFF (audio off, Reset Core)\n", __func__);
-	/* todo: Audio */
+	DEV_INFO("%s: HDMI Core: OFF\n", __func__);
+
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+		switch_set_state(&hdmi_ctrl->audio_sdev, 0);
+		DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+			hdmi_ctrl->audio_sdev.state);
+
+		hdmi_tx_audio_off(hdmi_ctrl);
+	}
+
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
 	hdmi_ctrl->panel_power_on = false;
 	hdmi_tx_core_off(hdmi_ctrl);
@@ -1546,6 +1928,7 @@
 	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID])
 		hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
 
+	switch_dev_unregister(&hdmi_ctrl->audio_sdev);
 	switch_dev_unregister(&hdmi_ctrl->sdev);
 	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 	if (hdmi_ctrl->workq)
@@ -1581,6 +1964,7 @@
 	hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
 	if (!hdmi_ctrl->workq) {
 		DEV_ERR("%s: hdmi_tx_workq creation failed.\n", __func__);
+		rc = -EPERM;
 		goto fail_create_workq;
 	}
 
@@ -1594,14 +1978,27 @@
 	hdmi_ctrl->hpd_state_timer.data = (u32)hdmi_ctrl;
 	hdmi_ctrl->hpd_state_timer.expires = 0xffffffffL;
 
+	hdmi_ctrl->audio_sample_rate = HDMI_SAMPLE_RATE_48KHZ;
+
 	hdmi_ctrl->sdev.name = "hdmi";
 	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
 		DEV_ERR("%s: Hdmi switch registration failed\n", __func__);
+		rc = -ENODEV;
 		goto fail_switch_dev;
 	}
 
+	hdmi_ctrl->audio_sdev.name = "hdmi_audio";
+	if (switch_dev_register(&hdmi_ctrl->audio_sdev) < 0) {
+		DEV_ERR("%s: hdmi_audio switch registration failed\n",
+			__func__);
+		rc = -ENODEV;
+		goto fail_audio_switch_dev;
+	}
+
 	return 0;
 
+fail_audio_switch_dev:
+	switch_dev_unregister(&hdmi_ctrl->sdev);
 fail_switch_dev:
 	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 fail_create_workq:
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 94e0fda..437f681 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -41,9 +41,12 @@
 	struct hdmi_tx_platform_data pdata;
 	struct mdss_panel_data panel_data;
 
+	int audio_sample_rate;
+
 	struct mutex mutex;
 	struct kobject *kobj;
 	struct switch_dev sdev;
+	struct switch_dev audio_sdev;
 	struct workqueue_struct *workq;
 
 	uint32_t video_resolution;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index d94bc5b..2c41ab4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -274,8 +274,8 @@
 		}
 		vidc_sm_get_profile_info(&ddl->shared_mem
 			[ddl->command_channel], &disp_profile_info);
-		disp_profile_info.pic_profile = seq_hdr_info.profile;
-		disp_profile_info.pic_level = seq_hdr_info.level;
+		seq_hdr_info.profile = disp_profile_info.pic_profile;
+		seq_hdr_info.level = disp_profile_info.pic_level;
 		ddl_get_dec_profile_level(decoder, seq_hdr_info.profile,
 			seq_hdr_info.level);
 		switch (decoder->codec.codec) {
@@ -493,6 +493,7 @@
 				ddl_get_state_string(ddl->client_state));
 			ddl_calc_core_proc_time(__func__, DEC_OP_TIME, ddl);
 			ddl_reset_core_time_variables(DEC_OP_TIME);
+			ddl_vidc_decode_reset_avg_time(ddl);
 			ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
 			ddl_vidc_decode_frame_run(ddl);
 			ret_status = false;
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 5b07403..98cce5b 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -445,3 +445,4 @@
 header-y += genlock.h
 header-y += msm_audio_amrwb.h
 header-y += coresight-stm.h
+header-y += ci-bridge-spi.h
\ No newline at end of file
diff --git a/include/linux/ci-bridge-spi.h b/include/linux/ci-bridge-spi.h
new file mode 100644
index 0000000..1e531db
--- /dev/null
+++ b/include/linux/ci-bridge-spi.h
@@ -0,0 +1,17 @@
+#ifndef _CI_BRIDGE_SPI_H_
+#define _CI_BRIDGE_SPI_H_
+
+#include <linux/ioctl.h>
+
+#define CI_BRIDGE_IOCTL_MAGIC 'c'
+#define CI_BRIDGE_IOCTL_RESET         _IOW(CI_BRIDGE_IOCTL_MAGIC, 0, unsigned)
+#define CI_BRIDGE_IOCTL_GET_INT_STATE _IOR(CI_BRIDGE_IOCTL_MAGIC, 1, unsigned)
+
+#ifdef __KERNEL__
+struct ci_bridge_platform_data {
+	unsigned int reset_pin;
+	unsigned int interrupt_pin;
+};
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 60fa04e..bb5f394 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -42,6 +42,7 @@
 #define DIAG_IOCTL_DCI_SUPPORT		22
 #define DIAG_IOCTL_DCI_REG		23
 #define DIAG_IOCTL_DCI_STREAM_INIT	24
+#define DIAG_IOCTL_DCI_HEALTH_STATS	25
 
 /* PC Tools IDs */
 #define APQ8060_TOOLS_ID	4062
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 5f2fe9f..ba70c96 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -127,6 +127,15 @@
  *					soc stored in a coincell backed register
  */
 void pm8921_bms_invalidate_shutdown_soc(void);
+
+/**
+ * pm8921_bms_cc_uah -	function to get the coulomb counter based charge. Note
+ *			that the coulomb counter are reset when the current
+ *			consumption is low (below 8mA for more than 5 minutes),
+ *			This will lead in a very low coulomb counter charge
+ *			value upon wakeup from sleep.
+ */
+int pm8921_bms_cc_uah(int *cc_uah);
 #else
 static inline int pm8921_bms_get_vsense_avg(int *result)
 {
@@ -165,6 +174,10 @@
 static inline void pm8921_bms_invalidate_shutdown_soc(void)
 {
 }
+static inline int pm8921_bms_cc_uah(int *cc_uah)
+{
+	return -ENXIO;
+}
 #endif
 
 #endif
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index c1ea490..ec043dd 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -39,8 +39,10 @@
 	ION_CP_MFC_HEAP_ID = 12,
 	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
 	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+	ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
 	ION_SF_HEAP_ID = 24,
 	ION_IOMMU_HEAP_ID = 25,
+	ION_PIL2_HEAP_ID = 26, /* Currently used for modem firmware images */
 	ION_QSECOM_HEAP_ID = 27,
 	ION_AUDIO_HEAP_ID = 28,
 
@@ -86,6 +88,8 @@
 #define ION_MFC_HEAP_NAME	"mfc"
 #define ION_WB_HEAP_NAME	"wb"
 #define ION_MM_FIRMWARE_HEAP_NAME	"mm_fw"
+#define ION_PIL1_HEAP_NAME  "pil_1"
+#define ION_PIL2_HEAP_NAME  "pil_2"
 #define ION_QSECOM_HEAP_NAME	"qsecom"
 #define ION_FMEM_HEAP_NAME	"fmem"
 
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
index 1894f42..4c1b7a0 100644
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -41,6 +41,7 @@
 	unsigned	big_endian_mmio:1;
 	unsigned	port_power_on:1;
 	unsigned	port_power_off:1;
+	unsigned	pool_64_bit_align:1;
 };
 
 #endif /* __USB_CORE_EHCI_PDRIVER_H */
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index 02d69ea..f5c2d13 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -88,6 +88,7 @@
 #define SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK ((__u32) 0x00000014)
 #define SND_AUDIOCODEC_PASS_THROUGH          ((__u32) 0x00000015)
 #define SND_AUDIOCODEC_MP2                   ((__u32) 0x00000016)
+#define SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH  ((__u32) 0x00000017)
 /*
  * Profile and modes are listed with bit masks. This allows for a
  * more compact representation of fields that will not evolve
diff --git a/mm/Kconfig b/mm/Kconfig
index 84489cd..4cde97f 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -379,3 +379,14 @@
 	  in a negligible performance hit.
 
 	  If unsure, say Y to enable cleancache
+
+config MEMORY_HOLE_CARVEOUT
+        bool
+        help
+          MEMORY_HOLE_CARVEOUT is needed to include the msm_mem_hole driver
+          which is needed to enable/disable memblock-remove features for
+          device tree nodes that set compatible="qcom,msm-mem-hole". The
+          corresponding device tree node provides the address and size of
+          the memory corresponding to the hole to be removed using memblock-
+          remove.
+
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 8202982..eeabb78 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -382,6 +382,7 @@
 		break;
 	case SND_AUDIOCODEC_AC3_PASS_THROUGH:
 	case SND_AUDIOCODEC_DTS_PASS_THROUGH:
+	case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH:
 		pr_debug("compressd playback, no need to send decoder params");
 		pr_debug("decoder id: %d\n",
 			compr->info.codec_param.codec.id);
@@ -675,7 +676,7 @@
 {
 	pr_debug("%s\n", __func__);
 	/* MP3 Block */
-	compr->info.compr_cap.num_codecs = 13;
+	compr->info.compr_cap.num_codecs = 14;
 	compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
 	compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
 	compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
@@ -693,6 +694,7 @@
 	compr->info.compr_cap.codecs[10] = SND_AUDIOCODEC_PASS_THROUGH;
 	compr->info.compr_cap.codecs[11] = SND_AUDIOCODEC_PCM;
 	compr->info.compr_cap.codecs[12] = SND_AUDIOCODEC_MP2;
+	compr->info.compr_cap.codecs[13] = SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH;
 	/* Add new codecs here and update num_codecs*/
 }
 
@@ -812,18 +814,19 @@
 	compressed_audio.prtd = NULL;
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
-	if ((compr->info.codec_param.codec.id !=
-			SND_AUDIOCODEC_AC3_PASS_THROUGH) &&
-			(compr->info.codec_param.codec.id !=
-			SND_AUDIOCODEC_DTS_PASS_THROUGH))
+	switch (compr->info.codec_param.codec.id) {
+	case SND_AUDIOCODEC_AC3_PASS_THROUGH:
+	case SND_AUDIOCODEC_DTS_PASS_THROUGH:
+	case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH:
+		msm_pcm_routing_reg_psthr_stream(
+			soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream,
+			0);
+	default:
 		msm_pcm_routing_dereg_phy_stream(
 			soc_prtd->dai_link->be_id,
 			SNDRV_PCM_STREAM_PLAYBACK);
-	else
-		msm_pcm_routing_reg_psthr_stream(
-					soc_prtd->dai_link->be_id,
-					prtd->session_id, substream->stream,
-					0);
+	}
 	q6asm_audio_client_free(prtd->audio_client);
 	kfree(prtd);
 	return 0;
@@ -941,6 +944,7 @@
 		switch (compr->info.codec_param.codec.id) {
 		case SND_AUDIOCODEC_AC3_PASS_THROUGH:
 		case SND_AUDIOCODEC_DTS_PASS_THROUGH:
+		case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH:
 			ret = q6asm_open_write_compressed(prtd->audio_client,
 					compr->codec);
 
@@ -1139,6 +1143,10 @@
 			pr_debug("SND_AUDIOCODEC_DTS_PASS_THROUGH\n");
 			compr->codec = FORMAT_DTS;
 			break;
+		case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH:
+			pr_debug("SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH\n");
+			compr->codec = FORMAT_DTS_LBR;
+			break;
 		case SND_AUDIOCODEC_DTS: {
 			char modelId[128];
 			struct snd_dec_dts opt_dts =
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index bd4a521..6cad0af 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -236,6 +236,11 @@
 			}
 			atomic_set(&prtd->start, 1);
 			break;
+		case ASM_STREAM_CMD_FLUSH:
+			pr_debug("ASM_STREAM_CMD_FLUSH\n");
+			prtd->cmd_ack = 1;
+			wake_up(&the_locks.flush_wait);
+			break;
 		default:
 			break;
 		}
@@ -800,13 +805,52 @@
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 	return 0;
 }
+static int msm_pcm_ioctl(struct snd_pcm_substream *substream,
+			unsigned int cmd, void *arg)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct msm_audio *prtd = runtime->private_data;
+	int ret = 0, rc;
+
+	pr_debug("%s\n", __func__);
+	ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+	if (ret < 0) {
+		pr_err("%s, snd_pcm_lib_ioctl error\n", __func__);
+		return ret;
+	}
+
+	switch (cmd) {
+	case SNDRV_PCM_IOCTL1_RESET:
+		pr_debug("%s, SNDRV_PCM_IOCTL1_RESET\n", __func__);
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			prtd->cmd_ack = 0;
+			rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
+			if (rc < 0) {
+				pr_err("%s: flush cmd failed rc=%d\n",
+					 __func__, rc);
+				break;
+			}
+			rc = wait_event_timeout(the_locks.flush_wait,
+				 prtd->cmd_ack, 5 * HZ);
+			if (rc < 0)
+				pr_err("Flush cmd timeout\n");
+			prtd->pcm_irq_pos = 0;
+			atomic_set(&prtd->out_count, runtime->periods);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
 
 static struct snd_pcm_ops msm_pcm_ops = {
 	.open           = msm_pcm_open,
 	.copy		= msm_pcm_copy,
 	.hw_params	= msm_pcm_hw_params,
 	.close          = msm_pcm_close,
-	.ioctl          = snd_pcm_lib_ioctl,
+	.ioctl          = msm_pcm_ioctl,
 	.prepare        = msm_pcm_prepare,
 	.trigger        = msm_pcm_trigger,
 	.pointer        = msm_pcm_pointer,
@@ -894,6 +938,7 @@
 	init_waitqueue_head(&the_locks.eos_wait);
 	init_waitqueue_head(&the_locks.write_wait);
 	init_waitqueue_head(&the_locks.read_wait);
+	init_waitqueue_head(&the_locks.flush_wait);
 
 	return platform_driver_register(&msm_pcm_driver);
 }
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index b3db9e1..08cd06c 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -788,6 +788,18 @@
 	return 0;
 }
 
+static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
 static int msm8930_aux_pcm_get_gpios(void)
 {
 	int ret = 0;
@@ -1195,6 +1207,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
 	},
 	{
@@ -1206,6 +1219,7 @@
 		.codec_dai_name = "msm-stub-tx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+		.be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
 	},
 	/* AUX PCM Backend DAI Links */
 	{
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 7e70d02..b7d5d33 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -896,10 +896,11 @@
 		case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
 			if (atomic_read(&ac->cmd_state) && wakeup_flag) {
 				atomic_set(&ac->cmd_state, 0);
+				pr_debug("response payload[1]:%d",
+							payload[1]);
 				if (payload[1] == ADSP_EUNSUPPORTED ||
+					payload[1] == ADSP_EBADPARAM ||
 					payload[1] == ADSP_EFAILED) {
-					pr_debug("payload[1]:%d unsupported",
-								payload[1]);
 					atomic_set(&ac->cmd_response, 1);
 				}
 				else
@@ -1485,6 +1486,10 @@
 			rc);
 		goto fail_cmd;
 	}
+	if (atomic_read(&ac->cmd_response)) {
+		pr_err("%s: format = %x not supported\n", __func__, format);
+		goto fail_cmd;
+	}
 	return 0;
 fail_cmd:
 	return -EINVAL;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index af1e19c..1e6fc04 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -297,6 +297,7 @@
 static int msm_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd;
 	int ret = 0;
 
@@ -314,8 +315,25 @@
 		kfree(prtd);
 		return -ENOMEM;
 	}
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		runtime->hw = msm_pcm_hardware_playback;
+		ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
+		if (ret < 0) {
+			pr_err("%s: pcm out open failed\n", __func__);
+			q6asm_audio_client_free(prtd->audio_client);
+			kfree(prtd);
+			return -ENOMEM;
+		}
+
+		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,
+			prtd->session_id, substream->stream);
+		prtd->cmd_ack = 1;
+
+	}
+	/* Capture path */
 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		runtime->hw = msm_pcm_hardware_capture;
 	else {
@@ -601,25 +619,15 @@
 	struct audio_buffer *buf;
 	int dir, ret;
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dir = IN;
-		pr_debug("%s Opening %d-ch PCM Write stream\n",
-			__func__, params_channels(params));
-
-		ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
-		if (ret < 0) {
-			pr_err("%s: pcm out open failed\n", __func__);
-			q6asm_audio_client_free(prtd->audio_client);
-			kfree(prtd);
-			return -ENOMEM;
-		}
-	} else {
+	else {
 		dir = OUT;
 		pr_debug("%s Opening %d-ch PCM read stream\n",
 			__func__, params_channels(params));
 		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
 		if (ret < 0) {
-			pr_err("%s: pcm in open failed\n", __func__);
+			pr_err("%s: q6asm_open_read failed\n", __func__);
 			q6asm_audio_client_free(prtd->audio_client);
 			prtd->audio_client = NULL;
 			return -ENOMEM;
@@ -631,10 +639,7 @@
 	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
 			prtd->session_id, substream->stream);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		prtd->cmd_ack = 1;
 
-	pr_debug("%s: before buf alloc\n", __func__);
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 			prtd->audio_client,
 			runtime->hw.period_bytes_min,
@@ -644,7 +649,6 @@
 							ret);
 		return -ENOMEM;
 	}
-	pr_debug("%s: after buf alloc\n", __func__);
 	buf = prtd->audio_client->port[dir].buf;
 	if (buf == NULL || buf[0].data == NULL)
 		return -ENOMEM;