Merge "usb: xhci: Add support for SINGLE_STEP_SET_FEATURE test of EHSET" into msm-3.4
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 70bf993..e724c62 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -65,6 +65,14 @@
   5 (2^5 = 32)   32 micro frame interrupt threshold aka 4ms interrupt threshold
   6 (2^6 = 64)   64 micro frame interrupt threshold aka 8ms interrupt threshold
 
+- hsic,disable-cerr: CERR is 2bit down error counter that keeps track of number
+  of consecutive errors detected on single usb transaction. When set to non
+  zero value, hw decrements the count and updates qTD when transaction fails.
+  If counter reaches zero, hw marks the qTD inactive and triggers the interrupt.
+  When CERR is programmed to zero, hw ignores transaction failures. ECHI stack
+  programs the CERR  to 3 by default. When this flag is true, CERR is set to
+  zero and transaction errors are ignored.
+
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
     - qcom,msm_bus,name
diff --git a/arch/arm/boot/dts/apq8084-coresight.dtsi b/arch/arm/boot/dts/apq8084-coresight.dtsi
new file mode 100644
index 0000000..610d80b
--- /dev/null
+++ b/arch/arm/boot/dts/apq8084-coresight.dtsi
@@ -0,0 +1,145 @@
+/* Copyright (c) 2013, 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.
+ */
+
+&soc {
+	tmc_etr: tmc@fc326000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc326000 0x1000>,
+		      <0xfc37c000 0x3000>;
+		reg-names = "tmc-base", "bam-base";
+
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+	};
+
+	replicator: replicator@fc324000 {
+		compatible = "qcom,coresight-replicator";
+		reg = <0xfc324000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-id = <2>;
+		coresight-name = "coresight-replicator";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etr>;
+		coresight-child-ports = <0>;
+	};
+
+	tmc_etf: tmc@fc325000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc325000 0x1000>;
+		reg-names = "tmc-base";
+
+		coresight-id = <3>;
+		coresight-name = "coresight-tmc-etf";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&replicator>;
+		coresight-child-ports = <0>;
+		coresight-default-sink;
+	};
+
+	funnel_merg: funnel@fc323000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc323000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-merg";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in0: funnel@fc321000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc321000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in1: funnel@fc322000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc322000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <6>;
+		coresight-name = "coresight-funnel-in1";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <1>;
+	};
+
+	funnel_kpss: funnel@fc355000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc355000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <7>;
+		coresight-name = "coresight-funnel-kpss";
+		coresight-nr-inports = <4>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <5>;
+	};
+
+	funnel_mmss: funnel@fc36c000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc36c000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <8>;
+		coresight-name = "coresight-funnel-mmss";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <1>;
+	};
+
+	stm: stm@fc302000 {
+		compatible = "arm,coresight-stm";
+		reg = <0xfc302000 0x1000>,
+		      <0xfa280000 0x180000>;
+		reg-names = "stm-base", "stm-data-base";
+
+		coresight-id = <9>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <7>;
+	};
+
+	csr: csr@fc301000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0xfc301000 0x1000>;
+		reg-names = "csr-base";
+
+		coresight-id = <14>;
+		coresight-name = "coresight-csr";
+		coresight-nr-inports = <0>;
+
+		qcom,blk-size = <3>;
+	};
+};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index e5f083a..80b6ffa 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -21,6 +21,7 @@
 
 /include/ "apq8084-ion.dtsi"
 /include/ "apq8084-smp2p.dtsi"
+/include/ "apq8084-coresight.dtsi"
 
 &soc {
 	#address-cells = <1>;
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index e8674a0..2eaa32f 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -210,6 +210,41 @@
 		qcom,pet-time = <10000>;
 		qcom,ipi-ping;
 	};
+
+	qcom,ocmem@fdd00000 {
+		compatible = "qcom,msm-ocmem";
+		reg = <0xfdd00000 0x2000>,
+		      <0xfdd02000 0x2000>,
+		      <0xfe070000 0x400>,
+		      <0xfec00000 0x180000>;
+		reg-names = "ocmem_ctrl_physical", "dm_ctrl_physical", "br_ctrl_physical", "ocmem_physical";
+		interrupts = <0 76 0>, <0 77 0>;
+		interrupt-names = "ocmem_irq", "dm_irq";
+		qcom,ocmem-num-regions = <0x3>;
+		qcom,ocmem-num-macros = <0x18>;
+		qcom,resource-type = <0x706d636f>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0xfec00000 0x180000>;
+
+		partition@0 {
+			reg = <0x0 0x100000>;
+			qcom,ocmem-part-name = "graphics";
+			qcom,ocmem-part-min = <0x80000>;
+		};
+
+		partition@80000 {
+			reg = <0x100000 0x80000>;
+			qcom,ocmem-part-name = "lp_audio";
+			qcom,ocmem-part-min = <0x80000>;
+		};
+
+		partition@100000 {
+			reg = <0x100000 0x80000>;
+			qcom,ocmem-part-name = "video";
+			qcom,ocmem-part-min = <0x55000>;
+		};
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 7b45194..4a2c57c 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -65,11 +65,11 @@
 			interrupts = <81 0x2>;
 			vdd-supply = <&pm8110_l19>;
 			vio-supply = <&pm8110_l14>;
-			kionix,min_interval = <5>;
-			kionix,init_interval = <200>;
-			kionix,axis_map_x = <1>;
-			kionix,axis_map_y = <0>;
-			kionix,axis_map_z = <2>;
+			kionix,min-interval = <5>;
+			kionix,init-interval = <200>;
+			kionix,axis-map-x = <1>;
+			kionix,axis-map-y = <0>;
+			kionix,axis-map-z = <2>;
 			kionix,g-range = <2>;
 			kionix,negate-x;
 			kionix,negate-y;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 2a60df4..6937385 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -48,6 +48,7 @@
 			atmel,i2c-pull-up;
 			atmel,no-force-update;
 			atmel,cfg_1 {
+				atmel,fw-name = "atmel_8974_fluid_v1_0_AA.hex";
 				atmel,family-id = <0x82>;
 				atmel,variant-id = <0x19>;
 				atmel,version = <0x10>;
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 3d2308d..638e6dd 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -43,6 +43,7 @@
 			atmel,i2c-pull-up;
 			atmel,no-force-update;
 			atmel,cfg_1 {
+				atmel,fw-name = "atmel_8974_fluid_v1_0_AA.hex";
 				atmel,family-id = <0x82>;
 				atmel,variant-id = <0x19>;
 				atmel,version = <0x10>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 28111fa..4af48cc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -43,6 +43,7 @@
 			atmel,i2c-pull-up;
 			atmel,no-force-update;
 			atmel,cfg_1 {
+				atmel,fw-name = "atmel_8974_fluid_v1_0_AA.hex";
 				atmel,family-id = <0x82>;
 				atmel,variant-id = <0x19>;
 				atmel,version = <0x10>;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 7c191fc..d9d5aaa 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -468,6 +468,7 @@
 		#size-cells = <1>;
 		ranges;
 		qcom,pfm-threshold = <73>;
+		qcom,use-phase-scaling-factor;
 
 		krait0_vreg: regulator@f9088000 {
 			compatible = "qcom,krait-regulator";
diff --git a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
new file mode 100644
index 0000000..74bd23d
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-cdp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974Pro CDP";
+	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
+	qcom,msm-id = <209 1 0x10000>,
+		      <211 1 0x10000>,
+		      <212 1 0x10000>,
+		      <214 1 0x10000>,
+		      <215 1 0x10000>,
+		      <217 1 0x10000>,
+		      <218 1 0x10000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-fluid.dts b/arch/arm/boot/dts/msm8974pro-ab-fluid.dts
new file mode 100644
index 0000000..9a31834
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ab-fluid.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-fluid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974Pro FLUID";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+	qcom,msm-id = <209 3 0x10000>,
+		      <211 3 0x10000>,
+		      <212 3 0x10000>,
+		      <214 3 0x10000>,
+		      <215 3 0x10000>,
+		      <217 3 0x10000>,
+		      <218 3 0x10000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-liquid.dts b/arch/arm/boot/dts/msm8974pro-ab-liquid.dts
new file mode 100644
index 0000000..0ec9d8a
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ab-liquid.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-liquid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974Pro LIQUID";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
+	qcom,msm-id = <209 9 0x10000>,
+		      <211 9 0x10000>,
+		      <212 9 0x10000>,
+		      <214 9 0x10000>,
+		      <215 9 0x10000>,
+		      <217 9 0x10000>,
+		      <218 9 0x10000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
new file mode 100644
index 0000000..002baf7
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974-mtp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974Pro MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+	qcom,msm-id = <209 8 0x10000>,
+		      <211 8 0x10000>,
+		      <212 8 0x10000>,
+		      <214 8 0x10000>,
+		      <215 8 0x10000>,
+		      <217 8 0x10000>,
+		      <218 8 0x10000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab.dtsi b/arch/arm/boot/dts/msm8974pro-ab.dtsi
new file mode 100644
index 0000000..9240514
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ab.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/*
+ * As a general rule, only chipset-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi / msm8974pro.dtsi file(s).
+ */
+
+/include/ "msm8974pro.dtsi"
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
new file mode 100644
index 0000000..c5042b7
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
@@ -0,0 +1,25 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974pro-ac.dtsi"
+/include/ "msm8974-mtp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974Pro-AC MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+	qcom,msm-id = <194 8 0x10000>,
+		      <210 8 0x10000>,
+		      <213 8 0x10000>,
+		      <216 8 0x10000>;
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
new file mode 100644
index 0000000..9240514
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/*
+ * As a general rule, only chipset-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi / msm8974pro.dtsi file(s).
+ */
+
+/include/ "msm8974pro.dtsi"
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
new file mode 100644
index 0000000..96e78ac
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -0,0 +1,138 @@
+/* Copyright (c) 2013, 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974.dtsi"
+/include/ "msm8974-v2-iommu.dtsi"
+/include/ "msm8974-v2-iommu-domains.dtsi"
+/include/ "msm8974-v2-pm.dtsi"
+
+&soc {
+	android_usb@fe8050c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
+	};
+
+	qcom,msm-imem@fe805000 {
+		compatible = "qcom,msm-imem";
+		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
+	};
+};
+
+/* GPU overrides */
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x03030001>;
+
+	/* Updated bus bandwidth requirements */
+	qcom,msm-bus,vectors-KBps =
+		/* Off */
+		<26 512 0 0>, <89 604 0 0>,
+		/* SVS */
+		<26 512 0 2400000>, <89 604 0 3000000>,
+		/* Nominal / SVS */
+		<26 512 0 4656000>, <89 604 0 3000000>,
+		/* Nominal */
+		<26 512 0 4656000>, <89 604 0 5120000>,
+		/* Turbo / Nominal */
+		<26 512 0 7464000>, <89 604 0 5120000>,
+		/* Turbo */
+		<26 512 0 7464000>, <89 604 0 6400000>;
+};
+
+&mdss_mdp {
+	qcom,vbif-settings = <0x0004 0x00000001>;
+
+	qcom,mdss-wb-off = <0x00011100 0x00011500
+			    0x00011900 0x00011D00 0x00012100>;
+	qcom,mdss-intf-off = <0x00012500 0x00012700
+			      0x00012900 0x00012b00>;
+	qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
+	qcom,mdss-has-bwc;
+	qcom,mdss-has-decimation;
+	qcom,mdss-ad-off = <0x0013100 0x00013300>;
+};
+
+&mdss_hdmi_tx {
+	reg =	<0xfd922100 0x370>,
+		<0xfd922500 0x7C>,
+		<0xfc4b8000 0x60F0>;
+	reg-names = "core_physical", "phy_physical", "qfprom_physical";
+};
+
+&msm_vidc {
+	qcom,vidc-ns-map = <0x40000000 0x40000000>;
+	qcom,load-freq-tbl = <979200 465000000>,
+		<783360 465000000>,
+		<489600 266670000>,
+		<244800 133330000>;
+	qcom,reg-presets = <0x80004 0x1>,
+		<0x80070 0x11FFF>,
+		<0x80074 0xA4>,
+		<0x800A8 0x1FFF>,
+		<0x80124 0x3>,
+		<0xE0020 0x5555556>,
+		<0xE0024 0x0>;
+	qcom,bus-ports = <1>;
+	qcom,enc-ocmem-ab-ib = <0 0>,
+		<138000 1034000>,
+		<414000 1034000>,
+		<940000 1034000>,
+		<1880000 2068000>,
+		<3008000 3309000>,
+		<3760000 4136000>,
+		<4468000 2457000>;
+	qcom,dec-ocmem-ab-ib = <0 0>,
+		<176000 519000>,
+		<456000 519000>,
+		<864000 519000>,
+		<1728000 1038000>,
+		<2766000 1661000>,
+		<3456000 2076000>,
+		<3662000 2198000>;
+	qcom,enc-ddr-ab-ib = <0 0>,
+		<120000 302000>,
+		<364000 302000>,
+		<804000 302000>,
+		<1608000 604000>,
+		<2576000 967000>,
+		<4680000 1404000>,
+		<49880000 1496000>;
+	qcom,dec-ddr-ab-ib = <0 0>,
+		<208000 303000>,
+		<536000 303000>,
+		<1012000 303000>,
+		<2024000 606000>,
+		<3240000 970000>,
+		<4048000 1212000>,
+		<4264000 1279000>;
+	qcom,iommu-groups = <&venus_domain_ns &venus_domain_sec_bitstream
+			&venus_domain_sec_pixel &venus_domain_sec_non_pixel>;
+	qcom,iommu-group-buffer-types = <0xfff 0x91 0x42 0x120>;
+	qcom,buffer-type-tz-usage-table = <0x91 0x1>,
+					<0x42 0x2>,
+					<0x120 0x3>;
+};
+
+&krait_pdn {
+	qcom,use-phase-switching;
+};
+
+&tspp {
+	vdd_cx-supply = <&pm8841_s2_corner>;
+};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 616995f..dda32ce 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -195,6 +195,7 @@
 		hsic,consider-ipa-handshake;
 		hsic,log2-itc = <3>;
 		qcom,ahb-async-bridge-bypass;
+		hsic,disable-cerr;
 	};
 
 	qcom,usbbam@f9a44000 {
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 9cd37d1..2965607 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -399,3 +399,8 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 07f7ed9..010bc10 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -384,3 +384,4 @@
 CONFIG_CRC_CCITT=y
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
+CONFIG_SENSORS_STK3X1X=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 34c0905..7225ec5 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -427,3 +427,4 @@
 CONFIG_CRC_CCITT=y
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
+CONFIG_SENSORS_STK3X1X=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 17db01e..300b2da 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -87,7 +87,7 @@
 obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V4) += pil-q6v4.o pil-q6v4-lpass.o
 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_MSS_QDSP6V5) += pil-q6v5.o pil-msa.o pil-q6v5-mss.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
diff --git a/arch/arm/mach-msm/board-8084.c b/arch/arm/mach-msm/board-8084.c
index 7dc9a90..2a6bbb7 100644
--- a/arch/arm/mach-msm/board-8084.c
+++ b/arch/arm/mach-msm/board-8084.c
@@ -28,6 +28,7 @@
 #include <mach/restart.h>
 #include <mach/socinfo.h>
 #include <mach/clk-provider.h>
+#include <mach/msm_smem.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
@@ -84,6 +85,7 @@
  */
 void __init apq8084_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_clock_init(&msm8084_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 39efcd8..5ad6175 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -44,6 +44,7 @@
 #include <mach/msm_smd.h>
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
+#include <mach/msm_smem.h>
 #include <linux/msm_thermal.h>
 #include "board-dt.h"
 #include "clock.h"
@@ -107,6 +108,7 @@
  */
 void __init msm8226_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index b4d77f1..c6c9d14 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -45,6 +45,7 @@
 #include <mach/msm_smd.h>
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
+#include <mach/msm_smem.h>
 #include <linux/msm_thermal.h>
 #include "board-dt.h"
 #include "clock.h"
@@ -102,6 +103,7 @@
 
 void __init msm8610_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 771359c..68af757 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -40,6 +40,7 @@
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
 #include <mach/socinfo.h>
+#include <mach/msm_smem.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
@@ -91,6 +92,7 @@
  */
 void __init msm8974_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 56246dd..fad2efc 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -39,6 +39,7 @@
 #include <mach/rpm-regulator-smd.h>
 #include "board-dt.h"
 #include <mach/msm_bus_board.h>
+#include <mach/msm_smem.h>
 #include "clock.h"
 #include "modem_notifier.h"
 #include "lpm_resources.h"
@@ -231,6 +232,7 @@
  */
 void __init msm9625_add_drivers(void)
 {
+	msm_smem_init();
 	msm_init_modem_notifier_list();
 	msm_smd_init();
 	msm_rpm_driver_init();
diff --git a/arch/arm/mach-msm/board-samarium.c b/arch/arm/mach-msm/board-samarium.c
index 574c979..cfdc074 100644
--- a/arch/arm/mach-msm/board-samarium.c
+++ b/arch/arm/mach-msm/board-samarium.c
@@ -26,6 +26,7 @@
 #include <mach/restart.h>
 #include <mach/socinfo.h>
 #include <mach/clk-provider.h>
+#include <mach/msm_smem.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
@@ -95,6 +96,7 @@
  */
 void __init msmsamarium_add_drivers(void)
 {
+	msm_smem_init();
 	msm_clock_init(&msm_dummy_clock_init_data);
 }
 
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index bec9f1b4..940e24b 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -369,6 +369,27 @@
 	CLK_DUMMY("core_clk", NULL, "fe054000.qcom,iommu", OFF),
 	CLK_DUMMY("iface_clk", NULL, "fe064000.qcom,iommu", OFF),
 	CLK_DUMMY("core_clk", NULL, "fe064000.qcom,iommu", OFF),
+
+	/* CoreSight clocks */
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc326000.tmc", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc324000.replicator", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc325000.tmc", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc323000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc321000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc322000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc345000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc36c000.funnel", OFF),
+	CLK_DUMMY("core_clk", qdss_clk.c, "fc302000.stm", OFF),
+
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc326000.tmc", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc324000.replicator", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc325000.tmc", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc323000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc321000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc322000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc345000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc36c000.funnel", OFF),
+	CLK_DUMMY("core_a_clk", qdss_a_clk.c, "fc302000.stm", OFF),
 };
 
 struct clock_init_data msm8084_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 2a4617d..d48fa4a 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2857,7 +2857,6 @@
 static struct clk_freq_tbl ftbl_kpss_ahb_clk[] = {
 	F_GCC(19200000, xo_a_clk, 0, 0, 0),
 	F_GCC(37500000, gpll0, 16, 0, 0),
-	F_GCC(75000000, gpll0,  8, 0, 0),
 	F_END
 };
 
@@ -2870,7 +2869,6 @@
 	.c = {
 		.dbg_name = "kpss_ahb_clk_src",
 		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
 		CLK_INIT(kpss_ahb_clk_src.c),
 	},
 };
diff --git a/arch/arm/mach-msm/clock-generic.c b/arch/arm/mach-msm/clock-generic.c
index e66764f..bea82d5 100644
--- a/arch/arm/mach-msm/clock-generic.c
+++ b/arch/arm/mach-msm/clock-generic.c
@@ -266,6 +266,12 @@
 	if (rrate != rate)
 		return -EINVAL;
 
+	/*
+	 * For fixed divider clock we don't want to return an error if the
+	 * requested rate matches the achievable rate. So, don't check for
+	 * !d->ops and return an error. __div_round_rate() ensures div ==
+	 * d->div if !d->ops.
+	 */
 	if (div > d->div)
 		rc = d->ops->set_div(d, div);
 	if (rc)
@@ -299,7 +305,7 @@
 static int div_enable(struct clk *c)
 {
 	struct div_clk *d = to_div_clk(c);
-	if (d->ops->enable)
+	if (d->ops && d->ops->enable)
 		return d->ops->enable(d);
 	return 0;
 }
@@ -307,7 +313,7 @@
 static void div_disable(struct clk *c)
 {
 	struct div_clk *d = to_div_clk(c);
-	if (d->ops->disable)
+	if (d->ops && d->ops->disable)
 		return d->ops->disable(d);
 }
 
@@ -315,7 +321,7 @@
 {
 	struct div_clk *d = to_div_clk(c);
 
-	if (d->ops->get_div)
+	if (d->ops && d->ops->get_div)
 		d->div = max(d->ops->get_div(d), 1);
 	d->div = max(d->div, 1U);
 	c->rate = clk_get_rate(c->parent) / d->div;
@@ -389,8 +395,13 @@
 	if (div == d->div)
 		return 0;
 
-	if (d->ops->set_div)
-		rc = d->ops->set_div(d, div);
+	/*
+	 * For fixed divider clock we don't want to return an error if the
+	 * requested rate matches the achievable rate. So, don't check for
+	 * !d->ops and return an error. __slave_div_round_rate() ensures
+	 * div == d->div if !d->ops.
+	 */
+	rc = d->ops->set_div(d, div);
 	if (rc)
 		return rc;
 
diff --git a/arch/arm/mach-msm/hsic_sysmon.c b/arch/arm/mach-msm/hsic_sysmon.c
index 8270197..79fb1a3 100644
--- a/arch/arm/mach-msm/hsic_sysmon.c
+++ b/arch/arm/mach-msm/hsic_sysmon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -239,7 +239,7 @@
 		if (!hs)
 			continue;
 
-		ret += scnprintf(buf, DEBUG_BUF_SIZE,
+		ret += scnprintf(buf + ret, DEBUG_BUF_SIZE - ret,
 				"---HSIC Sysmon #%d---\n"
 				"epin:%d, epout:%d\n"
 				"bytes to host: %d\n"
@@ -324,15 +324,6 @@
 	struct usb_endpoint_descriptor	*ep_desc;
 	int				i;
 	int				ret = -ENOMEM;
-	__u8				ifc_num;
-
-	pr_debug("id:%lu", id->driver_info);
-
-	ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
-
-	/* is this the interface we're looking for? */
-	if (ifc_num != id->driver_info)
-		return -ENODEV;
 
 	hs = kzalloc(sizeof(*hs), GFP_KERNEL);
 	if (!hs) {
@@ -367,12 +358,17 @@
 		goto error;
 	}
 
-	hs->id = HSIC_SYSMON_DEV_EXT_MODEM;
-	hsic_sysmon_devices[HSIC_SYSMON_DEV_EXT_MODEM] = hs;
+	hs->id = HSIC_SYSMON_DEV_EXT_MODEM + id->driver_info;
+	if (hs->id >= NUM_HSIC_SYSMON_DEVS) {
+		pr_warn("invalid dev id(%d)", hs->id);
+		hs->id = 0;
+	}
+
+	hsic_sysmon_devices[hs->id] = hs;
 	usb_set_intfdata(ifc, hs);
 
 	hs->pdev.name = "sys_mon";
-	hs->pdev.id = SYSMON_SS_EXT_MODEM;
+	hs->pdev.id = SYSMON_SS_EXT_MODEM + hs->id;
 	hs->pdev.dev.release = hsic_sysmon_pdev_release;
 	platform_device_register(&hs->pdev);
 
@@ -406,11 +402,12 @@
 	return 0;
 }
 
-/* driver_info maps to the interface number corresponding to sysmon */
+/* driver_info is the instance number when multiple devices are present */
 static const struct usb_device_id hsic_sysmon_ids[] = {
-	{ USB_DEVICE(0x5c6, 0x9048), .driver_info = 1, },
-	{ USB_DEVICE(0x5c6, 0x904C), .driver_info = 1, },
-	{ USB_DEVICE(0x5c6, 0x9075), .driver_info = 1, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 1), .driver_info = 0, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904C, 1), .driver_info = 0, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 1), .driver_info = 0, },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9079, 1), .driver_info = 1, },
 	{} /* terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, hsic_sysmon_ids);
diff --git a/arch/arm/mach-msm/hsic_sysmon.h b/arch/arm/mach-msm/hsic_sysmon.h
index 983f464..9655dc0 100644
--- a/arch/arm/mach-msm/hsic_sysmon.h
+++ b/arch/arm/mach-msm/hsic_sysmon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013 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
@@ -18,6 +18,7 @@
  */
 enum hsic_sysmon_device_id {
 	HSIC_SYSMON_DEV_EXT_MODEM,
+	HSIC_SYSMON_DEV_EXT_MODEM_2,
 	NUM_HSIC_SYSMON_DEVS
 };
 
diff --git a/arch/arm/mach-msm/hsic_sysmon_test.c b/arch/arm/mach-msm/hsic_sysmon_test.c
index bc60c6e..fac6575 100644
--- a/arch/arm/mach-msm/hsic_sysmon_test.c
+++ b/arch/arm/mach-msm/hsic_sysmon_test.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -15,6 +15,7 @@
 
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
@@ -36,13 +37,14 @@
 				 size_t count, loff_t *ppos)
 {
 	struct sysmon_test_dev *dev = sysmon_dev;
+	enum hsic_sysmon_device_id id =
+				(enum hsic_sysmon_device_id)file->private_data;
 	int ret;
 
 	if (!dev)
 		return -ENODEV;
 
-	ret = hsic_sysmon_read(HSIC_SYSMON_DEV_EXT_MODEM, dev->buf, RD_BUF_SIZE,
-				&dev->buflen, 3000);
+	ret = hsic_sysmon_read(id, dev->buf, RD_BUF_SIZE, &dev->buflen, 3000);
 	if (!ret)
 		return simple_read_from_buffer(ubuf, count, ppos,
 					dev->buf, dev->buflen);
@@ -53,7 +55,9 @@
 static ssize_t sysmon_test_write(struct file *file, const char __user *ubuf,
 				 size_t count, loff_t *ppos)
 {
-	struct sysmon_test_dev	*dev = sysmon_dev;
+	struct sysmon_test_dev *dev = sysmon_dev;
+	enum hsic_sysmon_device_id id =
+				(enum hsic_sysmon_device_id)file->private_data;
 	int ret;
 
 	if (!dev)
@@ -64,8 +68,7 @@
 		return 0;
 	}
 
-	ret = hsic_sysmon_write(HSIC_SYSMON_DEV_EXT_MODEM,
-				dev->buf, count, 1000);
+	ret = hsic_sysmon_write(id, dev->buf, count, 1000);
 	if (ret < 0) {
 		pr_err("error writing to hsic_sysmon");
 		return ret;
@@ -76,38 +79,44 @@
 
 static int sysmon_test_open(struct inode *inode, struct file *file)
 {
-	return hsic_sysmon_open(HSIC_SYSMON_DEV_EXT_MODEM);
+	file->private_data = inode->i_private;
+	return hsic_sysmon_open((enum hsic_sysmon_device_id)inode->i_private);
 }
 
 static int sysmon_test_release(struct inode *inode, struct file *file)
 {
-	hsic_sysmon_close(HSIC_SYSMON_DEV_EXT_MODEM);
+	hsic_sysmon_close((enum hsic_sysmon_device_id)inode->i_private);
 	return 0;
 }
 
-static struct dentry *dfile;
-const struct file_operations sysmon_test_ops = {
+static const struct file_operations sysmon_test_ops = {
 	.read = sysmon_test_read,
 	.write = sysmon_test_write,
 	.open = sysmon_test_open,
 	.release = sysmon_test_release
 };
 
+static struct dentry *dfile0, *dfile1;
+
 static int __init sysmon_test_init(void)
 {
 	sysmon_dev = kzalloc(sizeof(*sysmon_dev), GFP_KERNEL);
 	if (!sysmon_dev)
 		return -ENOMEM;
 
-	dfile = debugfs_create_file("hsic_sysmon_test", 0666, NULL,
-			0, &sysmon_test_ops);
+	dfile0 = debugfs_create_file("hsic_sysmon_test.0", 0666, NULL,
+			(void *)HSIC_SYSMON_DEV_EXT_MODEM, &sysmon_test_ops);
+	dfile1 = debugfs_create_file("hsic_sysmon_test.1", 0666, NULL,
+			(void *)HSIC_SYSMON_DEV_EXT_MODEM_2, &sysmon_test_ops);
 	return 0;
 }
 
 static void __exit sysmon_test_exit(void)
 {
-	if (dfile)
-		debugfs_remove(dfile);
+	if (dfile0)
+		debugfs_remove(dfile0);
+	if (dfile1)
+		debugfs_remove(dfile1);
 	kfree(sysmon_dev);
 }
 
diff --git a/arch/arm/mach-msm/include/mach/clock-generic.h b/arch/arm/mach-msm/include/mach/clock-generic.h
index 0f689f1..f6feda0 100644
--- a/arch/arm/mach-msm/include/mach/clock-generic.h
+++ b/arch/arm/mach-msm/include/mach/clock-generic.h
@@ -72,8 +72,6 @@
 struct clk_div_ops {
 	int (*set_div)(struct div_clk *clk, int div);
 	int (*get_div)(struct div_clk *clk);
-
-	/* Optional */
 	bool (*is_enabled)(struct div_clk *clk);
 	int (*enable)(struct div_clk *clk);
 	void (*disable)(struct div_clk *clk);
@@ -84,6 +82,7 @@
 	unsigned int	min_div;
 	unsigned int	max_div;
 	unsigned long	rate_margin;
+	/* Optional */
 	struct clk_div_ops *ops;
 
 	/* Fields not used by helper function. */
diff --git a/arch/arm/mach-msm/include/mach/ipa.h b/arch/arm/mach-msm/include/mach/ipa.h
index 697de5e..b6acef2 100644
--- a/arch/arm/mach-msm/include/mach/ipa.h
+++ b/arch/arm/mach-msm/include/mach/ipa.h
@@ -648,6 +648,8 @@
 
 int a2_mux_write(enum a2_mux_logical_channel_id lcid, struct sk_buff *skb);
 
+int a2_mux_is_ch_empty(enum a2_mux_logical_channel_id lcid);
+
 int a2_mux_is_ch_low(enum a2_mux_logical_channel_id lcid);
 
 int a2_mux_is_ch_full(enum a2_mux_logical_channel_id lcid);
@@ -667,6 +669,8 @@
 
 int teth_bridge_set_aggr_params(struct teth_aggr_params *aggr_params);
 
+void ipa_bam_reg_dump(void);
+
 #else /* CONFIG_IPA */
 
 static inline int a2_mux_open_channel(enum a2_mux_logical_channel_id lcid,
@@ -686,6 +690,11 @@
 	return -EPERM;
 }
 
+static inline int a2_mux_is_ch_empty(enum a2_mux_logical_channel_id lcid)
+{
+	return -EPERM;
+}
+
 static inline int a2_mux_is_ch_low(enum a2_mux_logical_channel_id lcid)
 {
 	return -EPERM;
@@ -1099,6 +1108,11 @@
 	return -EPERM;
 }
 
+static inline void ipa_bam_reg_dump(void)
+{
+	return;
+}
+
 #endif /* CONFIG_IPA*/
 
 #endif /* _IPA_H_ */
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 2cc7b10..62fada1 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -134,25 +134,10 @@
 	int disable_smsm_reset_handshake;
 };
 
-/*
- * Shared Memory Regions
- *
- * the array of these regions is expected to be in ascending order by phys_addr
- *
- * @phys_addr: physical base address of the region
- * @size: size of the region in bytes
- */
-struct smd_smem_regions {
-	phys_addr_t phys_addr;
-	resource_size_t size;
-};
-
 struct smd_platform {
 	uint32_t num_ss_configs;
 	struct smd_subsystem_config *smd_ss_configs;
 	struct smd_subsystem_restart_config *smd_ssr_config;
-	uint32_t num_smem_areas;
-	struct smd_smem_regions *smd_smem_areas;
 };
 
 #ifdef CONFIG_MSM_SMD
@@ -322,24 +307,6 @@
  */
 int smd_is_pkt_avail(smd_channel_t *ch);
 
-/**
- * smd_module_init_notifier_register() - Register a smd module
- *					 init notifier block
- * @nb: Notifier block to be registered
- *
- * In order to mark the dependency on SMD Driver module initialization
- * register a notifier using this API. Once the smd module_init is
- * done, notification will be passed to the registered module.
- */
-int smd_module_init_notifier_register(struct notifier_block *nb);
-
-/**
- * smd_module_init_notifier_register() - Unregister a smd module
- *					 init notifier block
- * @nb: Notifier block to be registered
- */
-int smd_module_init_notifier_unregister(struct notifier_block *nb);
-
 /*
  * SMD initialization function that registers for a SMD platform driver.
  *
@@ -474,16 +441,6 @@
 	return -ENODEV;
 }
 
-static inline int smd_module_init_notifier_register(struct notifier_block *nb)
-{
-	return -ENODEV;
-}
-
-static inline int smd_module_init_notifier_unregister(struct notifier_block *nb)
-{
-	return -ENODEV;
-}
-
 static inline int __init msm_smd_init(void)
 {
 	return 0;
diff --git a/arch/arm/mach-msm/include/mach/msm_smem.h b/arch/arm/mach-msm/include/mach/msm_smem.h
index 78d2b00..64ab6bf 100644
--- a/arch/arm/mach-msm/include/mach/msm_smem.h
+++ b/arch/arm/mach-msm/include/mach/msm_smem.h
@@ -169,6 +169,13 @@
  */
 phys_addr_t smem_virt_to_phys(void *smem_address);
 
+/**
+ * SMEM initialization function that registers for a SMEM platform driver.
+ *
+ * @returns: success on successful driver registration.
+ */
+int __init msm_smem_init(void);
+
 #else
 static inline void *smem_alloc(unsigned id, unsigned size)
 {
@@ -194,5 +201,9 @@
 {
 	return (phys_addr_t) NULL;
 }
+static int __init msm_smem_init(void)
+{
+	return 0;
+}
 #endif /* CONFIG_MSM_SMD  */
 #endif /* _ARCH_ARM_MACH_MSM_SMEM_H_ */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index d52686c..52102e3 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -115,6 +115,9 @@
 	MSM_CPU_7X27AA,
 	MSM_CPU_9615,
 	MSM_CPU_8974,
+	MSM_CPU_8974PRO_AA,
+	MSM_CPU_8974PRO_AB,
+	MSM_CPU_8974PRO_AC,
 	MSM_CPU_8627,
 	MSM_CPU_8625,
 	MSM_CPU_9625,
@@ -434,6 +437,42 @@
 #endif
 }
 
+static inline int cpu_is_msm8974pro_aa(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8974PRO_AA;
+#else
+	return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974pro_ab(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8974PRO_AB;
+#else
+	return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974pro_ac(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+	enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+	BUG_ON(cpu == MSM_CPU_UNKNOWN);
+	return cpu == MSM_CPU_8974PRO_AC;
+#else
+	return 0;
+#endif
+}
+
 static inline int cpu_is_mpq8092(void)
 {
 #ifdef CONFIG_ARCH_MPQ8092
@@ -499,4 +538,10 @@
 	       cpu_is_msm8627();
 }
 
+static inline int soc_class_is_msm8974(void)
+{
+	return cpu_is_msm8974() || cpu_is_msm8974pro_aa() ||
+	       cpu_is_msm8974pro_ab() || cpu_is_msm8974pro_ac();
+}
+
 #endif
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 32589f1..5a69ea3 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2228,6 +2228,7 @@
 		pr_err("%s: msm_ipc_router_send_to failed - ret: %d\n",
 			__func__, ret);
 		msm_ipc_router_free_skb(out_skb_head);
+		return ret;
 	}
 	return 0;
 }
diff --git a/arch/arm/mach-msm/msm_qmi_interface.c b/arch/arm/mach-msm/msm_qmi_interface.c
index 8d96bd8..a8fed52 100644
--- a/arch/arm/mach-msm/msm_qmi_interface.c
+++ b/arch/arm/mach-msm/msm_qmi_interface.c
@@ -439,12 +439,12 @@
 
 	/* Wait for the response */
 	if (!timeout_ms) {
-		rc = wait_event_interruptible(txn_handle->wait_q,
-				(txn_handle->resp_received ||
-				 handle->handle_reset ||
-				(txn_handle->send_stat < 0)));
+		wait_event(txn_handle->wait_q,
+			   (txn_handle->resp_received ||
+			    handle->handle_reset ||
+			   (txn_handle->send_stat < 0)));
 	} else {
-		rc = wait_event_interruptible_timeout(txn_handle->wait_q,
+		rc = wait_event_timeout(txn_handle->wait_q,
 				(txn_handle->resp_received ||
 				handle->handle_reset ||
 				(txn_handle->send_stat < 0)),
diff --git a/arch/arm/mach-msm/pil-msa.c b/arch/arm/mach-msm/pil-msa.c
new file mode 100644
index 0000000..a8f5b0e
--- /dev/null
+++ b/arch/arm/mach-msm/pil-msa.c
@@ -0,0 +1,407 @@
+/* Copyright (c) 2012-2013, 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/module.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+#include <linux/dma-mapping.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+#include "pil-msa.h"
+
+/* Q6 Register Offsets */
+#define QDSP6SS_RST_EVB			0x010
+
+/* AXI Halting Registers */
+#define MSS_Q6_HALT_BASE		0x180
+#define MSS_MODEM_HALT_BASE		0x200
+#define MSS_NC_HALT_BASE		0x280
+
+/* RMB Status Register Values */
+#define STATUS_PBL_SUCCESS		0x1
+#define STATUS_XPU_UNLOCKED		0x1
+#define STATUS_XPU_UNLOCKED_SCRIBBLED	0x2
+
+/* 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 MAX_VDD_MX_UV			1150000
+
+#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
+
+/* External BHS */
+#define EXTERNAL_BHS_ON			BIT(0)
+#define EXTERNAL_BHS_STATUS		BIT(4)
+#define BHS_TIMEOUT_US			50
+
+static int pbl_mba_boot_timeout_ms = 1000;
+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_msa_pbl_power_up(struct q6v5_data *drv)
+{
+	int ret = 0;
+	struct device *dev = drv->desc.dev;
+	u32 regval;
+
+	if (drv->vreg) {
+		ret = regulator_enable(drv->vreg);
+		if (ret)
+			dev_err(dev, "Failed to enable modem regulator.\n");
+	}
+
+	if (drv->cxrail_bhs) {
+		regval = readl_relaxed(drv->cxrail_bhs);
+		regval |= EXTERNAL_BHS_ON;
+		writel_relaxed(regval, drv->cxrail_bhs);
+
+		ret = readl_poll_timeout(drv->cxrail_bhs, regval,
+			regval & EXTERNAL_BHS_STATUS, 1, BHS_TIMEOUT_US);
+	}
+
+	return ret;
+}
+
+static int pil_msa_pbl_power_down(struct q6v5_data *drv)
+{
+	u32 regval;
+
+	if (drv->cxrail_bhs) {
+		regval = readl_relaxed(drv->cxrail_bhs);
+		regval &= ~EXTERNAL_BHS_ON;
+		writel_relaxed(regval, drv->cxrail_bhs);
+	}
+
+	if (drv->vreg)
+		return regulator_disable(drv->vreg);
+
+	return 0;
+}
+
+static int pil_msa_pbl_enable_clks(struct q6v5_data *drv)
+{
+	int ret;
+
+	ret = clk_prepare_enable(drv->ahb_clk);
+	if (ret)
+		goto err_ahb_clk;
+	ret = clk_prepare_enable(drv->axi_clk);
+	if (ret)
+		goto err_axi_clk;
+	ret = clk_prepare_enable(drv->rom_clk);
+	if (ret)
+		goto err_rom_clk;
+
+	return 0;
+
+err_rom_clk:
+	clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+	clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+	return ret;
+}
+
+static void pil_msa_pbl_disable_clks(struct q6v5_data *drv)
+{
+	clk_disable_unprepare(drv->rom_clk);
+	clk_disable_unprepare(drv->axi_clk);
+	clk_disable_unprepare(drv->ahb_clk);
+}
+
+static int pil_msa_wait_for_mba_ready(struct q6v5_data *drv)
+{
+	struct device *dev = drv->desc.dev;
+	int ret;
+	u32 status;
+
+	/* Wait for PBL completion. */
+	ret = readl_poll_timeout(drv->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");
+		return ret;
+	}
+	if (status != STATUS_PBL_SUCCESS) {
+		dev_err(dev, "PBL returned unexpected status %d\n", status);
+		return -EINVAL;
+	}
+
+	/* Wait for MBA completion. */
+	ret = readl_poll_timeout(drv->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");
+		return ret;
+	}
+	if (status != STATUS_XPU_UNLOCKED &&
+	    status != STATUS_XPU_UNLOCKED_SCRIBBLED) {
+		dev_err(dev, "MBA returned unexpected status %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int pil_msa_pbl_shutdown(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_Q6_HALT_BASE);
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_MODEM_HALT_BASE);
+	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_NC_HALT_BASE);
+
+	writel_relaxed(1, drv->restart_reg);
+
+	if (drv->is_booted) {
+		pil_msa_pbl_disable_clks(drv);
+		pil_msa_pbl_power_down(drv);
+		drv->is_booted = false;
+	}
+
+	return 0;
+}
+
+static int pil_msa_pbl_reset(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
+	int ret;
+
+	/*
+	 * Bring subsystem out of reset and enable required
+	 * regulators and clocks.
+	 */
+	ret = pil_msa_pbl_power_up(drv);
+	if (ret)
+		goto err_power;
+
+	/* Deassert reset to subsystem and wait for propagation */
+	writel_relaxed(0, drv->restart_reg);
+	mb();
+	udelay(2);
+
+	ret = pil_msa_pbl_enable_clks(drv);
+	if (ret)
+		goto err_clks;
+
+	/* Program Image Address */
+	if (drv->self_auth) {
+		writel_relaxed(start_addr, drv->rmb_base + RMB_MBA_IMAGE);
+		/* Ensure write to RMB base occurs before reset is released. */
+		mb();
+	} else {
+		writel_relaxed((start_addr >> 4) & 0x0FFFFFF0,
+				drv->reg_base + QDSP6SS_RST_EVB);
+	}
+
+	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) {
+		ret = pil_msa_wait_for_mba_ready(drv);
+		if (ret)
+			goto err_auth;
+	}
+
+	drv->is_booted = true;
+
+	return 0;
+
+err_auth:
+	pil_q6v5_shutdown(pil);
+err_q6v5_reset:
+	pil_msa_pbl_disable_clks(drv);
+err_clks:
+	pil_msa_pbl_power_down(drv);
+err_power:
+	return ret;
+}
+
+static int pil_msa_pbl_make_proxy_votes(struct pil_desc *pil)
+{
+	int ret;
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+
+	ret = regulator_set_voltage(drv->vreg_mx, VDD_MSS_UV, MAX_VDD_MX_UV);
+	if (ret) {
+		dev_err(pil->dev, "Failed to request vreg_mx voltage\n");
+		return ret;
+	}
+
+	ret = regulator_enable(drv->vreg_mx);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable vreg_mx\n");
+		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
+		return ret;
+	}
+
+	ret = pil_q6v5_make_proxy_votes(pil);
+	if (ret) {
+		regulator_disable(drv->vreg_mx);
+		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
+	}
+
+	return ret;
+}
+
+static void pil_msa_pbl_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	pil_q6v5_remove_proxy_votes(pil);
+	regulator_disable(drv->vreg_mx);
+	regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
+}
+
+struct pil_reset_ops pil_msa_pbl_ops = {
+	.proxy_vote = pil_msa_pbl_make_proxy_votes,
+	.proxy_unvote = pil_msa_pbl_remove_proxy_votes,
+	.auth_and_reset = pil_msa_pbl_reset,
+	.shutdown = pil_msa_pbl_shutdown,
+};
+
+static int pil_msa_mba_make_proxy_votes(struct pil_desc *pil)
+{
+	int ret;
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+	return 0;
+}
+
+static void pil_msa_mba_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	clk_disable_unprepare(drv->xo);
+}
+
+static int pil_msa_mba_init_image(struct pil_desc *pil,
+				  const u8 *metadata, size_t size)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	void *mdata_virt;
+	dma_addr_t mdata_phys;
+	s32 status;
+	int ret;
+
+	/* Make metadata physically contiguous and 4K aligned. */
+	mdata_virt = dma_alloc_coherent(pil->dev, size, &mdata_phys,
+					GFP_KERNEL);
+	if (!mdata_virt) {
+		dev_err(pil->dev, "MBA metadata buffer allocation failed\n");
+		return -ENOMEM;
+	}
+	memcpy(mdata_virt, metadata, size);
+	/* wmb() ensures copy completes prior to starting authentication. */
+	wmb();
+
+	/* Initialize length counter to 0 */
+	writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_LENGTH);
+
+	/* Pass address of meta-data to the MBA and perform authentication */
+	writel_relaxed(mdata_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;
+	}
+
+	dma_free_coherent(pil->dev, size, mdata_virt, mdata_phys);
+
+	return ret;
+}
+
+static int pil_msa_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr,
+				   size_t size)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	s32 status;
+	u32 img_length = readl_relaxed(drv->rmb_base + RMB_PMI_CODE_LENGTH);
+
+	/* Begin image authentication */
+	if (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 */
+	img_length += size;
+	writel_relaxed(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_msa_mba_auth(struct pil_desc *pil)
+{
+	struct mba_data *drv = container_of(pil, struct mba_data, desc);
+	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;
+}
+
+struct pil_reset_ops pil_msa_mba_ops = {
+	.init_image = pil_msa_mba_init_image,
+	.proxy_vote = pil_msa_mba_make_proxy_votes,
+	.proxy_unvote = pil_msa_mba_remove_proxy_votes,
+	.verify_blob = pil_msa_mba_verify_blob,
+	.auth_and_reset = pil_msa_mba_auth,
+};
diff --git a/arch/arm/mach-msm/pil-msa.h b/arch/arm/mach-msm/pil-msa.h
new file mode 100644
index 0000000..9a7b56e
--- /dev/null
+++ b/arch/arm/mach-msm/pil-msa.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2012-2013, 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 __MSM_PIL_MSA_H
+#define __MSM_PIL_MSA_H
+
+#include "peripheral-loader.h"
+
+#define VDD_MSS_UV	1050000
+
+struct mba_data {
+	void __iomem *rmb_base;
+	struct clk *xo;
+	struct pil_desc desc;
+};
+
+extern struct pil_reset_ops pil_msa_pbl_ops;
+extern struct pil_reset_ops pil_msa_mba_ops;
+
+#endif
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index b83202b..3a21e39 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -35,62 +35,20 @@
 
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
+#include "pil-msa.h"
 #include "sysmon.h"
 
-/* Q6 Register Offsets */
-#define QDSP6SS_RST_EVB			0x010
+#define MAX_VDD_MSS_UV		1150000
+#define PROXY_TIMEOUT_MS	10000
+#define MAX_SSR_REASON_LEN	81U
+#define STOP_ACK_TIMEOUT_MS	1000
 
-/* AXI Halting Registers */
-#define MSS_Q6_HALT_BASE		0x180
-#define MSS_MODEM_HALT_BASE		0x200
-#define MSS_NC_HALT_BASE		0x280
-
-/* RMB Status Register Values */
-#define STATUS_PBL_SUCCESS		0x1
-#define STATUS_XPU_UNLOCKED		0x1
-#define STATUS_XPU_UNLOCKED_SCRIBBLED	0x2
-
-/* 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 VDD_MSS_UV			1050000
-#define MAX_VDD_MSS_UV			1150000
-#define MAX_VDD_MX_UV			1150000
-
-#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
-
-/* External BHS */
-#define EXTERNAL_BHS_ON			BIT(0)
-#define EXTERNAL_BHS_STATUS		BIT(4)
-#define BHS_TIMEOUT_US			50
-
-#define STOP_ACK_TIMEOUT_MS		1000
-
-struct mba_data {
-	void __iomem *rmb_base;
-	void __iomem *io_clamp_reg;
-	struct pil_desc desc;
+struct modem_data {
+	struct mba_data *mba;
+	struct q6v5_data *q6;
 	struct subsys_device *subsys;
 	struct subsys_desc subsys_desc;
 	void *adsp_state_notifier;
-	u32 img_length;
-	struct q6v5_data *q6;
-	bool self_auth;
 	void *ramdump_dev;
 	void *smem_ramdump_dev;
 	bool crash_shutdown;
@@ -101,354 +59,7 @@
 	struct completion stop_ack;
 };
 
-static int pbl_mba_boot_timeout_ms = 1000;
-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 = 0;
-	struct device *dev = drv->desc.dev;
-	u32 regval;
-
-	if (drv->vreg) {
-		ret = regulator_enable(drv->vreg);
-		if (ret)
-			dev_err(dev, "Failed to enable modem regulator.\n");
-	}
-
-	if (drv->cxrail_bhs) {
-		regval = readl_relaxed(drv->cxrail_bhs);
-		regval |= EXTERNAL_BHS_ON;
-		writel_relaxed(regval, drv->cxrail_bhs);
-
-		ret = readl_poll_timeout(drv->cxrail_bhs, regval,
-			regval & EXTERNAL_BHS_STATUS, 1, BHS_TIMEOUT_US);
-	}
-
-	return ret;
-}
-
-static int pil_mss_power_down(struct q6v5_data *drv)
-{
-	u32 regval;
-
-	if (drv->cxrail_bhs) {
-		regval = readl_relaxed(drv->cxrail_bhs);
-		regval &= ~EXTERNAL_BHS_ON;
-		writel_relaxed(regval, drv->cxrail_bhs);
-	}
-
-	if (drv->vreg)
-		return regulator_disable(drv->vreg);
-
-	return 0;
-}
-
-static int pil_mss_enable_clks(struct q6v5_data *drv)
-{
-	int ret;
-
-	ret = clk_prepare_enable(drv->ahb_clk);
-	if (ret)
-		goto err_ahb_clk;
-	ret = clk_prepare_enable(drv->axi_clk);
-	if (ret)
-		goto err_axi_clk;
-	ret = clk_prepare_enable(drv->rom_clk);
-	if (ret)
-		goto err_rom_clk;
-
-	return 0;
-
-err_rom_clk:
-	clk_disable_unprepare(drv->axi_clk);
-err_axi_clk:
-	clk_disable_unprepare(drv->ahb_clk);
-err_ahb_clk:
-	return ret;
-}
-
-static void pil_mss_disable_clks(struct q6v5_data *drv)
-{
-	clk_disable_unprepare(drv->rom_clk);
-	clk_disable_unprepare(drv->axi_clk);
-	clk_disable_unprepare(drv->ahb_clk);
-}
-
-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(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");
-		return ret;
-	}
-	if (status != STATUS_PBL_SUCCESS) {
-		dev_err(dev, "PBL returned unexpected status %d\n", status);
-		return -EINVAL;
-	}
-
-	/* Wait for MBA completion. */
-	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");
-		return ret;
-	}
-	if (status != STATUS_XPU_UNLOCKED &&
-	    status != STATUS_XPU_UNLOCKED_SCRIBBLED) {
-		dev_err(dev, "MBA returned unexpected status %d\n", status);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int pil_mss_shutdown(struct pil_desc *pil)
-{
-	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-
-	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_Q6_HALT_BASE);
-	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_MODEM_HALT_BASE);
-	pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_NC_HALT_BASE);
-
-	writel_relaxed(1, drv->restart_reg);
-
-	if (drv->is_booted) {
-		pil_mss_disable_clks(drv);
-		pil_mss_power_down(drv);
-		drv->is_booted = false;
-	}
-
-	return 0;
-}
-
-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);
-	phys_addr_t start_addr = pil_get_entry_addr(pil);
-	int ret;
-
-	/*
-	 * Bring subsystem out of reset and enable required
-	 * regulators and clocks.
-	 */
-	ret = pil_mss_power_up(drv);
-	if (ret)
-		goto err_power;
-
-	/* Deassert reset to subsystem and wait for propagation */
-	writel_relaxed(0, drv->restart_reg);
-	mb();
-	udelay(2);
-
-	ret = pil_mss_enable_clks(drv);
-	if (ret)
-		goto err_clks;
-
-	/* Program Image Address */
-	if (mba->self_auth) {
-		writel_relaxed(start_addr, mba->rmb_base + RMB_MBA_IMAGE);
-		/* Ensure write to RMB base occurs before reset is released. */
-		mb();
-	} else {
-		writel_relaxed((start_addr >> 4) & 0x0FFFFFF0,
-				drv->reg_base + QDSP6SS_RST_EVB);
-	}
-
-	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 (mba->self_auth) {
-		ret = wait_for_mba_ready(drv);
-		if (ret)
-			goto err_auth;
-	}
-
-	drv->is_booted = true;
-
-	return 0;
-
-err_auth:
-	pil_q6v5_shutdown(pil);
-err_q6v5_reset:
-	pil_mss_disable_clks(drv);
-err_clks:
-	pil_mss_power_down(drv);
-err_power:
-	return ret;
-}
-
-static int pil_q6v5_mss_make_proxy_votes(struct pil_desc *pil)
-{
-	int ret;
-	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-
-	ret = regulator_set_voltage(drv->vreg_mx, VDD_MSS_UV, MAX_VDD_MX_UV);
-	if (ret) {
-		dev_err(pil->dev, "Failed to request vreg_mx voltage\n");
-		return ret;
-	}
-
-	ret = regulator_enable(drv->vreg_mx);
-	if (ret) {
-		dev_err(pil->dev, "Failed to enable vreg_mx\n");
-		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
-		return ret;
-	}
-
-	ret = pil_q6v5_make_proxy_votes(pil);
-	if (ret) {
-		regulator_disable(drv->vreg_mx);
-		regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
-	}
-
-	return ret;
-}
-
-static void pil_q6v5_mss_remove_proxy_votes(struct pil_desc *pil)
-{
-	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-	pil_q6v5_remove_proxy_votes(pil);
-	regulator_disable(drv->vreg_mx);
-	regulator_set_voltage(drv->vreg_mx, 0, MAX_VDD_MX_UV);
-}
-
-static struct pil_reset_ops pil_mss_ops = {
-	.proxy_vote = pil_q6v5_mss_make_proxy_votes,
-	.proxy_unvote = pil_q6v5_mss_remove_proxy_votes,
-	.auth_and_reset = pil_mss_reset,
-	.shutdown = pil_mss_shutdown,
-};
-
-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->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);
-	void *mdata_virt;
-	dma_addr_t mdata_phys;
-	s32 status;
-	int ret;
-
-	/* Make metadata physically contiguous and 4K aligned. */
-	mdata_virt = dma_alloc_coherent(pil->dev, size, &mdata_phys,
-					GFP_KERNEL);
-	if (!mdata_virt) {
-		dev_err(pil->dev, "MBA metadata buffer allocation failed\n");
-		return -ENOMEM;
-	}
-	memcpy(mdata_virt, metadata, size);
-	/* wmb() ensures copy completes prior to starting authentication. */
-	wmb();
-
-	/* 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(mdata_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;
-	}
-
-	dma_free_coherent(pil->dev, size, mdata_virt, mdata_phys);
-
-	return ret;
-}
-
-static int pil_mba_verify_blob(struct pil_desc *pil, phys_addr_t 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 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,
-};
-
-#define subsys_to_drv(d) container_of(d, struct mba_data, subsys_desc)
+#define subsys_to_drv(d) container_of(d, struct modem_data, subsys_desc)
 
 static void log_modem_sfr(void)
 {
@@ -472,7 +83,7 @@
 	wmb();
 }
 
-static void restart_modem(struct mba_data *drv)
+static void restart_modem(struct modem_data *drv)
 {
 	log_modem_sfr();
 	drv->ignore_errors = true;
@@ -481,7 +92,7 @@
 
 static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id)
 {
-	struct mba_data *drv = dev_id;
+	struct modem_data *drv = dev_id;
 
 	/* Ignore if we're the one that set the force stop GPIO */
 	if (drv->crash_shutdown)
@@ -495,7 +106,7 @@
 
 static irqreturn_t modem_stop_ack_intr_handler(int irq, void *dev_id)
 {
-	struct mba_data *drv = dev_id;
+	struct modem_data *drv = dev_id;
 	pr_info("Received stop ack interrupt from modem\n");
 	complete(&drv->stop_ack);
 	return IRQ_HANDLED;
@@ -503,7 +114,7 @@
 
 static int modem_shutdown(const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	unsigned long ret;
 
 	if (subsys->is_not_loadable)
@@ -518,14 +129,14 @@
 		gpio_set_value(drv->force_stop_gpio, 0);
 	}
 
-	pil_shutdown(&drv->desc);
+	pil_shutdown(&drv->mba->desc);
 	pil_shutdown(&drv->q6->desc);
 	return 0;
 }
 
 static int modem_powerup(const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	int ret;
 
 	if (subsys->is_not_loadable)
@@ -540,7 +151,7 @@
 	ret = pil_boot(&drv->q6->desc);
 	if (ret)
 		return ret;
-	ret = pil_boot(&drv->desc);
+	ret = pil_boot(&drv->mba->desc);
 	if (ret)
 		pil_shutdown(&drv->q6->desc);
 	return ret;
@@ -548,7 +159,7 @@
 
 static void modem_crash_shutdown(const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	drv->crash_shutdown = true;
 	if (!subsys_get_crash_status(drv->subsys)) {
 		gpio_set_value(drv->force_stop_gpio, 1);
@@ -562,7 +173,7 @@
 
 static int modem_ramdump(int enable, const struct subsys_desc *subsys)
 {
-	struct mba_data *drv = subsys_to_drv(subsys);
+	struct modem_data *drv = subsys_to_drv(subsys);
 	int ret;
 
 	if (!enable)
@@ -572,7 +183,7 @@
 	if (ret)
 		return ret;
 
-	ret = pil_do_ramdump(&drv->desc, drv->ramdump_dev);
+	ret = pil_do_ramdump(&drv->mba->desc, drv->ramdump_dev);
 	if (ret < 0) {
 		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
 		goto out;
@@ -606,7 +217,7 @@
 
 static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
 {
-	struct mba_data *drv = dev_id;
+	struct modem_data *drv = dev_id;
 	if (drv->ignore_errors)
 		return IRQ_HANDLED;
 	pr_err("Watchdog bite received from modem software!\n");
@@ -618,7 +229,7 @@
 static int mss_start(const struct subsys_desc *desc)
 {
 	int ret;
-	struct mba_data *drv = subsys_to_drv(desc);
+	struct modem_data *drv = subsys_to_drv(desc);
 
 	if (desc->is_not_loadable)
 		return 0;
@@ -627,7 +238,7 @@
 	ret = pil_boot(&drv->q6->desc);
 	if (ret)
 		return ret;
-	ret = pil_boot(&drv->desc);
+	ret = pil_boot(&drv->mba->desc);
 	if (ret)
 		pil_shutdown(&drv->q6->desc);
 	return ret;
@@ -635,16 +246,16 @@
 
 static void mss_stop(const struct subsys_desc *desc)
 {
-	struct mba_data *drv = subsys_to_drv(desc);
+	struct modem_data *drv = subsys_to_drv(desc);
 
 	if (desc->is_not_loadable)
 		return;
 
-	pil_shutdown(&drv->desc);
+	pil_shutdown(&drv->mba->desc);
 	pil_shutdown(&drv->q6->desc);
 }
 
-static int __devinit pil_subsys_init(struct mba_data *drv,
+static int __devinit pil_subsys_init(struct modem_data *drv,
 					struct platform_device *pdev)
 {
 	int irq, ret;
@@ -740,10 +351,11 @@
 	return ret;
 }
 
-static int __devinit pil_mss_loadable_init(struct mba_data *drv,
+static int __devinit pil_mss_loadable_init(struct modem_data *drv,
 					struct platform_device *pdev)
 {
 	struct q6v5_data *q6;
+	struct mba_data *mba;
 	struct pil_desc *q6_desc, *mba_desc;
 	struct resource *res;
 	struct property *prop;
@@ -758,25 +370,32 @@
 	if (clk_ready < 0)
 		return clk_ready;
 
+	mba = devm_kzalloc(&pdev->dev, sizeof(*mba), GFP_KERNEL);
+	if (IS_ERR(mba))
+		return PTR_ERR(mba);
+	drv->mba = mba;
+
 	q6 = pil_q6v5_init(pdev);
 	if (IS_ERR(q6))
 		return PTR_ERR(q6);
 	drv->q6 = q6;
+	drv->mba->xo = q6->xo;
 
 	q6_desc = &q6->desc;
-	q6_desc->ops = &pil_mss_ops;
+	q6_desc->ops = &pil_msa_pbl_ops;
 	q6_desc->owner = THIS_MODULE;
 	q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
 	q6_desc->proxy_unvote_irq = clk_ready;
 
-	drv->self_auth = of_property_read_bool(pdev->dev.of_node,
+	q6->self_auth = of_property_read_bool(pdev->dev.of_node,
 							"qcom,pil-self-auth");
-	if (drv->self_auth) {
+	if (q6->self_auth) {
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						    "rmb_base");
-		drv->rmb_base = devm_request_and_ioremap(&pdev->dev, res);
-		if (!drv->rmb_base)
+		q6->rmb_base = devm_request_and_ioremap(&pdev->dev, res);
+		if (!q6->rmb_base)
 			return -ENOMEM;
+		mba->rmb_base = q6->rmb_base;
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
@@ -830,10 +449,10 @@
 	if (ret)
 		return ret;
 
-	mba_desc = &drv->desc;
+	mba_desc = &mba->desc;
 	mba_desc->name = "modem";
 	mba_desc->dev = &pdev->dev;
-	mba_desc->ops = &pil_mba_ops;
+	mba_desc->ops = &pil_msa_mba_ops;
 	mba_desc->owner = THIS_MODULE;
 	mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
 	mba_desc->proxy_unvote_irq = clk_ready;
@@ -852,7 +471,7 @@
 
 static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
 {
-	struct mba_data *drv;
+	struct modem_data *drv;
 	int ret, err_fatal_gpio, is_not_loadable, stop_ack_gpio;
 
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
@@ -901,14 +520,14 @@
 
 static int __devexit pil_mss_driver_exit(struct platform_device *pdev)
 {
-	struct mba_data *drv = platform_get_drvdata(pdev);
+	struct modem_data *drv = platform_get_drvdata(pdev);
 
 	subsys_notif_unregister_notifier(drv->adsp_state_notifier,
 						&adsp_state_notifier_block);
 	subsys_unregister(drv->subsys);
 	destroy_ramdump_device(drv->smem_ramdump_dev);
 	destroy_ramdump_device(drv->ramdump_dev);
-	pil_desc_release(&drv->desc);
+	pil_desc_release(&drv->mba->desc);
 	pil_desc_release(&drv->q6->desc);
 	return 0;
 }
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index 48d10df..b2fb7f7 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -22,6 +22,7 @@
 
 struct q6v5_data {
 	void __iomem *reg_base;
+	void __iomem *rmb_base;
 	void __iomem *cxrail_bhs;  /* External BHS register */
 	struct clk *xo;		   /* XO clock source */
 	struct clk *ahb_clk;	   /* PIL access to registers */
@@ -37,6 +38,7 @@
 	struct regulator *vreg_pll;
 	bool is_booted;
 	struct pil_desc desc;
+	bool self_auth;
 };
 
 int pil_q6v5_make_proxy_votes(struct pil_desc *pil);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 146dc0b..be32e82 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -1285,14 +1285,90 @@
 	},
 };
 
+#ifdef CONFIG_ARM_LPAE
+static int msm_pm_idmap_add_pmd(pud_t *pud, unsigned long addr,
+				unsigned long end, unsigned long prot)
+{
+	pmd_t *pmd;
+	unsigned long next;
 
-static int __init msm_pm_setup_saved_state(void)
+	if (pud_none_or_clear_bad(pud) || (pud_val(*pud) & L_PGD_SWAPPER)) {
+		pmd = pmd_alloc_one(&init_mm, addr);
+		if (!pmd)
+			return -ENOMEM;
+
+		pud_populate(&init_mm, pud, pmd);
+		pmd += pmd_index(addr);
+	} else {
+		pmd = pmd_offset(pud, addr);
+	}
+
+	do {
+		next = pmd_addr_end(addr, end);
+		*pmd = __pmd((addr & PMD_MASK) | prot);
+		flush_pmd_entry(pmd);
+	} while (pmd++, addr = next, addr != end);
+
+	return 0;
+}
+#else   /* !CONFIG_ARM_LPAE */
+static int msm_pm_idmap_add_pmd(pud_t *pud, unsigned long addr,
+				unsigned long end, unsigned long prot)
+{
+	pmd_t *pmd = pmd_offset(pud, addr);
+
+	addr = (addr & PMD_MASK) | prot;
+	pmd[0] = __pmd(addr);
+	addr += SECTION_SIZE;
+	pmd[1] = __pmd(addr);
+	flush_pmd_entry(pmd);
+
+	return 0;
+}
+#endif  /* CONFIG_ARM_LPAE */
+
+static int msm_pm_idmap_add_pud(pgd_t *pgd, unsigned long addr,
+					unsigned long end,
+					unsigned long prot)
+{
+	pud_t *pud = pud_offset(pgd, addr);
+	unsigned long next;
+	int ret;
+
+	do {
+		next = pud_addr_end(addr, end);
+		ret = msm_pm_idmap_add_pmd(pud, addr, next, prot);
+		if (ret)
+			return ret;
+	} while (pud++, addr = next, addr != end);
+
+	return 0;
+}
+
+static int msm_pm_add_idmap(pgd_t *pgd, unsigned long addr,
+						unsigned long end,
+						unsigned long prot)
+{
+	unsigned long next;
+	int ret;
+
+	pgd += pgd_index(addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		ret = msm_pm_idmap_add_pud(pgd, addr, next, prot);
+		if (ret)
+			return ret;
+	} while (pgd++, addr = next, addr != end);
+
+	return 0;
+}
+
+static int msm_pm_setup_pagetable(void)
 {
 	pgd_t *pc_pgd;
-	pmd_t *pmd;
-	unsigned long pmdval;
 	unsigned long exit_phys;
-	dma_addr_t temp_phys;
+	unsigned long end;
+	int ret;
 
 	/* Page table for cores to come back up safely. */
 	pc_pgd = pgd_alloc(&init_mm);
@@ -1301,12 +1377,33 @@
 
 	exit_phys = virt_to_phys(msm_pm_collapse_exit);
 
-	pmd = pmd_offset(pud_offset(pc_pgd + pgd_index(exit_phys),exit_phys),
-					exit_phys);
-	pmdval = (exit_phys & PGDIR_MASK) |
-		     PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
-	pmd[0] = __pmd(pmdval);
-	pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
+	/*
+	 * Make the (hopefully) reasonable assumption that the code size of
+	 * msm_pm_collapse_exit won't be more than a section in size
+	 */
+	end = exit_phys + SECTION_SIZE;
+
+	ret = msm_pm_add_idmap(pc_pgd, exit_phys, end,
+					PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
+
+	if (ret)
+		return ret;
+
+	msm_pm_pc_pgd = virt_to_phys(pc_pgd);
+	clean_caches((unsigned long)&msm_pm_pc_pgd, sizeof(msm_pm_pc_pgd),
+		     virt_to_phys(&msm_pm_pc_pgd));
+
+	return 0;
+}
+
+static int __init msm_pm_setup_saved_state(void)
+{
+	int ret;
+	dma_addr_t temp_phys;
+
+	ret = msm_pm_setup_pagetable();
+	if (ret)
+		return ret;
 
 	msm_saved_state = dma_zalloc_coherent(NULL, CPU_SAVED_STATE_SIZE *
 						num_possible_cpus(),
@@ -1322,19 +1419,6 @@
 	 */
 	msm_saved_state_phys = (unsigned long)temp_phys;
 
-
-	/* It is remotely possible that the code in msm_pm_collapse_exit()
-	 * which turns on the MMU with this mapping is in the
-	 * next even-numbered megabyte beyond the
-	 * start of msm_pm_collapse_exit().
-	 * Map this megabyte in as well.
-	 */
-	pmd[2] = __pmd(pmdval + (2 << (PGDIR_SHIFT - 1)));
-	flush_pmd_entry(pmd);
-	msm_pm_pc_pgd = virt_to_phys(pc_pgd);
-	clean_caches((unsigned long)&msm_pm_pc_pgd, sizeof(msm_pm_pc_pgd),
-		     virt_to_phys(&msm_pm_pc_pgd));
-
 	return 0;
 }
 arch_initcall(msm_pm_setup_saved_state);
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 38ed867..2bae37a 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -60,12 +60,13 @@
 	spinlock_t smd_lock_write;
 	spinlock_t smd_lock_read;
 	struct completion smd_open;
+	struct completion remote_open;
 };
 
 #define DEFAULT_BUFFER_SIZE 256
 #define DEBUG_PRINT_BUFFER_SIZE 512
 #define MAX_SLEEP_BUFFER 128
-
+#define SMD_CHANNEL_NOTIF_TIMEOUT 5000
 #define GFP_FLAG(noirq) (noirq ? GFP_ATOMIC : GFP_KERNEL)
 #define INV_RSC "resource does not exist"
 #define ERR "err\0"
@@ -1303,6 +1304,20 @@
 }
 EXPORT_SYMBOL(msm_rpm_exit_sleep);
 
+static int __devinit msm_rpm_smd_remote_probe(struct platform_device *pdev)
+{
+	if (pdev && pdev->id == msm_rpm_data.ch_type)
+		complete(&msm_rpm_data.remote_open);
+	return 0;
+}
+
+static struct platform_driver msm_rpm_smd_remote_driver = {
+	.probe = msm_rpm_smd_remote_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+	},
+};
+
 static int __devinit msm_rpm_dev_probe(struct platform_device *pdev)
 {
 	char *key = NULL;
@@ -1323,13 +1338,21 @@
 	key = "rpm-standalone";
 	standalone = of_property_read_bool(pdev->dev.of_node, key);
 
+	msm_rpm_smd_remote_driver.driver.name = msm_rpm_data.ch_name;
+	init_completion(&msm_rpm_data.remote_open);
 	init_completion(&msm_rpm_data.smd_open);
 	spin_lock_init(&msm_rpm_data.smd_lock_write);
 	spin_lock_init(&msm_rpm_data.smd_lock_read);
 	INIT_WORK(&msm_rpm_data.work, msm_rpm_smd_work);
 
-	if (smd_named_open_on_edge(msm_rpm_data.ch_name, msm_rpm_data.ch_type,
-				&msm_rpm_data.ch_info, &msm_rpm_data,
+	platform_driver_register(&msm_rpm_smd_remote_driver);
+	ret = wait_for_completion_timeout(&msm_rpm_data.remote_open,
+			msecs_to_jiffies(SMD_CHANNEL_NOTIF_TIMEOUT));
+
+	if (!ret || smd_named_open_on_edge(msm_rpm_data.ch_name,
+				msm_rpm_data.ch_type,
+				&msm_rpm_data.ch_info,
+				&msm_rpm_data,
 				msm_rpm_notify)) {
 		pr_info("Cannot open RPM channel %s %d\n", msm_rpm_data.ch_name,
 				msm_rpm_data.ch_type);
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index 4cb43b1..b244c6f 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -268,7 +268,7 @@
 	rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
 	clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
 
-	if (cpu_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
+	if (soc_class_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
 		scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
 		scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
 	} else {
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index 6e05177..e9f44e3 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -191,12 +191,12 @@
 	u32 cmd_addr = virt_to_phys(cmd);
 
 	/*
-	 * Flush the entire cache here so callers don't have to remember
-	 * to flush the cache when passing physical addresses to the secure
-	 * side in the buffer.
+	 * Flush the command buffer so that the secure world sees
+	 * the correct data.
 	 */
-	flush_cache_all();
-	outer_flush_all();
+	__cpuc_flush_dcache_area((void *)cmd, cmd->len);
+	outer_flush_range(cmd_addr, cmd_addr + cmd->len);
+
 	ret = smc(cmd_addr);
 	if (ret < 0)
 		ret = scm_remap_error(ret);
@@ -233,6 +233,13 @@
  * @resp_len: length of the response buffer
  *
  * Sends a command to the SCM and waits for the command to finish processing.
+ *
+ * A note on cache maintenance:
+ * Note that any buffers that are expected to be accessed by the secure world
+ * must be flushed before invoking scm_call and invalidated in the cache
+ * immediately after scm_call returns. Cache maintenance on the command and
+ * response buffers is taken care of by scm_call; however, callers are
+ * responsible for any other cached buffers passed over to the secure world.
  */
 int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
 		void *resp_buf, size_t resp_len)
diff --git a/arch/arm/mach-msm/smcmod.c b/arch/arm/mach-msm/smcmod.c
index 705bab5..fc7ffd5 100644
--- a/arch/arm/mach-msm/smcmod.c
+++ b/arch/arm/mach-msm/smcmod.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -28,6 +28,7 @@
 #include <linux/printk.h>
 #include <linux/msm_ion.h>
 #include <asm/smcmod.h>
+#include <asm/cacheflush.h>
 #include <mach/scm.h>
 
 static DEFINE_MUTEX(ioctl_lock);
@@ -113,6 +114,20 @@
 	isb();
 }
 
+/*
+ * FIXME:
+ * scm_call will no longer flush the entire cache before calling into the secure
+ * world. Until individual buffers in this driver can be flushed, flush the
+ * entire cache before calling into scm_call.
+ */
+int smcmod_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
+		void *resp_buf, size_t resp_len)
+{
+	flush_cache_all();
+	outer_flush_all();
+	return scm_call(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len);
+}
+
 static int smcmod_ion_fd_to_phys(int32_t fd, struct ion_client *ion_clientp,
 	struct ion_handle **ion_handlep, uint32_t *phys_addrp, size_t *sizep)
 {
@@ -235,7 +250,7 @@
 	}
 
 	/* call scm function to switch to secure world */
-	reqp->return_val = scm_call(reqp->service_id, reqp->command_id,
+	reqp->return_val = smcmod_scm_call(reqp->service_id, reqp->command_id,
 		cmd_vaddrp, reqp->cmd_len, resp_vaddrp, reqp->resp_len);
 
 buf_cleanup:
@@ -356,7 +371,7 @@
 	}
 
 	/* call scm function to switch to secure world */
-	reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
+	reqp->return_val = smcmod_scm_call(SMCMOD_SVC_CRYPTO,
 		SMCMOD_CRYPTO_CMD_CIPHER, &scm_req,
 		sizeof(scm_req), NULL, 0);
 
@@ -494,13 +509,13 @@
 
 	/* call scm function to switch to secure world */
 	if (reqp->fixed_block)
-		reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
+		reqp->return_val = smcmod_scm_call(SMCMOD_SVC_CRYPTO,
 			SMCMOD_CRYPTO_CMD_MSG_DIGEST_FIXED,
 			&scm_req,
 			sizeof(scm_req),
 			NULL, 0);
 	else
-		reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
+		reqp->return_val = smcmod_scm_call(SMCMOD_SVC_CRYPTO,
 			SMCMOD_CRYPTO_CMD_MSG_DIGEST,
 			&scm_req,
 			sizeof(scm_req),
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 4649390..c97ba68 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -176,8 +176,6 @@
 	},
 };
 
-static void *smd_dev;
-
 struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
 
 #define SMSM_STATE_ADDR(entry)           (smsm_info.state + entry)
@@ -381,14 +379,6 @@
 static DEFINE_MUTEX(smsm_lock);
 static struct smsm_state_info *smsm_states;
 
-/**
- * Variables to indicate smd module initialization.
- * Dependents to register for smd module init notifier.
- */
-static int smd_module_inited;
-static RAW_NOTIFIER_HEAD(smd_module_init_notifier_list);
-static DEFINE_MUTEX(smd_module_init_notifier_lock);
-static void smd_module_init_notify(uint32_t state, void *data);
 static int smd_stream_write_avail(struct smd_channel *ch);
 static int smd_stream_read_avail(struct smd_channel *ch);
 
@@ -708,6 +698,7 @@
 	uint32_t	local_pid;
 	uint32_t	remote_pid;
 	char		subsys_name[SMD_MAX_CH_NAME_LEN];
+	bool		initialized;
 };
 
 /**
@@ -762,6 +753,11 @@
 
 static int smd_alloc_channel(struct smd_alloc_elm *alloc_elm);
 
+static bool smd_edge_inited(int edge)
+{
+	return edge_to_pids[edge].initialized;
+}
+
 /* on smp systems, the probe might get called from multiple cores,
    hence use a lock */
 static DEFINE_MUTEX(smd_probe_lock);
@@ -795,6 +791,11 @@
 		if (!shared[n].name[0])
 			continue;
 
+		if (!smd_initialized && !smd_edge_inited(type)) {
+			SMD_INFO("Probe skipping ch %d, edge not inited\n", n);
+			continue;
+		}
+
 		if (!smd_alloc_channel(&shared[n]))
 			smd_ch_allocated[n] = 1;
 		else
@@ -1913,7 +1914,7 @@
 	struct smd_channel *ch;
 	unsigned long flags;
 
-	if (smd_initialized == 0) {
+	if (smd_initialized == 0 && !smd_edge_inited(edge)) {
 		SMD_INFO("smd_open() before smd_init()\n");
 		return -ENODEV;
 	}
@@ -2436,16 +2437,23 @@
 	struct smsm_size_info_type *smsm_size_info;
 	unsigned long flags;
 	unsigned long j_start;
+	static int first = 1;
+	remote_spinlock_t *remote_spinlock;
+
+	if (!first)
+		return 0;
+	first = 0;
 
 	/* Verify that remote spinlock is not deadlocked */
+	remote_spinlock = smem_get_remote_spinlock();
 	j_start = jiffies;
-	while (!remote_spin_trylock_irqsave(&remote_spinlock, flags)) {
+	while (!remote_spin_trylock_irqsave(remote_spinlock, flags)) {
 		if (jiffies_to_msecs(jiffies - j_start) > RSPIN_INIT_WAIT_MS) {
 			panic("%s: Remote processor %d will not release spinlock\n",
-				__func__, remote_spin_owner(&remote_spinlock));
+				__func__, remote_spin_owner(remote_spinlock));
 		}
 	}
-	remote_spin_unlock_irqrestore(&remote_spinlock, flags);
+	remote_spin_unlock_irqrestore(remote_spinlock, flags);
 
 	smsm_size_info = smem_alloc(SMEM_SMSM_SIZE_INFO,
 				sizeof(struct smsm_size_info_type));
@@ -2860,9 +2868,6 @@
 	int ret;
 	unsigned long flags;
 
-	if (!smd_initialized)
-		return;
-
 	while (kfifo_len(&smsm_snapshot_fifo) >= SMSM_SNAPSHOT_SIZE) {
 		mutex_lock(&smsm_lock);
 		for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
@@ -3084,42 +3089,6 @@
 }
 EXPORT_SYMBOL(smsm_state_cb_deregister);
 
-int smd_module_init_notifier_register(struct notifier_block *nb)
-{
-	int ret;
-	if (!nb)
-		return -EINVAL;
-	mutex_lock(&smd_module_init_notifier_lock);
-	ret = raw_notifier_chain_register(&smd_module_init_notifier_list, nb);
-	if (smd_module_inited)
-		nb->notifier_call(nb, 0, NULL);
-	mutex_unlock(&smd_module_init_notifier_lock);
-	return ret;
-}
-EXPORT_SYMBOL(smd_module_init_notifier_register);
-
-int smd_module_init_notifier_unregister(struct notifier_block *nb)
-{
-	int ret;
-	if (!nb)
-		return -EINVAL;
-	mutex_lock(&smd_module_init_notifier_lock);
-	ret = raw_notifier_chain_unregister(&smd_module_init_notifier_list,
-					    nb);
-	mutex_unlock(&smd_module_init_notifier_lock);
-	return ret;
-}
-EXPORT_SYMBOL(smd_module_init_notifier_unregister);
-
-static void smd_module_init_notify(uint32_t state, void *data)
-{
-	mutex_lock(&smd_module_init_notifier_lock);
-	smd_module_inited = 1;
-	raw_notifier_call_chain(&smd_module_init_notifier_list,
-				state, data);
-	mutex_unlock(&smd_module_init_notifier_lock);
-}
-
 int smd_core_init(void)
 {
 	int r;
@@ -3315,9 +3284,6 @@
 	struct smd_subsystem_config *smd_ss_config_list;
 	struct smd_subsystem_config *cfg;
 	int err_ret = 0;
-	struct smd_smem_regions *smd_smem_areas;
-	struct smem_area *smem_areas_tmp = NULL;
-	int smem_idx;
 
 	smd_platform_data = pdev->dev.platform_data;
 	num_ss = smd_platform_data->num_ss_configs;
@@ -3327,57 +3293,6 @@
 		disable_smsm_reset_handshake = smd_platform_data->
 			   smd_ssr_config->disable_smsm_reset_handshake;
 
-	smd_smem_areas = smd_platform_data->smd_smem_areas;
-	num_smem_areas = smd_platform_data->num_smem_areas + 1;
-
-	/* Initialize main SMEM region */
-	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
-				GFP_KERNEL);
-	if (!smem_areas_tmp) {
-		pr_err("%s: smem_areas kmalloc failed\n", __func__);
-		err_ret = -ENOMEM;
-		goto smem_areas_alloc_fail;
-	}
-
-	smem_areas_tmp[0].phys_addr =  msm_shared_ram_phys;
-	smem_areas_tmp[0].size = MSM_SHARED_RAM_SIZE;
-	smem_areas_tmp[0].virt_addr = MSM_SHARED_RAM_BASE;
-
-	/* Configure auxiliary SMEM regions */
-	for (smem_idx = 1; smem_idx < num_smem_areas; ++smem_idx) {
-		smem_areas_tmp[smem_idx].phys_addr =
-				smd_smem_areas[smem_idx].phys_addr;
-		smem_areas_tmp[smem_idx].size =
-				smd_smem_areas[smem_idx].size;
-		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
-			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
-			smem_areas_tmp[smem_idx].size);
-		if (!smem_areas_tmp[smem_idx].virt_addr) {
-			pr_err("%s: ioremap_nocache() of addr: %pa size: %pa\n",
-				__func__,
-				&smem_areas_tmp[smem_idx].phys_addr,
-				&smem_areas_tmp[smem_idx].size);
-			err_ret = -ENOMEM;
-			goto smem_failed;
-		}
-
-		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
-				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
-				smem_areas_tmp[smem_idx].size)) {
-			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
-					__func__, smem_idx,
-					smem_areas_tmp[smem_idx].virt_addr,
-					&smem_areas_tmp[smem_idx].size);
-			++smem_idx;
-			err_ret = -EINVAL;
-			goto smem_failed;
-		}
-
-		SMD_DBG("%s: %d = %pa %pa", __func__, smem_idx,
-				&smd_smem_areas[smem_idx].phys_addr,
-				&smd_smem_areas[smem_idx].size);
-	}
-
 	for (i = 0; i < num_ss; i++) {
 		cfg = &smd_ss_config_list[i];
 
@@ -3421,7 +3336,6 @@
 
 	SMD_INFO("smd_core_platform_init() done\n");
 
-	smem_areas = smem_areas_tmp;
 	return 0;
 
 intr_failed:
@@ -3438,19 +3352,105 @@
 				(void *)cfg->smsm_int.dev_id
 				);
 	}
-smem_failed:
-	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
-		iounmap(smem_areas_tmp[smem_idx].virt_addr);
-
-	num_smem_areas = 0;
-	kfree(smem_areas_tmp);
-
-smem_areas_alloc_fail:
 	return err_ret;
 }
 
-static int __devinit parse_smd_devicetree(struct device_node *node,
-						void *irq_out_base)
+static int msm_smsm_probe(struct platform_device *pdev)
+{
+	uint32_t edge;
+	char *key;
+	int ret;
+	uint32_t irq_offset;
+	uint32_t irq_bitmask;
+	uint32_t irq_line;
+	struct interrupt_config_item *private_irq;
+	struct device_node *node;
+	void *irq_out_base;
+	resource_size_t irq_out_size;
+	struct platform_device *parent_pdev;
+	struct resource *r;
+
+	disable_smsm_reset_handshake = 1;
+
+	node = pdev->dev.of_node;
+
+	if (!pdev->dev.parent) {
+		pr_err("%s: missing link to parent device\n", __func__);
+		return -ENODEV;
+	}
+
+	parent_pdev = to_platform_device(pdev->dev.parent);
+
+	key = "irq-reg-base";
+	/* existance check verified in smem driver */
+	r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+	irq_out_size = resource_size(r);
+	irq_out_base = ioremap_nocache(r->start, irq_out_size);
+	if (!irq_out_base) {
+		pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
+				__func__, &r->start, &irq_out_size);
+		return -ENOMEM;
+	}
+	SMSM_DBG("%s: %s = %p", __func__, key, irq_out_base);
+
+	key = "qcom,smsm-edge";
+	ret = of_property_read_u32(node, key, &edge);
+	if (ret)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %d", __func__, key, edge);
+
+	key = "qcom,smsm-irq-offset";
+	ret = of_property_read_u32(node, key, &irq_offset);
+	if (ret)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %x", __func__, key, irq_offset);
+
+	key = "qcom,smsm-irq-bitmask";
+	ret = of_property_read_u32(node, key, &irq_bitmask);
+	if (ret)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %x", __func__, key, irq_bitmask);
+
+	key = "interrupts";
+	irq_line = irq_of_parse_and_map(node, 0);
+	if (!irq_line)
+		goto missing_key;
+	SMSM_DBG("%s: %s = %d", __func__, key, irq_line);
+
+	private_irq = &private_intr_config[edge_to_pids[edge].remote_pid].smsm;
+	private_irq->out_bit_pos = irq_bitmask;
+	private_irq->out_offset = irq_offset;
+	private_irq->out_base = irq_out_base;
+	private_irq->irq_id = irq_line;
+
+	ret = request_irq(irq_line,
+				private_irq->irq_handler,
+				IRQF_TRIGGER_RISING,
+				"smsm_dev",
+				NULL);
+	if (ret < 0) {
+		pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
+		return ret;
+	} else {
+		ret = enable_irq_wake(irq_line);
+		if (ret < 0)
+			pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
+					irq_line);
+	}
+
+	if (smsm_init())
+		pr_err("smsm_init() failed\n");
+
+	smsm_irq_handler(0, 0);
+
+	return 0;
+
+missing_key:
+	pr_err("%s: missing key: %s", __func__, key);
+	return -ENODEV;
+}
+
+static int msm_smd_probe(struct platform_device *pdev)
 {
 	uint32_t edge;
 	char *key;
@@ -3461,6 +3461,32 @@
 	unsigned long irq_flags = IRQF_TRIGGER_RISING;
 	const char *pilstr;
 	struct interrupt_config_item *private_irq;
+	struct device_node *node;
+	void *irq_out_base;
+	resource_size_t irq_out_size;
+	struct platform_device *parent_pdev;
+	struct resource *r;
+
+	node = pdev->dev.of_node;
+
+	if (!pdev->dev.parent) {
+		pr_err("%s: missing link to parent device\n", __func__);
+		return -ENODEV;
+	}
+
+	parent_pdev = to_platform_device(pdev->dev.parent);
+
+	key = "irq-reg-base";
+	/* existance check verified in smem driver */
+	r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+	irq_out_size = resource_size(r);
+	irq_out_base = ioremap_nocache(r->start, irq_out_size);
+	if (!irq_out_base) {
+		pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
+				__func__, &r->start, &irq_out_size);
+		return -ENOMEM;
+	}
+	SMD_DBG("%s: %s = %p", __func__, key, irq_out_base);
 
 	key = "qcom,smd-edge";
 	ret = of_property_read_u32(node, key, &edge);
@@ -3521,68 +3547,9 @@
 		strlcpy(edge_to_pids[edge].subsys_name, pilstr,
 						SMD_MAX_CH_NAME_LEN);
 
-	return 0;
+	edge_to_pids[edge].initialized = true;
 
-missing_key:
-	pr_err("%s: missing key: %s", __func__, key);
-	return -ENODEV;
-}
-
-static int __devinit parse_smsm_devicetree(struct device_node *node,
-						void *irq_out_base)
-{
-	uint32_t edge;
-	char *key;
-	int ret;
-	uint32_t irq_offset;
-	uint32_t irq_bitmask;
-	uint32_t irq_line;
-	struct interrupt_config_item *private_irq;
-
-	key = "qcom,smsm-edge";
-	ret = of_property_read_u32(node, key, &edge);
-	if (ret)
-		goto missing_key;
-	SMD_DBG("%s: %s = %d", __func__, key, edge);
-
-	key = "qcom,smsm-irq-offset";
-	ret = of_property_read_u32(node, key, &irq_offset);
-	if (ret)
-		goto missing_key;
-	SMD_DBG("%s: %s = %x", __func__, key, irq_offset);
-
-	key = "qcom,smsm-irq-bitmask";
-	ret = of_property_read_u32(node, key, &irq_bitmask);
-	if (ret)
-		goto missing_key;
-	SMD_DBG("%s: %s = %x", __func__, key, irq_bitmask);
-
-	key = "interrupts";
-	irq_line = irq_of_parse_and_map(node, 0);
-	if (!irq_line)
-		goto missing_key;
-	SMD_DBG("%s: %s = %d", __func__, key, irq_line);
-
-	private_irq = &private_intr_config[edge_to_pids[edge].remote_pid].smsm;
-	private_irq->out_bit_pos = irq_bitmask;
-	private_irq->out_offset = irq_offset;
-	private_irq->out_base = irq_out_base;
-	private_irq->irq_id = irq_line;
-
-	ret = request_irq(irq_line,
-				private_irq->irq_handler,
-				IRQF_TRIGGER_RISING,
-				"smsm_dev",
-				NULL);
-	if (ret < 0) {
-		pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
-		return ret;
-	} else {
-		ret = enable_irq_wake(irq_line);
-		if (ret < 0)
-			pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
-					irq_line);
-	}
+	schedule_work(&probe_work);
 
 	return 0;
 
@@ -3591,213 +3558,7 @@
 	return -ENODEV;
 }
 
-static void __devinit unparse_smd_devicetree(struct device_node *node)
-{
-	uint32_t irq_line;
-
-	irq_line = irq_of_parse_and_map(node, 0);
-
-	free_irq(irq_line, NULL);
-}
-
-static void __devinit unparse_smsm_devicetree(struct device_node *node)
-{
-	uint32_t irq_line;
-
-	irq_line = irq_of_parse_and_map(node, 0);
-
-	free_irq(irq_line, NULL);
-}
-
-static int __devinit smd_core_devicetree_init(struct platform_device *pdev)
-{
-	char *key;
-	struct resource *r;
-	void *irq_out_base;
-	phys_addr_t aux_mem_base;
-	resource_size_t aux_mem_size;
-	int temp_string_size = 11; /* max 3 digit count */
-	char temp_string[temp_string_size];
-	struct device_node *node;
-	int ret;
-	const char *compatible;
-	struct ramdump_segment *ramdump_segments_tmp = NULL;
-	struct smem_area *smem_areas_tmp = NULL;
-	int smem_idx = 0;
-	int subnode_num = 0;
-	int i;
-	resource_size_t irq_out_size;
-
-	disable_smsm_reset_handshake = 1;
-
-	key = "irq-reg-base";
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
-	if (!r) {
-		pr_err("%s: missing '%s'\n", __func__, key);
-		return -ENODEV;
-	}
-	irq_out_size = resource_size(r);
-	irq_out_base = ioremap_nocache(r->start, irq_out_size);
-	if (!irq_out_base) {
-		pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
-				__func__, &r->start, &irq_out_size);
-		return -ENOMEM;
-	}
-	SMD_DBG("%s: %s = %p", __func__, key, irq_out_base);
-
-	num_smem_areas = 1;
-	while (1) {
-		scnprintf(temp_string, temp_string_size, "aux-mem%d",
-				num_smem_areas);
-		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-								temp_string);
-		if (!r)
-			break;
-
-		++num_smem_areas;
-		if (num_smem_areas > 999) {
-			pr_err("%s: max num aux mem regions reached\n",
-								__func__);
-			break;
-		}
-	}
-
-	/* Initialize main SMEM region and SSR ramdump region */
-	key = "smem";
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
-	if (!r) {
-		pr_err("%s: missing '%s'\n", __func__, key);
-		return -ENODEV;
-	}
-
-	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
-				GFP_KERNEL);
-	if (!smem_areas_tmp) {
-		pr_err("%s: smem areas kmalloc failed\n", __func__);
-		ret = -ENOMEM;
-		goto free_smem_areas;
-	}
-
-	ramdump_segments_tmp = kmalloc_array(num_smem_areas,
-			sizeof(struct ramdump_segment), GFP_KERNEL);
-	if (!ramdump_segments_tmp) {
-		pr_err("%s: ramdump segment kmalloc failed\n", __func__);
-		ret = -ENOMEM;
-		goto free_smem_areas;
-	}
-
-	smem_areas_tmp[smem_idx].phys_addr =  r->start;
-	smem_areas_tmp[smem_idx].size = resource_size(r);
-	smem_areas_tmp[smem_idx].virt_addr = MSM_SHARED_RAM_BASE;
-
-	ramdump_segments_tmp[smem_idx].address = r->start;
-	ramdump_segments_tmp[smem_idx].size = resource_size(r);
-	++smem_idx;
-
-	/* Configure auxiliary SMEM regions */
-	while (1) {
-		scnprintf(temp_string, temp_string_size, "aux-mem%d",
-								smem_idx);
-		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-							temp_string);
-		if (!r)
-			break;
-		aux_mem_base = r->start;
-		aux_mem_size = resource_size(r);
-
-		ramdump_segments_tmp[smem_idx].address = aux_mem_base;
-		ramdump_segments_tmp[smem_idx].size = aux_mem_size;
-
-		smem_areas_tmp[smem_idx].phys_addr = aux_mem_base;
-		smem_areas_tmp[smem_idx].size = aux_mem_size;
-		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
-			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
-			smem_areas_tmp[smem_idx].size);
-		SMD_DBG("%s: %s = %pa %pa -> %p", __func__, temp_string,
-				&aux_mem_base, &aux_mem_size,
-				smem_areas_tmp[smem_idx].virt_addr);
-
-		if (!smem_areas_tmp[smem_idx].virt_addr) {
-			pr_err("%s: ioremap_nocache() of addr:%pa size: %pa\n",
-				__func__,
-				&smem_areas_tmp[smem_idx].phys_addr,
-				&smem_areas_tmp[smem_idx].size);
-			ret = -ENOMEM;
-			goto free_smem_areas;
-		}
-
-		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
-				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
-				smem_areas_tmp[smem_idx].size)) {
-			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
-					__func__, smem_idx,
-					smem_areas_tmp[smem_idx].virt_addr,
-					&smem_areas_tmp[smem_idx].size);
-			++smem_idx;
-			ret = -EINVAL;
-			goto free_smem_areas;
-		}
-
-		++smem_idx;
-		if (smem_idx > 999) {
-			pr_err("%s: max num aux mem regions reached\n",
-							__func__);
-			break;
-		}
-	}
-
-	for_each_child_of_node(pdev->dev.of_node, node) {
-		compatible = of_get_property(node, "compatible", NULL);
-		if (!compatible) {
-			pr_err("%s: invalid child node: compatible null\n",
-				__func__);
-			ret = -ENODEV;
-			goto rollback_subnodes;
-		}
-		if (!strcmp(compatible, "qcom,smd")) {
-			ret = parse_smd_devicetree(node, irq_out_base);
-			if (ret)
-				goto rollback_subnodes;
-		} else if (!strcmp(compatible, "qcom,smsm")) {
-			ret = parse_smsm_devicetree(node, irq_out_base);
-			if (ret)
-				goto rollback_subnodes;
-		} else {
-			pr_err("%s: invalid child node named: %s\n", __func__,
-							compatible);
-			ret = -ENODEV;
-			goto rollback_subnodes;
-		}
-		++subnode_num;
-	}
-
-	smem_areas = smem_areas_tmp;
-	smem_ramdump_segments = ramdump_segments_tmp;
-	return 0;
-
-rollback_subnodes:
-	i = 0;
-	for_each_child_of_node(pdev->dev.of_node, node) {
-		if (i >= subnode_num)
-			break;
-		++i;
-		compatible = of_get_property(node, "compatible", NULL);
-		if (!strcmp(compatible, "qcom,smd"))
-			unparse_smd_devicetree(node);
-		else
-			unparse_smsm_devicetree(node);
-	}
-free_smem_areas:
-	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
-		iounmap(smem_areas_tmp[smem_idx].virt_addr);
-
-	num_smem_areas = 0;
-	kfree(ramdump_segments_tmp);
-	kfree(smem_areas_tmp);
-	return ret;
-}
-
-static int __devinit msm_smd_probe(struct platform_device *pdev)
+static int msm_smd_probe_legacy(struct platform_device *pdev)
 {
 	int ret;
 
@@ -3805,13 +3566,6 @@
 		return -ENODEV;
 
 	SMD_INFO("smd probe\n");
-	INIT_WORK(&probe_work, smd_channel_probe_worker);
-
-	channel_close_wq = create_singlethread_workqueue("smd_channel_close");
-	if (IS_ERR(channel_close_wq)) {
-		pr_err("%s: create_singlethread_workqueue ENOMEM\n", __func__);
-		return -ENOMEM;
-	}
 
 	if (smsm_init()) {
 		pr_err("smsm_init() failed\n");
@@ -3820,13 +3574,8 @@
 
 	if (pdev) {
 		if (pdev->dev.of_node) {
-			ret = smd_core_devicetree_init(pdev);
-			if (ret) {
-				pr_err("%s: device tree init failed\n",
-								__func__);
-				return ret;
-			}
-			smd_dev = &pdev->dev;
+			pr_err("%s: invalid device tree init\n", __func__);
+			return -ENODEV;
 		} else if (pdev->dev.platform_data) {
 			ret = smd_core_platform_init(pdev);
 			if (ret) {
@@ -3872,6 +3621,8 @@
 				  unsigned long code,
 				  void *data)
 {
+	remote_spinlock_t *remote_spinlock;
+
 	/*
 	 * Some SMD or SMSM clients assume SMD/SMSM SSR handling will be
 	 * done in the AFTER_SHUTDOWN level.  If this ever changes, extra
@@ -3886,7 +3637,8 @@
 				__func__, notifier->processor,
 				notifier->name);
 
-		remote_spin_release(&remote_spinlock, notifier->processor);
+		remote_spinlock = smem_get_remote_spinlock();
+		remote_spin_release(remote_spinlock, notifier->processor);
 		remote_spin_release_all(notifier->processor);
 
 		smd_channel_reset(notifier->processor);
@@ -3912,17 +3664,39 @@
 }
 late_initcall(modem_restart_late_init);
 
-static struct of_device_id msm_smem_match_table[] = {
-	{ .compatible = "qcom,smem" },
+static struct of_device_id msm_smd_match_table[] = {
+	{ .compatible = "qcom,smd" },
 	{},
 };
 
 static struct platform_driver msm_smd_driver = {
 	.probe = msm_smd_probe,
 	.driver = {
+		.name = "msm_smd_dt",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_smd_match_table,
+	},
+};
+
+static struct of_device_id msm_smsm_match_table[] = {
+	{ .compatible = "qcom,smsm" },
+	{},
+};
+
+static struct platform_driver msm_smsm_driver = {
+	.probe = msm_smsm_probe,
+	.driver = {
+		.name = "msm_smsm",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_smsm_match_table,
+	},
+};
+
+static struct platform_driver msm_smd_driver_legacy = {
+	.probe = msm_smd_probe_legacy,
+	.driver = {
 		.name = MODULE_NAME,
 		.owner = THIS_MODULE,
-		.of_match_table = msm_smem_match_table,
 	},
 };
 
@@ -3941,9 +3715,19 @@
 	}
 
 	registered = true;
-	rc = init_smem_remote_spinlock();
+
+	INIT_WORK(&probe_work, smd_channel_probe_worker);
+
+	channel_close_wq = create_singlethread_workqueue("smd_channel_close");
+	if (IS_ERR(channel_close_wq)) {
+		pr_err("%s: create_singlethread_workqueue ENOMEM\n", __func__);
+		return -ENOMEM;
+	}
+
+	rc = platform_driver_register(&msm_smd_driver_legacy);
 	if (rc) {
-		pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
+		pr_err("%s: msm_smd_driver_legacy register failed %d\n",
+			__func__, rc);
 		return rc;
 	}
 
@@ -3954,7 +3738,12 @@
 		return rc;
 	}
 
-	smd_module_init_notify(0, NULL);
+	rc = platform_driver_register(&msm_smsm_driver);
+	if (rc) {
+		pr_err("%s: msm_smsm_driver register failed %d\n",
+			__func__, rc);
+		return rc;
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 0b270b7..3461e49 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -175,8 +175,10 @@
 		if (dev == smd_tty[num_dev].device_ptr)
 			break;
 	}
-	if (num_dev >= MAX_SMD_TTYS)
+	if (num_dev >= MAX_SMD_TTYS) {
 		SMD_TTY_ERR("[%s]: Device Not Found", __func__);
+		return -EINVAL;
+	}
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			smd_tty[num_dev].open_wait);
diff --git a/arch/arm/mach-msm/smem.c b/arch/arm/mach-msm/smem.c
index 181b504..1ec2a78 100644
--- a/arch/arm/mach-msm/smem.c
+++ b/arch/arm/mach-msm/smem.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
 #include <linux/printk.h>
+#include <linux/notifier.h>
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
@@ -53,15 +54,20 @@
 			pr_debug(x);                      \
 	} while (0)
 
-remote_spinlock_t remote_spinlock;
-int spinlocks_initialized;
-uint32_t num_smem_areas;
-struct smem_area *smem_areas;
-struct ramdump_segment *smem_ramdump_segments;
+#define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
 
+static remote_spinlock_t remote_spinlock;
+static uint32_t num_smem_areas;
+static struct smem_area *smem_areas;
+static struct ramdump_segment *smem_ramdump_segments;
+static int spinlocks_initialized;
 static void *smem_ramdump_dev;
 static DEFINE_MUTEX(spinlock_init_lock);
 static DEFINE_SPINLOCK(smem_init_check_lock);
+static int smem_module_inited;
+static RAW_NOTIFIER_HEAD(smem_module_init_notifier_list);
+static DEFINE_MUTEX(smem_module_init_notifier_lock);
+
 
 struct restart_notifier_block {
 	unsigned processor;
@@ -82,6 +88,8 @@
 	{SMEM_Q6, "adsp", .nb.notifier_call = restart_notifier_cb},
 };
 
+static int init_smem_remote_spinlock(void);
+
 /**
  * smem_phys_to_virt() - Convert a physical base and offset to virtual address
  *
@@ -350,6 +358,8 @@
  */
 remote_spinlock_t *smem_get_remote_spinlock(void)
 {
+	if (unlikely(!spinlocks_initialized))
+		init_smem_remote_spinlock();
 	return &remote_spinlock;
 }
 EXPORT_SYMBOL(smem_get_remote_spinlock);
@@ -359,7 +369,7 @@
  *
  * @returns: sucess or error code for failure
  */
-int init_smem_remote_spinlock(void)
+static int init_smem_remote_spinlock(void)
 {
 	int rc = 0;
 
@@ -499,3 +509,223 @@
 	return 0;
 }
 late_initcall(modem_restart_late_init);
+
+int smem_module_init_notifier_register(struct notifier_block *nb)
+{
+	int ret;
+	if (!nb)
+		return -EINVAL;
+	mutex_lock(&smem_module_init_notifier_lock);
+	ret = raw_notifier_chain_register(&smem_module_init_notifier_list, nb);
+	if (smem_module_inited)
+		nb->notifier_call(nb, 0, NULL);
+	mutex_unlock(&smem_module_init_notifier_lock);
+	return ret;
+}
+EXPORT_SYMBOL(smem_module_init_notifier_register);
+
+int smem_module_init_notifier_unregister(struct notifier_block *nb)
+{
+	int ret;
+	if (!nb)
+		return -EINVAL;
+	mutex_lock(&smem_module_init_notifier_lock);
+	ret = raw_notifier_chain_unregister(&smem_module_init_notifier_list,
+						nb);
+	mutex_unlock(&smem_module_init_notifier_lock);
+	return ret;
+}
+EXPORT_SYMBOL(smem_module_init_notifier_unregister);
+
+static void smem_module_init_notify(uint32_t state, void *data)
+{
+	mutex_lock(&smem_module_init_notifier_lock);
+	smem_module_inited = 1;
+	raw_notifier_call_chain(&smem_module_init_notifier_list,
+					state, data);
+	mutex_unlock(&smem_module_init_notifier_lock);
+}
+
+static int msm_smem_probe(struct platform_device *pdev)
+{
+	char *key;
+	struct resource *r;
+	phys_addr_t aux_mem_base;
+	resource_size_t aux_mem_size;
+	int temp_string_size = 11; /* max 3 digit count */
+	char temp_string[temp_string_size];
+	int ret;
+	struct ramdump_segment *ramdump_segments_tmp = NULL;
+	struct smem_area *smem_areas_tmp = NULL;
+	int smem_idx = 0;
+
+	if (!smem_initialized_check())
+		return -ENODEV;
+
+	key = "irq-reg-base";
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
+	if (!r) {
+		pr_err("%s: missing '%s'\n", __func__, key);
+		return -ENODEV;
+	}
+
+	num_smem_areas = 1;
+	while (1) {
+		scnprintf(temp_string, temp_string_size, "aux-mem%d",
+				num_smem_areas);
+		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+								temp_string);
+		if (!r)
+			break;
+
+		++num_smem_areas;
+		if (num_smem_areas > 999) {
+			pr_err("%s: max num aux mem regions reached\n",
+								__func__);
+			break;
+		}
+	}
+	/* Initialize main SMEM region and SSR ramdump region */
+	key = "smem";
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
+	if (!r) {
+		pr_err("%s: missing '%s'\n", __func__, key);
+		return -ENODEV;
+	}
+
+	smem_areas_tmp = kmalloc_array(num_smem_areas, sizeof(struct smem_area),
+				GFP_KERNEL);
+	if (!smem_areas_tmp) {
+		pr_err("%s: smem areas kmalloc failed\n", __func__);
+		ret = -ENOMEM;
+		goto free_smem_areas;
+	}
+
+	ramdump_segments_tmp = kmalloc_array(num_smem_areas,
+			sizeof(struct ramdump_segment), GFP_KERNEL);
+	if (!ramdump_segments_tmp) {
+		pr_err("%s: ramdump segment kmalloc failed\n", __func__);
+		ret = -ENOMEM;
+		goto free_smem_areas;
+	}
+	smem_areas_tmp[smem_idx].phys_addr =  r->start;
+	smem_areas_tmp[smem_idx].size = resource_size(r);
+	smem_areas_tmp[smem_idx].virt_addr = MSM_SHARED_RAM_BASE;
+
+	ramdump_segments_tmp[smem_idx].address = r->start;
+	ramdump_segments_tmp[smem_idx].size = resource_size(r);
+	++smem_idx;
+
+	/* Configure auxiliary SMEM regions */
+	while (1) {
+		scnprintf(temp_string, temp_string_size, "aux-mem%d",
+								smem_idx);
+		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+							temp_string);
+		if (!r)
+			break;
+		aux_mem_base = r->start;
+		aux_mem_size = resource_size(r);
+
+		ramdump_segments_tmp[smem_idx].address = aux_mem_base;
+		ramdump_segments_tmp[smem_idx].size = aux_mem_size;
+
+		smem_areas_tmp[smem_idx].phys_addr = aux_mem_base;
+		smem_areas_tmp[smem_idx].size = aux_mem_size;
+		smem_areas_tmp[smem_idx].virt_addr = ioremap_nocache(
+			(unsigned long)(smem_areas_tmp[smem_idx].phys_addr),
+			smem_areas_tmp[smem_idx].size);
+		SMEM_DBG("%s: %s = %pa %pa -> %p", __func__, temp_string,
+				&aux_mem_base, &aux_mem_size,
+				smem_areas_tmp[smem_idx].virt_addr);
+
+		if (!smem_areas_tmp[smem_idx].virt_addr) {
+			pr_err("%s: ioremap_nocache() of addr:%pa size: %pa\n",
+				__func__,
+				&smem_areas_tmp[smem_idx].phys_addr,
+				&smem_areas_tmp[smem_idx].size);
+			ret = -ENOMEM;
+			goto free_smem_areas;
+		}
+
+		if (OVERFLOW_ADD_UNSIGNED(uintptr_t,
+				(uintptr_t)smem_areas_tmp[smem_idx].virt_addr,
+				smem_areas_tmp[smem_idx].size)) {
+			pr_err("%s: invalid virtual address block %i: %p:%pa\n",
+					__func__, smem_idx,
+					smem_areas_tmp[smem_idx].virt_addr,
+					&smem_areas_tmp[smem_idx].size);
+			++smem_idx;
+			ret = -EINVAL;
+			goto free_smem_areas;
+		}
+
+		++smem_idx;
+		if (smem_idx > 999) {
+			pr_err("%s: max num aux mem regions reached\n",
+							__func__);
+			break;
+		}
+	}
+
+	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (ret)
+		pr_err("%s: of_platform_populate failed %d\n", __func__, ret);
+
+	smem_areas = smem_areas_tmp;
+	smem_ramdump_segments = ramdump_segments_tmp;
+	return 0;
+
+free_smem_areas:
+	for (smem_idx = smem_idx - 1; smem_idx >= 1; --smem_idx)
+		iounmap(smem_areas_tmp[smem_idx].virt_addr);
+
+	num_smem_areas = 0;
+	kfree(ramdump_segments_tmp);
+	kfree(smem_areas_tmp);
+	return ret;
+}
+
+static struct of_device_id msm_smem_match_table[] = {
+	{ .compatible = "qcom,smem" },
+	{},
+};
+
+static struct platform_driver msm_smem_driver = {
+	.probe = msm_smem_probe,
+	.driver = {
+		.name = "msm_smem",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_smem_match_table,
+	},
+};
+
+int __init msm_smem_init(void)
+{
+	static bool registered;
+	int rc;
+
+	if (registered)
+		return 0;
+
+	registered = true;
+
+	rc = init_smem_remote_spinlock();
+	if (rc) {
+		pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
+		return rc;
+	}
+
+	rc = platform_driver_register(&msm_smem_driver);
+	if (rc) {
+		pr_err("%s: msm_smem_driver register failed %d\n",
+							__func__, rc);
+		return rc;
+	}
+
+	smem_module_init_notify(0, NULL);
+
+	return 0;
+}
+
+module_init(msm_smem_init);
diff --git a/arch/arm/mach-msm/smem_log.c b/arch/arm/mach-msm/smem_log.c
index 87f141d2..6f20e24 100644
--- a/arch/arm/mach-msm/smem_log.c
+++ b/arch/arm/mach-msm/smem_log.c
@@ -39,6 +39,7 @@
 #include "smd_private.h"
 #include "smd_rpc_sym.h"
 #include "modem_notifier.h"
+#include "smem_private.h"
 
 #define DEBUG
 #undef DEBUG
@@ -2005,7 +2006,7 @@
 	return ret;
 }
 
-static int smd_module_init_notifier(struct notifier_block *this,
+static int smem_module_init_notifier(struct notifier_block *this,
 				    unsigned long code,
 				    void *_cmd)
 {
@@ -2016,12 +2017,12 @@
 }
 
 static struct notifier_block nb = {
-	.notifier_call = smd_module_init_notifier,
+	.notifier_call = smem_module_init_notifier,
 };
 
 static int __init smem_log_init(void)
 {
-	return smd_module_init_notifier_register(&nb);
+	return smem_module_init_notifier_register(&nb);
 }
 
 
diff --git a/arch/arm/mach-msm/smem_private.h b/arch/arm/mach-msm/smem_private.h
index c4f9a77..ceb8028 100644
--- a/arch/arm/mach-msm/smem_private.h
+++ b/arch/arm/mach-msm/smem_private.h
@@ -17,10 +17,6 @@
 
 #include <mach/ramdump.h>
 
-#define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
-extern remote_spinlock_t remote_spinlock;
-extern int spinlocks_initialized; /* only modify in init_smem_remote_spinlock */
-
 #define SMD_HEAP_SIZE 512
 
 struct smem_heap_info {
@@ -58,19 +54,26 @@
 	void __iomem *virt_addr;
 };
 
-extern uint32_t num_smem_areas;
-extern struct smem_area *smem_areas;
-
-extern struct ramdump_segment *smem_ramdump_segments;
-
 /* used for unit testing spinlocks */
 remote_spinlock_t *smem_get_remote_spinlock(void);
 
-/*
- * used to ensure the remote spinlock is only inited once since local
- * spinlock init code appears non-reentrant
- */
-int init_smem_remote_spinlock(void);
-
 bool smem_initialized_check(void);
+
+/**
+ * smem_module_init_notifier_register() - Register a smem module
+ *                                       init notifier block
+ * @nb: Notifier block to be registered
+ *
+ * In order to mark the dependency on SMEM Driver module initialization
+ * register a notifier using this API. Once the smem module_init is
+ * done, notification will be passed to the registered module.
+ */
+int smem_module_init_notifier_register(struct notifier_block *nb);
+
+/**
+ * smem_module_init_notifier_register() - Unregister a smem module
+ *                                       init notifier block
+ * @nb: Notifier block to be unregistered
+ */
+int smem_module_init_notifier_unregister(struct notifier_block *nb);
 #endif /* _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_ */
diff --git a/arch/arm/mach-msm/smp2p.c b/arch/arm/mach-msm/smp2p.c
index ee262b0..4b69cf0 100644
--- a/arch/arm/mach-msm/smp2p.c
+++ b/arch/arm/mach-msm/smp2p.c
@@ -379,7 +379,7 @@
 	struct smp2p_out_list_item *out_item)
 {
 	void *item_ptr = NULL;
-	unsigned size;
+	unsigned size = 0;
 
 	if (!out_item)
 		return item_ptr;
@@ -1241,7 +1241,7 @@
 {
 	unsigned long flags;
 	struct smp2p_out_list_item *out_item;
-	uint32_t *entry_ptr;
+	uint32_t *entry_ptr = NULL;
 
 	if (remote_pid >= SMP2P_NUM_PROCS)
 		return -EINVAL;
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 575cb49..41509f7 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -282,6 +282,24 @@
 	[185] = MSM_CPU_8974,
 	[186] = MSM_CPU_8974,
 
+	/* 8974AA IDs */
+	[208] = MSM_CPU_8974PRO_AA,
+	[211] = MSM_CPU_8974PRO_AA,
+	[214] = MSM_CPU_8974PRO_AA,
+	[217] = MSM_CPU_8974PRO_AA,
+
+	/* 8974AB IDs */
+	[209] = MSM_CPU_8974PRO_AB,
+	[212] = MSM_CPU_8974PRO_AB,
+	[215] = MSM_CPU_8974PRO_AB,
+	[218] = MSM_CPU_8974PRO_AB,
+
+	/* 8974AC IDs */
+	[194] = MSM_CPU_8974PRO_AC,
+	[210] = MSM_CPU_8974PRO_AC,
+	[213] = MSM_CPU_8974PRO_AC,
+	[216] = MSM_CPU_8974PRO_AC,
+
 	/* 8625 IDs */
 	[127] = MSM_CPU_8625,
 	[128] = MSM_CPU_8625,
diff --git a/block/row-iosched.c b/block/row-iosched.c
index e71f6af..3fa3b1a 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -97,7 +97,7 @@
 
 /* Default values for idling on read queues (in msec) */
 #define ROW_IDLE_TIME_MSEC 5
-#define ROW_READ_FREQ_MSEC 20
+#define ROW_READ_FREQ_MSEC 5
 
 /**
  * struct rowq_idling_data -  parameters for idling on the queue
@@ -331,6 +331,10 @@
 	struct row_queue *rqueue = RQ_ROWQ(rq);
 	s64 diff_ms;
 	bool queue_was_empty = list_empty(&rqueue->fifo);
+	unsigned long bv_page_flags = 0;
+
+	if (rq->bio && rq->bio->bi_io_vec && rq->bio->bi_io_vec->bv_page)
+		bv_page_flags = rq->bio->bi_io_vec->bv_page->flags;
 
 	list_add_tail(&rq->queuelist, &rqueue->fifo);
 	rd->nr_reqs[rq_data_dir(rq)]++;
@@ -360,7 +364,9 @@
 			rqueue->idle_data.begin_idling = false;
 			return;
 		}
-		if (diff_ms < rd->rd_idle_data.freq_ms) {
+
+		if ((bv_page_flags & (1L << PG_readahead)) ||
+		    (diff_ms < rd->rd_idle_data.freq_ms)) {
 			rqueue->idle_data.begin_idling = true;
 			row_log_rowq(rd, rqueue->prio, "Enable idling");
 		} else {
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index b1c1c5d..a80b0c6 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -94,8 +94,10 @@
 		}
 
 		info = kmalloc(sizeof(struct page_info), GFP_KERNEL);
-		info->page = page;
-		info->order = orders[i];
+		if (info) {
+			info->page = page;
+			info->order = orders[i];
+		}
 		return info;
 	}
 	return NULL;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 44c9c29..ed266dc 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -258,6 +258,10 @@
 	struct adreno_perfcount_group *group;
 	unsigned int i, j;
 
+	/* perfcounter start does nothing on a2xx */
+	if (adreno_is_a2xx(adreno_dev))
+		return;
+
 	/* group id iter */
 	for (i = 0; i < counters->group_count; i++) {
 		group = &(counters->groups[i]);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e62dac9..e790d88 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2429,6 +2429,7 @@
 	int result;
 	struct kgsl_process_private *private = dev_priv->process_priv;
 	struct kgsl_mem_entry *entry;
+	int align;
 
 	/*
 	 * Mask off unknown flags from userspace. This way the caller can
@@ -2440,6 +2441,16 @@
 		| KGSL_MEMALIGN_MASK
 		| KGSL_MEMFLAGS_USE_CPU_MAP;
 
+	/* Cap the alignment bits to the highest number we can handle */
+
+	align = (flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
+	if (align >= 32) {
+		KGSL_CORE_ERR("Alignment too big, restricting to 2^31\n");
+
+		flags &= ~KGSL_MEMALIGN_MASK;
+		flags |= (31 << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK;
+	}
+
 	entry = kgsl_mem_entry_create();
 	if (entry == NULL)
 		return -ENOMEM;
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 204ad94..dd2e5d8 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -144,6 +144,13 @@
 	y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]);
 	z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]);
 
+	/* 8 bits output mode support */
+	if (!(tj9->ctrl_reg1 & RES_12BIT)) {
+		x <<= 4;
+		y <<= 4;
+		z <<= 4;
+	}
+
 	x >>= tj9->shift;
 	y >>= tj9->shift;
 	z >>= tj9->shift;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index cb8d821..2db25a6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -39,7 +39,7 @@
 #define VFE40_BURST_LEN 3
 #define VFE40_STATS_BURST_LEN 2
 #define VFE40_UB_SIZE 1536
-#define VFE40_EQUAL_SLICE_UB 286
+#define VFE40_EQUAL_SLICE_UB 228
 #define VFE40_WM_BASE(idx) (0x6C + 0x24 * idx)
 #define VFE40_RDI_BASE(idx) (0x2E8 + 0x4 * idx)
 #define VFE40_XBAR_BASE(idx) (0x58 + 0x4 * (idx / 2))
@@ -1299,7 +1299,7 @@
 }
 
 static struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
-	.num_wm = 4,
+	.num_wm = 5,
 	.num_comp_mask = 3,
 	.num_rdi = 3,
 	.num_rdi_master = 3,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index a6c5639..a27ca99 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -795,10 +795,7 @@
 		rc = msm_cci_config(sd, arg);
 		break;
 	case MSM_SD_SHUTDOWN: {
-		struct msm_camera_cci_ctrl ctrl_cmd;
-		ctrl_cmd.cmd = MSM_CCI_RELEASE;
-		rc = msm_cci_config(sd, &ctrl_cmd);
-		break;
+		return rc;
 	}
 	default:
 		rc = -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 34f4428..7f474bb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1175,9 +1175,10 @@
 	case VIDIOC_MSM_SENSOR_CFG:
 		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
 	case VIDIOC_MSM_SENSOR_RELEASE:
-	case MSM_SD_SHUTDOWN:
 		msm_sensor_stop_stream(s_ctrl);
 		return 0;
+	case MSM_SD_SHUTDOWN:
+		return 0;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index b81af11..d8cff35 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -55,7 +55,7 @@
 
 	for (i = 0; i < nr_strings; i++) {
 		buffer[i] = string;
-		strlcpy(string, buf, strlen(buf));
+		strlcpy(string, buf, strlen(buf) + 1);
 		string += strlen(string) + 1;
 		buf += strlen(buf) + 1;
 	}
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index f000df7..644a751 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -1307,6 +1307,8 @@
 			next_state = ECM_IPA_INITIALIZED;
 		else if (operation == ECM_IPA_CONNECT)
 			next_state = ECM_IPA_CONNECTED_AND_UP;
+		else if (operation == ECM_IPA_CLEANUP)
+			next_state = ECM_IPA_UNLOADED;
 		break;
 	case ECM_IPA_CONNECTED_AND_UP:
 		if (operation == ECM_IPA_STOP)
diff --git a/drivers/net/ethernet/msm/msm_rmnet_wwan.c b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
index 98bdccc..3e4605f 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_wwan.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_wwan.c
@@ -188,6 +188,9 @@
 		      __func__, skb);
 		netif_wake_queue(dev);
 	}
+	if (a2_mux_is_ch_empty(a2_mux_lcid_by_ch_id[wwan_ptr->ch_id]))
+		ipa_rm_inactivity_timer_release_resource(
+			ipa_rm_resource_by_ch_id[wwan_ptr->ch_id]);
 	spin_unlock_irqrestore(&wwan_ptr->lock, flags);
 }
 
@@ -533,6 +536,7 @@
 		       __func__, skb);
 	}
 	spin_unlock_irqrestore(&wwan_ptr->lock, flags);
+	return ret;
 exit:
 	ipa_rm_inactivity_timer_release_resource(
 		ipa_rm_resource_by_ch_id[wwan_ptr->ch_id]);
@@ -548,6 +552,7 @@
 static void wwan_tx_timeout(struct net_device *dev)
 {
 	pr_warning("[%s] wwan_tx_timeout(), data stall in UL\n", dev->name);
+	ipa_bam_reg_dump();
 }
 
 /**
diff --git a/drivers/net/ethernet/msm/qfec.c b/drivers/net/ethernet/msm/qfec.c
index 164b734..e68c395 100644
--- a/drivers/net/ethernet/msm/qfec.c
+++ b/drivers/net/ethernet/msm/qfec.c
@@ -2921,6 +2921,8 @@
 	priv->mii.dev           = dev;
 	priv->mii.mdio_read     = qfec_mdio_read;
 	priv->mii.mdio_write    = qfec_mdio_write;
+	/* initialize mdio clock */
+	priv->mdio_clk    = GMII_ADR_REG_CR_62;
 
 	/* map register regions */
 	ret = qfec_map_resource(
diff --git a/drivers/net/ethernet/msm/qfec.h b/drivers/net/ethernet/msm/qfec.h
index 525fd9c..a25436f 100644
--- a/drivers/net/ethernet/msm/qfec.h
+++ b/drivers/net/ethernet/msm/qfec.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2011,2013 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
@@ -411,6 +411,14 @@
 # define GMII_ADR_REG_GR           0x000007c0 /* addr bits */
 # define GMII_ADR_REG_RSVRD1       0x00000020 /* */
 # define GMII_ADR_REG_CR           0x0000001c /* csr clock range */
+
+# define GMII_ADR_REG_CR_42        0x00000000 /* csr clock 42 */
+# define GMII_ADR_REG_CR_62        0x00000001 /* csr clock 62 */
+# define GMII_ADR_REG_CR_16        0x00000002 /* csr clock 16 */
+# define GMII_ADR_REG_CR_26        0x00000003 /* csr clock 26 */
+# define GMII_ADR_REG_CR_102       0x00000004 /* csr clock 102 */
+# define GMII_ADR_REG_CR_124       0x00000005 /* csr clock 124 */
+
 # define GMII_ADR_REG_GW           0x00000002 /* gmii write */
 # define GMII_ADR_REG_GB           0x00000001 /* gmii busy */
 
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index a3d7f12..5e22c35 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -112,6 +112,9 @@
 #define CCU_PRONTO_LAST_ADDR1_OFFSET		0x10
 #define CCU_PRONTO_LAST_ADDR2_OFFSET		0x14
 
+#define MSM_PRONTO_SAW2_BASE			0xfb219000
+#define PRONTO_SAW2_SPM_STS_OFFSET		0x0c
+
 #define WCNSS_DEF_WLAN_RX_BUFF_COUNT		1024
 
 #define WCNSS_CTRL_CHANNEL			"WCNSS_CTRL"
@@ -288,6 +291,7 @@
 	void __iomem *riva_ccu_base;
 	void __iomem *pronto_a2xb_base;
 	void __iomem *pronto_ccpu_base;
+	void __iomem *pronto_saw2_base;
 	void __iomem *fiq_reg;
 	int	ssr_boot;
 	int	nv_downloaded;
@@ -479,6 +483,10 @@
 	reg = readl_relaxed(reg_addr);
 	pr_info_ratelimited("%s: CCU_CCPU_LAST_ADDR2 %08x\n", __func__, reg);
 
+	reg_addr = penv->pronto_saw2_base + PRONTO_SAW2_SPM_STS_OFFSET;
+	reg = readl_relaxed(reg_addr);
+	pr_info_ratelimited("%s: PRONTO_SAW2_SPM_STS %08x\n", __func__, reg);
+
 	tst_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_OFFSET;
 	tst_ctrl_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_CTRL_OFFSET;
 
@@ -1683,6 +1691,14 @@
 			ret = -ENOMEM;
 			goto fail_ioremap4;
 		}
+		penv->pronto_saw2_base = ioremap_nocache(MSM_PRONTO_SAW2_BASE,
+				SZ_32);
+		if (!penv->pronto_saw2_base) {
+			pr_err("%s: ioremap wcnss physical(saw2) failed\n",
+					__func__);
+			ret = -ENOMEM;
+			goto fail_ioremap5;
+		}
 	}
 
 	/* trigger initialization of the WCNSS */
@@ -1699,6 +1715,9 @@
 fail_pil:
 	if (penv->riva_ccu_base)
 		iounmap(penv->riva_ccu_base);
+	if (penv->pronto_saw2_base)
+		iounmap(penv->pronto_saw2_base);
+fail_ioremap5:
 	if (penv->fiq_reg)
 		iounmap(penv->fiq_reg);
 fail_ioremap4:
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index 4921ec2..ae9277e 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -1469,6 +1469,35 @@
 	return ret;
 }
 
+/**
+ * a2_mux_is_ch_empty() - checks if channel is empty.
+ * @lcid: logical channel ID
+ *
+ * Returns: true if the channel is empty,
+ *		false otherwise
+ */
+int a2_mux_is_ch_empty(enum a2_mux_logical_channel_id lcid)
+{
+	unsigned long flags;
+	int ret;
+
+	if (lcid >= A2_MUX_NUM_CHANNELS ||
+			lcid < 0)
+		return -EINVAL;
+	if (!a2_mux_ctx->a2_mux_initialized)
+		return -ENODEV;
+	spin_lock_irqsave(&a2_mux_ctx->bam_ch[lcid].lock, flags);
+	a2_mux_ctx->bam_ch[lcid].use_wm = 1;
+	ret = a2_mux_ctx->bam_ch[lcid].num_tx_pkts == 0;
+	if (!bam_ch_is_local_open(lcid)) {
+		ret = -ENODEV;
+		IPAERR("%s: port not open: %d\n", __func__,
+		       a2_mux_ctx->bam_ch[lcid].status);
+	}
+	spin_unlock_irqrestore(&a2_mux_ctx->bam_ch[lcid].lock, flags);
+	return ret;
+}
+
 static int a2_mux_initialize_context(int handle)
 {
 	int i;
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index 83c4db0..f9401f0 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -468,7 +468,7 @@
 {
 	int i;
 
-	ipa_ctx->smem_pipe_mem = smem_alloc(SMEM_BAM_PIPE_MEMORY,
+	ipa_ctx->smem_pipe_mem = smem_alloc2(SMEM_BAM_PIPE_MEMORY,
 			IPA_SMEM_PIPE_MEM_SZ);
 	if (!ipa_ctx->smem_pipe_mem) {
 		IPAERR("smem alloc failed\n");
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index e98c9b7..f20f37f 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -203,6 +203,7 @@
 	}
 
 	memset(&ipa_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa_ep_context));
+	ipa_enable_data_path(ipa_ep_idx);
 
 	ep->valid = 1;
 	ep->client = in->client;
@@ -380,7 +381,6 @@
 		return -EPERM;
 	}
 
-	ipa_enable_data_path(clnt_hdl);
 	memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
 
 	ipa_dec_client_disable_clks();
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 1f232d4..e2856cf 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -641,7 +641,7 @@
 	switch (notify->event_id) {
 	case SPS_EVENT_EOT:
 		tx_pkt = notify->data.transfer.user;
-		queue_work(ipa_ctx->tx_wq, &tx_pkt->work);
+		schedule_work(&tx_pkt->work);
 		break;
 	default:
 		IPAERR("recieved unexpected event id %d\n", notify->event_id);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index b1e2d93..e38b796 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -13,7 +13,9 @@
 #include <net/ip.h>
 #include <linux/genalloc.h>	/* gen_pool_alloc() */
 #include <linux/io.h>
+#include <linux/ratelimit.h>
 #include "ipa_i.h"
+
 static const int ipa_ofst_meq32[] = { IPA_OFFSET_MEQ32_0,
 					IPA_OFFSET_MEQ32_1, -1 };
 static const int ipa_ofst_meq128[] = { IPA_OFFSET_MEQ128_0,
@@ -1382,3 +1384,26 @@
 	else
 		return 0;
 }
+
+/**
+ * ipa_bam_reg_dump() - Dump selected BAM registers for IPA and DMA-BAM
+ *
+ * Function is rate limited to avoid flooding kernel log buffer
+ */
+void ipa_bam_reg_dump(void)
+{
+	static DEFINE_RATELIMIT_STATE(_rs, 500*HZ, 1);
+	if (__ratelimit(&_rs)) {
+		ipa_inc_client_enable_clks();
+		pr_err("IPA BAM START\n");
+		sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 1048575, 0, 0);
+		sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
+		pr_err("BAM-DMA BAM START\n");
+		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 5, 1044480,
+				0, 0);
+		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 93, 0, 0, 0);
+		ipa_dec_client_disable_clks();
+	}
+}
+EXPORT_SYMBOL(ipa_bam_reg_dump);
+
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index fae09fc..4889a79 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -153,7 +153,6 @@
 	bool prod_stopped;
 
 	struct completion prod_avail[MAX_BAMS];
-	struct completion cons_released[MAX_BAMS];
 	struct completion prod_released[MAX_BAMS];
 
 	struct mutex suspend_resume_mutex;
@@ -175,7 +174,6 @@
 static int __usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
 	void *param, bool trigger_cb_per_pipe);
 static void wait_for_prod_release(enum usb_bam cur_bam);
-static void wait_for_cons_release(enum usb_bam cur_bam);
 
 void msm_bam_set_hsic_host_dev(struct device *dev)
 {
@@ -936,7 +934,6 @@
 			__func__, bam_enable_strings[cur_bam]);
 
 	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-	complete_all(&info.cons_released[cur_bam]);
 
 	spin_lock(&usb_bam_lock);
 	if (!ctx.pipes_enabled_per_bam[cur_bam]) {
@@ -1078,7 +1075,6 @@
 		pr_debug("%s producer already released\n", __func__);
 
 	init_completion(&info.prod_released[cur_bam]);
-	init_completion(&info.cons_released[cur_bam]);
 	pr_debug("%s: Releasing %s_PROD\n", __func__,
 				bam_enable_strings[cur_bam]);
 	ret = ipa_rm_release_resource(ipa_rm_resource_prod[cur_bam]);
@@ -1908,19 +1904,6 @@
 	return 0;
 }
 
-static void wait_for_cons_release(enum usb_bam cur_bam)
-{
-	 pr_debug("%s: Waiting for CONS release\n", __func__);
-	 if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
-		if (!wait_for_completion_timeout(&info.cons_released[cur_bam],
-						  USB_BAM_TIMEOUT))
-			pr_err("%s: Timeout wainting for CONS_RELEASE\n",
-				__func__);
-	 } else
-		pr_debug("%s Didn't need to wait for CONS release\n",
-		     __func__);
-}
-
 int usb_bam_disconnect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	int ret;
@@ -1987,7 +1970,6 @@
 		pipe_connect->priv = NULL;
 
 		cur_bam = pipe_connect->bam_type;
-		wait_for_cons_release(cur_bam);
 		/* close IPA -> USB pipe */
 		ret = ipa_disconnect(ipa_params->cons_clnt_hdl);
 		if (ret) {
@@ -2542,8 +2524,6 @@
 		ctx.is_bam_inactivity[i] = false;
 		init_completion(&info.prod_avail[i]);
 		complete(&info.prod_avail[i]);
-		init_completion(&info.cons_released[i]);
-		complete(&info.cons_released[i]);
 		init_completion(&info.prod_released[i]);
 		complete(&info.prod_released[i]);
 		info.cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 3322da5..577a4fe 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -200,7 +200,6 @@
 	int ret;
 
 	pr_debug("%s: Connect workqueue started", __func__);
-	usb_bam_reset_complete();
 
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
 		if (d->func_type == USB_FUNC_MBIM) {
@@ -268,17 +267,18 @@
 			}
 		}
 	} else { /* transport type is USB_GADGET_XPORT_BAM2BAM */
-	ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
-	if (ret) {
-		pr_err("usb_bam_connect (src) failed: err:%d\n", ret);
-		return;
+		usb_bam_reset_complete();
+		ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
+		if (ret) {
+			pr_err("usb_bam_connect (src) failed: err:%d\n", ret);
+			return;
+		}
+		ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
+		if (ret) {
+			pr_err("usb_bam_connect (dst) failed: err:%d\n", ret);
+			return;
+		}
 	}
-	ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
-	if (ret) {
-		pr_err("usb_bam_connect (dst) failed: err:%d\n", ret);
-		return;
-	}
-}
 
 	if (!port->port_usb) {
 		pr_err("port_usb is NULL");
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 14c3323..ef45d49 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1895,6 +1895,8 @@
 				"hsic,consider-ipa-handshake"));
 	pdata->ahb_async_bridge_bypass = of_property_read_bool(node,
 				"qcom,ahb-async-bridge-bypass");
+	pdata->disable_cerr = of_property_read_bool(node,
+				"hsic,disable-cerr");
 
 	return pdata;
 }
@@ -1982,8 +1984,10 @@
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
 	mehci->enable_hbm = pdata->enable_hbm;
 
-	if (pdata)
+	if (pdata) {
 		mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
+		mehci->ehci.disable_cerr = pdata->disable_cerr;
+	}
 
 	ret = msm_hsic_init_gdsc(mehci, 1);
 	if (ret) {
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 0b89dd0..823229b 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -1,6 +1,6 @@
 /* ehci-msm.c - HSUSB Host Controller Driver Implementation
  *
- * Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * Partly derived from ehci-fsl.c and ehci-hcd.c
  * Copyright (c) 2000-2004 by David Brownell
@@ -260,15 +260,23 @@
 static int ehci_msm_pm_resume(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	int ret;
 
 	dev_dbg(dev, "ehci-msm PM resume\n");
 
 	if (!hcd->rh_registered)
 		return 0;
 
-	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	/* Notify OTG to bring hw out of LPM before restoring wakeup flags */
+	ret = usb_phy_set_suspend(phy, 0);
+	if (ret)
+		return ret;
 
-	return usb_phy_set_suspend(phy, 0);
+	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	/* Resume root-hub to handle USB event if any else initiate LPM again */
+	usb_hcd_resume_root_hub(hcd);
+
+	return ret;
 }
 #endif
 
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index db49c07..b029be2 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -637,7 +637,8 @@
 	qtd->urb = urb;
 
 	token = QTD_STS_ACTIVE;
-	token |= (EHCI_TUNE_CERR << 10);
+	if (!ehci->disable_cerr)
+		token |= (EHCI_TUNE_CERR << 10);
 	/* for split transactions, SplitXState initialized to zero */
 
 	len = urb->transfer_buffer_length;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index edf2a73..0498a6a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -154,6 +154,7 @@
 	unsigned		susp_sof_bug:1; /*Chip Idea HC*/
 	unsigned		resume_sof_bug:1;/*Chip Idea HC*/
 	unsigned		reset_sof_bug:1; /*Chip Idea HC*/
+	bool			disable_cerr;
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index aecb19d..91e70a7 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -539,13 +539,6 @@
 	return 0;
 }
 
-static int mdp3_iommu_fault_handler(struct iommu_domain *domain,
-		struct device *dev, unsigned long iova, int flags, void *token)
-{
-	pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
-	return 0;
-}
-
 int mdp3_iommu_attach(int context)
 {
 	struct mdp3_iommu_ctx_map *context_map;
@@ -621,9 +614,6 @@
 			else
 				return PTR_ERR(mdp3_iommu_domains[i].domain);
 		}
-		iommu_set_fault_handler(mdp3_iommu_domains[i].domain,
-					mdp3_iommu_fault_handler,
-					NULL);
 	}
 
 	mdp3_res->domains = mdp3_iommu_domains;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 366209b..fb0e8ba 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -416,6 +416,14 @@
 
 	mdss_dsi_clk_ctrl(ctrl_pdata, 0);
 
+	ret = mdss_dsi_enable_bus_clocks(ctrl_pdata);
+	if (ret) {
+		pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
+			ret);
+		mdss_dsi_panel_power_on(pdata, 0);
+		return ret;
+	}
+
 	/* disable DSI phy */
 	mdss_dsi_phy_enable(ctrl_pdata, 0);
 
@@ -479,6 +487,7 @@
 
 	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
 	mdss_dsi_phy_init(pdata);
+	mdss_dsi_disable_bus_clocks(ctrl_pdata);
 
 	mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 
@@ -593,6 +602,13 @@
 	}
 	mdss_dsi_op_mode_config(mipi->mode, pdata);
 
+	if (pdata->panel_info.type == MIPI_CMD_PANEL) {
+		if (mipi->vsync_enable && mipi->hw_vsync_mode
+			&& gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+				mdss_dsi_set_tear_on(ctrl_pdata);
+		}
+	}
+
 	pr_debug("%s-:\n", __func__);
 
 	return ret;
@@ -601,6 +617,7 @@
 static int mdss_dsi_blank(struct mdss_panel_data *pdata)
 {
 	int ret = 0;
+	struct mipi_panel_info *mipi;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	pr_debug("%s+:\n", __func__);
@@ -612,9 +629,17 @@
 
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
 				panel_data);
+	mipi = &pdata->panel_info.mipi;
 
 	mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
 
+	if (pdata->panel_info.type == MIPI_CMD_PANEL) {
+		if (mipi->vsync_enable && mipi->hw_vsync_mode
+			&& gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+			mdss_dsi_set_tear_off(ctrl_pdata);
+		}
+	}
+
 	if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
 		ret = ctrl_pdata->off(pdata);
 		if (ret) {
@@ -1143,15 +1168,6 @@
 			return rc;
 		}
 
-		rc = mdss_dsi_enable_bus_clocks(ctrl_pdata);
-		if (rc) {
-			pr_err("%s: failed to enable bus clocks. rc=%d\n",
-				__func__, rc);
-			rc = mdss_dsi_panel_power_on(
-				&(ctrl_pdata->panel_data), 0);
-			return rc;
-		}
-
 		mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 		ctrl_pdata->ctrl_state |=
 			(CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 965a23f..8a8e4ca 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -382,6 +382,8 @@
 
 void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
 				struct mdss_panel_data *pdata);
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_op_mode_config(int mode,
 				struct mdss_panel_data *pdata);
 void mdss_dsi_cmd_mode_ctrl(int enable);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 60b8b2e..2f29b3d 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -80,6 +80,7 @@
 	mutex_lock(&ctrl->mutex);
 	if (enable) {
 		if (ctrl->clk_cnt == 0) {
+			mdss_dsi_enable_bus_clocks(ctrl);
 			mdss_dsi_prepare_clocks(ctrl);
 			mdss_dsi_clk_enable(ctrl);
 		}
@@ -90,6 +91,7 @@
 			if (ctrl->clk_cnt == 0) {
 				mdss_dsi_clk_disable(ctrl);
 				mdss_dsi_unprepare_clocks(ctrl);
+				mdss_dsi_disable_bus_clocks(ctrl);
 			}
 		}
 	}
@@ -1098,6 +1100,40 @@
 	pr_debug("%s: BTA done, status = %d\n", __func__, status);
 }
 
+static char set_tear_on[2] = {0x35, 0x00};
+static struct dsi_cmd_desc dsi_tear_on_cmd = {
+	{DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
+
+static char set_tear_off[2] = {0x34, 0x00};
+static struct dsi_cmd_desc dsi_tear_off_cmd = {
+	{DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off)}, set_tear_off};
+
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_on_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_off_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
 int mdss_dsi_cmd_reg_tx(u32 data,
 			unsigned char *ctrl_base)
 {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 287f2cd..91e5660 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -2250,6 +2250,8 @@
 	 */
 	hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate = 0;
 
+	hdmi_cec_deconfig(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
+
 	hdmi_tx_core_off(hdmi_ctrl);
 
 	if (hdmi_ctrl->hpd_off_pending) {
@@ -2257,8 +2259,6 @@
 		hdmi_ctrl->hpd_off_pending = false;
 	}
 
-	hdmi_cec_deconfig(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
-
 	mutex_lock(&hdmi_ctrl->mutex);
 	hdmi_ctrl->panel_power_on = false;
 	mutex_unlock(&hdmi_ctrl->mutex);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index c4bf67e..fc8c6e3 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -703,13 +703,6 @@
 	return 0;
 }
 
-static int mdss_iommu_fault_handler(struct iommu_domain *domain,
-		struct device *dev, unsigned long iova, int flags, void *token)
-{
-	pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
-	return 0;
-}
-
 int mdss_iommu_attach(struct mdss_data_type *mdata)
 {
 	struct iommu_domain *domain;
@@ -796,7 +789,6 @@
 				iomap->domain_idx);
 			return -EINVAL;
 		}
-		iommu_set_fault_handler(domain, mdss_iommu_fault_handler, NULL);
 
 		iomap->ctx = msm_iommu_get_ctx(iomap->ctx_name);
 		if (!iomap->ctx) {
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 52224e2..7cae18c 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -430,6 +430,7 @@
 struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
 					struct msm_fb_data_type *mfd);
 int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_video_copy_splash_screen(struct mdss_panel_data *pdata);
 void mdss_mdp_ctl_splash_start(struct mdss_panel_data *pdata);
 int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 9eaff61..86f632c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -517,6 +517,7 @@
 	case MIPI_VIDEO_PANEL:
 		return mdss_mdp_video_reconfigure_splash_done(ctl);
 	case MIPI_CMD_PANEL:
+		return mdss_mdp_cmd_reconfigure_splash_done(ctl);
 	default:
 		return 0;
 	}
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 89e21d2..d0c1818 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -357,6 +357,24 @@
 	return 0;
 }
 
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_panel_data *pdata;
+	int ret = 0;
+
+	pdata = ctl->panel_data;
+
+	pdata->panel_info.cont_splash_enabled = 0;
+
+	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_FINISH,
+			NULL);
+
+	mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return ret;
+}
+
 static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg)
 {
 	struct mdss_mdp_cmd_ctx *ctx;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 75b6056..4dd9dcb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -3329,6 +3329,14 @@
 				ret = 1;
 		else if (ptr >= 0x3200 || ptr == 0x100)
 				ret = 1;
+		else if (ptr == 0x104 || ptr == 0x614 || ptr == 0x714 ||
+			ptr == 0x814 || ptr == 0x914 || ptr == 0xa14)
+				ret = 1;
+		else if (ptr == 0x618 || ptr == 0x718 || ptr == 0x818 ||
+				 ptr == 0x918 || ptr == 0xa18)
+				ret = 1;
+		else if (ptr == 0x2234 || ptr == 0x1e34 || ptr == 0x2634)
+				ret = 1;
 	}
 end:
 	return ret;
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index c88d2a9..86e4c91 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -108,6 +108,7 @@
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 	PG_compound_lock,
 #endif
+	PG_readahead,		/* page in a readahead window */
 	__NR_PAGEFLAGS,
 
 	/* Filesystems */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 44c6d7f..bfed960 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -457,6 +457,7 @@
 	bool disable_park_mode;
 	bool consider_ipa_handshake;
 	bool ahb_async_bridge_bypass;
+	bool disable_cerr;
 };
 
 struct msm_usb_host_platform_data {
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 5148c1a..9cc2f45 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -6093,6 +6093,7 @@
 #ifdef CONFIG_MEMORY_FAILURE
 	{1UL << PG_hwpoison,		"hwpoison"	},
 #endif
+	{1UL << PG_readahead,           "PG_readahead"  },
 	{-1UL,				NULL		},
 };
 
diff --git a/mm/readahead.c b/mm/readahead.c
index 728a7a3..56f8a24 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -184,6 +184,9 @@
 		if (!page)
 			break;
 		page->index = page_offset;
+
+		page->flags |= (1L << PG_readahead);
+
 		list_add(&page->lru, &page_pool);
 		if (page_idx == nr_to_read - lookahead_size)
 			SetPageReadahead(page);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 4a20af1..687f10d 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -625,20 +625,26 @@
 {
 	int rc = 0;
 	int avg_vol = 0;
+	int lgain = (volume >> 16) & 0xFFFF;
+	int rgain = volume & 0xFFFF;
 	if (compressed_audio.prtd && compressed_audio.prtd->audio_client) {
-		if (compressed_audio.prtd->channel_mode > 2) {
-			avg_vol = (((volume >> 16) & 0xFFFF) +
-				   (volume & 0xFFFF)) / 2;
-			rc = q6asm_set_volume(
-				compressed_audio.prtd->audio_client, avg_vol);
-		} else {
+		pr_debug("%s: channels %d volume 0x%x\n", __func__,
+			compressed_audio.prtd->channel_mode, volume);
+		if ((compressed_audio.prtd->channel_mode <= 2) &&
+			(lgain != rgain)) {
+			pr_debug("%s: call q6asm_set_lrgain\n", __func__);
 			rc = q6asm_set_lrgain(
 				compressed_audio.prtd->audio_client,
-				(volume >> 16) & 0xFFFF, volume & 0xFFFF);
+				lgain, rgain);
+		} else {
+			avg_vol = (lgain + rgain)/2;
+			pr_debug("%s: call q6asm_set_volume\n", __func__);
+			rc = q6asm_set_volume(
+				compressed_audio.prtd->audio_client, avg_vol);
 		}
 		if (rc < 0) {
 			pr_err("%s: Send Volume command failed rc=%d\n",
-						__func__, rc);
+				__func__, rc);
 		}
 	}
 	compressed_audio.volume = volume;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 77f3a07..11f9e72 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -42,12 +42,6 @@
 	struct snd_pcm *pcm;
 };
 
-struct snd_msm_volume {
-	struct msm_audio *prtd;
-	unsigned volume;
-};
-static struct snd_msm_volume pcm_audio = {NULL, 0x2000};
-
 #define PLAYBACK_MIN_NUM_PERIODS    2
 #define PLAYBACK_MAX_NUM_PERIODS    8
 #define PLAYBACK_MAX_PERIOD_SIZE    12288
@@ -390,7 +384,6 @@
 	prtd->dsp_cnt = 0;
 	prtd->set_channel_map = false;
 	runtime->private_data = prtd;
-	pcm_audio.prtd = prtd;
 
 	return 0;
 }
@@ -479,7 +472,6 @@
 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 		q6asm_audio_client_buf_free_contiguous(dir,
 					prtd->audio_client);
-		pcm_audio.prtd = NULL;
 		q6asm_audio_client_free(prtd->audio_client);
 	}
 	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
@@ -760,30 +752,71 @@
 	.mmap		= msm_pcm_mmap,
 };
 
-static int pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
+static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
 	int i;
-	char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	struct snd_pcm_substream *substream;
+	struct msm_audio *prtd;
 
 	pr_debug("%s", __func__);
-	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
-		channel_mapping[i] = (char)(ucontrol->value.integer.value[i]);
-	if (pcm_audio.prtd) {
-		pcm_audio.prtd->set_channel_map = true;
-		memcpy(pcm_audio.prtd->channel_map, channel_mapping,
-			PCM_FORMAT_MAX_NUM_CHANNEL);
+	substream = snd_pcm_chmap_substream(info, idx);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+
+	prtd = substream->runtime->private_data;
+	if (prtd) {
+		prtd->set_channel_map = true;
+			for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+				prtd->channel_map[i] =
+				(char)(ucontrol->value.integer.value[i]);
 	}
 	return 0;
 }
 
+static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
+	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	struct snd_pcm_substream *substream;
+	struct msm_audio *prtd;
+
+	pr_debug("%s", __func__);
+	substream = snd_pcm_chmap_substream(info, idx);
+	if (!substream)
+		return -ENODEV;
+	memset(ucontrol->value.integer.value, 0,
+		sizeof(ucontrol->value.integer.value));
+	if (!substream->runtime)
+		return 0; /* no channels set */
+
+	prtd = substream->runtime->private_data;
+
+	if (prtd && prtd->set_channel_map == true) {
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+			ucontrol->value.integer.value[i] =
+					(int)prtd->channel_map[i];
+	} else {
+		for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+			ucontrol->value.integer.value[i] = 0;
+	}
+
+	return 0;
+}
+
 static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
-	struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
+	struct snd_pcm *pcm = rtd->pcm;
 	struct snd_pcm_chmap *chmap_info;
 	struct snd_kcontrol *kctl;
-	char device_num[3];
+	char device_num[12];
 	int i, ret = 0;
 
 	if (!card->dev->coherent_dma_mask)
@@ -791,8 +824,9 @@
 
 	pr_debug("%s, Channel map cntrl add\n", __func__);
 	ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-					NULL, PCM_FORMAT_MAX_NUM_CHANNEL, 0,
-					&chmap_info);
+				     snd_pcm_std_chmaps,
+				     PCM_FORMAT_MAX_NUM_CHANNEL, 0,
+				     &chmap_info);
 	if (ret < 0)
 		return ret;
 	kctl = chmap_info->kctl;
@@ -802,7 +836,8 @@
 	strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
 	pr_debug("%s, Overwriting channel map control name to: %s",
 		__func__, kctl->id.name);
-	kctl->put = pcm_chmap_ctl_put;
+	kctl->put = msm_pcm_chmap_ctl_put;
+	kctl->get = msm_pcm_chmap_ctl_get;
 	return ret;
 }