Merge "msm: apq8084: Enable the memory hole Kconfigs"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 23498e5..6ef2b77 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -24,6 +24,8 @@
 
 Optional properties
 
+- qcom,freq-control-mask: The cpu mask that will be used to determine if a
+			core can be used for freq control.
 - qcom,core-limit-temp: Threshold temperature to start shutting down cores
 			in degC
 - qcom,core-temp-hysterisis: Degrees C below which the cores will be brought
@@ -77,6 +79,7 @@
 		qcom,limit-temp = <60>;
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
+		qcom,freq-control-mask = <0xf>
 		qcom,core-limit-temp = <90>;
 		qcom,core-temp-hysterisis = <10>;
 		qcom,core-control-mask = <7>;
diff --git a/Documentation/devicetree/bindings/arm/msm/pm_snoc_client.txt b/Documentation/devicetree/bindings/arm/msm/pm_snoc_client.txt
new file mode 100644
index 0000000..4f7111f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/pm_snoc_client.txt
@@ -0,0 +1,35 @@
+* MSM PM SNOC client
+
+MSM PM SNOC client device is used to setup a bus request for 100 Mhz for the
+SNOC bus when the Apps cores are active. This bus request helps mitigate the
+exit latency from power collapse in cases where there aren't any active bus
+requests for SNOC.
+
+This device is dependent on the pm-8x60 device, which configures the low power
+mode of respective cores.
+
+The required properties of this device are:
+
+- compatible: qcom,pm-snoc-client
+- qcom,msm-bus,name:            String representing the client-name
+- qcom,msm-bus,num-cases:       Total number of usecases
+- qcom,msm-bus,active-only:     Boolean context flag for requests in active or
+                                dual (active & sleep) contex
+- qcom,msm-bus,num-paths:       Total number of master-slave pairs
+- qcom,msm-bus,vectors-KBps:    Arrays of unsigned integers representing:
+                                master-id, slave-id, arbitrated bandwidth
+                                in KBps, instantaneous bandwidth in KBps
+
+
+Example:
+	qcom,pm-snoc-client {
+		compatible = "qcom,pm-snoc-client";
+		qcom,msm-bus,name = "ocimem_snoc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors =
+			<22 512 0 0>,
+			<22 512 320000 3200000>;
+	};
+
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
index 706ffe6..c7c6415 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
@@ -13,6 +13,7 @@
 - qcom,iommu-pmu-event-classes: List of event classes supported.
 - qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
   access to the IOMMU configuration registers
+- Bus scaling properties: See msm_bus.txt
 
 - List of sub nodes, one for each of the translation context banks supported.
     Required properties for each sub-node:
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
index 56f4767..ed45979 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v1.txt
@@ -21,6 +21,7 @@
 - qcom,iommu-pmu-ngroups: Number of Performance Monitor Unit (PMU) groups.
 - qcom,iommu-pmu-ncounters: Number of PMU counters per group.
 - qcom,iommu-pmu-event-classes: List of event classes supported.
+- Bus scaling properties: See msm_bus.txt
 
 - List of sub nodes, one for each of the translation context banks supported.
   Each sub node has the following required properties:
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 7616505..1836867 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -51,6 +51,9 @@
 - qcom,sensor-name : should contain unique sensor name to differentiate from
     other sensor
     - "s5k3l1yx"
+- qcom,vdd-cx-supply : should contain regulator from which cx voltage is
+    supplied
+- qcom,vdd-cx-name : should contain names of cx regulator
 - cam_vdig-supply : should contain regulator from which digital voltage is
     supplied
 - cam_vana-supply : should contain regulator from which analog voltage is
@@ -191,6 +194,8 @@
                qcom,led-flash-src = <&led_flash0>;
                qcom,mount-angle = <90>;
                qcom,sensor-name = "s5k3l1yx";
+               qcom,vdd-cx-supply = <&pm8841_s2>;
+               qcom,vdd-cx-name = "qcom,vdd-cx";
                cam_vdig-supply = <&pm8941_l3>;
                cam_vana-supply = <&pm8941_l17>;
                cam_vio-supply = <&pm8941_lvs3>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index fced0d7..359ee6c 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -56,6 +56,13 @@
 - qcom,warm-bat-mv:			Warm temperature battery target voltage.
 - qcom,cool-bat-mv:			Cool temperature battery target voltage.
 - qcom,tchg-mins:			Maximum total software initialized charge time.
+- qcom,bpd-detection:			Select a battery presence detection scheme by
+					specifying either "bpd_thm", "bpd_id" or
+					"bpd_thm_id". "bpd_thm" selects the temperature
+					pin, "bpd_id" uses the id pin for battery presence
+					detection, "bpd_thm_id" selects both.
+					If the property is not set the hw default will
+					be used.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index f2cfe34..daa68b3 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -15,6 +15,8 @@
  - qcom,retain-mems: Presence denotes a hardware requirement to leave the
 		     forced memory retention signals in the core's clock
 		     branch control register asserted.
+ - qcom,retain-logic: Presence denotes a requirement to leave power to the
+		      core's logic enabled.
 
 Example:
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index c56f06a..ea626c8 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -230,8 +230,31 @@
 	qcom,rfr-gpio = <&msmgpio 44 0x00>;
 };
 
+&usb_otg {
+	status = "ok";
+	qcom,hsusb-otg-otg-control = <2>;
+	qcom,hsusb-otg-mode = <3>;
+	vbus_otg-supply = <&pm8941_mvs1>;
+	qcom,usb2-enable-hsphy2;
+	qcom,dp-manual-pullup;
+
+	#address-cells = <0>;
+	interrupt-parent = <&usb_otg>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 134 0
+		1 &intc 0 140 0
+		2 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "core_irq", "async_irq", "pmic_id_irq";
+};
+
 &usb3 {
 	qcom,charging-disabled;
+	vbus_dwc3-supply = <0>;
+	dwc3@f9200000 {
+		host-only-mode;
+	};
 };
 
 &slim_msm {
diff --git a/arch/arm/boot/dts/msm-gdsc.dtsi b/arch/arm/boot/dts/msm-gdsc.dtsi
index d4c5061..78234e8 100644
--- a/arch/arm/boot/dts/msm-gdsc.dtsi
+++ b/arch/arm/boot/dts/msm-gdsc.dtsi
@@ -11,8 +11,6 @@
  * GNU General Public License for more details.
  */
 
-/include/ "skeleton.dtsi"
-
 &soc {
 	gdsc_venus: qcom,gdsc@fd8c1024 {
 		compatible = "qcom,gdsc";
diff --git a/arch/arm/boot/dts/msm-iommu-v0.dtsi b/arch/arm/boot/dts/msm-iommu-v0.dtsi
index 35829a7..65075e5 100644
--- a/arch/arm/boot/dts/msm-iommu-v0.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v0.dtsi
@@ -27,6 +27,13 @@
 						0x10
 						0x12
 						0x80>;
+		qcom,msm-bus,name = "lpass_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<11 512 0 0>,
+				<11 512 0 1000>;
 		status = "disabled";
 
 		lpass_q6_fw: qcom,iommu-ctx@fd000000 {
@@ -78,6 +85,14 @@
 						0x10
 						0x12
 						0x80>;
+		qcom,msm-bus,name = "copss_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<88 512 0 0>,
+				<88 512 0 1000>;
+
 		status = "disabled";
 
 		qcom,iommu-ctx@fd010000 {
@@ -161,6 +176,13 @@
 						0x10
 						0x12
 						0x80>;
+		qcom,msm-bus,name = "mdpe_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<92 512 0 0>,
+				<92 512 0 1000>;
 		status = "disabled";
 
 		qcom,iommu-ctx@fd860000 {
@@ -196,6 +218,13 @@
 						0x10
 						0x12
 						0x80>;
+		qcom,msm-bus,name = "mdps_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<22 512 0 0>,
+				<22 512 0 1000>;
 		status = "disabled";
 
 		qcom,iommu-ctx@fd870000 {
@@ -232,6 +261,13 @@
 						0x10
 						0x12
 						0x80>;
+		qcom,msm-bus,name = "gfx_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<26 512 0 0>,
+				<26 512 0 1000>;
 		status = "disabled";
 
 		qcom,iommu-ctx@fd880000 {
@@ -277,6 +313,13 @@
 						0x10
 						0x12
 						0x80>;
+		qcom,msm-bus,name = "vfe_ebi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<29 512 0 0>,
+				<29 512 0 1000>;
 		status = "disabled";
 
 		qcom,iommu-ctx@fd890000 {
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 0db886b..d6d919b 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -205,6 +205,12 @@
 			};
 		};
 
+		qcom,leds@a100 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa100 0x100>;
+			label = "mpp";
+		};
+
 		pm8226_gpios: gpios {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
@@ -382,6 +388,21 @@
 			};
 		};
 
+		pm8226_adc_tm: vadc@3400 {
+			compatible = "qcom,qpnp-adc-tm";
+			reg = <0x3400 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts =	<0x0 0x34 0x0>,
+					<0x0 0x34 0x3>,
+				     <0x0 0x34 0x4>;
+			interrupt-names =	"eoc-int-en-set",
+						"high-thr-en-set",
+						"low-thr-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+		};
+
 		qcom,pm8226_rtc {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-rtc";
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 916345c..b96a9e1 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -18,7 +18,10 @@
 / {
 	model = "Qualcomm MSM 8226 CDP";
 	compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
-	qcom,msm-id = <145 1 0>;
+	qcom,msm-id = <145 1 0>,
+		      <158 1 0>,
+		      <159 1 0>,
+		      <198 1 0>;
 };
 
 &soc {
@@ -240,6 +243,24 @@
 };
 
 &spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = <2>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
 	qcom,pm8226@1 {
 		qcom,leds@d800 {
 			status = "okay";
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 7c19bc0..e11c963 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -34,6 +34,11 @@
 		coresight-id = <1>;
 		coresight-name = "coresight-tpiu";
 		coresight-nr-inports = <1>;
+
+		vdd-supply = <&pm8226_l18>;
+
+		qcom,vdd-voltage-level = <2950000 2950000>;
+		qcom,vdd-current-level = <9000 800000>;
 	};
 
 	replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm8226-fluid.dts b/arch/arm/boot/dts/msm8226-fluid.dts
index 7b11200..c58b43b 100644
--- a/arch/arm/boot/dts/msm8226-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-fluid.dts
@@ -16,7 +16,10 @@
 / {
 	model = "Qualcomm MSM 8226 FLUID";
 	compatible = "qcom,msm8226-fluid", "qcom,msm8226", "qcom,fluid";
-	qcom,msm-id = <145 3 0>;
+	qcom,msm-id = <145 3 0>,
+		      <158 3 0>,
+		      <159 3 0>,
+		      <198 3 0>;
 };
 
 &soc {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 589fe69..65b71e9 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -18,7 +18,10 @@
 / {
 	model = "Qualcomm MSM 8226 MTP";
 	compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
-	qcom,msm-id = <145 8 0>;
+	qcom,msm-id = <145 8 0>,
+		      <158 8 0>,
+		      <159 8 0>,
+		      <198 8 0>;
 };
 
 &soc {
@@ -228,6 +231,24 @@
 };
 
 &spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = <2>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
 	qcom,pm8226@1 {
                 qcom,leds@d300 {
                         status = "okay";
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index f917d45..aba5c4a 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -18,7 +18,10 @@
 / {
 	model = "Qualcomm MSM 8226 QRD";
 	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
-	qcom,msm-id = <145 11 0>;
+	qcom,msm-id = <145 11 0>,
+		      <158 11 0>,
+		      <159 11 0>,
+		      <198 11 0>;
 };
 
 &soc {
@@ -231,6 +234,24 @@
 };
 
 &spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = <2>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
 	qcom,pm8226@1 {
                 qcom,leds@d300 {
                         status = "okay";
@@ -265,6 +286,18 @@
 	};
 };
 
+&pm8226_bms {
+	status = "okay";
+	qcom,batt-type = <4>;
+	qcom,max-voltage-uv = <4350000>;
+};
+
+&pm8226_chg {
+	status = "okay";
+	qcom,chg-vddmax-mv = <4350>;
+	qcom,chg-vddsafe-mv = <4350>;
+};
+
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
 		/* XO_PMIC_CDC_MCLK enable for tapan codec */
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index 3cca8b0..2405646 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -17,7 +17,10 @@
 / {
 	model = "Qualcomm MSM 8226 Simulator";
 	compatible = "qcom,msm8226-sim", "qcom,msm8226", "qcom,sim";
-	qcom,msm-id = <145 16 0>;
+	qcom,msm-id = <145 16 0>,
+		      <158 16 0>,
+		      <159 16 0>,
+		      <198 16 0>;
 };
 
 &soc {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index b2933db..17cda51 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -869,6 +869,7 @@
 		qcom,limit-temp = <60>;
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
+		qcom,freq-control-mask = <0xf>;
 	};
 
 	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
@@ -1140,6 +1141,71 @@
 	};
 };
 
+&pm8226_adc_tm {
+	/* Channel Node */
+	chan@30 {
+		label = "batt_therm";
+		reg = <0x30>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <1>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x48>;
+	};
+
+	chan@8 {
+		label = "die_temp";
+		reg = <8>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <3>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x68>;
+	};
+
+	chan@6 {
+		label = "vbat_sns";
+		reg = <6>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <3>;
+		qcom,btm-channel-number = <0x70>;
+	};
+
+	chan@14 {
+		label = "pa_therm0";
+		reg = <0x14>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,btm-channel-number = <0x78>;
+		qcom,thermal-node;
+	};
+
+	chan@17 {
+		label = "pa_therm1";
+		reg = <0x17>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,btm-channel-number = <0x80>;
+		qcom,thermal-node;
+	};
+};
+
 &pm8226_chg {
 	status = "ok";
 
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
index 2e7ba25..7ed914e 100644
--- a/arch/arm/boot/dts/msm8610-bus.dtsi
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -29,11 +29,13 @@
 			qcom,masterp = <2>;
 			qcom,tier = <2>;
 			qcom,hw-sel = "NoC";
-			qcom,perm-mode = "Bypass";
-			qcom,mode = "Bypass";
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
 			qcom,qport = <0>;
 			qcom,ws = <10000>;
 			qcom,mas-hw-id = <8>;
+			qcom,prio1 = <2>;
+			qcom,prio0 = <2>;
 		};
 
 		mas-vfe {
@@ -47,6 +49,8 @@
 			qcom,ws = <10000>;
 			qcom,qport = <2>;
 			qcom,mas-hw-id = <11>;
+			qcom,prio1 = <2>;
+			qcom,prio0 = <2>;
 		};
 
 		mas-mdpe {
@@ -55,11 +59,13 @@
 			qcom,masterp = <4>;
 			qcom,tier = <2>;
 			qcom,hw-sel = "NoC";
-			qcom,perm-mode = "Bypass";
-			qcom,mode = "Bypass";
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
 			qcom,ws = <10000>;
 			qcom,qport = <7>;
 			qcom,mas-hw-id = <11>;
+			qcom,prio1 = <2>;
+			qcom,prio0 = <2>;
 		};
 
 		fab-bimc {
@@ -67,7 +73,7 @@
 			label = "fab-bimc";
 			qcom,gateway;
 			qcom,slavep = <16>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <16>;
 		};
@@ -77,7 +83,7 @@
 			label = "slv-camera-cfg";
 			qcom,slavep = <0>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <3>;
 		};
@@ -87,7 +93,7 @@
 			label = "slv-display-cfg";
 			qcom,slavep = <1>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <4>;
 		};
@@ -97,7 +103,7 @@
 			label = "slv-cpr-cfg";
 			qcom,slavep = <3>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <6>;
 		};
@@ -107,7 +113,7 @@
 			label = "slv-cpr-xpu-cfg";
 			qcom,slavep = <4>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <7>;
 		};
@@ -117,7 +123,7 @@
 			label = "slv-misc-cfg";
 			qcom,slavep = <6>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <8>;
 		};
@@ -127,7 +133,7 @@
 			label = "slv-misc-xpu-cfg";
 			qcom,slavep = <7>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <9>;
 		};
@@ -137,7 +143,7 @@
 			label = "slv-gfx3d-cfg";
 			qcom,slavep = <9>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <11>;
 		};
@@ -147,7 +153,7 @@
 			label = "slv-mmss-clk-cfg";
 			qcom,slavep = <11>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <12>;
 		};
@@ -157,7 +163,7 @@
 			label = "slv-mmss-clk-xpu-cfg";
 			qcom,slavep = <12>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <13>;
 		};
@@ -167,7 +173,7 @@
 			label = "slv-mnoc-mpu-cfg";
 			qcom,slavep = <13>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <14>;
 		};
@@ -177,7 +183,7 @@
 			label = "slv-onoc-mpu-cfg";
 			qcom,slavep = <14>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <15>;
 		};
@@ -187,7 +193,7 @@
 			label = "slv-service-mnoc";
 			qcom,slavep = <18>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <17>;
 		};
@@ -197,7 +203,7 @@
 			label = "slv-dsi-cfg";
 			qcom,slavep = <19>;
 			qcom,tier = <2>;
-			qcom,buswidth = <16>;
+			qcom,buswidth = <8>;
 			qcom,hw-sel = "NoC";
 			qcom,slv-hw-id = <19>;
 		};
@@ -272,8 +278,8 @@
 			qcom,mas-hw-id = <29>;
 			qcom,slv-hw-id = <28>;
 			qcom,mode = "Fixed";
-			qcom,prio-rd = <2>;
-			qcom,prio-wr = <2>;
+			qcom,prio0 = <2>;
+			qcom,prio1 = <2>;
 		};
 
 		fab-ovnoc {
@@ -291,6 +297,9 @@
 			qcom,masterp = <5>;
 			qcom,tier = <2>;
 			qcom,mas-hw-id = <23>;
+			qcom,hw-sel = "NoC";
+			qcom,prio0 = <1>;
+			qcom,prio1 = <1>;
 		};
 
 		mas-mss {
@@ -899,6 +908,7 @@
 			qcom,mas-hw-id = <0>;
 			qcom,prio-rd = <1>;
 			qcom,prio-wr = <1>;
+			qcom,prio-lvl = <1>;
 		};
 
 		mas-mss-proc {
@@ -943,8 +953,8 @@
 			qcom,qport = <4>;
 			qcom,mas-hw-id = <25>;
 			qcom,mode = "Fixed";
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
+			qcom,prio0 = <1>;
+			qcom,prio1 = <1>;
 		};
 
 		mas-gfx3d {
@@ -952,13 +962,11 @@
 			label = "mas-gfx3d";
 			qcom,masterp = <5>;
 			qcom,tier = <2>;
-			qcom,hw-sel = "NoC";
-			qcom,perm-mode = "Bypass";
-			qcom,mode = "Bypass";
+			qcom,hw-sel = "BIMC";
+			qcom,perm-mode = "Fixed";
+			qcom,mode = "Fixed";
 			qcom,ws = <10000>;
 			qcom,qport = <5>;
-			qcom,prio-rd = <1>;
-			qcom,prio-wr = <1>;
 			qcom,mas-hw-id = <6>;
 		};
 
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 9dbd71d..6347902 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -736,6 +736,7 @@
 		qcom,limit-temp = <60>;
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
+		qcom,freq-control-mask = <0xf>;
 	};
 
 	qcom,ipc-spinlock@fd484000 {
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index efd9c32..4a9820d 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -36,6 +36,8 @@
 		qcom,actuator-src = <&actuator0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "s5k3l1yx";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -77,6 +79,8 @@
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "imx135";
 		qcom,actuator-src = <&actuator1>;
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -118,6 +122,8 @@
 		qcom,csid-sd-index = <2>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "ov2720";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -153,6 +159,8 @@
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <0>;
 		qcom,sensor-name = "mt9m114";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index 9cbd45c..f61b83a 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -37,6 +37,8 @@
 		qcom,led-flash-src = <&led_flash0>;
 		qcom,mount-angle = <270>;
 		qcom,sensor-name = "s5k3l1yx";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -78,6 +80,8 @@
 		qcom,mount-angle = <270>;
 		qcom,sensor-name = "imx135";
 		qcom,actuator-src = <&actuator1>;
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -119,6 +123,8 @@
 		qcom,csid-sd-index = <2>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "ov2720";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -154,6 +160,8 @@
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <0>;
 		qcom,sensor-name = "mt9m114";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index e9d3d75..e0b572e 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -36,6 +36,8 @@
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <0>;
 		qcom,sensor-name = "s5k3l1yx";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs2>;
@@ -73,6 +75,8 @@
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <0>;
 		qcom,sensor-name = "imx135";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		qcom,actuator-src = <&actuator1>;
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
@@ -115,6 +119,8 @@
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <180>;
 		qcom,sensor-name = "ov2720";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs2>;
@@ -149,6 +155,8 @@
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <0>;
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		qcom,sensor-name = "mt9m114";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 68af4a6..6ad6213 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -37,6 +37,8 @@
 		qcom,led-flash-src = <&led_flash0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "s5k3l1yx";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -77,6 +79,8 @@
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "imx135";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		qcom,actuator-src = <&actuator1>;
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
@@ -120,6 +124,8 @@
 		qcom,csid-sd-index = <2>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "ov2720";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -155,6 +161,8 @@
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <0>;
 		qcom,sensor-name = "mt9m114";
+		qcom,vdd-cx-supply = <&pm8841_s2>;
+		qcom,vdd-cx-name = "qcom,vdd-cx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 5fa7c08..3e65b8a 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -247,7 +247,7 @@
 				<85 512 40000 160000>,
 				<85 512 40000 320000>,
 				<85 512 40000 480000>,
-				<85 512 40000 640000>;
+				<85 512 40000 800000>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index ee8152d..63f6d59 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -53,7 +53,7 @@
 			reg = <28>;
 			qcom,heap-align = <0x1000>;
 			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x314000>;
+			qcom,memory-reservation-size = <0x614000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index e63b53b..c2dae28 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -294,9 +294,19 @@
 		enable-active-high;
 	};
 
+	ath_chip_pwd_l: ath_chip_reset {
+		compatible = "regulator-fixed";
+		regulator-name = "ath_chip_pwd_l";
+		gpio = <&pm8941_gpios 33 0>;
+		enable-active-high;
+	};
+
 	bt_ar3002 {
 		compatible = "qca,ar3002";
 		qca,bt-reset-gpio = <&pm8941_gpios 34 0>;
+		qca,bt-chip-pwd-supply = <&ath_chip_pwd_l>;
+		qca,bt-vdd-io-supply = <&pm8941_s3>;
+		qca,bt-vdd-pa-supply = <&pm8941_l19>;
 	};
 
 	bt_ar3002_sleep {
@@ -717,8 +727,10 @@
 
 &slim_msm {
 	taiko_codec {
+		qcom,cdc-micbias1-ext-cap;
 		qcom,cdc-micbias2-ext-cap;
 		qcom,cdc-micbias3-ext-cap;
+		qcom,cdc-micbias4-ext-cap;
 
 		/*
 		 * Liquid has external spkrdrv supply. Give a dummy supply to
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index c25c385..1735515 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -34,3 +34,7 @@
 
 	qcom,misc-ref = <&pm8941_misc>;
 };
+
+&pm8941_chg {
+	qcom,bpd-detection = "bpd_id";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 29dce2a..d3a0bc8 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -190,9 +190,9 @@
 			qcom,irqs-detectable;
 			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
-			qcom,ss-power = <784>;
-			qcom,energy-overhead = <190000>;
-			qcom,time-overhead = <100>;
+			qcom,ss-power = <715>;
+			qcom,energy-overhead = <17700>;
+			qcom,time-overhead = <2>;
 		};
 
 		qcom,lpm-level@1 {
@@ -206,10 +206,10 @@
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
 			qcom,gpio-detectable;
-			qcom,latency-us = <75>;
-			qcom,ss-power = <735>;
-			qcom,energy-overhead = <77341>;
-			qcom,time-overhead = <105>;
+			qcom,latency-us = <35>;
+			qcom,ss-power = <542>;
+			qcom,energy-overhead = <34920>;
+			qcom,time-overhead = <40>;
 		};
 
 
@@ -224,10 +224,10 @@
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
 			qcom,gpio-detectable;
-			qcom,latency-us = <95>;
-			qcom,ss-power = <725>;
-			qcom,energy-overhead = <99500>;
-			qcom,time-overhead = <130>;
+			qcom,latency-us = <300>;
+			qcom,ss-power = <476>;
+			qcom,energy-overhead = <225300>;
+			qcom,time-overhead = <350>;
 		};
 
 		qcom,lpm-level@3 {
@@ -241,10 +241,10 @@
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,irqs-detectable;
 			qcom,gpio-detectable;
-			qcom,latency-us = <2000>;
-			qcom,ss-power = <138>;
-			qcom,energy-overhead = <1208400>;
-			qcom,time-overhead = <3200>;
+			qcom,latency-us = <2817>;
+			qcom,ss-power = <163>;
+			qcom,energy-overhead = <1577736>;
+			qcom,time-overhead = <5067>;
 		};
 
 		qcom,lpm-level@4 {
@@ -258,44 +258,29 @@
 			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
 			qcom,irqs-detectable;
 			qcom,gpio-detectable;
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <110>;
-			qcom,energy-overhead = <1250300>;
-			qcom,time-overhead = <3500>;
+			qcom,latency-us = <3922>;
+			qcom,ss-power = <83>;
+			qcom,energy-overhead = <2274420>;
+			qcom,time-overhead = <6605>;
 		};
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
-			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
-			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
-			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <68>;
-			qcom,energy-overhead = <1350200>;
-			qcom,time-overhead = <4000>;
-		};
-
-		qcom,lpm-level@6 {
-			reg = <0x6>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
 			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
 			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
 			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
 			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
-			qcom,latency-us = <10300>;
-			qcom,ss-power = <63>;
-			qcom,energy-overhead = <2128000>;
-			qcom,time-overhead = <18200>;
+			qcom,latency-us = <4922>;
+			qcom,ss-power = <68>;
+			qcom,energy-overhead = <2568180>;
+			qcom,time-overhead = <8812>;
 		};
 
-		qcom,lpm-level@7 {
-			reg = <0x7>;
+		qcom,lpm-level@6 {
+			reg = <0x6>;
 			qcom,mode= "pc";
 			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
@@ -303,14 +288,14 @@
 			qcom,vdd-mem-lower-bound = <950000>;  /* SVS SOC */
 			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
 			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
-			qcom,latency-us = <18000>;
-			qcom,ss-power = <10>;
-			qcom,energy-overhead = <3202600>;
-			qcom,time-overhead = <27000>;
+			qcom,latency-us = <5890>;
+			qcom,ss-power = <60>;
+			qcom,energy-overhead = <2675900>;
+			qcom,time-overhead = <10140>;
 		};
 
-		qcom,lpm-level@8 {
-			reg = <0x8>;
+		qcom,lpm-level@7 {
+			reg = <0x7>;
 			qcom,mode= "pc";
 			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
@@ -318,10 +303,10 @@
 			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
 			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
 			qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
-			qcom,latency-us = <20000>;
-			qcom,ss-power = <2>;
-			qcom,energy-overhead = <4252000>;
-			qcom,time-overhead = <32000>;
+			qcom,latency-us = <8500>;
+			qcom,ss-power = <18>;
+			qcom,energy-overhead = <3286600>;
+			qcom,time-overhead = <15760>;
 		};
 	};
 
@@ -428,6 +413,17 @@
 		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 
+		qcom,pm-snoc-client {
+			compatible = "qcom,pm-snoc-client";
+			qcom,msm-bus,name = "ocimem_snoc";
+			qcom,msm-bus,num-cases = <2>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,vectors-KBps =
+				<54 585 0 0>,
+				<54 585 0 800000>;
+		};
+
 		qcom,cpu-sleep-status@f9088008{
 			compatible = "qcom,cpu-sleep-status";
 			reg = <0xf9088008 0x100>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index a4a3efe..e2dd3fd 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1419,6 +1419,7 @@
 		qcom,limit-temp = <60>;
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
+		qcom,freq-control-mask = <0xf>;
 		qcom,core-limit-temp = <80>;
 		qcom,core-temp-hysteresis = <10>;
 		qcom,core-control-mask = <0xe>;
diff --git a/arch/arm/boot/dts/msmsamarium-ion.dtsi b/arch/arm/boot/dts/msmsamarium-ion.dtsi
new file mode 100644
index 0000000..ea954b8
--- /dev/null
+++ b/arch/arm/boot/dts/msmsamarium-ion.dtsi
@@ -0,0 +1,31 @@
+/* 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 {
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ion-heap@30 { /* SYSTEM HEAP */
+			reg = <30>;
+		};
+
+		qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+			reg = <21>;
+		};
+
+		qcom,ion-heap@25 { /* IOMMU HEAP */
+			reg = <25>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msmsamarium-sim.dts b/arch/arm/boot/dts/msmsamarium-sim.dts
new file mode 100644
index 0000000..2774f7f
--- /dev/null
+++ b/arch/arm/boot/dts/msmsamarium-sim.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/ "msmsamarium.dtsi"
+
+/ {
+	model = "Qualcomm MSM SAMARIUM SIM";
+	compatible = "qcom,msmsamarium-sim", "qcom,msmsamarium", "qcom,sim";
+	qcom,msm-id = <195 0 0>;
+};
+
+&uartblsp0dm2{
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
new file mode 100644
index 0000000..9d9ff87
--- /dev/null
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -0,0 +1,66 @@
+/* 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.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM SAMARIUM";
+	compatible = "qcom,msmsamarium";
+	interrupt-parent = <&intc>;
+	soc: soc { };
+};
+
+/include/ "msmsamarium-ion.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xf9000000 0x1000>,
+		      <0xf9002000 0x1000>;
+	};
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+		ngpio = <145>;
+		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 2 0 1 3 0>;
+		clock-frequency = <19200000>;
+	};
+
+	uartblsp0dm2: serial@f991f000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991f000 0x1000>;
+		interrupts = <0 109 0>;
+		status = "disabled";
+	};
+
+	qcom,msm-imem@fe805000 {
+		compatible = "qcom,msm-imem";
+		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
+	};
+};
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index aea092e..ba36df1 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -370,6 +370,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_SHIRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index b385669..ef56fec 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -217,6 +217,8 @@
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 5e38ef1..e4497e1 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -216,6 +216,7 @@
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index dda9bd3..5885c6e 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -428,6 +428,7 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index f90e5f3..6c18a97 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -510,6 +510,7 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index bae4ee9..72032dc 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -459,6 +459,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_TIMER_STATS=y
+CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 8036a44..091cdd9 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -37,6 +37,7 @@
 CONFIG_DEFAULT_ROW=y
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8974=y
+CONFIG_ARCH_MSMSAMARIUM=y
 CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 2d3b52f..108a68f 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -145,7 +145,7 @@
 	select CPU_V7
 	select GPIO_MSM_V2
 	select MSM_GPIOMUX
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
 	select MSM_RPM_REGULATOR
@@ -187,7 +187,7 @@
 	select CPU_V7
 	select GPIO_MSM_V2
 	select MSM_GPIOMUX
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
 	select MSM_RPM_REGULATOR
@@ -223,7 +223,7 @@
 	select GPIO_MSM_V2
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MSM_REMOTE_SPINLOCK_SFPB
 	select MSM_PIL
@@ -257,7 +257,7 @@
 	select GPIO_MSM_V3
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_MULTIMEDIA_USE_ION
@@ -292,7 +292,7 @@
 	select GPIO_MSM_V3
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_NATIVE_RESTART
@@ -319,6 +319,25 @@
 	select SPARSE_IRQ
 	select MSM_NOPM
 
+config ARCH_FSM9900
+	bool "FSM9900"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select CPU_V7
+	select MSM_SCM
+	select MSM_GPIOMUX
+	select MULTI_IRQ_HANDLER
+	select MSM_PIL
+	select MSM_NATIVE_RESTART
+	select MSM_RESTART_V2
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select REGULATOR
+	select ARM_HAS_SG_CHAIN
+	select MSM_RUN_QUEUE_STATS
+	select MSM_NOPM
+
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
 	select ARCH_MSM_SCORPION
@@ -380,7 +399,6 @@
 	select MSM_RESTART_V2
 	select MSM_SPM_V2
 	select MSM_PM8X60 if PM
-	select MSM_SCM if SMP
 	select MULTI_IRQ_HANDLER
 	select GPIO_MSM_V3
 	select MAY_HAVE_SPARSE_IRQ
@@ -416,7 +434,7 @@
 	select GIC_SECURE
 	select ARCH_MSM_CORTEXMP
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
@@ -458,7 +476,7 @@
 	select GIC_SECURE
 	select ARCH_MSM_CORTEXMP
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
@@ -493,6 +511,26 @@
 	select MSM_RPM_LOG
 	select MSM_RPM_STATS_LOG
 	select ARCH_WANT_KMAP_ATOMIC_FLUSH
+
+config ARCH_MSMSAMARIUM
+	bool "MSMSAMARIUM"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select CPU_V7
+	select MSM_SCM
+	select MSM_GPIOMUX
+	select MULTI_IRQ_HANDLER
+	select MSM_SPM_V2
+	select MSM_L2_SPM
+	select MSM_NATIVE_RESTART
+	select MSM_RESTART_V2
+	select MSM_PM8X60 if PM
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select ARM_HAS_SG_CHAIN
+	select MSM_RUN_QUEUE_STATS
+	select ARCH_WANT_KMAP_ATOMIC_FLUSH
 endmenu
 
 choice
@@ -1095,7 +1133,9 @@
 	default "0x00000000" if ARCH_MPQ8092
 	default "0x00000000" if ARCH_MSM8226
 	default "0x00000000" if ARCH_MSM8610
+	default "0x00000000" if ARCH_MSMSAMARIUM
 	default "0x10000000" if ARCH_FSM9XXX
+	default "0x00000000" if ARCH_FSM9900
 	default "0x00200000" if ARCH_MSM9625
 	default "0x00000000" if ARCH_MSMKRYPTON
 	default "0x00200000" if !MSM_STACKED_MEMORY
@@ -1259,6 +1299,22 @@
                 help
                   Say Y here if you want the debug print routines to direct
                   their output to the serial port on MSM9625 devices.
+
+	config DEBUG_FSM9900_UART
+		bool "Kernel low-level debugging messages via FSM9900 UART"
+		depends on ARCH_FSM9900
+		select MSM_HAS_DEBUG_UART_HS_V14
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on FSM9900 devices.
+
+	config DEBUG_MSMSAMARIUM_UART
+		bool "Kernel low-level debugging messages via MSM SAMARIUM UART"
+		depends on ARCH_MSMSAMARIUM
+		select MSM_HAS_DEBUG_UART_HS_V14
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on MSM SAMARIUM devices.
 endchoice
 
 choice
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 400f859..4f4bfbc 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -121,6 +121,8 @@
 ifndef CONFIG_ARCH_MSM8610
 ifndef CONFIG_ARCH_APQ8084
 ifndef CONFIG_ARCH_MSMKRYPTON
+ifndef CONFIG_ARCH_FSM9900
+ifndef CONFIG_ARCH_MSMSAMARIUM
 	obj-y += nand_partitions.o
 endif
 endif
@@ -132,6 +134,8 @@
 endif
 endif
 endif
+endif
+endif
 obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -230,6 +234,7 @@
 obj-$(CONFIG_ARCH_FSM9XXX) += clock-fsm9xxx.o clock-local.o acpuclock-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += dfe-fsm9xxx.o rfic-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += restart-fsm9xxx.o xo-fsm9xxx.o
+obj-$(CONFIG_ARCH_FSM9900) += board-fsm9900.o board-fsm9900-gpiomux.o
 
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog.o
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog_asm.o
@@ -288,7 +293,7 @@
 obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
 obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
 obj-$(CONFIG_QPNP_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
-obj-$(CONFIG_QPNP_BMS) += bms-batterydata-oem.o
+obj-$(CONFIG_QPNP_BMS) += bms-batterydata-oem.o bms-batterydata-qrd-4v35-2000mah.o
 obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
@@ -307,6 +312,7 @@
 obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
+obj-$(CONFIG_ARCH_MSMSAMARIUM) += board-samarium.o board-samarium-gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
@@ -373,10 +379,12 @@
 obj-$(CONFIG_ARCH_MSM8974) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM9625) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSMKRYPTON) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSMSAMARIUM) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MPQ8092) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_APQ8084) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_FSM9900) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
 obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 2827e65..b40c70a 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -93,6 +93,11 @@
 params_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x10000100
 initrd_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x12000000
 
+# FSM9900
+   zreladdr-$(CONFIG_ARCH_FSM9900)	:= 0x00008000
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-rumi.dtb
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-sim.dtb
+
 # MPQ8092
    zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
 
@@ -100,3 +105,7 @@
    zreladdr-$(CONFIG_ARCH_MSM8610)	:= 0x00008000
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-rumi.dtb
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-sim.dtb
+
+# MSMSAMARIUM
+   zreladdr-$(CONFIG_ARCH_MSMSAMARIUM)	:= 0x00008000
+	dtb-$(CONFIG_ARCH_MSMSAMARIUM)	+= msmsamarium-sim.dtb
diff --git a/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
new file mode 100644
index 0000000..8adf8ca
--- /dev/null
+++ b/arch/arm/mach-msm/bms-batterydata-qrd-4v35-2000mah.c
@@ -0,0 +1,117 @@
+/* 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.
+ */
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
+
+static struct single_row_lut fcc_temp = {
+	.x		= {-20, 0, 25, 40, 60},
+	.y		= {2096, 2124, 2121, 2118, 2103},
+	.cols	= 5
+};
+
+static struct single_row_lut fcc_sf = {
+	.x		= {0},
+	.y		= {100},
+	.cols	= 1
+};
+
+static struct sf_lut rbatt_sf = {
+	.rows		= 30,
+	.cols		= 5,
+	.row_entries		= {-20, 0, 25, 40, 60},
+	.percent	= {100, 95, 90, 85, 80, 75, 70, 65, 60,
+		55, 50, 45, 40, 35, 30, 25, 20, 16, 13,
+		11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
+	.sf		= {
+				{2422, 324, 100, 79, 72},
+				{2417, 325, 100, 79, 71},
+				{2344, 327, 100, 80, 72},
+				{2416, 336, 102, 81, 73},
+				{2072, 354, 107, 82, 73},
+				{1961, 372, 113, 84, 75},
+				{1929, 341, 118, 87, 77},
+				{1929, 321, 130, 93, 80},
+				{2041, 306, 140, 104, 85},
+				{2202, 292, 119, 96, 83},
+				{2374, 290, 98, 80, 73},
+				{2550, 292, 98, 79, 72},
+				{2727, 294, 99, 81, 73},
+				{2904, 303, 100, 82, 75},
+				{3091, 323, 100, 81, 73},
+				{3278, 348, 100, 80, 73},
+				{3470, 376, 99, 79, 72},
+				{3627, 386, 100, 79, 72},
+				{3672, 398, 100, 80, 71},
+				{3812, 424, 100, 80, 73},
+				{3895, 443, 101, 80, 73},
+				{3985, 465, 102, 82, 75},
+				{4094, 497, 105, 83, 76},
+				{4211, 533, 109, 85, 79},
+				{4335, 579, 113, 87, 80},
+				{4505, 612, 113, 85, 76},
+				{4693, 643, 113, 86, 77},
+				{4930, 712, 120, 90, 81},
+				{5283, 835, 145, 111, 107},
+				{10293, 15765, 5566, 6904, 2547},
+	}
+};
+
+static struct pc_temp_ocv_lut pc_temp_ocv = {
+	.rows		= 31,
+	.cols		= 5,
+	.temp		= {-20, 0, 25, 40, 60},
+	.percent	= {100, 95, 90, 85, 80, 75, 70, 65, 60,
+		55, 50, 45, 40, 35, 30, 25, 20, 16, 13,
+		11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
+	.ocv		= {
+				{4340, 4340, 4335, 4330, 4323},
+				{4217, 4260, 4265, 4263, 4258},
+				{4135, 4203, 4207, 4205, 4201},
+				{4084, 4150, 4152, 4150, 4146},
+				{3992, 4101, 4101, 4097, 4093},
+				{3934, 4049, 4051, 4046, 4044},
+				{3889, 3974, 3995, 3998, 3999},
+				{3852, 3926, 3958, 3961, 3959},
+				{3832, 3892, 3921, 3923, 3921},
+				{3819, 3859, 3874, 3877, 3877},
+				{3807, 3831, 3838, 3838, 3838},
+				{3796, 3809, 3815, 3815, 3814},
+				{3784, 3792, 3797, 3797, 3796},
+				{3770, 3780, 3783, 3782, 3781},
+				{3754, 3770, 3772, 3769, 3764},
+				{3737, 3758, 3763, 3754, 3742},
+				{3717, 3737, 3744, 3735, 3720},
+				{3700, 3713, 3718, 3710, 3696},
+				{3687, 3701, 3692, 3683, 3671},
+				{3674, 3695, 3689, 3681, 3669},
+				{3667, 3692, 3688, 3680, 3669},
+				{3659, 3690, 3687, 3680, 3668},
+				{3649, 3687, 3685, 3678, 3667},
+				{3636, 3683, 3683, 3676, 3664},
+				{3618, 3674, 3679, 3671, 3658},
+				{3596, 3652, 3663, 3652, 3632},
+				{3566, 3611, 3620, 3606, 3584},
+				{3522, 3547, 3555, 3540, 3517},
+				{3460, 3449, 3461, 3446, 3424},
+				{3356, 3282, 3312, 3299, 3273},
+				{3000, 3000, 3000, 3000, 3000}
+	}
+};
+
+
+struct bms_battery_data QRD_4v35_2000mAh_data = {
+	.fcc				= 2000,
+	.fcc_temp_lut			= &fcc_temp,
+	.fcc_sf_lut				= &fcc_sf,
+	.pc_temp_ocv_lut		= &pc_temp_ocv,
+	.rbatt_sf_lut			= &rbatt_sf,
+	.default_rbatt_mohm	= 172
+};
diff --git a/arch/arm/mach-msm/board-samarium-gpiomux.c b/arch/arm/mach-msm/board-samarium-gpiomux.c
new file mode 100644
index 0000000..645cb6f
--- /dev/null
+++ b/arch/arm/mach-msm/board-samarium-gpiomux.c
@@ -0,0 +1,53 @@
+/* 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+
+static struct gpiomux_setting gpio_uart_config = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_HIGH,
+};
+
+static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
+	{
+		.gpio      = 4,	       /* BLSP2 UART TX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
+		},
+	},
+	{
+		.gpio      = 5,	       /* BLSP2 UART RX */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
+		},
+	},
+};
+
+void __init msmsamarium_init_gpiomux(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init_dt();
+	if (rc) {
+		pr_err("%s failed %d\n", __func__, rc);
+		return;
+	}
+
+	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+}
diff --git a/arch/arm/mach-msm/board-samarium.c b/arch/arm/mach-msm/board-samarium.c
new file mode 100644
index 0000000..00d63a3
--- /dev/null
+++ b/arch/arm/mach-msm/board-samarium.c
@@ -0,0 +1,90 @@
+/* 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.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memory.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memtypes.h>
+#include <mach/restart.h>
+#include <mach/socinfo.h>
+#include <mach/clk-provider.h>
+#include "board-dt.h"
+#include "clock.h"
+#include "devices.h"
+#include "platsmp.h"
+
+static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
+};
+
+static struct clock_init_data msm_dummy_clock_init_data __initdata = {
+	.table = msm_clocks_dummy,
+	.size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+static struct of_dev_auxdata msmsamarium_auxdata_lookup[] __initdata = {
+	{},
+};
+
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msmsamarium_add_drivers(void)
+{
+	msm_clock_init(&msm_dummy_clock_init_data);
+}
+
+static void __init msmsamarium_map_io(void)
+{
+	msm_map_msmsamarium_io();
+}
+
+void __init msmsamarium_init(void)
+{
+	struct of_dev_auxdata *adata = msmsamarium_auxdata_lookup;
+
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed\n", __func__);
+
+	msmsamarium_init_gpiomux();
+	board_dt_populate(adata);
+	msmsamarium_add_drivers();
+}
+
+static const char *msmsamarium_dt_match[] __initconst = {
+	"qcom,msmsamarium",
+	NULL
+};
+
+DT_MACHINE_START(MSMSAMARIUM_DT, "Qualcomm MSM Samarium(Flattened Device Tree)")
+	.map_io = msmsamarium_map_io,
+	.init_irq = msm_dt_init_irq,
+	.init_machine = msmsamarium_init,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_dt_timer,
+	.dt_compat = msmsamarium_dt_match,
+	.restart = msm_restart,
+	.smp = &msm8974_smp_ops,
+MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 7fe3f97..f3de05a 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -169,11 +169,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
@@ -2753,11 +2753,11 @@
 	VDD_SR2_PLL_NUM
 };
 
-static int *vdd_sr2_levels[] = {
-	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
-	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_sr2_levels[] = {
+	0,       RPM_REGULATOR_CORNER_NONE,		/* VDD_SR2_PLL_OFF */
+	1800000, RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_SR2_PLL_SVS */
+	1800000, RPM_REGULATOR_CORNER_NORMAL,		/* VDD_SR2_PLL_NOM */
+	1800000, RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_SR2_PLL_TUR */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2,
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 17468d2..340f1ef 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -434,11 +434,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
@@ -533,11 +533,11 @@
 	VDD_SR2_PLL_NUM
 };
 
-static int *vdd_sr2_levels[] = {
-	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
-	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_sr2_levels[] = {
+	0,       RPM_REGULATOR_CORNER_NONE,		/* VDD_SR2_PLL_OFF */
+	1800000, RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_SR2_PLL_SVS */
+	1800000, RPM_REGULATOR_CORNER_NORMAL,		/* VDD_SR2_PLL_NOM */
+	1800000, RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_SR2_PLL_TUR */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2,
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index ec94f00..4a16b42 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -638,11 +638,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 5bfc4bb..3277d75 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -280,11 +280,11 @@
 	VDD_DIG_NUM
 };
 
-static int *vdd_corner[] = {
-	[VDD_DIG_NONE]	  = VDD_UV(RPM_REGULATOR_CORNER_NONE),
-	[VDD_DIG_LOW]	  = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
-	[VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
-	[VDD_DIG_HIGH]	  = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
+static int vdd_corner[] = {
+	RPM_REGULATOR_CORNER_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_CORNER_SVS_SOC,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_CORNER_NORMAL,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_CORNER_SUPER_TURBO,	/* VDD_DIG_HIGH */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 08817c0..608018c 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -62,27 +62,31 @@
 {
 	int level, rc = 0, i;
 	struct regulator **r = vdd_class->regulator;
-	int **vdd_uv = vdd_class->vdd_uv;
-	int **vdd_ua = vdd_class->vdd_ua;
-	int max_level = vdd_class->num_levels - 1;
+	int *uv = vdd_class->vdd_uv;
+	int *ua = vdd_class->vdd_ua;
+	int n_reg = vdd_class->num_regulators;
+	int max_lvl = vdd_class->num_levels - 1;
+	int lvl_base;
 
-	for (level = max_level; level > 0; level--)
+	for (level = max_lvl; level > 0; level--)
 		if (vdd_class->level_votes[level])
 			break;
 
 	if (level == vdd_class->cur_level)
 		return 0;
 
+	max_lvl = max_lvl * n_reg;
+	lvl_base = level * n_reg;
 	for (i = 0; i < vdd_class->num_regulators; i++) {
-		rc = regulator_set_voltage(r[i], vdd_uv[level][i],
-			vdd_uv[max_level][i]);
+		rc = regulator_set_voltage(r[i], uv[lvl_base + i],
+					   uv[max_lvl + i]);
 		if (rc)
 			goto set_voltage_fail;
 
-		if (!vdd_ua)
+		if (!ua)
 			continue;
 
-		rc = regulator_set_optimum_mode(r[i], vdd_ua[level][i]);
+		rc = regulator_set_optimum_mode(r[i], ua[lvl_base + i]);
 		if (rc < 0)
 			goto set_mode_fail;
 	}
@@ -95,18 +99,17 @@
 	return 0;
 
 set_mode_fail:
-	regulator_set_voltage(r[i], vdd_uv[vdd_class->cur_level][i],
-				vdd_uv[max_level][i]);
+	regulator_set_voltage(r[i], uv[vdd_class->cur_level * n_reg + i],
+			      uv[max_lvl + i]);
 
 set_voltage_fail:
+	lvl_base = vdd_class->cur_level * n_reg;
 	for (i--; i >= 0; i--) {
-		regulator_set_voltage(r[i], vdd_uv[vdd_class->cur_level][i],
-					vdd_uv[max_level][i]);
+		regulator_set_voltage(r[i], uv[lvl_base + i], uv[max_lvl + i]);
 
-		if (!vdd_ua)
+		if (!ua)
 			continue;
-		regulator_set_optimum_mode(r[i],
-					vdd_ua[vdd_class->cur_level][i]);
+		regulator_set_optimum_mode(r[i], ua[lvl_base + i]);
 	}
 
 	return rc;
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 30a034e..1701262 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -48,6 +48,7 @@
 	struct clk		**clocks;
 	int			clock_count;
 	bool			toggle_mems;
+	bool			retain_logic;
 };
 
 static int gdsc_is_enabled(struct regulator_dev *rdev)
@@ -96,16 +97,20 @@
 {
 	struct gdsc *sc = rdev_get_drvdata(rdev);
 	uint32_t regval;
-	int i, ret;
+	int i, ret = 0;
 
-	regval = readl_relaxed(sc->gdscr);
-	regval |= SW_COLLAPSE_MASK;
-	writel_relaxed(regval, sc->gdscr);
+	if (!sc->retain_logic) {
+		regval = readl_relaxed(sc->gdscr);
+		regval |= SW_COLLAPSE_MASK;
+		writel_relaxed(regval, sc->gdscr);
 
-	ret = readl_tight_poll_timeout(sc->gdscr, regval,
-				       !(regval & PWR_ON_MASK), TIMEOUT_US);
-	if (ret)
-		dev_err(&rdev->dev, "%s disable timed out\n", sc->rdesc.name);
+		ret = readl_tight_poll_timeout(sc->gdscr, regval,
+					       !(regval & PWR_ON_MASK),
+						TIMEOUT_US);
+		if (ret)
+			dev_err(&rdev->dev, "%s disable timed out\n",
+				sc->rdesc.name);
+	}
 
 	if (sc->toggle_mems) {
 		for (i = 0; i < sc->clock_count; i++) {
@@ -214,6 +219,8 @@
 		}
 	}
 	sc->toggle_mems = !retain_mems;
+	sc->retain_logic = of_property_read_bool(pdev->dev.of_node,
+					    "qcom,retain-logic");
 
 	sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
 				      pdev->dev.of_node);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 690e52a..d3ef0be 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -604,6 +604,7 @@
 void msm_map_8974_io(void);
 void msm_map_8084_io(void);
 void msm_map_msmkrypton_io(void);
+void msm_map_msmsamarium_io(void);
 void msm_map_msm8625_io(void);
 void msm_map_msm9625_io(void);
 void msm_init_irq(void);
@@ -615,6 +616,7 @@
 void apq8084_init_gpiomux(void);
 void msm9625_init_gpiomux(void);
 void msmkrypton_init_gpiomux(void);
+void msmsamarium_init_gpiomux(void);
 void msm_map_mpq8092_io(void);
 void mpq8092_init_gpiomux(void);
 void msm_map_msm8226_io(void);
diff --git a/arch/arm/mach-msm/include/mach/camera2.h b/arch/arm/mach-msm/include/mach/camera2.h
index 248c9b0..3e7e5fd 100644
--- a/arch/arm/mach-msm/include/mach/camera2.h
+++ b/arch/arm/mach-msm/include/mach/camera2.h
@@ -79,6 +79,7 @@
 	struct msm_camera_i2c_conf *i2c_conf;
 	struct msm_sensor_info_t *sensor_info;
 	struct msm_sensor_init_params *sensor_init_params;
+	const char *misc_regulator;
 };
 
 enum msm_camera_i2c_cmd_type {
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 0dd4957..27c6df4 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -61,8 +61,8 @@
 	struct regulator **regulator;
 	int num_regulators;
 	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
-	int **vdd_uv;
-	int **vdd_ua;
+	int *vdd_uv;
+	int *vdd_ua;
 	int *level_votes;
 	int num_levels;
 	unsigned long cur_level;
@@ -93,9 +93,6 @@
 		.lock = __MUTEX_INITIALIZER(_name.lock) \
 	}
 
-#define VDD_UV(...) ((int []){__VA_ARGS__})
-#define VDD_UA(...) ((int []){__VA_ARGS__})
-
 enum handoff {
 	HANDOFF_ENABLED_CLK,
 	HANDOFF_DISABLED_CLK,
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 23d204a..decf9bb 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -98,6 +98,7 @@
  * @halt_enabled: Set to 1 if IOMMU halt is supported in the IOMMU, 0 otherwise.
  * @asid:         List of ASID and their usage count (index is ASID value).
  * @ctx_attach_count: Count of how many context are attached.
+ * @bus_client  : Bus client needed to vote for bus bandwidth.
  *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
@@ -121,12 +122,14 @@
 	int halt_enabled;
 	int *asid;
 	unsigned int ctx_attach_count;
+	unsigned int bus_client;
 };
 
 /**
  * struct iommu_access_ops - Callbacks for accessing IOMMU
  * @iommu_power_on:     Turn on power to unit
  * @iommu_power_off:    Turn off power to unit
+ * @iommu_bus_vote:     Vote for bus bandwidth
  * @iommu_clk_on:       Turn on clks to unit
  * @iommu_clk_off:      Turn off clks to unit
  * @iommu_lock_initialize: Initialize the remote lock
@@ -136,6 +139,8 @@
 struct iommu_access_ops {
 	int (*iommu_power_on)(struct msm_iommu_drvdata *);
 	void (*iommu_power_off)(struct msm_iommu_drvdata *);
+	int (*iommu_bus_vote)(struct msm_iommu_drvdata *drvdata,
+			      unsigned int vote);
 	int (*iommu_clk_on)(struct msm_iommu_drvdata *);
 	void (*iommu_clk_off)(struct msm_iommu_drvdata *);
 	void * (*iommu_lock_initialize)(void);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-samarium.h b/arch/arm/mach-msm/include/mach/msm_iomap-samarium.h
new file mode 100644
index 0000000..7a6b626
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-samarium.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 __ASM_ARCH_MSM_IOMAP_SAMARIUM_H
+#define __ASM_ARCH_MSM_IOMAP_SAMARIUM_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSMSAMARIUM_SHARED_RAM_PHYS	0x0FA00000
+
+#define MSMSAMARIUM_QGIC_DIST_PHYS	0xF9000000
+#define MSMSAMARIUM_QGIC_DIST_SIZE	SZ_4K
+
+#define MSMSAMARIUM_TLMM_PHYS	0xFD510000
+#define MSMSAMARIUM_TLMM_SIZE	SZ_16K
+
+#define MSMSAMARIUM_MPM2_PSHOLD_PHYS	0xFC4AB000
+#define MSMSAMARIUM_MPM2_PSHOLD_SIZE	SZ_4K
+
+#ifdef CONFIG_DEBUG_MSMSAMARIUM_UART
+#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
+#define MSM_DEBUG_UART_PHYS	0xF991E000
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 185958c..676df66 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -137,6 +137,8 @@
 #include "msm_iomap-8610.h"
 #include "msm_iomap-krypton.h"
 #include "msm_iomap-fsm9900.h"
+#include "msm_iomap-samarium.h"
+
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index dc8cbaa..99bff66 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -55,6 +55,8 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmkrypton")
 #define early_machine_is_fsm9900()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,fsm9900")
+#define early_machine_is_msmsamarium()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmsamarium")
 #else
 #define of_board_is_sim()		0
 #define of_board_is_rumi()		0
@@ -73,6 +75,7 @@
 #define early_machine_is_apq8084()	0
 #define early_machine_is_msmkrypton()	0
 #define early_machine_is_fsm9900()	0
+#define early_machine_is_msmsamarium()	0
 #endif
 
 #define PLATFORM_SUBTYPE_MDM	1
@@ -114,6 +117,7 @@
 	MSM_CPU_8084,
 	MSM_CPU_KRYPTON,
 	FSM_CPU_9900,
+	MSM_CPU_SAMARIUM,
 };
 
 enum pmic_model {
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index da7c039..5ecc63b 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -101,6 +101,7 @@
 * @desc_mem_buf: descriptor fifo buffer.
 * @event: event for wakeup.
 * @enabled: true if pipe is enabled.
+* @ipa_clnt_hdl : pipe handle to ipa api.
 * @priv: private data to return upon activity_notify
 *	or inactivity_notify callbacks.
 * @activity_notify: callback to invoke on activity on one of the in pipes.
@@ -125,6 +126,7 @@
 	struct sps_mem_buffer desc_mem_buf;
 	struct usb_bam_event_info event;
 	bool enabled;
+	int ipa_clnt_hdl;
 	void *priv;
 	int (*activity_notify)(void *priv);
 	int (*inactivity_notify)(void *priv);
@@ -195,6 +197,14 @@
 		struct usb_bam_connect_ipa_params *ipa_params);
 
 /**
+ * Wait for Consumer granted from Resource Manager.
+ *
+ * @ipa_params - in/out parameters
+ *
+ */
+void usb_bam_wait_for_cons_granted(
+	struct usb_bam_connect_ipa_params *ipa_params);
+/**
  * Register a wakeup callback from peer BAM.
  *
  * @idx - Connection index.
@@ -221,6 +231,39 @@
 int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param);
 
 /**
+ * Register callbacks for start/stop of transfers.
+ *
+ * @start - the callback function that will be called in USB
+ *				driver to start transfers
+ * @stop - the callback function that will be called in USB
+ *				driver to stop transfers
+ *
+ * @param - context that the caller can supply
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param);
+
+/**
+ * Start usb suspend sequence
+ *
+ * @ipa_params -  in/out parameters
+ *
+ */
+void usb_bam_suspend(struct usb_bam_connect_ipa_params *ipa_params);
+
+/**
+ * Start usb resume sequence
+ *
+ * @ipa_params -  in/out parameters
+ *
+ */
+void usb_bam_resume(struct usb_bam_connect_ipa_params *ipa_params);
+/**
  * Disconnect USB-to-Periperal SPS connection.
  *
  * @idx - Connection index.
@@ -315,6 +358,12 @@
 	return -ENODEV;
 }
 
+static inline void usb_bam_wait_for_cons_granted(
+			struct usb_bam_connect_ipa_params *ipa_params)
+{
+	return;
+}
+
 static inline int usb_bam_register_wake_cb(u8 idx,
 	int (*callback)(void *), void* param)
 {
@@ -327,6 +376,20 @@
 	return -ENODEV;
 }
 
+static inline int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param)
+{
+	return -ENODEV;
+}
+
+static inline void usb_bam_suspend(
+	struct usb_bam_connect_ipa_params *ipa_params){}
+
+static inline void usb_bam_resume(
+	struct usb_bam_connect_ipa_params *ipa_params) {}
+
 static inline int usb_bam_disconnect_pipe(u8 idx)
 {
 	return -ENODEV;
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 099862f..73e960f 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -614,3 +614,26 @@
 	of_scan_flat_dt(msm_scan_dt_map_imem, NULL);
 }
 #endif /* CONFIG_ARCH_MSM8610 */
+
+#ifdef CONFIG_ARCH_MSMSAMARIUM
+static struct map_desc msmsamarium_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(QGIC_DIST, MSMSAMARIUM),
+	MSM_CHIP_DEVICE(TLMM, MSMSAMARIUM),
+	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSMSAMARIUM),
+	{
+		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
+		.length =   MSM_SHARED_RAM_SIZE,
+		.type =     MT_DEVICE,
+	},
+#if defined(CONFIG_DEBUG_MSMSAMARIUM_UART) || defined(CONFIG_DEBUG_MSM8974_UART)
+	MSM_DEVICE(DEBUG_UART),
+#endif
+};
+
+void __init msm_map_msmsamarium_io(void)
+{
+	msm_shared_ram_phys = MSMSAMARIUM_SHARED_RAM_PHYS;
+	msm_map_io(msmsamarium_io_desc, ARRAY_SIZE(msmsamarium_io_desc));
+	of_scan_flat_dt(msm_scan_dt_map_imem, NULL);
+}
+#endif /* CONFIG_ARCH_MSMSAMARIUM */
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index f4ac37e..12f5a8e 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -570,12 +570,14 @@
 			goto out;
 		}
 		ctx = msm_iommu_get_ctx(name);
-		if (!ctx) {
-			pr_err("Unable to find context %s\n", name);
-			ret_val = -EINVAL;
+		if (IS_ERR(ctx)) {
+			ret_val = PTR_ERR(ctx);
 			goto out;
 		}
-		iommu_group_add_device(group, ctx);
+
+		ret_val = iommu_group_add_device(group, ctx);
+		if (ret_val)
+			goto out;
 	}
 out:
 	return ret_val;
@@ -590,7 +592,7 @@
 	struct msm_iova_layout l;
 	struct msm_iova_partition *part = 0;
 	struct iommu_domain *domain = 0;
-	unsigned int *addr_array;
+	unsigned int *addr_array = 0;
 	unsigned int array_size;
 	int domain_no;
 	int secure_domain;
@@ -661,11 +663,46 @@
 	iommu_group_set_iommudata(group, domain, NULL);
 
 free_mem:
+	kfree(addr_array);
 	kfree(part);
 out:
 	return ret_val;
 }
 
+static int __msm_group_get_domain(struct device *dev, void *data)
+{
+	struct msm_iommu_data_entry *list_entry;
+	struct list_head *dev_list = data;
+	int ret_val = 0;
+
+	list_entry = kmalloc(sizeof(*list_entry), GFP_KERNEL);
+	if (list_entry) {
+		list_entry->data = dev;
+		list_add(&list_entry->list, dev_list);
+	} else {
+		ret_val = -ENOMEM;
+	}
+
+	return ret_val;
+}
+
+static void __msm_iommu_group_remove_device(struct iommu_group *grp)
+{
+	struct msm_iommu_data_entry *tmp;
+	struct msm_iommu_data_entry *list_entry;
+	struct list_head dev_list;
+
+	INIT_LIST_HEAD(&dev_list);
+	iommu_group_for_each_dev(grp, &dev_list, __msm_group_get_domain);
+
+	list_for_each_entry_safe(list_entry, tmp, &dev_list, list) {
+		iommu_group_remove_device(list_entry->data);
+		list_del(&list_entry->list);
+		kfree(list_entry);
+	}
+}
+
+
 static int iommu_domain_parse_dt(const struct device_node *dt_node)
 {
 	struct device_node *node;
@@ -674,13 +711,30 @@
 	int ret_val = 0;
 	struct iommu_group *group = 0;
 	const char *name;
+	struct msm_iommu_data_entry *grp_list_entry;
+	struct msm_iommu_data_entry *tmp;
+	struct list_head iommu_group_list;
+	INIT_LIST_HEAD(&iommu_group_list);
 
 	for_each_child_of_node(dt_node, node) {
 		group = iommu_group_alloc();
 		if (IS_ERR(group)) {
 			ret_val = PTR_ERR(group);
-			goto out;
+			group = 0;
+			goto free_group;
 		}
+
+		/* This is only needed to clean up memory if something fails */
+		grp_list_entry = kmalloc(sizeof(*grp_list_entry),
+					   GFP_KERNEL);
+		if (grp_list_entry) {
+			grp_list_entry->data = group;
+			list_add(&grp_list_entry->list, &iommu_group_list);
+		} else {
+			ret_val = -ENOMEM;
+			goto free_group;
+		}
+
 		if (of_property_read_string(node, "label", &name)) {
 			ret_val = -EINVAL;
 			goto free_group;
@@ -696,7 +750,6 @@
 
 		ret_val = find_and_add_contexts(group, node, num_contexts);
 		if (ret_val) {
-			ret_val = -EINVAL;
 			goto free_group;
 		}
 		ret_val = create_and_add_domain(group, node, name);
@@ -704,9 +757,33 @@
 			ret_val = -EINVAL;
 			goto free_group;
 		}
+
+		/* Remove reference to the group that is taken when the group
+		 * is allocated. This will ensure that when all the devices in
+		 * the group are removed the group will be released.
+		 */
+		iommu_group_put(group);
 	}
+
+	list_for_each_entry_safe(grp_list_entry, tmp, &iommu_group_list, list) {
+		list_del(&grp_list_entry->list);
+		kfree(grp_list_entry);
+	}
+	goto out;
+
 free_group:
-	/* No iommu_group_free() function */
+	list_for_each_entry_safe(grp_list_entry, tmp, &iommu_group_list, list) {
+		struct iommu_domain *d;
+
+		d = iommu_group_get_iommudata(grp_list_entry->data);
+		if (d)
+			msm_unregister_domain(d);
+
+		__msm_iommu_group_remove_device(grp_list_entry->data);
+		list_del(&grp_list_entry->list);
+		kfree(grp_list_entry);
+	}
+	iommu_group_put(group);
 out:
 	return ret_val;
 }
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index aee691f..c620419 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2962,9 +2962,14 @@
 		D("open event for '%s'\n", xprt->name);
 		xprt_work = kmalloc(sizeof(struct msm_ipc_router_xprt_work),
 				GFP_ATOMIC);
-		xprt_work->xprt = xprt;
-		INIT_WORK(&xprt_work->work, xprt_open_worker);
-		queue_work(msm_ipc_router_workqueue, &xprt_work->work);
+		if (xprt_work) {
+			xprt_work->xprt = xprt;
+			INIT_WORK(&xprt_work->work, xprt_open_worker);
+			queue_work(msm_ipc_router_workqueue, &xprt_work->work);
+		} else {
+			pr_err("%s: malloc failure - Couldn't notify OPEN event",
+				__func__);
+		}
 		break;
 
 	case IPC_ROUTER_XPRT_EVENT_CLOSE:
@@ -2972,9 +2977,14 @@
 		atomic_inc(&pending_close_count);
 		xprt_work = kmalloc(sizeof(struct msm_ipc_router_xprt_work),
 				GFP_ATOMIC);
-		xprt_work->xprt = xprt;
-		INIT_WORK(&xprt_work->work, xprt_close_worker);
-		queue_work(msm_ipc_router_workqueue, &xprt_work->work);
+		if (xprt_work) {
+			xprt_work->xprt = xprt;
+			INIT_WORK(&xprt_work->work, xprt_close_worker);
+			queue_work(msm_ipc_router_workqueue, &xprt_work->work);
+		} else {
+			pr_err("%s: malloc failure - Couldn't notify CLOSE event",
+				__func__);
+		}
 		break;
 	}
 
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
index f05b381..d531aaa 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
@@ -1460,7 +1460,7 @@
 		 * boundary in future
 		 */
 		wmb();
-		set_qos_mode(binfo->base, mas_index, 0, 1, 1);
+		set_qos_mode(binfo->base, mas_index, 1, 1, 1);
 		break;
 
 	case BIMC_QOS_MODE_BYPASS:
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 2c7ceab..62da5ac 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -364,7 +364,7 @@
 {
 	struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
 	void *sel_cdata;
-	int i;
+	long rounded_rate;
 
 	sel_cdata = fabric->cdata[ctx];
 
@@ -379,8 +379,17 @@
 	}
 
 	/* Enable clocks before accessing QoS registers */
-	for (i = 0; i < NUM_CTX; i++)
-		clk_prepare_enable(fabric->info.nodeclk[i].clk);
+	if (fabric->info.nodeclk[DUAL_CTX].clk)
+		if (fabric->info.nodeclk[DUAL_CTX].rate == 0) {
+			rounded_rate = clk_round_rate(fabric->
+				info.nodeclk[DUAL_CTX].clk, 1);
+		if (clk_set_rate(fabric->info.nodeclk[DUAL_CTX].clk,
+				rounded_rate))
+			MSM_BUS_ERR("Error: clk: en: Node: %d rate: %ld",
+				fabric->fabdev.id, rounded_rate);
+
+		clk_prepare_enable(fabric->info.nodeclk[DUAL_CTX].clk);
+	}
 
 	if (info->iface_clk.clk)
 		clk_prepare_enable(info->iface_clk.clk);
@@ -392,8 +401,9 @@
 		master_tiers, add_bw);
 
 	/* Disable clocks after accessing QoS registers */
-	for (i = 0; i < NUM_CTX; i++)
-		clk_disable_unprepare(fabric->info.nodeclk[i].clk);
+	if (fabric->info.nodeclk[DUAL_CTX].clk &&
+			fabric->info.nodeclk[DUAL_CTX].rate == 0)
+		clk_disable_unprepare(fabric->info.nodeclk[DUAL_CTX].clk);
 
 	if (info->iface_clk.clk) {
 		MSM_BUS_DBG("Commented: Will disable clock for info: %d\n",
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 30168b8..098cbd5 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -330,12 +330,13 @@
 
 	drv->crash = true;
 
+	disable_irq_nosync(drv->irq);
+
 	if (drv->restart_inprogress) {
 		pr_err("Ignoring wcnss bite irq, restart in progress\n");
 		return IRQ_HANDLED;
 	}
 
-	disable_irq_nosync(drv->irq);
 	drv->restart_inprogress = true;
 	restart_wcnss(drv);
 
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 9a5883f..19b5671 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -410,12 +410,6 @@
 	drv->err_fatal_irq = ret;
 
 	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
-					    "qcom,gpio-err-ready", 0));
-	if (ret < 0)
-		return ret;
-	drv->subsys_desc.err_ready_irq = ret;
-
-	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
 					    "qcom,gpio-proxy-unvote", 0));
 	if (ret < 0)
 		return ret;
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 5419bf0..7fd76ab 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -313,6 +313,7 @@
 	}
 
 	pr_err("riva: smsm state changed to smsm reset\n");
+	wcnss_riva_dump_pmic_regs();
 
 	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
 		&smem_reset_size);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index afb2b84..5e44a4e 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -36,6 +36,7 @@
 #include <mach/scm.h>
 #include <mach/socinfo.h>
 #include <mach/msm-krait-l2-accessors.h>
+#include <mach/msm_bus.h>
 #include <asm/cacheflush.h>
 #include <asm/hardware/gic.h>
 #include <asm/pgtable.h>
@@ -854,8 +855,10 @@
 	time = ktime_to_ns(ktime_get());
 
 	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
+		int64_t ns = msm_pm_timer_enter_idle();
 		notify_rpm = true;
-		sleep_delay = (uint32_t)msm_pm_timer_enter_idle();
+		do_div(ns, NSEC_PER_SEC / SCLK_HZ);
+		sleep_delay = (uint32_t)ns;
 
 		if (sleep_delay == 0) /* 0 would mean infinite time */
 			sleep_delay = 1;
@@ -1110,6 +1113,36 @@
 	.enter = msm_pm_enter,
 	.valid = suspend_valid_only_mem,
 };
+
+static int __devinit msm_pm_snoc_client_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	static struct msm_bus_scale_pdata *msm_pm_bus_pdata;
+	static uint32_t msm_pm_bus_client;
+
+	msm_pm_bus_pdata = msm_bus_cl_get_pdata(pdev);
+
+	if (msm_pm_bus_pdata) {
+		msm_pm_bus_client =
+			msm_bus_scale_register_client(msm_pm_bus_pdata);
+
+		if (!msm_pm_bus_client) {
+			pr_err("%s: Failed to register SNOC client",
+							__func__);
+			rc = -ENXIO;
+			goto snoc_cl_probe_done;
+		}
+
+		rc = msm_bus_scale_client_update_request(msm_pm_bus_client, 1);
+
+		if (rc)
+			pr_err("%s: Error setting bus rate", __func__);
+	}
+
+snoc_cl_probe_done:
+	return rc;
+}
+
 static int __devinit msm_cpu_status_probe(struct platform_device *pdev)
 {
 	struct msm_pm_sleep_status_data *pdata;
@@ -1198,6 +1231,21 @@
 	},
 };
 
+static struct of_device_id msm_snoc_clnt_match_tbl[] = {
+	{.compatible = "qcom,pm-snoc-client"},
+	{},
+};
+
+static struct platform_driver msm_cpu_pm_snoc_client_driver = {
+	.probe = msm_pm_snoc_client_probe,
+	.driver = {
+		.name = "pm_snoc_client",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_snoc_clnt_match_tbl,
+	},
+};
+
+
 static int __init msm_pm_setup_saved_state(void)
 {
 	pgd_t *pc_pgd;
@@ -1538,6 +1586,14 @@
 		return rc;
 	}
 
+	rc = platform_driver_register(&msm_cpu_pm_snoc_client_driver);
+
+	if (rc) {
+		pr_err("%s(): failed to register driver %s\n", __func__,
+				msm_cpu_pm_snoc_client_driver.driver.name);
+		return rc;
+	}
+
 	return platform_driver_register(&msm_pm_8x60_driver);
 }
 device_initcall(msm_pm_8x60_init);
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 1945651..a177593 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -3939,12 +3939,11 @@
 	}
 
 	registered = true;
-	rc = remote_spin_lock_init(&remote_spinlock, SMEM_SPINLOCK_SMEM_ALLOC);
+	rc = init_smem_remote_spinlock();
 	if (rc) {
 		pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
 		return rc;
 	}
-	spinlocks_initialized = 1;
 
 	rc = platform_driver_register(&msm_smd_driver);
 	if (rc) {
diff --git a/arch/arm/mach-msm/smem.c b/arch/arm/mach-msm/smem.c
index c00f96f..2204609 100644
--- a/arch/arm/mach-msm/smem.c
+++ b/arch/arm/mach-msm/smem.c
@@ -56,6 +56,7 @@
 struct ramdump_segment *smem_ramdump_segments;
 
 static void *smem_ramdump_dev;
+static DEFINE_MUTEX(spinlock_init_lock);
 
 struct restart_notifier_block {
 	unsigned processor;
@@ -215,6 +216,7 @@
 	struct smem_heap_entry *toc = shared->heap_toc;
 	unsigned long flags;
 	void *ret = NULL;
+	int rc;
 
 	if (!shared->heap_info.initialized) {
 		pr_err("%s: smem heap info not initialized\n", __func__);
@@ -224,6 +226,15 @@
 	if (id >= SMEM_NUM_ITEMS)
 		return NULL;
 
+	if (unlikely(!spinlocks_initialized)) {
+		rc = init_smem_remote_spinlock();
+		if (unlikely(rc)) {
+			pr_err("%s: remote spinlock init failed %d\n",
+								__func__, rc);
+			return NULL;
+		}
+	}
+
 	size_in = ALIGN(size_in, 8);
 	remote_spin_lock_irqsave(&remote_spinlock, flags);
 	if (toc[id].allocated) {
@@ -301,6 +312,35 @@
 }
 EXPORT_SYMBOL(smem_get_remote_spinlock);
 
+/**
+ * init_smem_remote_spinlock - Reentrant remote spinlock initialization
+ *
+ * @returns: sucess or error code for failure
+ */
+int init_smem_remote_spinlock(void)
+{
+	int rc = 0;
+
+	/*
+	 * Optimistic locking.  Init only needs to be done once by the first
+	 * caller.  After that, serializing inits between different callers
+	 * is unnecessary.  The second check after the lock ensures init
+	 * wasn't previously completed by someone else before the lock could
+	 * be grabbed.
+	 */
+	if (!spinlocks_initialized) {
+		mutex_lock(&spinlock_init_lock);
+		if (!spinlocks_initialized) {
+			rc = remote_spin_lock_init(&remote_spinlock,
+						SMEM_SPINLOCK_SMEM_ALLOC);
+			if (!rc)
+				spinlocks_initialized = 1;
+		}
+		mutex_unlock(&spinlock_init_lock);
+	}
+	return rc;
+}
+
 static int restart_notifier_cb(struct notifier_block *this,
 				unsigned long code,
 				void *data)
diff --git a/arch/arm/mach-msm/smem_private.h b/arch/arm/mach-msm/smem_private.h
index 89b2b7b..b631e7c 100644
--- a/arch/arm/mach-msm/smem_private.h
+++ b/arch/arm/mach-msm/smem_private.h
@@ -19,7 +19,7 @@
 
 #define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
 extern remote_spinlock_t remote_spinlock;
-extern int spinlocks_initialized;
+extern int spinlocks_initialized; /* only modify in init_smem_remote_spinlock */
 
 #define SMD_HEAP_SIZE 512
 
@@ -65,4 +65,10 @@
 
 /* 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);
 #endif /* _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_ */
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 0c02b51..928f5cb 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -324,6 +324,9 @@
 
 	/* 8226 IDs */
 	[145] = MSM_CPU_8226,
+	[158] = MSM_CPU_8226,
+	[159] = MSM_CPU_8226,
+	[198] = MSM_CPU_8226,
 
 	/* 8092 IDs */
 	[146] = MSM_CPU_8092,
@@ -364,6 +367,9 @@
 	/* FSM9900 ID */
 	[188] = FSM_CPU_9900,
 
+	/* Samarium IDs */
+	[195] = MSM_CPU_SAMARIUM,
+
 	/* Uninitialized IDs are not known to run Linux.
 	   MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
 	   considered as unknown CPU. */
@@ -871,6 +877,10 @@
 		dummy_socinfo.id = 187;
 		strlcpy(dummy_socinfo.build_id, "msmkrypton - ",
 			sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_msmsamarium()) {
+		dummy_socinfo.id = 195;
+		strlcpy(dummy_socinfo.build_id, "msmsamarium - ",
+			sizeof(dummy_socinfo.build_id));
 	}
 	strlcat(dummy_socinfo.build_id, "Dummy socinfo",
 		sizeof(dummy_socinfo.build_id));
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index c971896..b956649 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -41,6 +41,9 @@
 
 #include "smd_private.h"
 
+static int enable_debug;
+module_param(enable_debug, int, S_IRUGO | S_IWUSR);
+
 /**
  * enum p_subsys_state - state of a subsystem (private)
  * @SUBSYS_NORMAL: subsystem is operating normally
@@ -419,7 +422,7 @@
 {
 	int ret;
 
-	if (!subsys->desc->err_ready_irq)
+	if (!subsys->desc->err_ready_irq || enable_debug == 1)
 		return 0;
 
 	ret = wait_for_completion_timeout(&subsys->err_ready,
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 51578e0..e98fff2 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -26,10 +26,13 @@
 #include <linux/msm_ion.h>
 #include <mach/msm_smd.h>
 #include <mach/ion.h>
+#include <mach/iommu_domains.h>
 #include <linux/scatterlist.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <linux/device.h>
+#include <linux/of.h>
+#include <linux/iommu.h>
 
 #ifndef ION_ADSPRPC_HEAP_ID
 #define ION_ADSPRPC_HEAP_ID ION_AUDIO_HEAP_ID
@@ -53,6 +56,8 @@
 		} while (0)
 
 
+#define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0)
+
 static inline uint32_t buf_page_start(void *buf)
 {
 	uint32_t start = (uint32_t) buf & PAGE_MASK;
@@ -84,8 +89,9 @@
 {
 	struct vm_area_struct *vma;
 	uint32_t start = buf_page_start(addr);
+	uint32_t end = buf_page_start((void *)((uint32_t)addr + sz - 1));
 	uint32_t len = nr_pages << PAGE_SHIFT;
-	unsigned long pfn;
+	unsigned long pfn, pfnend;
 	int n = -1, err = 0;
 
 	VERIFY(err, 0 != access_ok(access ? VERIFY_WRITE : VERIFY_READ,
@@ -102,6 +108,12 @@
 	VERIFY(err, 0 == follow_pfn(vma, start, &pfn));
 	if (err)
 		goto bail;
+	VERIFY(err, 0 == follow_pfn(vma, end, &pfnend));
+	if (err)
+		goto bail;
+	VERIFY(err, (pfn + nr_pages - 1) == pfnend);
+	if (err)
+		goto bail;
 	VERIFY(err, nr_elems > 0);
 	if (err)
 		goto bail;
@@ -124,6 +136,13 @@
 	int last;
 };
 
+struct fastrpc_smmu {
+	struct iommu_group *group;
+	struct iommu_domain *domain;
+	int domain_id;
+	bool enabled;
+};
+
 struct fastrpc_apps {
 	smd_channel_t *chan;
 	struct smq_context_list clst;
@@ -132,6 +151,7 @@
 	struct cdev cdev;
 	struct class *class;
 	struct device *dev;
+	struct fastrpc_smmu smmu;
 	dev_t dev_no;
 	spinlock_t wrlock;
 	spinlock_t hlock;
@@ -172,7 +192,12 @@
 {
 	struct fastrpc_apps *me = &gfa;
 
-	if (buf->handle) {
+	if (!IS_ERR_OR_NULL(buf->handle)) {
+		if (me->smmu.enabled && buf->phys) {
+			ion_unmap_iommu(me->iclient, buf->handle,
+					me->smmu.domain_id, 0);
+			buf->phys = 0;
+		}
 		if (buf->virt) {
 			ion_unmap_kernel(me->iclient, buf->handle);
 			buf->virt = 0;
@@ -185,7 +210,7 @@
 static void free_map(struct fastrpc_mmap *map)
 {
 	struct fastrpc_apps *me = &gfa;
-	if (map->handle) {
+	if (!IS_ERR_OR_NULL(map->handle)) {
 		if (map->virt) {
 			ion_unmap_kernel(me->iclient, map->handle);
 			map->virt = 0;
@@ -197,26 +222,39 @@
 
 static int alloc_mem(struct fastrpc_buf *buf)
 {
+	struct fastrpc_apps *me = &gfa;
 	struct ion_client *clnt = gfa.iclient;
 	struct sg_table *sg;
 	int err = 0;
+	unsigned int heap;
+	unsigned long len;
 	buf->handle = 0;
 	buf->virt = 0;
-	buf->handle = ion_alloc(clnt, buf->size, SZ_4K,
-				ION_HEAP(ION_AUDIO_HEAP_ID), 0);
+	heap = me->smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) :
+		ION_HEAP(ION_ADSP_HEAP_ID) | ION_HEAP(ION_AUDIO_HEAP_ID);
+	buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, 0);
 	VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle));
 	if (err)
 		goto bail;
 	VERIFY(err, 0 != (buf->virt = ion_map_kernel(clnt, buf->handle)));
 	if (err)
 		goto bail;
-	VERIFY(err, 0 != (sg = ion_sg_table(clnt, buf->handle)));
-	if (err)
-		goto bail;
-	VERIFY(err, 1 == sg->nents);
-	if (err)
-		goto bail;
-	buf->phys = sg_dma_address(sg->sgl);
+	if (me->smmu.enabled) {
+		len = buf->size;
+		VERIFY(err, 0 == ion_map_iommu(clnt, buf->handle,
+					me->smmu.domain_id, 0, SZ_4K, 0,
+					&buf->phys, &len, 0, 0));
+		if (err)
+			goto bail;
+	} else {
+		VERIFY(err, 0 != (sg = ion_sg_table(clnt, buf->handle)));
+		if (err)
+			goto bail;
+		VERIFY(err, 1 == sg->nents);
+		if (err)
+			goto bail;
+		buf->phys = sg_dma_address(sg->sgl);
+	}
  bail:
 	if (err && !IS_ERR_OR_NULL(buf->handle))
 		free_mem(buf);
@@ -481,6 +519,28 @@
 	return err;
 }
 
+static void inv_args_pre(uint32_t sc, remote_arg_t *rpra)
+{
+	int i, inbufs, outbufs;
+	uint32_t end;
+
+	inbufs = REMOTE_SCALARS_INBUFS(sc);
+	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+	for (i = inbufs; i < inbufs + outbufs; ++i) {
+		if (!rpra[i].buf.len)
+			continue;
+		if (buf_page_start(rpra) == buf_page_start(rpra[i].buf.pv))
+			continue;
+		if (!IS_CACHE_ALIGNED((uint32_t)rpra[i].buf.pv))
+			dmac_flush_range(rpra[i].buf.pv,
+				(char *)rpra[i].buf.pv + 1);
+		end = (uint32_t)rpra[i].buf.pv + rpra[i].buf.len;
+		if (!IS_CACHE_ALIGNED(end))
+			dmac_flush_range((char *)end,
+				(char *)end + 1);
+	}
+}
+
 static void inv_args(uint32_t sc, remote_arg_t *rpra, int used)
 {
 	int i, inbufs, outbufs;
@@ -572,6 +632,8 @@
 {
 	int err = 0;
 	struct fastrpc_apps *me = &gfa;
+	struct device_node *node;
+	bool enabled = 0;
 
 	if (me->chan == 0) {
 		int i;
@@ -588,6 +650,22 @@
 		VERIFY(err, 0 == IS_ERR_OR_NULL(me->iclient));
 		if (err)
 			goto ion_bail;
+		node = of_find_compatible_node(NULL, NULL,
+						"qcom,msm-audio-ion");
+		if (node)
+			enabled = of_property_read_bool(node,
+						"qcom,smmu-enabled");
+		if (enabled)
+			me->smmu.group = iommu_group_find("lpass_audio");
+		if (me->smmu.group)
+			me->smmu.domain = iommu_group_get_iommudata(
+							me->smmu.group);
+		if (!IS_ERR_OR_NULL(me->smmu.domain)) {
+			me->smmu.domain_id = msm_find_domain_no(
+							me->smmu.domain);
+			if (me->smmu.domain_id >= 0)
+				me->smmu.enabled = enabled;
+		}
 		VERIFY(err, 0 == smd_named_open_on_edge(FASTRPC_SMD_GUID,
 						SMD_APPS_QDSP, &me->chan,
 						me, smd_event_handler));
@@ -704,6 +782,12 @@
 
 	sc = invoke->sc;
 	obuf.handle = 0;
+	if (me->smmu.enabled) {
+		VERIFY(err, 0 == iommu_attach_group(me->smmu.domain,
+							me->smmu.group));
+		if (err)
+			return err;
+	}
 	if (REMOTE_SCALARS_LENGTH(sc)) {
 		VERIFY(err, 0 == get_dev(me, &dev));
 		if (err)
@@ -720,6 +804,7 @@
 	}
 
 	context_list_alloc_ctx(&me->clst, &ctx);
+	inv_args_pre(sc, rpra);
 	VERIFY(err, 0 == fastrpc_invoke_send(me, kernel, invoke->handle, sc,
 						ctx, &obuf));
 	if (err)
@@ -743,6 +828,8 @@
 	}
 	context_free(ctx);
 
+	if (me->smmu.enabled)
+		iommu_detach_group(me->smmu.domain, me->smmu.group);
 	for (i = 0, b = abufs; i < nbufs; ++i, ++b)
 		free_mem(b);
 
@@ -1093,6 +1180,7 @@
 	struct fastrpc_apps *me = &gfa;
 	int err = 0;
 
+	memset(me, 0, sizeof(*me));
 	VERIFY(err, 0 == fastrpc_init());
 	if (err)
 		goto fastrpc_bail;
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 684f11d..292a0be 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -219,6 +219,7 @@
 	int num_clients;
 	int polling_reg_flag;
 	struct diag_write_device *buf_tbl;
+	unsigned int buf_tbl_size;
 	int use_device_tree;
 	/* DCI related variables */
 	struct dci_pkt_req_tracking_tbl *req_tracking_tbl;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7022a6f..96e8b11 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1167,7 +1167,7 @@
 		/* place holder for number of data field */
 		ret += 4;
 
-		for (i = 0; i < driver->poolsize_write_struct; i++) {
+		for (i = 0; i < driver->buf_tbl_size; i++) {
 			if (driver->buf_tbl[i].length > 0) {
 #ifdef DIAG_DEBUG
 				pr_debug("diag: WRITING the buf address "
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 151e304..f76d41a 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -48,7 +48,8 @@
 
 int diag_debug_buf_idx;
 unsigned char diag_debug_buf[1024];
-static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
+/* Number of entries in table of buffers */
+static unsigned int buf_tbl_size = 10;
 struct diag_master_table entry;
 struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
@@ -467,7 +468,7 @@
 	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
 		int hsic_updated = 0;
 		if (data_type == APPS_DATA) {
-			for (i = 0; i < driver->poolsize_write_struct; i++)
+			for (i = 0; i < driver->buf_tbl_size; i++)
 				if (driver->buf_tbl[i].length == 0) {
 					driver->buf_tbl[i].buf = buf;
 					driver->buf_tbl[i].length =
@@ -1768,6 +1769,12 @@
 	driver->read_len_legacy = 0;
 	driver->use_device_tree = has_device_tree();
 	driver->real_time_mode = 1;
+	/*
+	 * The number of entries in table of buffers
+	 * should not be any smaller than hdlc poolsize.
+	 */
+	driver->buf_tbl_size = (buf_tbl_size < driver->poolsize_hdlc) ?
+				driver->poolsize_hdlc : buf_tbl_size;
 	mutex_init(&driver->diag_hdlc_mutex);
 	mutex_init(&driver->diag_cntl_mutex);
 
@@ -1802,7 +1809,7 @@
 		goto err;
 	kmemleak_not_leak(driver->client_map);
 	if (driver->buf_tbl == NULL)
-			driver->buf_tbl = kzalloc(buf_tbl_size *
+			driver->buf_tbl = kzalloc(driver->buf_tbl_size *
 			  sizeof(struct diag_write_device), GFP_KERNEL);
 	if (driver->buf_tbl == NULL)
 		goto err;
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 0e2e2d9..2b14f86 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -2,7 +2,6 @@
 # Makefile for CoreSight drivers.
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
-obj-$(CONFIG_OF) += of_coresight.o
 obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
 obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
 obj-$(CONFIG_CORESIGHT_TMC) += coresight-tmc.o
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index a506aa8..7b01432 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -4,6 +4,7 @@
  *  Copyright (C)  2001 Russell King
  *            (C)  2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
  *                      Jun Nakajima <jun.nakajima@intel.com>
+ *            (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 as
@@ -124,6 +125,14 @@
 
 static DEFINE_PER_CPU(struct dbs_work_struct, dbs_refresh_work);
 
+struct dbs_sync_work_struct {
+	struct work_struct work;
+	unsigned int src_cpu;
+	unsigned int targ_cpu;
+};
+
+static DEFINE_PER_CPU(struct dbs_sync_work_struct, dbs_sync_work);
+
 static struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int up_threshold;
@@ -1020,6 +1029,92 @@
 	return;
 }
 
+static int dbs_migration_notify(struct notifier_block *nb,
+				unsigned long target_cpu, void *arg)
+{
+	struct dbs_sync_work_struct *sync_work =
+		&per_cpu(dbs_sync_work, target_cpu);
+	sync_work->src_cpu = (unsigned int)arg;
+
+	queue_work_on(target_cpu, input_wq,
+		&per_cpu(dbs_sync_work, target_cpu).work);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block dbs_migration_nb = {
+	.notifier_call = dbs_migration_notify,
+};
+
+void dbs_synchronize(struct work_struct *work)
+{
+	struct cpufreq_policy *policy;
+	struct cpu_dbs_info_s *this_dbs_info, *src_dbs_info;
+	struct dbs_sync_work_struct *dbs_work;
+	unsigned int cpu, src_cpu;
+	unsigned int src_freq, src_max_load;
+	int delay;
+
+	dbs_work = container_of(work, struct dbs_sync_work_struct, work);
+	cpu = dbs_work->targ_cpu;
+	src_cpu = dbs_work->src_cpu;
+
+	get_online_cpus();
+
+	/* Getting source cpu info  */
+	src_dbs_info = &per_cpu(od_cpu_dbs_info, src_cpu);
+	if (src_dbs_info != NULL && src_dbs_info->cur_policy != NULL) {
+		src_freq = src_dbs_info->cur_policy->cur;
+		src_max_load = src_dbs_info->max_load;
+	} else {
+		src_freq = dbs_tuners_ins.sync_freq;
+		src_max_load = 0;
+	}
+
+	if (lock_policy_rwsem_write(cpu) < 0)
+		goto bail_acq_sema_failed;
+
+	this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+	policy = this_dbs_info->cur_policy;
+	if (!policy) {
+		/* CPU not using ondemand governor */
+		goto bail_incorrect_governor;
+	}
+
+	delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+
+	if (policy->cur < src_freq) {
+
+		/* Cancelling the next ondemand sample */
+		cancel_delayed_work_sync(&this_dbs_info->work);
+
+		/*
+		 * Arch specific cpufreq driver may fail.
+		 * Don't update governor frequency upon failure.
+		 */
+		if (__cpufreq_driver_target(policy, src_freq,
+					CPUFREQ_RELATION_L) >= 0) {
+			policy->cur = src_freq;
+			if (src_max_load > this_dbs_info->max_load) {
+				this_dbs_info->max_load = src_max_load;
+				this_dbs_info->prev_load = src_max_load;
+			}
+		}
+
+		/* Rescheduling the next ondemand sample */
+		mutex_lock(&this_dbs_info->timer_mutex);
+		schedule_delayed_work_on(cpu, &this_dbs_info->work,
+					delay);
+		mutex_unlock(&this_dbs_info->timer_mutex);
+	}
+bail_incorrect_governor:
+	unlock_policy_rwsem_write(cpu);
+
+bail_acq_sema_failed:
+	put_online_cpus();
+	return;
+}
+
 static void dbs_input_event(struct input_handle *handle, unsigned int type,
 		unsigned int code, int value)
 {
@@ -1148,6 +1243,9 @@
 
 			if (dbs_tuners_ins.sync_freq == 0)
 				dbs_tuners_ins.sync_freq = policy->min;
+
+			atomic_notifier_chain_register(&migration_notifier_head,
+					&dbs_migration_nb);
 		}
 		if (!cpu)
 			rc = input_register_handler(&dbs_input_handler);
@@ -1171,9 +1269,14 @@
 		this_dbs_info->cur_policy = NULL;
 		if (!cpu)
 			input_unregister_handler(&dbs_input_handler);
-		if (!dbs_enable)
+		if (!dbs_enable) {
 			sysfs_remove_group(cpufreq_global_kobject,
 					   &dbs_attr_group);
+			atomic_notifier_chain_unregister(
+				&migration_notifier_head,
+				&dbs_migration_nb);
+		}
+
 		mutex_unlock(&dbs_mutex);
 
 		break;
@@ -1232,10 +1335,17 @@
 			&per_cpu(od_cpu_dbs_info, i);
 		struct dbs_work_struct *dbs_work =
 			&per_cpu(dbs_refresh_work, i);
+		struct dbs_sync_work_struct *dbs_sync =
+			&per_cpu(dbs_sync_work, i);
 
 		mutex_init(&this_dbs_info->timer_mutex);
 		INIT_WORK(&dbs_work->work, dbs_refresh_callback);
 		dbs_work->cpu = i;
+
+		INIT_WORK(&dbs_sync->work, dbs_synchronize);
+		dbs_sync->src_cpu = 0;
+		dbs_sync->targ_cpu = i;
+
 	}
 
 	return cpufreq_register_governor(&cpufreq_gov_ondemand);
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 58fa5c9..2b70d3f 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -717,6 +717,9 @@
 	bool sha1 = false;
 	uint32_t auth_cfg = 0;
 
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
 							CRYPTO_CONFIG_REG));
 	/*
@@ -896,6 +899,9 @@
 	uint32_t ivsize = creq->ivsize;
 	int i;
 
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
 							CRYPTO_CONFIG_REG));
 	/*
@@ -1213,6 +1219,7 @@
 {
 	struct aead_request *areq;
 	unsigned char mac[SHA256_DIGEST_SIZE];
+	uint32_t status;
 
 	areq = (struct aead_request *) pce_dev->areq;
 	if (areq->src != areq->dst) {
@@ -1227,16 +1234,55 @@
 	/* check MAC */
 	memcpy(mac, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
 						SHA256_DIGEST_SIZE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
 
 	if (pce_dev->mode == QCE_MODE_CCM) {
-		uint32_t result_status;
+		int32_t result_status;
+
+		/*
+		 * Don't use result dump status. The operation may not
+		 * be complete.
+		 * Instead, use the status we just read of device.
+		 * In case, we need to use result_status from result
+		 * dump the result_status needs to be byte swapped,
+		 * since we set the device to little endian.
+		 */
+
 		result_status = pce_dev->ce_sps.result->status;
-		result_status &= (1 << CRYPTO_MAC_FAILED);
-		result_status |= (pce_dev->ce_sps.consumer_status |
-					pce_dev->ce_sps.producer_status);
+		pce_dev->ce_sps.result->status = 0;
+
+		if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+
+			pr_err("aead operation error. Status %x\n",
+				status);
+			result_status = -ENXIO;
+		} else if (pce_dev->ce_sps.consumer_status |
+				pce_dev->ce_sps.producer_status)  {
+			pr_err("aead sps operation error. sps status %x %x\n",
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+			result_status = -ENXIO;
+		} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+			pr_err("aead operation not done? Status %x, sps status %x %x\n",
+				status,
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+			result_status = -ENXIO;
+
+		} else if (status & (1 << CRYPTO_MAC_FAILED)) {
+			result_status = -EBADMSG;
+		} else {
+			result_status = 0;
+		}
+
 		pce_dev->qce_cb(areq, mac, NULL, result_status);
+
 	} else {
 		uint32_t ivsize = 0;
 		struct crypto_aead *aead;
@@ -1260,6 +1306,8 @@
 	struct ahash_request *areq;
 	unsigned char digest[SHA256_DIGEST_SIZE];
 	uint32_t bytecount32[2];
+	int32_t result_status = pce_dev->ce_sps.result->status;
+	uint32_t status;
 
 	areq = (struct ahash_request *) pce_dev->areq;
 	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
@@ -1269,10 +1317,39 @@
 	_byte_stream_to_net_words(bytecount32,
 		(unsigned char *)pce_dev->ce_sps.result->auth_byte_count,
 					2 * CRYPTO_REG_SIZE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
+
+	/*
+	 * Don't use result dump status. The operation may not be complete.
+	 * Instead, use the status we just read of device.
+	 * In case, we need to use result_status from result
+	 * dump the result_status needs to be byte swapped,
+	 * since we set the device to little endian.
+	 */
+
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+
+		pr_err("sha operation error. Status %x\n", status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status) {
+		pr_err("sha sps operation error. sps status %x\n",
+			pce_dev->ce_sps.consumer_status);
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("sha operation not done? Status %x, sps status %x\n",
+			status, pce_dev->ce_sps.consumer_status);
+		result_status = -ENXIO;
+	} else {
+		result_status = 0;
+	}
 	pce_dev->qce_cb(areq, digest, (char *)bytecount32,
-				pce_dev->ce_sps.consumer_status);
+				result_status);
 	return 0;
 };
 
@@ -1280,6 +1357,8 @@
 {
 	struct ablkcipher_request *areq;
 	unsigned char iv[NUM_OF_CRYPTO_CNTR_IV_REG * CRYPTO_REG_SIZE];
+	uint32_t status;
+	int32_t result_status;
 
 	areq = (struct ablkcipher_request *) pce_dev->areq;
 
@@ -1290,13 +1369,46 @@
 	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 		(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 						DMA_TO_DEVICE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
 
+	/*
+	 * Don't use result dump status. The operation may not be complete.
+	 * Instead, use the status we just read of device.
+	 * In case, we need to use result_status from result
+	 * dump the result_status needs to be byte swapped,
+	 * since we set the device to little endian.
+	 */
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+		pr_err("ablk_cipher operation error. Status %x\n",
+				status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status |
+				pce_dev->ce_sps.producer_status)  {
+		pr_err("ablk_cipher sps operation error. sps status %x %x\n",
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("ablk_cipher operation not done? Status %x, sps status %x %x\n",
+			status,
+			pce_dev->ce_sps.consumer_status,
+			pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+
+	} else {
+		result_status = 0;
+	}
+
 	if (pce_dev->mode == QCE_MODE_ECB) {
 		pce_dev->qce_cb(areq, NULL, NULL,
 					pce_dev->ce_sps.consumer_status |
-					pce_dev->ce_sps.producer_status);
+					result_status);
 	} else {
 		if (pce_dev->ce_sps.minor_version == 0) {
 			if (pce_dev->mode == QCE_MODE_CBC) {
@@ -1342,9 +1454,7 @@
 				(char *)(pce_dev->ce_sps.result->encr_cntr_iv),
 				sizeof(iv));
 		}
-		pce_dev->qce_cb(areq, NULL, iv,
-			pce_dev->ce_sps.consumer_status |
-			pce_dev->ce_sps.producer_status);
+		pce_dev->qce_cb(areq, NULL, iv, result_status);
 	}
 	return 0;
 };
@@ -1993,6 +2103,9 @@
 	break;
 	}
 
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
@@ -2037,13 +2150,9 @@
 	if (mode == QCE_MODE_XTS) {
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
 						0, &pcl_info->auth_seg_size);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-						0, &pcl_info->auth_seg_size);
 	} else {
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
 						0, &pcl_info->auth_seg_size);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-						0, &pcl_info->auth_seg_size);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG,
 						0, &pcl_info->auth_seg_size);
 	}
@@ -2130,6 +2239,9 @@
 	break;
 	}
 
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
@@ -2156,13 +2268,7 @@
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR1_IV1_REG, 0,
 								NULL);
 	}
-	/* Add dummy to  align size to burst-size multiple */
-	if (!mode_cbc) {
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
-						0, &pcl_info->auth_seg_size);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-						0, &pcl_info->auth_seg_size);
-	}
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_le, NULL);
 
@@ -2206,10 +2312,13 @@
 
 		auth_cfg = pdev->reg.auth_cfg_sha1;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-							0, NULL);
 
 	break;
 	case QCE_HASH_SHA256:
@@ -2218,13 +2327,16 @@
 
 		auth_cfg = pdev->reg.auth_cfg_sha256;
 		iv_reg = 8;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	case QCE_HASH_SHA1_HMAC:
 		cmdlistptr->auth_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2233,10 +2345,13 @@
 		auth_cfg = pdev->reg.auth_cfg_hmac_sha1;
 		key_reg = 16;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-							0, NULL);
 	break;
 	case QCE_AEAD_SHA1_HMAC:
 		cmdlistptr->aead_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2245,13 +2360,16 @@
 		auth_cfg = pdev->reg.auth_cfg_aead_sha1_hmac;
 		key_reg = 16;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-							0, NULL);
 	break;
 	case QCE_HASH_SHA256_HMAC:
 		cmdlistptr->auth_sha256_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2261,13 +2379,15 @@
 		key_reg = 16;
 		iv_reg = 8;
 
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
+					NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	case QCE_HASH_AES_CMAC:
 		if (key_128 == true) {
@@ -2285,13 +2405,16 @@
 			auth_cfg = pdev->reg.auth_cfg_cmac_256;
 			key_reg = 8;
 		}
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
+					NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	default:
 		pr_err("Unknown algorithms %d received, exiting now\n", alg);
@@ -2395,10 +2518,13 @@
 
 		key_reg = 8;
 	}
+
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_START_REG, 0,
 									NULL);
diff --git a/drivers/crypto/msm/qcryptohw_50.h b/drivers/crypto/msm/qcryptohw_50.h
index 1be2702..e93e25c 100644
--- a/drivers/crypto/msm/qcryptohw_50.h
+++ b/drivers/crypto/msm/qcryptohw_50.h
@@ -297,6 +297,7 @@
 #define CRYPTO_DOUT_SIZE_AVAIL_MASK		(0x1F << CRYPTO_DOUT_SIZE_AVAIL)
 #define CRYPTO_DIN_SIZE_AVAIL			21 /* bit 21-25 */
 #define CRYPTO_DIN_SIZE_AVAIL_MASK		(0x1F << CRYPTO_DIN_SIZE_AVAIL)
+#define CRYPTO_HSD_ERR				20
 #define CRYPTO_ACCESS_VIOL			19
 #define CRYPTO_PIPE_ACTIVE_ERR			18
 #define CRYPTO_CFG_CHNG_ERR			17
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index 193f4d4..e7f7836 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -115,6 +115,7 @@
 	dev_dbg(dev, "Release buffer %p\n", buffer);
 	/* release memory */
 	dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle);
+	sg_free_table(info->table);
 	/* release sg table */
 	kfree(info->table);
 	kfree(info);
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index e1b3eea..b3960b2 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -154,6 +154,7 @@
 	dev_dbg(dev, "Release buffer %p\n", buffer);
 	/* release memory */
 	dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle);
+	sg_free_table(info->table);
 	/* release sg table */
 	kfree(info->table);
 	kfree(info);
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 3b01e54..a1fc5a2 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -268,7 +268,8 @@
 		 * timestamp on the event has passed - return that up a layer
 		 */
 
-		return device->ftbl->next_event(device, event);
+		if (device->ftbl->next_event)
+			return device->ftbl->next_event(device, event);
 	}
 
 	return 0;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index e071650..52340cc 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1454,6 +1454,8 @@
 	}
 	if (ret == 0)
 		device->active_cnt++;
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	return ret;
 }
 EXPORT_SYMBOL(kgsl_active_count_get);
@@ -1482,6 +1484,8 @@
 	}
 
 	device->active_cnt++;
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_active_count_get_light);
@@ -1504,6 +1508,8 @@
 	kgsl_pwrscale_idle(device);
 	if (device->active_cnt > 1) {
 		device->active_cnt--;
+		trace_kgsl_active_count(device,
+			(unsigned long) __builtin_return_address(0));
 		return;
 	}
 
@@ -1520,6 +1526,8 @@
 	}
 	device->active_cnt--;
 
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	if (device->active_cnt == 0)
 		complete(&device->suspend_gate);
 }
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index b9bc432..4071b37 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -598,7 +598,7 @@
 			gfp_mask |= __GFP_COMP | __GFP_NORETRY |
 				__GFP_NO_KSWAPD | __GFP_NOWARN;
 		else
-			gfp_mask |= GFP_KERNEL | __GFP_NORETRY;
+			gfp_mask |= GFP_KERNEL;
 
 		page = alloc_pages(gfp_mask, get_order(page_size));
 
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 5f7ee3c..08677ef 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -739,6 +739,30 @@
 			__entry->id, __entry->ts, __entry->age)
 );
 
+TRACE_EVENT(kgsl_active_count,
+
+	TP_PROTO(struct kgsl_device *device, unsigned long ip),
+
+	TP_ARGS(device, ip),
+
+	TP_STRUCT__entry(
+		__string(device_name, device->name)
+		__field(unsigned int, count)
+		__field(unsigned long, ip)
+	),
+
+	TP_fast_assign(
+		__assign_str(device_name, device->name);
+		__entry->count = device->active_cnt;
+		__entry->ip = ip;
+	),
+
+	TP_printk(
+		"d_name=%s active_cnt=%x func=%pf",
+		__get_str(device_name), __entry->count, (void *) __entry->ip
+	)
+);
+
 #endif /* _KGSL_TRACE_H */
 
 /* This part must be outside protection */
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index b3b3b5e..4306b1d 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -83,6 +83,14 @@
 #define QPNP_VADC_M1_LOW_THR_MSB					0x6a
 #define QPNP_VADC_M1_HIGH_THR_LSB				0x6b
 #define QPNP_VADC_M1_HIGH_THR_MSB				0x6c
+#define QPNP_VADC_ACCESS					0xd0
+#define QPNP_VADC_ACCESS_DATA					0xa5
+#define QPNP_VADC_PERH_RESET_CTL3				0xda
+#define QPNP_FOLLOW_OTST2_RB					BIT(3)
+#define QPNP_FOLLOW_WARM_RB					BIT(2)
+#define QPNP_FOLLOW_SHUTDOWN1_RB				BIT(1)
+#define QPNP_FOLLOW_SHUTDOWN2_RB				BIT(0)
+
 #define QPNP_INT_TEST_VAL					0xE1
 
 #define QPNP_VADC_DATA0						0x60
@@ -150,6 +158,40 @@
 	return 0;
 }
 
+static int32_t qpnp_vadc_warm_rst_configure(void)
+{
+	int rc = 0;
+	u8 data = 0;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_PERH_RESET_CTL3, &data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 read failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	data |= QPNP_FOLLOW_WARM_RB;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_PERH_RESET_CTL3, data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 write failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int32_t qpnp_vadc_enable(bool state)
 {
 	int rc = 0;
@@ -1126,6 +1168,12 @@
 	}
 	vadc->id = fab_id;
 
+	rc = qpnp_vadc_warm_rst_configure();
+	if (rc < 0) {
+		pr_err("Setting perp reset on warm reset failed %d\n", rc);
+		return rc;
+	}
+
 	vadc->vadc_initialized = true;
 	vadc->vadc_iadc_sync_lock = false;
 
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index ed53c41..ba94178 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -2567,7 +2567,7 @@
 
 	if (rmi4_data->board->i2c_pull_up) {
 		retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
-			RMI4_I2C_LOAD_UA);
+			RMI4_I2C_LPM_LOAD_UA);
 		if (retval < 0) {
 			dev_err(&rmi4_data->i2c_client->dev,
 				"Regulator vcc_i2c set_opt failed rc=%d\n",
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index 06f4a0f..10fa5b1 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -32,6 +32,7 @@
 #include <mach/msm_iommu_priv.h>
 #include <mach/iommu.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus.h>
 
 #define MRC(reg, processor, op1, crn, crm, op2)				\
 __asm__ __volatile__ (							\
@@ -135,6 +136,20 @@
 	return msm_iommu_remote_lock.lock;
 }
 
+static int apply_bus_vote(struct msm_iommu_drvdata *drvdata, unsigned int vote)
+{
+	int ret = 0;
+
+	if (drvdata->bus_client) {
+		ret = msm_bus_scale_client_update_request(drvdata->bus_client,
+							  vote);
+		if (ret)
+			pr_err("%s: Failed to vote for bus: %d\n", __func__,
+				vote);
+	}
+	return ret;
+}
+
 static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
 {
 	int ret;
@@ -202,6 +217,7 @@
 struct iommu_access_ops iommu_access_ops_v0 = {
 	.iommu_power_on = __enable_regulators,
 	.iommu_power_off = __disable_regulators,
+	.iommu_bus_vote = apply_bus_vote,
 	.iommu_clk_on = __enable_clocks,
 	.iommu_clk_off = __disable_clocks,
 	.iommu_lock_initialize = _iommu_lock_initialize,
@@ -506,6 +522,11 @@
 			goto unlock;
 		}
 
+	ret = apply_bus_vote(iommu_drvdata, 1);
+
+	if (ret)
+		goto unlock;
+
 	ret = __enable_clocks(iommu_drvdata);
 	if (ret)
 		goto unlock;
@@ -572,6 +593,9 @@
 	msm_iommu_remote_spin_unlock();
 
 	__disable_clocks(iommu_drvdata);
+
+	apply_bus_vote(iommu_drvdata, 0);
+
 	list_del_init(&ctx_drvdata->attached_elm);
 	ctx_drvdata->attached_domain = NULL;
 unlock:
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 8e68beb..f90bf6c 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -32,6 +32,7 @@
 #include <mach/iommu.h>
 #include <mach/msm_iommu_priv.h>
 #include <mach/iommu_perfmon.h>
+#include <mach/msm_bus.h>
 #include "msm_iommu_pagetable.h"
 
 /* bitmap of the page sizes currently supported */
@@ -62,6 +63,20 @@
 	regulator_disable(drvdata->gdsc);
 }
 
+static int apply_bus_vote(struct msm_iommu_drvdata *drvdata, unsigned int vote)
+{
+	int ret = 0;
+
+	if (drvdata->bus_client) {
+		ret = msm_bus_scale_client_update_request(drvdata->bus_client,
+							  vote);
+		if (ret)
+			pr_err("%s: Failed to vote for bus: %d\n", __func__,
+				vote);
+	}
+	return ret;
+}
+
 static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
 {
 	int ret;
@@ -116,6 +131,7 @@
 struct iommu_access_ops iommu_access_ops_v1 = {
 	.iommu_power_on = __enable_regulators,
 	.iommu_power_off = __disable_regulators,
+	.iommu_bus_vote = apply_bus_vote,
 	.iommu_clk_on = __enable_clocks,
 	.iommu_clk_off = __disable_clocks,
 	.iommu_lock_acquire = _iommu_lock_acquire,
@@ -513,6 +529,10 @@
 	if (ret)
 		goto fail;
 
+	ret = apply_bus_vote(iommu_drvdata, 1);
+	if (ret)
+		goto fail;
+
 	ret = __enable_clocks(iommu_drvdata);
 	if (ret) {
 		__disable_regulators(iommu_drvdata);
@@ -602,6 +622,8 @@
 
 	__disable_clocks(iommu_drvdata);
 
+	apply_bus_vote(iommu_drvdata, 0);
+
 	__disable_regulators(iommu_drvdata);
 
 	list_del_init(&ctx_drvdata->attached_elm);
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 059216e..4ee65d8 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -30,10 +30,13 @@
 #include <mach/iommu_perfmon.h>
 #include <mach/iommu_hw-v0.h>
 #include <mach/iommu.h>
+#include <mach/msm_bus.h>
 
 static DEFINE_MUTEX(iommu_list_lock);
 static LIST_HEAD(iommu_list);
 
+static struct of_device_id msm_iommu_v0_ctx_match_table[];
+
 void msm_iommu_add_drv(struct msm_iommu_drvdata *drv)
 {
 	mutex_lock(&iommu_list_lock);
@@ -77,10 +80,13 @@
 	}
 	mutex_unlock(&iommu_list_lock);
 
-	if (!dev || !dev_get_drvdata(dev))
-		pr_err("Could not find context <%s>\n", ctx_name);
 	put_device(dev);
 
+	if (!dev || !dev_get_drvdata(dev)) {
+		pr_debug("Could not find context <%s>\n", ctx_name);
+		dev = ERR_PTR(-EPROBE_DEFER);
+	}
+
 	return dev;
 }
 EXPORT_SYMBOL(msm_iommu_get_ctx);
@@ -128,74 +134,24 @@
 	mb();
 }
 
-static int msm_iommu_parse_dt(struct platform_device *pdev,
-				struct msm_iommu_drvdata *drvdata,
-				int *needs_alt_core_clk)
-{
-#ifdef CONFIG_OF_DEVICE
-	struct device_node *child;
-	struct resource *r;
-	u32 glb_offset = 0;
-	int ret;
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
-		pr_err("%s: Missing property reg\n", __func__);
-		return -EINVAL;
-	}
-	drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
-	if (!drvdata->base) {
-		pr_err("%s: Unable to ioremap %pr\n", __func__, r);
-		return -ENOMEM;
-	}
-	drvdata->glb_base = drvdata->base;
-
-	if (!of_property_read_u32(pdev->dev.of_node, "qcom,glb-offset",
-			&glb_offset)) {
-		drvdata->glb_base += glb_offset;
-	} else {
-		pr_err("%s: Missing property qcom,glb-offset\n", __func__);
-		return -EINVAL;
-	}
-
-	for_each_child_of_node(pdev->dev.of_node, child) {
-		drvdata->ncb++;
-		if (!of_platform_device_create(child, NULL, &pdev->dev))
-			pr_err("Failed to create %s device\n", child->name);
-	}
-
-	ret = of_property_read_string(pdev->dev.of_node, "label",
-			&drvdata->name);
-	if (ret) {
-		pr_err("%s: Missing property label\n", __func__);
-		return -EINVAL;
-	}
-
-	*needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node,
-						   "qcom,needs-alt-core-clk");
-
-	drvdata->sec_id = -1;
-	drvdata->ttbr_split = 0;
-#endif
-	return 0;
-}
-
 static int __get_clocks(struct platform_device *pdev,
 			struct msm_iommu_drvdata *drvdata,
 			int needs_alt_core_clk)
 {
 	int ret = 0;
 
-	drvdata->pclk = clk_get(&pdev->dev, "iface_clk");
+	drvdata->pclk = devm_clk_get(&pdev->dev, "iface_clk");
 	if (IS_ERR(drvdata->pclk)) {
 		ret = PTR_ERR(drvdata->pclk);
 		drvdata->pclk = NULL;
-		pr_err("Unable to get %s clock for %s IOMMU device\n",
-			dev_name(&pdev->dev), drvdata->name);
+		if (ret != -EPROBE_DEFER) {
+			pr_err("Unable to get %s clock for %s IOMMU device\n",
+				dev_name(&pdev->dev), drvdata->name);
+		}
 		goto fail;
 	}
 
-	drvdata->clk = clk_get(&pdev->dev, "core_clk");
+	drvdata->clk = devm_clk_get(&pdev->dev, "core_clk");
 
 	if (!IS_ERR(drvdata->clk)) {
 		if (clk_get_rate(drvdata->clk) == 0) {
@@ -208,8 +164,10 @@
 
 	if (needs_alt_core_clk) {
 		drvdata->aclk = devm_clk_get(&pdev->dev, "alt_core_clk");
-		if (IS_ERR(drvdata->aclk))
-			return PTR_ERR(drvdata->aclk);
+		if (IS_ERR(drvdata->aclk)) {
+			ret = PTR_ERR(drvdata->aclk);
+			goto fail;
+		}
 	}
 
 	if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) {
@@ -222,15 +180,127 @@
 	return ret;
 }
 
-static void __put_clocks(struct msm_iommu_drvdata *drvdata)
+#ifdef CONFIG_OF_DEVICE
+
+static int __get_bus_vote_client(struct platform_device *pdev,
+				  struct msm_iommu_drvdata *drvdata)
 {
-	if (drvdata->aclk)
-		clk_put(drvdata->aclk);
-	if (drvdata->clk)
-		clk_put(drvdata->clk);
-	clk_put(drvdata->pclk);
+	int ret = 0;
+	struct msm_bus_scale_pdata *bs_table;
+	const char *dummy;
+
+	/* Check whether bus scaling has been specified for this node */
+	ret = of_property_read_string(pdev->dev.of_node, "qcom,msm-bus,name",
+				      &dummy);
+	if (ret)
+		return 0;
+
+	bs_table = msm_bus_cl_get_pdata(pdev);
+
+	if (bs_table) {
+		drvdata->bus_client = msm_bus_scale_register_client(bs_table);
+		if (IS_ERR(&drvdata->bus_client)) {
+			pr_err("%s(): Bus client register failed.\n", __func__);
+			ret = -EINVAL;
+		}
+	}
+	return ret;
 }
 
+static void __put_bus_vote_client(struct msm_iommu_drvdata *drvdata)
+{
+	msm_bus_scale_unregister_client(drvdata->bus_client);
+	drvdata->bus_client = 0;
+}
+
+static int msm_iommu_parse_dt(struct platform_device *pdev,
+				struct msm_iommu_drvdata *drvdata)
+{
+	struct device_node *child;
+	struct resource *r;
+	u32 glb_offset = 0;
+	int ret = 0;
+	int needs_alt_core_clk;
+
+	ret = __get_bus_vote_client(pdev, drvdata);
+
+	if (ret)
+		goto fail;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		pr_err("%s: Missing property reg\n", __func__);
+		ret = -EINVAL;
+		goto fail;
+	}
+	drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+	if (!drvdata->base) {
+		pr_err("%s: Unable to ioremap %pr\n", __func__, r);
+		ret = -ENOMEM;
+		goto fail;
+	}
+	drvdata->glb_base = drvdata->base;
+
+	if (!of_property_read_u32(pdev->dev.of_node, "qcom,glb-offset",
+			&glb_offset)) {
+		drvdata->glb_base += glb_offset;
+	} else {
+		pr_err("%s: Missing property qcom,glb-offset\n", __func__);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	for_each_child_of_node(pdev->dev.of_node, child)
+		drvdata->ncb++;
+
+	ret = of_property_read_string(pdev->dev.of_node, "label",
+			&drvdata->name);
+	if (ret) {
+		pr_err("%s: Missing property label\n", __func__);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node,
+						   "qcom,needs-alt-core-clk");
+
+	ret = __get_clocks(pdev, drvdata, needs_alt_core_clk);
+
+	if (ret)
+		goto fail;
+
+	drvdata->sec_id = -1;
+	drvdata->ttbr_split = 0;
+
+	ret = of_platform_populate(pdev->dev.of_node,
+				   msm_iommu_v0_ctx_match_table,
+				   NULL, &pdev->dev);
+	if (ret) {
+		pr_err("Failed to create iommu context device\n");
+		goto fail;
+	}
+
+	return ret;
+
+fail:
+	__put_bus_vote_client(drvdata);
+	return ret;
+}
+
+#else
+static int msm_iommu_parse_dt(struct platform_device *pdev,
+				struct msm_iommu_drvdata *drvdata)
+{
+	return 0;
+}
+
+static void __put_bus_vote_client(struct msm_iommu_drvdata *drvdata)
+{
+
+}
+
+#endif
+
 /*
  * Do a basic check of the IOMMU by performing an ATS operation
  * on context bank 0.
@@ -322,23 +392,27 @@
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
 	int ret;
-	int needs_alt_core_clk = 0;
 
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
 
 	if (!drvdata) {
 		ret = -ENOMEM;
-		goto fail;
+		goto fail_mem;
 	}
 
 	if (pdev->dev.of_node) {
-		ret = msm_iommu_parse_dt(pdev, drvdata, &needs_alt_core_clk);
+		ret = msm_iommu_parse_dt(pdev, drvdata);
 		if (ret)
 			goto fail;
 	} else if (pdev->dev.platform_data) {
 		struct resource *r, *r2;
 		resource_size_t	len;
 
+		ret = __get_clocks(pdev, drvdata, 0);
+
+		if (ret)
+			goto fail;
+
 		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"physbase");
 
@@ -349,7 +423,8 @@
 
 		len = resource_size(r);
 
-		r2 = request_mem_region(r->start, len, r->name);
+		r2 = devm_request_mem_region(&pdev->dev, r->start,
+					     len, r->name);
 		if (!r2) {
 			pr_err("Could not request memory region: %pr\n", r);
 			ret = -EBUSY;
@@ -379,11 +454,6 @@
 
 	drvdata->dev = &pdev->dev;
 
-	ret = __get_clocks(pdev, drvdata, needs_alt_core_clk);
-
-	if (ret)
-		goto fail;
-
 	iommu_access_ops_v0.iommu_clk_on(drvdata);
 
 	msm_iommu_reset(drvdata->base, drvdata->glb_base, drvdata->ncb);
@@ -392,14 +462,14 @@
 	if (ret)
 		goto fail_clk;
 
+	iommu_access_ops_v0.iommu_clk_off(drvdata);
+
 	pr_info("device %s mapped at %p, with %d ctx banks\n",
 		drvdata->name, drvdata->base, drvdata->ncb);
 
 	msm_iommu_add_drv(drvdata);
 	platform_set_drvdata(pdev, drvdata);
 
-	iommu_access_ops_v0.iommu_clk_off(drvdata);
-
 	pmon_info = msm_iommu_pm_alloc(&pdev->dev);
 	if (pmon_info != NULL) {
 		ret = msm_iommu_pmon_parse_dt(pdev, pmon_info);
@@ -428,8 +498,9 @@
 
 fail_clk:
 	iommu_access_ops_v0.iommu_clk_off(drvdata);
-	__put_clocks(drvdata);
 fail:
+	__put_bus_vote_client(drvdata);
+fail_mem:
 	return ret;
 }
 
@@ -437,12 +508,13 @@
 {
 	struct msm_iommu_drvdata *drv = NULL;
 
+	msm_iommu_pm_iommu_unregister(&pdev->dev);
+	msm_iommu_pm_free(&pdev->dev);
+
 	drv = platform_get_drvdata(pdev);
 	if (drv) {
+		__put_bus_vote_client(drv);
 		msm_iommu_remove_drv(drv);
-		if (drv->clk)
-			clk_put(drv->clk);
-		clk_put(drv->pclk);
 		platform_set_drvdata(pdev, NULL);
 	}
 	return 0;
@@ -458,26 +530,28 @@
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq > 0) {
-		ret = request_threaded_irq(irq, NULL,
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
 				msm_iommu_fault_handler,
 				IRQF_ONESHOT | IRQF_SHARED,
 				"msm_iommu_nonsecure_irq", ctx_drvdata);
 		if (ret) {
 			pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-			return ret;
+			goto out;
 		}
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
 		pr_err("Could not find reg property for context bank\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	ret = of_address_to_resource(pdev->dev.parent->of_node, 0, &rp);
 	if (ret) {
 		pr_err("of_address_to_resource failed\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	/* Calculate the context bank number using the base addresses. CB0
@@ -488,29 +562,34 @@
 	if (of_property_read_string(pdev->dev.of_node, "label",
 					&ctx_drvdata->name)) {
 		pr_err("Could not find label property\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-mids",
 			     &nmid_array_size)) {
 		pr_err("Could not find iommu-ctx-mids property\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	if (nmid_array_size >= sizeof(ctx_drvdata->sids)) {
 		pr_err("Too many mids defined - array size: %u, mids size: %u\n",
 			nmid_array_size, sizeof(ctx_drvdata->sids));
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	nmid = nmid_array_size / sizeof(*ctx_drvdata->sids);
 
 	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-mids",
 				       ctx_drvdata->sids, nmid)) {
 		pr_err("Could not find iommu-ctx-mids property\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	ctx_drvdata->nsid = nmid;
 
-	return 0;
+out:
+	return ret;
 }
 
 static void __program_m2v_tables(struct msm_iommu_drvdata *drvdata,
@@ -560,7 +639,7 @@
 	drvdata = dev_get_drvdata(pdev->dev.parent);
 
 	if (!drvdata) {
-		ret = -ENODEV;
+		ret = -EPROBE_DEFER;
 		goto fail;
 	}
 
@@ -578,8 +657,10 @@
 
 	if (pdev->dev.of_node) {
 		ret = msm_iommu_ctx_parse_dt(pdev, ctx_drvdata);
-		if (ret)
+		if (ret) {
+			platform_set_drvdata(pdev, NULL);
 			goto fail;
+		}
 	} else if (pdev->dev.platform_data) {
 		struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
 
@@ -601,7 +682,8 @@
 			goto fail;
 		}
 
-		ret = request_threaded_irq(irq, NULL, msm_iommu_fault_handler,
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					msm_iommu_fault_handler,
 					IRQF_ONESHOT | IRQF_SHARED,
 					"msm_iommu_nonsecure_irq", ctx_drvdata);
 
@@ -647,15 +729,15 @@
 	.remove		= __devexit_p(msm_iommu_remove),
 };
 
-static struct of_device_id msm_iommu_ctx_match_table[] = {
-	{ .name = "qcom,iommu-ctx", },
+static struct of_device_id msm_iommu_v0_ctx_match_table[] = {
+	{ .compatible = "qcom,msm-smmu-v0-ctx", },
 	{}
 };
 
 static struct platform_driver msm_iommu_ctx_driver = {
 	.driver = {
 		.name	= "msm_iommu_ctx",
-		.of_match_table = msm_iommu_ctx_match_table,
+		.of_match_table = msm_iommu_v0_ctx_match_table,
 	},
 	.probe		= msm_iommu_ctx_probe,
 	.remove		= __devexit_p(msm_iommu_ctx_remove),
diff --git a/drivers/iommu/msm_iommu_dev-v1.c b/drivers/iommu/msm_iommu_dev-v1.c
index 418a086..c0e05f4 100644
--- a/drivers/iommu/msm_iommu_dev-v1.c
+++ b/drivers/iommu/msm_iommu_dev-v1.c
@@ -28,6 +28,9 @@
 #include <mach/iommu_hw-v1.h>
 #include <mach/iommu.h>
 #include <mach/iommu_perfmon.h>
+#include <mach/msm_bus.h>
+
+static struct of_device_id msm_iommu_v1_ctx_match_table[];
 
 static int msm_iommu_parse_bfb_settings(struct platform_device *pdev,
 				    struct msm_iommu_drvdata *drvdata)
@@ -84,6 +87,36 @@
 	return 0;
 }
 
+static int __get_bus_vote_client(struct platform_device *pdev,
+				  struct msm_iommu_drvdata *drvdata)
+{
+	int ret = 0;
+	struct msm_bus_scale_pdata *bs_table;
+	const char *dummy;
+
+	/* Check whether bus scaling has been specified for this node */
+	ret = of_property_read_string(pdev->dev.of_node, "qcom,msm-bus,name",
+				      &dummy);
+	if (ret)
+		return 0;
+
+	bs_table = msm_bus_cl_get_pdata(pdev);
+
+	if (bs_table) {
+		drvdata->bus_client = msm_bus_scale_register_client(bs_table);
+		if (IS_ERR(&drvdata->bus_client)) {
+			pr_err("%s(): Bus client register failed.\n", __func__);
+			ret = -EINVAL;
+		}
+	}
+	return ret;
+}
+
+static void __put_bus_vote_client(struct msm_iommu_drvdata *drvdata)
+{
+	msm_bus_scale_unregister_client(drvdata->bus_client);
+}
+
 static int msm_iommu_parse_dt(struct platform_device *pdev,
 				struct msm_iommu_drvdata *drvdata)
 {
@@ -92,17 +125,18 @@
 	struct resource *r;
 
 	drvdata->dev = &pdev->dev;
-	msm_iommu_add_drv(drvdata);
+
+	ret = __get_bus_vote_client(pdev, drvdata);
+
+	if (ret)
+		goto fail;
 
 	ret = msm_iommu_parse_bfb_settings(pdev, drvdata);
 	if (ret)
 		goto fail;
 
-	for_each_child_of_node(pdev->dev.of_node, child) {
+	for_each_child_of_node(pdev->dev.of_node, child)
 		drvdata->ncb++;
-		if (!of_platform_device_create(child, NULL, &pdev->dev))
-			pr_err("Failed to create %s device\n", child->name);
-	}
 
 	drvdata->asid = devm_kzalloc(&pdev->dev, drvdata->ncb * sizeof(int),
 				     GFP_KERNEL);
@@ -137,8 +171,15 @@
 	drvdata->halt_enabled = of_property_read_bool(pdev->dev.of_node,
 						      "qcom,iommu-enable-halt");
 
-	return 0;
+	ret = of_platform_populate(pdev->dev.of_node,
+				   msm_iommu_v1_ctx_match_table,
+				   NULL, &pdev->dev);
+	if (ret)
+		pr_err("Failed to create iommu context device\n");
+
+	msm_iommu_add_drv(drvdata);
 fail:
+	__put_bus_vote_client(drvdata);
 	return ret;
 }
 
@@ -224,7 +265,7 @@
 
 	drvdata->gdsc = devm_regulator_get(&pdev->dev, "vdd");
 	if (IS_ERR(drvdata->gdsc))
-		return -EINVAL;
+		return PTR_ERR(drvdata->gdsc);
 
 	drvdata->alt_gdsc = devm_regulator_get(&pdev->dev, "qcom,alt-vdd");
 	if (IS_ERR(drvdata->alt_gdsc))
@@ -301,10 +342,8 @@
 
 	drv = platform_get_drvdata(pdev);
 	if (drv) {
+		__put_bus_vote_client(drv);
 		msm_iommu_remove_drv(drv);
-		if (drv->clk)
-			clk_put(drv->clk);
-		clk_put(drv->pclk);
 		platform_set_drvdata(pdev, NULL);
 	}
 	return 0;
@@ -314,7 +353,7 @@
 				struct msm_iommu_ctx_drvdata *ctx_drvdata)
 {
 	struct resource *r, rp;
-	int irq, ret;
+	int irq = 0, ret = 0;
 	u32 nsid;
 
 	ctx_drvdata->secure_context = of_property_read_bool(pdev->dev.of_node,
@@ -323,25 +362,27 @@
 	if (!ctx_drvdata->secure_context) {
 		irq = platform_get_irq(pdev, 0);
 		if (irq > 0) {
-			ret = request_threaded_irq(irq, NULL,
+			ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
 					msm_iommu_fault_handler_v2,
 					IRQF_ONESHOT | IRQF_SHARED,
 					"msm_iommu_nonsecure_irq", pdev);
 			if (ret) {
 				pr_err("Request IRQ %d failed with ret=%d\n",
 					irq, ret);
-				return ret;
+				goto out;
 			}
 		}
 	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -EINVAL;
+	if (!r) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	ret = of_address_to_resource(pdev->dev.parent->of_node, 0, &rp);
 	if (ret)
-		return -EINVAL;
+		goto out;
 
 	/* Calculate the context bank number using the base addresses. The
 	 * first 8 pages belong to the global address space which is followed
@@ -354,21 +395,26 @@
 					&ctx_drvdata->name))
 		ctx_drvdata->name = dev_name(&pdev->dev);
 
-	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &nsid))
-		return -EINVAL;
-
-	if (nsid >= sizeof(ctx_drvdata->sids))
-		return -EINVAL;
+	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &nsid)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	if (nsid >= sizeof(ctx_drvdata->sids)) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-sids",
 				       ctx_drvdata->sids,
 				       nsid / sizeof(*ctx_drvdata->sids))) {
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	ctx_drvdata->nsid = nsid;
 
 	ctx_drvdata->asid = -1;
-	return 0;
+out:
+	return ret;
 }
 
 static int __devinit msm_iommu_ctx_probe(struct platform_device *pdev)
@@ -386,12 +432,14 @@
 
 	ctx_drvdata->pdev = pdev;
 	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
-	platform_set_drvdata(pdev, ctx_drvdata);
 
 	ret = msm_iommu_ctx_parse_dt(pdev, ctx_drvdata);
-	if (!ret)
+	if (!ret) {
+		platform_set_drvdata(pdev, ctx_drvdata);
+
 		dev_info(&pdev->dev, "context %s using bank %d\n",
 			 ctx_drvdata->name, ctx_drvdata->num);
+	}
 
 	return ret;
 }
@@ -416,15 +464,15 @@
 	.remove		= __devexit_p(msm_iommu_remove),
 };
 
-static struct of_device_id msm_iommu_ctx_match_table[] = {
-	{ .name = "qcom,iommu-ctx", },
+static struct of_device_id msm_iommu_v1_ctx_match_table[] = {
+	{ .compatible = "qcom,msm-smmu-v1-ctx", },
 	{}
 };
 
 static struct platform_driver msm_iommu_ctx_driver = {
 	.driver = {
 		.name	= "msm_iommu_ctx_v1",
-		.of_match_table = msm_iommu_ctx_match_table,
+		.of_match_table = msm_iommu_v1_ctx_match_table,
 	},
 	.probe		= msm_iommu_ctx_probe,
 	.remove		= __devexit_p(msm_iommu_ctx_remove),
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index a11d794..958c6ca 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -257,6 +257,7 @@
 					dev_get_drvdata(iommu->iommu_dev);
 
 	iommu->ops->iommu_power_on(iommu_drvdata);
+	iommu->ops->iommu_bus_vote(iommu_drvdata, 1);
 	iommu->ops->iommu_clk_on(iommu_drvdata);
 
 	/* Reset counters in HW */
@@ -311,6 +312,7 @@
 
 	iommu->ops->iommu_lock_release();
 	iommu->ops->iommu_clk_off(iommu_drvdata);
+	iommu->ops->iommu_bus_vote(iommu_drvdata, 0);
 	iommu->ops->iommu_power_off(iommu_drvdata);
 
 	pr_info("%s: TLB performance monitoring turned OFF\n",
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index fcade49..2c2b339 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -75,7 +75,8 @@
 	DMX_FIFO_ERROR, /* Receiver FIFO overrun */
 	DMX_MISSED_ERROR, /* Receiver missed packet */
 	DMX_OK_DECODER_BUF, /* Received OK, new ES data in decoder buffer */
-	DMX_OK_IDX /* Received OK, new index event */
+	DMX_OK_IDX, /* Received OK, new index event */
+	DMX_OK_SCRAMBLING_STATUS, /* Received OK, new scrambling status */
 } ;
 
 
@@ -135,6 +136,7 @@
 		} marker;
 
 		struct dmx_index_event_info idx_event;
+		struct dmx_scrambling_status_event_info scrambling_bits;
 	};
 };
 
@@ -250,6 +252,7 @@
 	int (*ts_insertion_terminate)(struct dmx_ts_feed *feed);
 	int (*ts_insertion_insert_buffer)(struct dmx_ts_feed *feed,
 			char *data, size_t size);
+	int (*get_scrambling_bits)(struct dmx_ts_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
@@ -300,6 +303,7 @@
 				struct dmx_secure_mode *sec_mode);
 	int (*oob_command) (struct dmx_section_feed *feed,
 				struct dmx_oob_command *cmd);
+	int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 2a750a6..6734da8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1796,6 +1796,35 @@
 	return 0;
 }
 
+static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter,
+	struct dmx_scrambling_bits *scrambling_bits)
+{
+	struct dmxdev_feed *feed;
+
+	if (!scrambling_bits ||
+		(filter->state != DMXDEV_STATE_GO))
+		return -EINVAL;
+
+	if (filter->type == DMXDEV_TYPE_SEC) {
+		if (filter->feed.sec.feed->get_scrambling_bits)
+			return filter->feed.sec.feed->get_scrambling_bits(
+						filter->feed.sec.feed,
+						&scrambling_bits->value);
+		return -EINVAL;
+	}
+
+	list_for_each_entry(feed, &filter->feed.ts, next) {
+		if (feed->pid == scrambling_bits->pid) {
+			if (feed->ts->get_scrambling_bits)
+				return feed->ts->get_scrambling_bits(feed->ts,
+						&scrambling_bits->value);
+			return -EINVAL;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void dvb_dmxdev_ts_insertion_work(struct work_struct *worker)
 {
 	struct ts_insertion_buffer *ts_buffer =
@@ -2519,6 +2548,13 @@
 			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
 			spin_unlock(&dmxdevfilter->dev->lock);
 			wake_up_all(&dmxdevfilter->buffer.queue);
+		} else if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+			event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+			event.params.scrambling_status =
+				dmx_data_ready->scrambling_bits;
+			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
+			spin_unlock(&dmxdevfilter->dev->lock);
+			wake_up_all(&dmxdevfilter->buffer.queue);
 		} else {
 			spin_unlock(&dmxdevfilter->dev->lock);
 		}
@@ -2635,6 +2671,16 @@
 		return 0;
 	}
 
+	if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+		event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+		event.params.scrambling_status =
+			dmx_data_ready->scrambling_bits;
+		dvb_dmxdev_add_event(events, &event);
+		spin_unlock(&dmxdevfilter->dev->lock);
+		wake_up_all(&buffer->queue);
+		return 0;
+	}
+
 	if (dmx_data_ready->status == DMX_OK_DECODER_BUF) {
 		event.type = DMX_EVENT_NEW_ES_DATA;
 		event.params.es_data.buf_handle = dmx_data_ready->buf.handle;
@@ -3938,6 +3984,15 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_GET_SCRAMBLING_BITS:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_get_scrambling_bits(dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -4193,6 +4248,7 @@
 	struct dmxdev_filter *filter;
 	int active_count = 0;
 	struct dmx_buffer_status buffer_status;
+	struct dmx_scrambling_bits scrambling_bits;
 	const char *pes_feeds[] = {"DEC", "PES", "DVR", "REC"};
 
 	if (!dmxdev)
@@ -4209,23 +4265,32 @@
 				seq_printf(s, "type: SEC, ");
 				seq_printf(s, "PID %04d ",
 						filter->params.sec.pid);
+				scrambling_bits.pid = filter->params.sec.pid;
 			} else {
 				seq_printf(s, "type: %s, ",
 					pes_feeds[filter->params.pes.output]);
 				seq_printf(s, "PID: %04d ",
 						filter->params.pes.pid);
+				scrambling_bits.pid = filter->params.pes.pid;
 			}
 
+			dvb_dmxdev_get_scrambling_bits(filter,
+				&scrambling_bits);
+
 			if (0 == dvb_dmxdev_get_buffer_status(
 						filter, &buffer_status)) {
 				seq_printf(s, "size: %08d, ",
 					buffer_status.size);
 				seq_printf(s, "fullness: %08d, ",
 					buffer_status.fullness);
-				seq_printf(s, "error: %d\n",
+				seq_printf(s, "error: %d, ",
 					buffer_status.error);
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
+
 			} else {
-				seq_printf(s, "\n");
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
 			}
 		}
 	}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 9844c64..8caa9dd 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -164,6 +164,11 @@
 	return ((buf[1] & 0x1f) << 8) + buf[2];
 }
 
+static inline u16 ts_scrambling_ctrl(const u8 *buf)
+{
+	return (buf[3] >> 6) & 0x3;
+}
+
 static inline u8 payload(const u8 *tsp)
 {
 	if (!(tsp[3] & 0x10))	// no payload?
@@ -1287,6 +1292,32 @@
 static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 			const u8 *buf, const u8 timestamp[TIMESTAMP_LEN])
 {
+	u16 pid = ts_pid(buf);
+	u8 scrambling_bits = ts_scrambling_ctrl(buf);
+	struct dmx_data_ready dmx_data_ready;
+
+	/*
+	 * Notify on scrambling status change only when we move
+	 * from clear (0) to non-clear and vise-versa
+	 */
+	if ((scrambling_bits && !feed->scrambling_bits) ||
+		(!scrambling_bits && feed->scrambling_bits)) {
+		dmx_data_ready.status = DMX_OK_SCRAMBLING_STATUS;
+		dmx_data_ready.data_length = 0;
+		dmx_data_ready.scrambling_bits.pid = pid;
+		dmx_data_ready.scrambling_bits.old_value =
+			feed->scrambling_bits;
+		dmx_data_ready.scrambling_bits.new_value = scrambling_bits;
+
+		if (feed->type == DMX_TYPE_SEC)
+			feed->data_ready_cb.sec(&feed->filter->filter,
+					&dmx_data_ready);
+		else
+			feed->data_ready_cb.ts(&feed->feed.ts, &dmx_data_ready);
+	}
+
+	feed->scrambling_bits = scrambling_bits;
+
 	switch (feed->type) {
 	case DMX_TYPE_TS:
 		if (!feed->feed.ts.is_filtering)
@@ -2047,6 +2078,7 @@
 	}
 
 	feed->first_cc = 1;
+	feed->scrambling_bits = 0;
 
 	if ((feed->ts_type & TS_PACKET) &&
 		!(feed->ts_type & TS_PAYLOAD_ONLY)) {
@@ -2302,6 +2334,25 @@
 	return ret;
 }
 
+static int dvbdmx_ts_get_scrambling_bits(struct dmx_ts_feed *ts_feed,
+			u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!ts_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_ts_insertion_insert_buffer(struct dmx_ts_feed *ts_feed,
 			char *data, size_t size)
 {
@@ -2391,6 +2442,7 @@
 	(*ts_feed)->notify_data_read = NULL;
 	(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
 	(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
+	(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
 	(*ts_feed)->ts_insertion_init = NULL;
 	(*ts_feed)->ts_insertion_terminate = NULL;
 	(*ts_feed)->ts_insertion_insert_buffer =
@@ -2557,6 +2609,7 @@
 	dvbdmxfeed->feed.sec.secbufp = 0;
 	dvbdmxfeed->feed.sec.seclen = 0;
 	dvbdmxfeed->first_cc = 1;
+	dvbdmxfeed->scrambling_bits = 0;
 
 	if (!dvbdmx->start_feed) {
 		mutex_unlock(&dvbdmx->mutex);
@@ -2723,6 +2776,25 @@
 	return ret;
 }
 
+static int dvbdmx_section_get_scrambling_bits(
+	struct dmx_section_feed *section_feed, u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)section_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!section_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
 					struct dmx_section_feed **feed,
 					dmx_section_cb callback)
@@ -2763,6 +2835,7 @@
 	(*feed)->notify_data_read = NULL;
 	(*feed)->set_secure_mode = dmx_section_set_secure_mode;
 	(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
+	(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
 
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 879aad2..9fb1a12 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -187,6 +187,8 @@
 	int first_cc;
 	int pusi_seen;		/* prevents feeding of garbage from previous section */
 
+	u8 scrambling_bits;
+
 	struct dvb_demux_rec_info *rec_info;
 	u64 prev_tsp_num;
 	u64 prev_stc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 59858b5..88f2f08 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -80,13 +80,20 @@
 }
 
 static uint32_t msm_isp_get_buf_handle(
-	struct msm_isp_buf_mgr *buf_mgr)
+	struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t session_id, uint32_t stream_id)
 {
 	int i;
 	if ((buf_mgr->buf_handle_cnt << 8) == 0)
 		buf_mgr->buf_handle_cnt++;
 
 	for (i = 0; i < buf_mgr->num_buf_q; i++) {
+		if (buf_mgr->bufq[i].session_id == session_id &&
+			buf_mgr->bufq[i].stream_id == stream_id)
+			return 0;
+	}
+
+	for (i = 0; i < buf_mgr->num_buf_q; i++) {
 		if (buf_mgr->bufq[i].bufq_handle == 0) {
 			memset(&buf_mgr->bufq[i],
 				0, sizeof(struct msm_isp_bufq));
@@ -604,7 +611,8 @@
 		return rc;
 	}
 
-	buf_request->handle = msm_isp_get_buf_handle(buf_mgr);
+	buf_request->handle = msm_isp_get_buf_handle(buf_mgr,
+		buf_request->session_id, buf_request->stream_id);
 	if (!buf_request->handle) {
 		pr_err("Invalid buffer handle\n");
 		return rc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 7bc2b7d..6de6e74 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -38,6 +38,8 @@
 #define VFE_PING_FLAG 0xFFFFFFFF
 #define VFE_PONG_FLAG 0x0
 
+#define VFE_MAX_CFG_TIMEOUT 3000
+
 struct vfe_device;
 struct msm_vfe_axi_stream;
 struct msm_vfe_stats_stream;
@@ -88,7 +90,7 @@
 	void (*enable_wm) (struct vfe_device *vfe_dev,
 		uint8_t wm_idx, uint8_t enable);
 	void (*cfg_io_format) (struct vfe_device *vfe_dev,
-		struct msm_vfe_axi_stream_request_cmd *stream_req_cmd);
+		struct msm_vfe_axi_stream *stream_info);
 	void (*cfg_framedrop) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info);
 	void (*clear_framedrop) (struct vfe_device *vfe_dev,
@@ -103,13 +105,13 @@
 		struct msm_vfe_axi_stream *stream_info);
 
 	void (*cfg_wm_reg) (struct vfe_device *vfe_dev,
-		struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+		struct msm_vfe_axi_stream *stream_info,
 		uint8_t plane_idx);
 	void (*clear_wm_reg) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx);
 
 	void (*cfg_wm_xbar_reg) (struct vfe_device *vfe_dev,
-		struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+		struct msm_vfe_axi_stream *stream_info,
 		uint8_t plane_idx);
 	void (*clear_wm_xbar_reg) (struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx);
@@ -231,7 +233,8 @@
 	enum msm_vfe_axi_stream_src stream_src;
 	uint8_t num_planes;
 	uint8_t wm[MAX_PLANES_PER_STREAM];
-	uint32_t plane_offset[MAX_PLANES_PER_STREAM];
+	uint32_t output_format;/*Planar/RAW/Misc*/
+	struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM];
 	uint8_t comp_mask_index;
 	struct msm_isp_buffer *buf[2];
 	uint32_t session_id;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 679c5cb..3a94af3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -441,11 +441,11 @@
 }
 
 static void msm_vfe32_cfg_io_format(struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_req_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int bpp, bpp_reg = 0;
 	uint32_t io_format_reg;
-	bpp = msm_isp_get_bit_per_pixel(stream_req_cmd->output_format);
+	bpp = msm_isp_get_bit_per_pixel(stream_info->output_format);
 
 	switch (bpp) {
 	case 8:
@@ -459,7 +459,7 @@
 		break;
 	}
 	io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x6F8);
-	switch (stream_req_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case CAMIF_RAW:
 		io_format_reg &= 0xFFFFCFFF;
 		io_format_reg |= bpp_reg << 12;
@@ -565,44 +565,40 @@
 
 static void msm_vfe32_axi_cfg_wm_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	struct msm_vfe_axi_stream *stream_info,
 	uint8_t plane_idx)
 {
 	uint32_t val;
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	uint32_t wm_base = VFE32_WM_BASE(stream_info->wm[plane_idx]);
 
 	if (!stream_info->frame_based) {
 		/*WR_IMAGE_SIZE*/
 		val =
 			((msm_isp_cal_word_per_line(
-			stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[plane_idx].
+			stream_info->output_format,
+			stream_info->plane_cfg[plane_idx].
 			output_width)+1)/2 - 1) << 16 |
-			(stream_cfg_cmd->plane_cfg[plane_idx].
+			(stream_info->plane_cfg[plane_idx].
 			output_height - 1);
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x10);
 
 		/*WR_BUFFER_CFG*/
 		val =
 			msm_isp_cal_word_per_line(
-			stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[plane_idx].
+			stream_info->output_format,
+			stream_info->plane_cfg[plane_idx].
 			output_stride) << 16 |
-			(stream_cfg_cmd->plane_cfg[plane_idx].
+			(stream_info->plane_cfg[plane_idx].
 			output_height - 1) << 4 | VFE32_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 	} else {
 		msm_camera_io_w(0x2, vfe_dev->vfe_base + wm_base);
 		val =
 			msm_isp_cal_word_per_line(
-			stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[plane_idx].
+			stream_info->output_format,
+			stream_info->plane_cfg[plane_idx].
 			output_width) << 16 |
-			(stream_cfg_cmd->plane_cfg[plane_idx].
+			(stream_info->plane_cfg[plane_idx].
 			output_height - 1) << 4 | VFE32_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 	}
@@ -624,19 +620,15 @@
 
 static void msm_vfe32_axi_cfg_wm_xbar_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
-	uint8_t plane_idx)
+	struct msm_vfe_axi_stream *stream_info, uint8_t plane_idx)
 {
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-	 &axi_data->stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	struct msm_vfe_axi_plane_cfg *plane_cfg =
-		&stream_cfg_cmd->plane_cfg[plane_idx];
+		&stream_info->plane_cfg[plane_idx];
 	uint8_t wm = stream_info->wm[plane_idx];
 	uint32_t xbar_cfg = 0;
 	uint32_t xbar_reg_cfg = 0;
 
-	switch (stream_cfg_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case PIX_ENCODER:
 	case PIX_VIEWFINDER: {
 		if (plane_cfg->output_plane_format != CRCB_PLANE &&
@@ -644,7 +636,7 @@
 			/*SINGLE_STREAM_SEL*/
 			xbar_cfg |= plane_cfg->output_plane_format << 5;
 		} else {
-			switch (stream_cfg_cmd->output_format) {
+			switch (stream_info->output_format) {
 			case V4L2_PIX_FMT_NV12:
 			case V4L2_PIX_FMT_NV16:
 				xbar_cfg |= 0x3 << 3; /*PAIR_STREAM_SWAP_CTRL*/
@@ -652,7 +644,7 @@
 			}
 			xbar_cfg |= BIT(1); /*PAIR_STREAM_EN*/
 		}
-		if (stream_cfg_cmd->stream_src == PIX_VIEWFINDER)
+		if (stream_info->stream_src == PIX_VIEWFINDER)
 			xbar_cfg |= 0x1; /*VIEW_STREAM_EN*/
 		break;
 	}
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 94041ea..c4a1b63 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -523,14 +523,14 @@
 	comp_mask &= ~(0x7F << (comp_mask_index * 8));
 	comp_mask |= (axi_data->composite_info[comp_mask_index].
 		stream_composite_mask << (comp_mask_index * 8));
-	if (stream_info->plane_offset[0])
+	if (stream_info->plane_cfg[0].plane_addr_offset)
 		comp_mask |= (axi_data->composite_info[comp_mask_index].
 		stream_composite_mask << 24);
 	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x40);
 
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
 	irq_mask |= 1 << (comp_mask_index + 25);
-	if (stream_info->plane_offset[0] && (comp_mask >> 24))
+	if (stream_info->plane_cfg[0].plane_addr_offset && (comp_mask >> 24))
 		irq_mask |= BIT(28);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
 }
@@ -544,14 +544,14 @@
 
 	comp_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x40);
 	comp_mask &= ~(0x7F << (comp_mask_index * 8));
-	if (stream_info->plane_offset[0])
+	if (stream_info->plane_cfg[0].plane_addr_offset)
 		comp_mask &= ~(axi_data->composite_info[comp_mask_index].
 		stream_composite_mask << 24);
 	msm_camera_io_w(comp_mask, vfe_dev->vfe_base + 0x40);
 
 	irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
 	irq_mask &= ~(1 << (comp_mask_index + 25));
-	if (stream_info->plane_offset[0] && !(comp_mask >> 24))
+	if (stream_info->plane_cfg[0].plane_addr_offset && (comp_mask >> 24))
 		irq_mask &= ~BIT(28);
 	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
 }
@@ -614,11 +614,11 @@
 }
 
 static void msm_vfe40_cfg_io_format(struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_req_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int bpp, bpp_reg = 0;
 	uint32_t io_format_reg;
-	bpp = msm_isp_get_bit_per_pixel(stream_req_cmd->output_format);
+	bpp = msm_isp_get_bit_per_pixel(stream_info->output_format);
 
 	switch (bpp) {
 	case 8:
@@ -632,7 +632,7 @@
 		break;
 	}
 	io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x54);
-	switch (stream_req_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case CAMIF_RAW:
 		io_format_reg &= 0xFFFFCFFF;
 		io_format_reg |= bpp_reg << 12;
@@ -753,43 +753,39 @@
 
 static void msm_vfe40_axi_cfg_wm_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	struct msm_vfe_axi_stream *stream_info,
 	uint8_t plane_idx)
 {
 	uint32_t val;
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	uint32_t wm_base = VFE40_WM_BASE(stream_info->wm[plane_idx]);
 
 	if (!stream_info->frame_based) {
 		/*WR_IMAGE_SIZE*/
 		val =
 			((msm_isp_cal_word_per_line(
-				stream_cfg_cmd->output_format,
-				stream_cfg_cmd->plane_cfg[plane_idx].
+				stream_info->output_format,
+				stream_info->plane_cfg[plane_idx].
 				output_width)+1)/2 - 1) << 16 |
-				(stream_cfg_cmd->plane_cfg[plane_idx].
+				(stream_info->plane_cfg[plane_idx].
 				output_height - 1);
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x14);
 
 		/*WR_BUFFER_CFG*/
 		val =
-			msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[
+			msm_isp_cal_word_per_line(stream_info->output_format,
+			stream_info->plane_cfg[
 				plane_idx].output_stride) << 16 |
-			(stream_cfg_cmd->plane_cfg[
+			(stream_info->plane_cfg[
 				plane_idx].output_height - 1) << 4 |
 			VFE40_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x18);
 	} else {
 		msm_camera_io_w(0x2, vfe_dev->vfe_base + wm_base);
 		val =
-			msm_isp_cal_word_per_line(stream_cfg_cmd->output_format,
-			stream_cfg_cmd->plane_cfg[
+			msm_isp_cal_word_per_line(stream_info->output_format,
+			stream_info->plane_cfg[
 				plane_idx].output_width) << 16 |
-			(stream_cfg_cmd->plane_cfg[
+			(stream_info->plane_cfg[
 				plane_idx].output_height - 1) << 4 |
 			VFE40_BURST_LEN;
 		msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x18);
@@ -821,20 +817,16 @@
 
 static void msm_vfe40_axi_cfg_wm_xbar_reg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd,
+	struct msm_vfe_axi_stream *stream_info,
 	uint8_t plane_idx)
 {
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
 	struct msm_vfe_axi_plane_cfg *plane_cfg =
-		&stream_cfg_cmd->plane_cfg[plane_idx];
+		&stream_info->plane_cfg[plane_idx];
 	uint8_t wm = stream_info->wm[plane_idx];
 	uint32_t xbar_cfg = 0;
 	uint32_t xbar_reg_cfg = 0;
 
-	switch (stream_cfg_cmd->stream_src) {
+	switch (stream_info->stream_src) {
 	case PIX_ENCODER:
 	case PIX_VIEWFINDER: {
 		if (plane_cfg->output_plane_format != CRCB_PLANE &&
@@ -842,7 +834,7 @@
 			/*SINGLE_STREAM_SEL*/
 			xbar_cfg |= plane_cfg->output_plane_format << 8;
 		} else {
-			switch (stream_cfg_cmd->output_format) {
+			switch (stream_info->output_format) {
 			case V4L2_PIX_FMT_NV12:
 			case V4L2_PIX_FMT_NV16:
 				xbar_cfg |= 0x3 << 4; /*PAIR_STREAM_SWAP_CTRL*/
@@ -850,7 +842,7 @@
 			}
 			xbar_cfg |= 0x1 << 1; /*PAIR_STREAM_EN*/
 		}
-		if (stream_cfg_cmd->stream_src == PIX_VIEWFINDER)
+		if (stream_info->stream_src == PIX_VIEWFINDER)
 			xbar_cfg |= 0x1; /*VIEW_STREAM_EN*/
 		break;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 13160ee..e3d036f6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -136,23 +136,23 @@
 	}
 
 	for (i = 0; i < stream_info->num_planes; i++) {
-		stream_info->plane_offset[i] =
-			stream_cfg_cmd->plane_cfg[i].plane_addr_offset;
+		stream_info->plane_cfg[i] = stream_cfg_cmd->plane_cfg[i];
 		stream_info->max_width = max(stream_info->max_width,
 			stream_cfg_cmd->plane_cfg[i].output_width);
 	}
 
+	stream_info->output_format = stream_cfg_cmd->output_format;
 	stream_info->stream_src = stream_cfg_cmd->stream_src;
 	stream_info->frame_based = stream_cfg_cmd->frame_base;
 	return 0;
 }
 
 static uint32_t msm_isp_axi_get_plane_size(
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd, int plane_idx)
+	struct msm_vfe_axi_stream *stream_info, int plane_idx)
 {
 	uint32_t size = 0;
-	struct msm_vfe_axi_plane_cfg *plane_cfg = stream_cfg_cmd->plane_cfg;
-	switch (stream_cfg_cmd->output_format) {
+	struct msm_vfe_axi_plane_cfg *plane_cfg = stream_info->plane_cfg;
+	switch (stream_info->output_format) {
 	case V4L2_PIX_FMT_SBGGR8:
 	case V4L2_PIX_FMT_SGBRG8:
 	case V4L2_PIX_FMT_SGRBG8:
@@ -211,21 +211,17 @@
 }
 
 void msm_isp_axi_reserve_wm(struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int i, j;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
-
 	for (i = 0; i < stream_info->num_planes; i++) {
 		for (j = 0; j < axi_data->hw_info->num_wm; j++) {
 			if (!axi_data->free_wm[j]) {
 				axi_data->free_wm[j] =
-					stream_cfg_cmd->axi_stream_handle;
+					stream_info->stream_handle;
 				axi_data->wm_image_size[j] =
 					msm_isp_axi_get_plane_size(
-						stream_cfg_cmd, i);
+						stream_info, i);
 				axi_data->num_used_wm++;
 				break;
 			}
@@ -246,20 +242,17 @@
 
 void msm_isp_axi_reserve_comp_mask(
 	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int i;
 	uint8_t comp_mask = 0;
-	struct msm_vfe_axi_stream *stream_info =
-		&axi_data->stream_info[
-			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 	for (i = 0; i < stream_info->num_planes; i++)
 		comp_mask |= 1 << stream_info->wm[i];
 
 	for (i = 0; i < axi_data->hw_info->num_comp_mask; i++) {
 		if (!axi_data->composite_info[i].stream_handle) {
 			axi_data->composite_info[i].stream_handle =
-			stream_cfg_cmd->axi_stream_handle;
+				stream_info->stream_handle;
 			axi_data->composite_info[i].
 				stream_composite_mask = comp_mask;
 			axi_data->num_used_composite_mask++;
@@ -384,7 +377,7 @@
 		break;
 	}
 
-	sof_event.frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
+	sof_event.frame_id = vfe_dev->axi_data.src_info[frame_src].frame_id;
 	sof_event.timestamp = ts->event_time;
 	msm_isp_send_event(vfe_dev, ISP_EVENT_SOF, &sof_event);
 }
@@ -471,18 +464,18 @@
 
 	stream_info = &vfe_dev->axi_data.
 		stream_info[HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
-	msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_cfg_cmd);
+	msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_info);
 
 	if (stream_cfg_cmd->stream_src == CAMIF_RAW ||
 		stream_cfg_cmd->stream_src == IDEAL_RAW)
 			vfe_dev->hw_info->vfe_ops.axi_ops.
-				cfg_io_format(vfe_dev, stream_cfg_cmd);
+				cfg_io_format(vfe_dev, stream_info);
 
 	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
 
 	if (stream_info->num_planes > 1) {
 		msm_isp_axi_reserve_comp_mask(
-			&vfe_dev->axi_data, stream_cfg_cmd);
+			&vfe_dev->axi_data, stream_info);
 		vfe_dev->hw_info->vfe_ops.axi_ops.
 		cfg_comp_mask(vfe_dev, stream_info);
 	} else {
@@ -492,10 +485,10 @@
 
 	for (i = 0; i < stream_info->num_planes; i++) {
 		vfe_dev->hw_info->vfe_ops.axi_ops.
-			cfg_wm_reg(vfe_dev, stream_cfg_cmd, i);
+			cfg_wm_reg(vfe_dev, stream_info, i);
 
 		vfe_dev->hw_info->vfe_ops.axi_ops.
-			cfg_wm_xbar_reg(vfe_dev, stream_cfg_cmd, i);
+			cfg_wm_xbar_reg(vfe_dev, stream_info, i);
 	}
 	return rc;
 }
@@ -610,7 +603,7 @@
 		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
 			vfe_dev, stream_info->wm[i],
 			VFE_PONG_FLAG, buf->mapped_info[i].paddr +
-			stream_info->plane_offset[i]);
+			stream_info->plane_cfg[i].plane_addr_offset);
 	stream_info->buf[1] = buf;
 }
 
@@ -657,7 +650,7 @@
 		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
 			vfe_dev, stream_info->wm[i],
 			pingpong_status, buf->mapped_info[i].paddr +
-			stream_info->plane_offset[i]);
+			stream_info->plane_cfg[i].plane_addr_offset);
 
 	pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
 	stream_info->buf[pingpong_bit] = buf;
@@ -852,7 +845,7 @@
 	spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stream_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
@@ -976,18 +969,33 @@
 			enum msm_isp_camif_update_state camif_update)
 {
 	int i, rc = 0;
+	uint8_t wait_for_complete = 0;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info = &axi_data->stream_info[
 			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+
 		stream_info->state = STOP_PENDING;
+		if (stream_info->stream_type == BURST_STREAM &&
+			stream_info->runtime_num_burst_capture == 0) {
+			/*Configure AXI writemasters to stop immediately
+			 *since for burst case, write masters already skip
+			 *all frames.
+			 */
+			msm_isp_axi_stream_enable_cfg(vfe_dev, stream_info);
+			stream_info->state = INACTIVE;
+		} else {
+			wait_for_complete = 1;
+		}
 	}
 
-	rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
-	if (rc < 0) {
-		pr_err("%s: wait for config done failed\n", __func__);
-		return rc;
+	if (wait_for_complete) {
+		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
+		if (rc < 0) {
+			pr_err("%s: wait for config done failed\n", __func__);
+			return rc;
+		}
 	}
 	msm_isp_update_stream_bandwidth(vfe_dev);
 	if (camif_update == DISABLE_CAMIF)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index f592a60..3d775f9 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -27,15 +27,11 @@
 
 void msm_isp_axi_reserve_wm(
 	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
-
-void msm_isp_axi_reserve_rdi(
-	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+	struct msm_vfe_axi_stream *stream_info);
 
 void msm_isp_axi_reserve_comp_mask(
 	struct msm_vfe_axi_shared_data *axi_data,
-	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd);
+	struct msm_vfe_axi_stream *stream_info);
 
 int msm_isp_axi_check_stream_state(
 	struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index ce71235..d857a14 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -343,7 +343,7 @@
 	atomic_set(&vfe_dev->stats_data.stats_update, 2);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stats_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
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 fa63e2b..27d3d40 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -16,6 +16,9 @@
 #include "msm_cci.h"
 #include "msm_camera_io_util.h"
 #include "msm_camera_i2c_mux.h"
+#include <mach/rpm-regulator.h>
+#include <mach/rpm-regulator-smd.h>
+#include <linux/regulator/consumer.h>
 
 #undef CDBG
 #ifdef CONFIG_MSMB_CAMERA_DEBUG
@@ -774,7 +777,17 @@
 	sensordata->slave_info->sensor_id_reg_addr = id_info[1];
 	sensordata->slave_info->sensor_id = id_info[2];
 
+	rc = of_property_read_string(of_node, "qcom,vdd-cx-name",
+		&sensordata->misc_regulator);
+	CDBG("%s qcom,misc_regulator %s, rc %d\n", __func__,
+		 sensordata->misc_regulator, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR9;
+	}
+
 	kfree(gpio_array);
+
 	return rc;
 
 ERROR9:
@@ -799,6 +812,41 @@
 	return rc;
 }
 
+static void msm_sensor_misc_regulator(
+	struct msm_sensor_ctrl_t *sctrl, uint32_t enable)
+{
+	int32_t rc = 0;
+	if (enable) {
+		sctrl->misc_regulator = (void *)rpm_regulator_get(
+			&sctrl->pdev->dev, sctrl->sensordata->misc_regulator);
+		if (sctrl->misc_regulator) {
+			rc = rpm_regulator_set_mode(sctrl->misc_regulator,
+				RPM_REGULATOR_MODE_HPM);
+			if (rc < 0) {
+				pr_err("%s: Failed to set for rpm regulator on %s: %d\n",
+					__func__,
+					sctrl->sensordata->misc_regulator, rc);
+				rpm_regulator_put(sctrl->misc_regulator);
+			}
+		} else {
+			pr_err("%s: Failed to vote for rpm regulator on %s: %d\n",
+				__func__,
+				sctrl->sensordata->misc_regulator, rc);
+		}
+	} else {
+		if (sctrl->misc_regulator) {
+			rc = rpm_regulator_set_mode(
+				(struct rpm_regulator *)sctrl->misc_regulator,
+				RPM_REGULATOR_MODE_AUTO);
+			if (rc < 0)
+				pr_err("%s: Failed to set for rpm regulator on %s: %d\n",
+					__func__,
+					sctrl->sensordata->misc_regulator, rc);
+			rpm_regulator_put(sctrl->misc_regulator);
+		}
+	}
+}
+
 int32_t msm_sensor_free_sensor_data(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	if (!s_ctrl->pdev)
@@ -814,6 +862,7 @@
 	kfree(s_ctrl->sensordata->sensor_info);
 	kfree(s_ctrl->sensordata->sensor_init_params);
 	kfree(s_ctrl->sensordata);
+	kfree(s_ctrl->clk_info);
 	return 0;
 }
 
@@ -1301,6 +1350,9 @@
 	}
 
 	case CFG_POWER_UP:
+		if (s_ctrl->sensordata->misc_regulator)
+			msm_sensor_misc_regulator(s_ctrl, 1);
+
 		if (s_ctrl->func_tbl->sensor_power_up)
 			rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
 		else
@@ -1308,6 +1360,8 @@
 		break;
 
 	case CFG_POWER_DOWN:
+		if (s_ctrl->sensordata->misc_regulator)
+			msm_sensor_misc_regulator(s_ctrl, 0);
 		if (s_ctrl->func_tbl->sensor_power_down)
 			rc = s_ctrl->func_tbl->sensor_power_down(
 				s_ctrl);
@@ -1468,12 +1522,20 @@
 			&msm_sensor_cci_func_tbl;
 	if (!s_ctrl->sensor_v4l2_subdev_ops)
 		s_ctrl->sensor_v4l2_subdev_ops = &msm_sensor_subdev_ops;
-	s_ctrl->clk_info = cam_8974_clk_info;
+	s_ctrl->clk_info = kzalloc(sizeof(cam_8974_clk_info),
+		GFP_KERNEL);
+	if (!s_ctrl->clk_info) {
+		pr_err("%s:%d failed nomem\n", __func__, __LINE__);
+		kfree(cci_client);
+		return -ENOMEM;
+	}
+	memcpy(s_ctrl->clk_info, cam_8974_clk_info, sizeof(cam_8974_clk_info));
 	s_ctrl->clk_info_size = ARRAY_SIZE(cam_8974_clk_info);
 	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
 	if (rc < 0) {
 		pr_err("%s %s power up failed\n", __func__,
 			s_ctrl->sensordata->sensor_name);
+		kfree(s_ctrl->clk_info);
 		kfree(cci_client);
 		return rc;
 	}
@@ -1554,12 +1616,19 @@
 	if (!s_ctrl->sensor_v4l2_subdev_ops)
 		s_ctrl->sensor_v4l2_subdev_ops = &msm_sensor_subdev_ops;
 
-	s_ctrl->clk_info = cam_8960_clk_info;
+	s_ctrl->clk_info = kzalloc(sizeof(cam_8960_clk_info),
+		GFP_KERNEL);
+	if (!s_ctrl->clk_info) {
+		pr_err("%s:%d failed nomem\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	memcpy(s_ctrl->clk_info, cam_8960_clk_info, sizeof(cam_8960_clk_info));
 	s_ctrl->clk_info_size = ARRAY_SIZE(cam_8960_clk_info);
 
 	rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
 	if (rc < 0) {
 		pr_err("%s %s power up failed\n", __func__, client->name);
+		kfree(s_ctrl->clk_info);
 		return rc;
 	}
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
index 6c36e47d..a1128a6 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
@@ -65,6 +65,7 @@
 	bool free_power_setting;
 	struct msm_cam_clk_info *clk_info;
 	uint16_t clk_info_size;
+	void *misc_regulator;
 };
 
 int32_t msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl,
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index 123b654..577b2b5 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -362,17 +362,18 @@
 
 void q6_hfi_delete_device(void *device)
 {
-	struct q6_hfi_device *close, *dev;
+	struct q6_hfi_device *close, *tmp, *dev;
 
 	if (device) {
 		q6_hfi_deinit_resources(device);
 		dev = (struct q6_hfi_device *) device;
-		list_for_each_entry(close, &hal_ctxt.dev_head, list) {
+		list_for_each_entry_safe(close, tmp, &hal_ctxt.dev_head, list) {
 			if (close->device_id == dev->device_id) {
 				hal_ctxt.dev_count--;
 				list_del(&close->list);
 				destroy_workqueue(close->vidc_workq);
 				kfree(close);
+				break;
 			}
 		}
 
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 74733c2..bc5adc11 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2953,12 +2953,12 @@
 
 void venus_hfi_delete_device(void *device)
 {
-	struct venus_hfi_device *close, *dev;
+	struct venus_hfi_device *close, *tmp, *dev;
 
 	if (device) {
 		venus_hfi_deinit_resources(device);
 		dev = (struct venus_hfi_device *) device;
-		list_for_each_entry(close, &hal_ctxt.dev_head, list) {
+		list_for_each_entry_safe(close, tmp, &hal_ctxt.dev_head, list) {
 			if (close->hal_data->irq == dev->hal_data->irq) {
 				hal_ctxt.dev_count--;
 				free_irq(dev->hal_data->irq, close);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index fa28d6a..d8a5669 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -540,6 +540,8 @@
 	unsigned long flags;
 	struct qseecom_client_listener_data_irsp send_data_rsp;
 	struct qseecom_registered_listener_list *ptr_svc = NULL;
+	sigset_t new_sigset;
+	sigset_t old_sigset;
 
 	while (resp->result == QSEOS_RESULT_INCOMPLETE) {
 		lstnr = resp->data;
@@ -564,17 +566,24 @@
 		}
 		pr_debug("waking up rcv_req_wq and "
 				"waiting for send_resp_wq\n");
-		if (wait_event_freezable(qseecom.send_resp_wq,
-				__qseecom_listener_has_sent_rsp(data))) {
-			pr_warning("Interrupted: exiting send_cmd loop\n");
-			ret = -ERESTARTSYS;
-		}
 
-		if ((data->abort) || (ret == -ERESTARTSYS)) {
+		/* initialize the new signal mask with all signals*/
+		sigfillset(&new_sigset);
+		/* block all signals */
+		sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
+
+		do {
+			if (!wait_event_freezable(qseecom.send_resp_wq,
+				__qseecom_listener_has_sent_rsp(data)))
+				break;
+		} while (1);
+
+		/* restore signal mask */
+		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+		if (data->abort) {
 			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
 				data->client.app_id, lstnr, ret);
-			if (data->abort)
-				rc = -ENODEV;
+			rc = -ENODEV;
 			send_data_rsp.status  = QSEOS_RESULT_FAILURE;
 		} else {
 			send_data_rsp.status  = QSEOS_RESULT_SUCCESS;
@@ -2410,12 +2419,13 @@
 	case QSEOS_RESULT_SUCCESS:
 		break;
 	case QSEOS_RESULT_FAIL_KEY_ID_EXISTS:
+		pr_debug("process_incomplete_cmd return Key ID exists.\n");
 		break;
 	case QSEOS_RESULT_INCOMPLETE:
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
 		if (ret) {
 			if (resp.result == QSEOS_RESULT_FAIL_KEY_ID_EXISTS) {
-				pr_warn("process_incomplete_cmd return Key ID exits.\n");
+				pr_debug("process_incomplete_cmd return Key ID exists.\n");
 				ret = 0;
 			} else {
 				pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
@@ -2494,9 +2504,8 @@
 			return -EFAULT;
 	}
 
-	if (qseecom.qsee.instance == qseecom.ce_drv.instance)
-		__qseecom_enable_clk(CLK_QSEE);
-	else
+	__qseecom_enable_clk(CLK_QSEE);
+	if (qseecom.qsee.instance != qseecom.ce_drv.instance)
 		__qseecom_enable_clk(CLK_CE_DRV);
 
 	memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
@@ -2520,6 +2529,9 @@
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
 		pr_err("scm call to set QSEOS_PIPE_ENC key failed : %d\n", ret);
+		__qseecom_disable_clk(CLK_QSEE);
+		if (qseecom.qsee.instance != qseecom.ce_drv.instance)
+			__qseecom_disable_clk(CLK_CE_DRV);
 		return ret;
 	}
 
@@ -2539,9 +2551,8 @@
 		break;
 	}
 
-	if (qseecom.qsee.instance == qseecom.ce_drv.instance)
-		__qseecom_disable_clk(CLK_QSEE);
-	else
+	__qseecom_disable_clk(CLK_QSEE);
+	if (qseecom.qsee.instance != qseecom.ce_drv.instance)
 		__qseecom_disable_clk(CLK_CE_DRV);
 
 	return ret;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index f837a06..c30f46f 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -31,6 +31,7 @@
 #include <linux/kthread.h>
 #include <linux/wait.h>
 #include <linux/uaccess.h>
+#include <linux/mfd/pm8xxx/misc.h>
 
 #include <mach/msm_smd.h>
 #include <mach/msm_iomap.h>
@@ -133,6 +134,21 @@
 	unsigned char  revision;
 };
 
+struct wcnss_pmic_dump {
+	char reg_name[10];
+	u16 reg_addr;
+};
+
+static struct wcnss_pmic_dump wcnss_pmic_reg_dump[] = {
+	{"S2", 0x1D8},
+	{"L4", 0xB4},
+	{"L10", 0xC0},
+	{"LVS2", 0x62},
+	{"S4", 0x1E8},
+	{"LVS7", 0x06C},
+	{"LVS1", 0x060},
+};
+
 #define NVBIN_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin"
 
 /*
@@ -342,6 +358,25 @@
 static DEVICE_ATTR(wcnss_version, S_IRUSR,
 		wcnss_version_show, NULL);
 
+void wcnss_riva_dump_pmic_regs(void)
+{
+	int i, rc;
+	u8  val;
+
+	for (i = 0; i < ARRAY_SIZE(wcnss_pmic_reg_dump); i++) {
+		val = 0;
+		rc = pm8xxx_read_register(wcnss_pmic_reg_dump[i].reg_addr,
+				&val);
+		if (rc)
+			pr_err("PMIC READ: Failed to read addr = %d\n",
+					wcnss_pmic_reg_dump[i].reg_addr);
+		else
+			pr_info_ratelimited("PMIC READ: %s addr = %x, value = %x\n",
+				wcnss_pmic_reg_dump[i].reg_name,
+				wcnss_pmic_reg_dump[i].reg_addr, val);
+	}
+}
+
 /* wcnss_reset_intr() is invoked when host drivers fails to
  * communicate with WCNSS over SMD; so logging these registers
  * helps to know WCNSS failure reason
@@ -366,6 +401,7 @@
 	ccu_reg = penv->riva_ccu_base + CCU_RIVA_LAST_ADDR2_OFFSET;
 	reg = readl_relaxed(ccu_reg);
 	pr_info_ratelimited("%s: CCU_CCPU_LAST_ADDR2 %08x\n", __func__, reg);
+	wcnss_riva_dump_pmic_regs();
 
 }
 EXPORT_SYMBOL(wcnss_riva_log_debug_regs);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index fe151b5..acd42ae3 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -107,4 +107,10 @@
 	help
 	  OpenFirmware SLIMBUS accessors
 
+config OF_CORESIGHT
+	def_bool y
+	depends on CORESIGHT
+	help
+	  OpenFirmware CoreSight accessors
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index c3a31c8..61a99f2 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -15,3 +15,4 @@
 obj-$(CONFIG_OF_SPMI)	+= of_spmi.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
 obj-$(CONFIG_OF_SLIMBUS)	+= of_slimbus.o
+obj-$(CONFIG_OF_CORESIGHT) += of_coresight.o
diff --git a/drivers/coresight/of_coresight.c b/drivers/of/of_coresight.c
similarity index 100%
rename from drivers/coresight/of_coresight.c
rename to drivers/of/of_coresight.c
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index a95eafe..d707648 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -13,6 +13,9 @@
 #include <linux/delay.h>
 #include "ipa_i.h"
 
+#define IPA_A2_HOLB_TMR_EN 0x1
+#define IPA_A2_HOLB_TMR_DEFAULT_VAL 0xff
+
 static void ipa_enable_data_path(u32 clnt_hdl)
 {
 	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL) {
@@ -175,6 +178,38 @@
 	return 0;
 }
 
+static void ipa_program_holb(struct ipa_ep_context *ep, int ipa_ep_idx)
+{
+	u32 hol_en;
+	u32 hol_tmr;
+
+	if (IPA_CLIENT_IS_PROD(ep->client))
+		return;
+
+	switch (ep->client) {
+	case IPA_CLIENT_HSIC1_CONS:
+	case IPA_CLIENT_HSIC2_CONS:
+	case IPA_CLIENT_HSIC3_CONS:
+	case IPA_CLIENT_HSIC4_CONS:
+		hol_en = ipa_ctx->hol_en;
+		hol_tmr = ipa_ctx->hol_timer;
+		break;
+	case IPA_CLIENT_A2_TETHERED_CONS:
+	case IPA_CLIENT_A2_EMBEDDED_CONS:
+		hol_en = IPA_A2_HOLB_TMR_EN;
+		hol_tmr = IPA_A2_HOLB_TMR_DEFAULT_VAL;
+		break;
+	default:
+		return;
+	}
+
+	IPADBG("disable holb for ep=%d tmr=%d\n", ipa_ep_idx, hol_tmr);
+	ipa_write_reg(ipa_ctx->mmio,
+		IPA_ENDP_INIT_HOL_BLOCK_EN_n_OFST(ipa_ep_idx), hol_en);
+	ipa_write_reg(ipa_ctx->mmio,
+		IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_OFST(ipa_ep_idx), hol_tmr);
+}
+
 /**
  * ipa_connect() - low-level IPA client connect
  * @in:	[in] input parameters from client
@@ -290,21 +325,7 @@
 	memcpy(&sps->desc, &ep->connect.desc, sizeof(struct sps_mem_buffer));
 	memcpy(&sps->data, &ep->connect.data, sizeof(struct sps_mem_buffer));
 
-	if (in->client == IPA_CLIENT_HSIC1_CONS ||
-			in->client == IPA_CLIENT_HSIC2_CONS ||
-			in->client == IPA_CLIENT_HSIC3_CONS ||
-			in->client == IPA_CLIENT_HSIC4_CONS ||
-			in->client == IPA_CLIENT_A2_TETHERED_CONS ||
-			in->client == IPA_CLIENT_A2_EMBEDDED_CONS) {
-		IPADBG("disable holb for ep=%d tmr=%d\n", ipa_ep_idx,
-			ipa_ctx->hol_timer);
-		ipa_write_reg(ipa_ctx->mmio,
-			IPA_ENDP_INIT_HOL_BLOCK_EN_n_OFST(ipa_ep_idx),
-			ipa_ctx->hol_en);
-		ipa_write_reg(ipa_ctx->mmio,
-			IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_OFST(ipa_ep_idx),
-			ipa_ctx->hol_timer);
-	}
+	ipa_program_holb(ep, ipa_ep_idx);
 
 	IPADBG("client %d (ep: %d) connected\n", in->client, ipa_ep_idx);
 
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 64e8d7a..fc85dba 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -129,15 +129,40 @@
 	[HSIC_BAM]  = hsic_cons_release_resource,
 };
 
-static enum ipa_rm_event cur_prod_state[MAX_BAMS];
-static enum ipa_rm_event cur_cons_state[MAX_BAMS];
-static int sched_lpm;
-static int lpm_wait_handshake;
-static struct completion prod_avail[MAX_BAMS];
-static struct completion cons_avail[MAX_BAMS];
-static struct completion cons_released[MAX_BAMS];
-static struct completion prod_released[MAX_BAMS];
+struct usb_bam_ipa_handshake_info {
+	enum ipa_rm_event cur_prod_state[MAX_BAMS];
+	enum ipa_rm_event cur_cons_state[MAX_BAMS];
 
+	int lpm_wait_handshake;
+	int connect_complete;
+	bool lpm_wait_pipes;
+	int bus_suspend;
+	bool in_lpm;
+
+	int (*wake_cb)(void *);
+	void *wake_param;
+	void (*start)(void *, enum usb_bam_pipe_dir);
+	void (*stop)(void *, enum usb_bam_pipe_dir);
+	void *start_stop_param;
+
+	u32 src_idx;
+	u32 dst_idx;
+	bool cons_stopped;
+	bool prod_stopped;
+
+	struct completion prod_avail[MAX_BAMS];
+	struct completion cons_avail[MAX_BAMS];
+	struct completion cons_released[MAX_BAMS];
+	struct completion prod_released[MAX_BAMS];
+
+	struct mutex suspend_resume_mutex;
+	struct work_struct resume_work;
+	struct work_struct suspend_work;
+	struct work_struct finish_suspend_work;
+};
+
+static spinlock_t usb_bam_ipa_handshake_info_lock;
+static struct usb_bam_ipa_handshake_info info;
 static spinlock_t usb_bam_peer_handshake_info_lock;
 static struct usb_bam_peer_handshake_info peer_handshake_info;
 static spinlock_t usb_bam_lock; /* Protect ctx and usb_bam_connections */
@@ -457,6 +482,7 @@
 		pr_err("%s: ipa_connect failed\n", __func__);
 		return ret;
 	}
+	pipe_connect->ipa_clnt_hdl = clnt_hdl;
 
 	*pipe = sps_alloc_endpoint();
 	if (*pipe == NULL) {
@@ -579,6 +605,31 @@
 	return 0;
 }
 
+static void usb_bam_resume_core(enum usb_bam cur_bam)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+
+	if (cur_bam != HSUSB_BAM)
+		return;
+	BUG_ON(trans == NULL);
+	pr_debug("%s: resume core", __func__);
+	pm_runtime_resume(trans->dev);
+}
+
+static void usb_bam_start_lpm(bool disconnect)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+	BUG_ON(trans == NULL);
+		pr_debug("%s: Going to LPM\n", __func__);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.lpm_wait_handshake = false;
+		info.lpm_wait_pipes = 0;
+	if (disconnect)
+		pm_runtime_put_noidle(trans->dev);
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	pm_runtime_suspend(trans->dev);
+}
+
 int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
 {
 	int ret;
@@ -608,26 +659,136 @@
 	}
 
 	spin_lock(&usb_bam_lock);
-
 	/* Check if BAM requires RESET before connect and reset of first pipe */
 	if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
 	    (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
 		sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
+	spin_unlock(&usb_bam_lock);
 
 	ret = connect_pipe(idx, bam_pipe_idx);
 	if (ret) {
 		pr_err("%s: pipe connection[%d] failure\n", __func__, idx);
-		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 1;
+	spin_lock(&usb_bam_lock);
 	ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
-
 	spin_unlock(&usb_bam_lock);
+
 	return 0;
 }
 
+static int ipa_suspend_pipes(void)
+{
+	struct usb_bam_pipe_connect *dst_pipe_connect, *src_pipe_connect;
+	int ret1, ret2;
+
+	dst_pipe_connect = &usb_bam_connections[info.dst_idx];
+	src_pipe_connect = &usb_bam_connections[info.src_idx];
+
+	if (dst_pipe_connect->ipa_clnt_hdl == -1 ||
+		src_pipe_connect->ipa_clnt_hdl == -1) {
+		pr_err("%s: One of handles is -1, not connected?", __func__);
+	}
+
+	ret1 = ipa_suspend(dst_pipe_connect->ipa_clnt_hdl);
+	if (ret1)
+		pr_err("%s: ipa_suspend on dst failed with %d", __func__, ret1);
+	ret2 = ipa_suspend(src_pipe_connect->ipa_clnt_hdl);
+	if (ret2)
+		pr_err("%s: ipa_suspend on src failed with %d", __func__, ret2);
+
+	return ret1 | ret2;
+}
+
+static int ipa_resume_pipes(void)
+{
+	struct usb_bam_pipe_connect *dst_pipe_connect, *src_pipe_connect;
+	int ret1, ret2;
+
+	src_pipe_connect = &usb_bam_connections[info.src_idx];
+	dst_pipe_connect = &usb_bam_connections[info.dst_idx];
+
+	if (dst_pipe_connect->ipa_clnt_hdl == -1 ||
+		src_pipe_connect->ipa_clnt_hdl == -1) {
+		pr_err("%s: One of handles is -1, not connected?", __func__);
+	}
+
+	ret1 = ipa_resume(dst_pipe_connect->ipa_clnt_hdl);
+	if (ret1)
+		pr_err("%s: ipa_resume on dst failed with %d", __func__, ret1);
+	ret2 = ipa_resume(src_pipe_connect->ipa_clnt_hdl);
+	if (ret2)
+		pr_err("%s: ipa_resume on src failed with %d", __func__, ret2);
+
+	return ret1 | ret2;
+}
+
+static void usb_bam_finish_suspend(void)
+{
+	int ret;
+	u32 cons_empty;
+	struct sps_pipe *cons_pipe = ctx.usb_bam_sps.sps_pipes[info.dst_idx];
+	struct usb_bam_pipe_connect *pipe_connect = &
+			usb_bam_connections[info.dst_idx];
+	enum usb_bam cur_bam = pipe_connect->bam_type;
+
+	if (cur_bam != HSUSB_BAM) {
+		pr_err("%s: Wrong type of BAM=%s\n", __func__,
+			bam_enable_strings[cur_bam]);
+		return;
+	}
+
+	mutex_lock(&info.suspend_resume_mutex);
+
+	/* If resume was called don't finish this work */
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (!info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Bus suspend in progress\n", __func__);
+		goto no_lpm;
+	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	ret = sps_is_pipe_empty(cons_pipe, &cons_empty);
+	if (ret) {
+		pr_err("%s: sps_is_pipe_empty failed with %d\n", __func__, ret);
+		goto no_lpm;
+	}
+
+	/* Stop CONS transfers and go to lpm if no more data in the pipe */
+	if (cons_empty) {
+		if (info.stop && !info.cons_stopped)
+			info.stop(info.start_stop_param,
+					PEER_PERIPHERAL_TO_USB);
+		pr_err("%s: Starting LPM on Bus Suspend\n", __func__);
+		info.cons_stopped = 1;
+		if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED) {
+			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+				ipa_rm_resource_cons[cur_bam]);
+		}
+		ipa_suspend_pipes();
+		mutex_unlock(&info.suspend_resume_mutex);
+		usb_bam_start_lpm(0);
+		return;
+	}
+
+no_lpm:
+
+	/* Finish the handshake. Resume Sequence will start automatically
+	   by the data in the pipes */
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+				ipa_rm_resource_cons[cur_bam]);
+	mutex_unlock(&info.suspend_resume_mutex);
+}
+
+void usb_bam_finish_suspend_(struct work_struct *w)
+{
+	usb_bam_finish_suspend();
+}
+
 static void usb_prod_notify_cb(void *user_data, enum ipa_rm_event event,
 	unsigned long data)
 {
@@ -637,14 +798,14 @@
 	case IPA_RM_RESOURCE_GRANTED:
 		pr_debug("%s: %s_PROD resource granted\n",
 			__func__, bam_enable_strings[*cur_bam]);
-		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_GRANTED;
-		complete_all(&prod_avail[*cur_bam]);
+		info.cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&info.prod_avail[*cur_bam]);
 		break;
 	case IPA_RM_RESOURCE_RELEASED:
 		pr_debug("%s: %s_PROD resource released\n",
 			__func__, bam_enable_strings[*cur_bam]);
-		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_RELEASED;
-		complete_all(&prod_released[*cur_bam]);
+		info.cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&info.prod_released[*cur_bam]);
 		break;
 	default:
 		break;
@@ -657,12 +818,33 @@
 	pr_debug("%s: Request %s_CONS resource\n",
 			__func__, bam_enable_strings[cur_bam]);
 
-	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
-	complete_all(&cons_avail[cur_bam]);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+	complete_all(&info.cons_avail[cur_bam]);
 
-	if (ctx.pipes_enabled_per_bam[cur_bam])
+	spin_lock(&usb_bam_lock);
+	if (ctx.pipes_enabled_per_bam[cur_bam] && info.connect_complete &&
+				!info.bus_suspend && !info.prod_stopped) {
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_debug("%s: ACK on cons_request", __func__);
 		return 0;
+	}
 
+	/* A2 wakeup from LPM */
+	if (cur_bam == HSUSB_BAM && ctx.pipes_enabled_per_bam[cur_bam] &&
+		info.connect_complete && info.bus_suspend) {
+		info.bus_suspend = 0;
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		if (info.wake_cb)
+			info.wake_cb(info.wake_param);
+	} else {
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+
+	pr_debug("%s: EINPROGRESS on cons_request", __func__);
 	return -EINPROGRESS;
 }
 
@@ -681,12 +863,23 @@
 	pr_debug("%s: Release %s_CONS resource\n",
 			__func__, bam_enable_strings[cur_bam]);
 
-	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-	complete_all(&cons_released[cur_bam]);
+	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+	complete_all(&info.cons_released[cur_bam]);
 
-	if (!ctx.pipes_enabled_per_bam[cur_bam])
+	spin_lock(&usb_bam_lock);
+	if (!ctx.pipes_enabled_per_bam[cur_bam]) {
+		spin_unlock(&usb_bam_lock);
+		pr_debug("%s: ACK on cons_release", __func__);
 		return 0;
+	}
+	spin_unlock(&usb_bam_lock);
 
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (cur_bam == HSUSB_BAM && info.bus_suspend)
+		queue_work(ctx.usb_bam_wq, &info.finish_suspend_work);
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	pr_debug("%s: EINPROGRESS cons_release", __func__);
 	return -EINPROGRESS;
 }
 
@@ -747,24 +940,24 @@
 
 	pr_debug("%s Request %s_PROD_RES\n", __func__,
 		bam_enable_strings[cur_bam]);
-	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
 		pr_debug("%s: CONS already granted for some reason\n",
 			__func__);
-	if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+	if (info.cur_prod_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
 		pr_debug("%s: PROD already granted for some reason\n",
 			__func__);
 
-	init_completion(&prod_avail[cur_bam]);
-	init_completion(&cons_avail[cur_bam]);
+	init_completion(&info.prod_avail[cur_bam]);
+	init_completion(&info.cons_avail[cur_bam]);
 
 	ret = ipa_rm_request_resource(ipa_rm_resource_prod[cur_bam]);
 	if (!ret) {
-		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
-		complete_all(&prod_avail[cur_bam]);
+		info.cur_prod_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&info.prod_avail[cur_bam]);
 		pr_debug("%s: PROD_GRANTED without wait\n", __func__);
 	} else if (ret == -EINPROGRESS) {
 		pr_debug("%s: Waiting for PROD_GRANTED\n", __func__);
-		if (!wait_for_completion_timeout(&prod_avail[cur_bam],
+		if (!wait_for_completion_timeout(&info.prod_avail[cur_bam],
 			USB_BAM_TIMEOUT))
 			pr_err("%s: Timeout wainting for PROD_GRANTED\n",
 				__func__);
@@ -772,6 +965,261 @@
 		pr_err("%s: ipa_rm_request_resource ret =%d\n", __func__, ret);
 }
 
+void wait_for_cons_granted(enum usb_bam cur_bam)
+{
+	pr_debug("%s: Waiting for CONS\n", __func__);
+	if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_GRANTED) {
+		if (!wait_for_completion_timeout(&info.cons_avail[cur_bam],
+						USB_BAM_TIMEOUT*6))
+			pr_err("%s: Timeout wainting for CONS_REQUEST\n",
+			__func__);
+		pr_err("%s: Finished waiting for CONS\n", __func__);
+	}
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.connect_complete = 1;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	pr_debug("%s: CONS is granted\n", __func__);
+
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_GRANTED) {
+		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+				 ipa_rm_resource_cons[HSUSB_BAM]);
+	}
+}
+
+void usb_bam_wait_for_cons_granted(
+	struct usb_bam_connect_ipa_params *ipa_params)
+{
+	struct usb_bam_pipe_connect *pipe_connect;
+	enum usb_bam cur_bam;
+	u8 src_idx;
+
+	src_idx = ipa_params->src_idx;
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+
+	wait_for_cons_granted(cur_bam);
+}
+
+static void wait_for_prod_release(enum usb_bam cur_bam)
+{
+	int ret;
+
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pr_debug("%s consumer already released\n", __func__);
+	 if (info.cur_prod_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		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]);
+	if (!ret) {
+		pr_debug("%s: Released without waiting\n", __func__);
+		info.cur_prod_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&info.prod_released[cur_bam]);
+	} else if (ret == -EINPROGRESS) {
+		pr_debug("%s: Waiting for PROD_RELEASED\n", __func__);
+		if (!wait_for_completion_timeout(&info.prod_released[cur_bam],
+						USB_BAM_TIMEOUT))
+			pr_err("%s: Timeout waiting for PROD_RELEASED\n",
+			__func__);
+	} else
+		pr_err("%s: ipa_rm_request_resource ret =%d", __func__, ret);
+}
+
+static int check_pipes_empty(u8 src_idx, u8 dst_idx)
+{
+	struct sps_pipe *prod_pipe, *cons_pipe;
+	u32 prod_empty, cons_empty;
+
+	/* If we have any remaints in the pipes we don't go to sleep */
+	prod_pipe = ctx.usb_bam_sps.sps_pipes[src_idx];
+	cons_pipe = ctx.usb_bam_sps.sps_pipes[dst_idx];
+	if (sps_is_pipe_empty(prod_pipe, &prod_empty) ||
+			sps_is_pipe_empty(cons_pipe, &cons_empty)) {
+		pr_err("%s: sps_is_pipe_empty failed with\n", __func__);
+		return 0;
+	}
+	if (!prod_empty || !cons_empty) {
+		pr_err("%s: pipes not empty prod=%d cond=%d", __func__,
+			prod_empty, cons_empty);
+		return 0;
+	}
+
+	return 1;
+}
+
+void usb_bam_suspend(struct usb_bam_connect_ipa_params *ipa_params)
+{
+	struct usb_bam_pipe_connect *pipe_connect;
+	enum usb_bam cur_bam;
+	u8 src_idx, dst_idx;
+
+	if (!ipa_params) {
+		pr_err("%s: Invalid ipa params\n", __func__);
+		return;
+	}
+
+	src_idx = ipa_params->src_idx;
+	dst_idx = ipa_params->dst_idx;
+
+	if (src_idx >= ctx.max_connections || dst_idx >= ctx.max_connections) {
+		pr_err("%s: Invalid connection index src=%d dst=%d\n",
+			__func__, src_idx, dst_idx);
+	}
+
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+	if (cur_bam != HSUSB_BAM)
+		return;
+
+	info.src_idx = src_idx;
+	info.dst_idx = dst_idx;
+
+	pr_err("%s: Starting suspend sequence(BAM=%s)\n", __func__,
+			bam_enable_strings[cur_bam]);
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.bus_suspend = 1;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	/* Stop PROD transfers */
+	if (info.stop) {
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		info.stop(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = true;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+
+	/* Don't go to LPM if data in the pipes */
+	if (!check_pipes_empty(src_idx, dst_idx)) {
+		pr_err("%s: pipes not empty, won't start suspend", __func__);
+		return;
+	}
+
+	queue_work(ctx.usb_bam_wq, &info.suspend_work);
+}
+
+static void usb_bam_start_suspend(struct work_struct *w)
+{
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (!info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Resume started, not suspending", __func__);
+		return;
+	}
+
+	/* Stop PROD transfers in case they were started */
+	if (info.stop && !info.prod_stopped) {
+		info.stop(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = true;
+	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	/* Don't start LPM seq if data in the pipes */
+	if (!check_pipes_empty(info.src_idx, info.dst_idx)) {
+		mutex_unlock(&info.suspend_resume_mutex);
+		return;
+	}
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.lpm_wait_handshake = true;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	wait_for_prod_release(HSUSB_BAM);
+
+	mutex_unlock(&info.suspend_resume_mutex);
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_RELEASED)
+		usb_bam_finish_suspend();
+	else
+		pr_debug("Consumer not released yet\n");
+}
+
+static void usb_bam_finish_resume(struct work_struct *w)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+
+	BUG_ON(trans == NULL);
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+	/* Suspend happened in the meantime */
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Bus suspended, not resuming", __func__);
+		mutex_unlock(&info.suspend_resume_mutex);
+		return;
+	}
+	info.lpm_wait_handshake = true;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	wait_for_prod_granted(HSUSB_BAM);
+	wait_for_cons_granted(HSUSB_BAM);
+	if (info.cons_stopped) {
+		ipa_resume_pipes();
+		if (info.start) {
+			pr_debug("%s: Enqueue CONS transfer", __func__);
+			info.start(info.start_stop_param,
+				PEER_PERIPHERAL_TO_USB);
+			info.cons_stopped = 0;
+		}
+	}
+
+	if (info.start) {
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		info.start(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = false;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_GRANTED) {
+		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+				 ipa_rm_resource_cons[HSUSB_BAM]);
+	}
+	mutex_unlock(&info.suspend_resume_mutex);
+	pr_debug("%s: done", __func__);
+}
+
+void usb_bam_resume(struct usb_bam_connect_ipa_params *ipa_params)
+{
+	enum usb_bam cur_bam;
+	u8 src_idx, dst_idx;
+	struct usb_bam_pipe_connect *pipe_connect;
+
+	pr_debug("%s: Resuming\n", __func__);
+
+	if (!ipa_params) {
+		pr_err("%s: Invalid ipa params\n", __func__);
+		return;
+	}
+
+	src_idx = ipa_params->src_idx;
+	dst_idx = ipa_params->dst_idx;
+
+	if (src_idx >= ctx.max_connections || dst_idx >= ctx.max_connections) {
+		pr_err("%s: Invalid connection index src=%d dst=%d\n",
+			__func__, src_idx, dst_idx);
+		return;
+	}
+
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+	if (cur_bam != HSUSB_BAM)
+		return;
+
+	info.in_lpm = false;
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.bus_suspend = 0;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	queue_work(ctx.usb_bam_wq, &info.resume_work);
+}
+
 int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	u8 idx;
@@ -800,27 +1248,38 @@
 	pipe_connect = &usb_bam_connections[idx];
 	cur_bam = pipe_connect->bam_type;
 
-	if (cur_bam == HSUSB_BAM) {
-		spin_lock(&usb_bam_lock);
-		sched_lpm = 0;
-		lpm_wait_handshake = 1;
-		spin_unlock(&usb_bam_lock);
-	}
-
 	if (pipe_connect->enabled) {
-		pr_debug("%s: connection %d was already established\n",
+		pr_err("%s: connection %d was already established\n",
 			__func__, idx);
 		return 0;
 	}
 
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+
 	spin_lock(&usb_bam_lock);
+	if (ctx.pipes_enabled_per_bam[cur_bam] == 0) {
+		spin_unlock(&usb_bam_lock);
+		if (cur_bam == HSUSB_BAM) {
+			spin_lock(&usb_bam_ipa_handshake_info_lock);
+			info.lpm_wait_handshake = 1;
+			info.connect_complete = 0;
+			info.lpm_wait_pipes = 1;
+			info.bus_suspend = 0;
+			info.cons_stopped = 0;
+			info.prod_stopped = 0;
+			spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		}
+		usb_bam_resume_core(cur_bam);
+	} else
+		spin_unlock(&usb_bam_lock);
 
 	 /* Check if BAM requires RESET before connect and reset first pipe */
+	 spin_lock(&usb_bam_lock);
 	 if ((pdata->reset_on_connect[cur_bam] == true) &&
 		 (ctx.pipes_enabled_per_bam[cur_bam] == 0))
 			sps_device_reset(ctx.h_bam[cur_bam]);
-
-	spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_lock);
 
 	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL) {
 		pr_debug("%s: Starting connect sequence\n", __func__);
@@ -830,23 +1289,19 @@
 	ret = connect_pipe_ipa(idx, ipa_params);
 	if (ret) {
 		pr_err("%s: pipe connection failure\n", __func__);
+		mutex_unlock(&info.suspend_resume_mutex);
 		return ret;
 	}
 
 	spin_lock(&usb_bam_lock);
-
 	pipe_connect->enabled = 1;
 	ctx.pipes_enabled_per_bam[cur_bam] += 1;
-
-	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB &&
-		cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED) {
-		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
-		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
-					 ipa_rm_resource_cons[cur_bam]);
-		pr_debug("%s: Ended connect sequence\n", __func__);
-	}
-
 	spin_unlock(&usb_bam_lock);
+	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB && cur_bam == HSUSB_BAM)
+		wait_for_cons_granted(cur_bam);
+
+	mutex_unlock(&info.suspend_resume_mutex);
+	pr_debug("%s: done", __func__);
 
 	return 0;
 }
@@ -904,6 +1359,14 @@
 			usb_bam_set_inactivity_timer(pipe_connect->bam_type);
 		spin_unlock(&usb_bam_lock);
 
+		/* A2 wakeup not from LPM (CONS was up) */
+		wait_for_prod_granted(pipe_connect->bam_type);
+		if (info.start) {
+			pr_debug("%s: Enqueue PROD transfer", __func__);
+			info.start(info.start_stop_param,
+					USB_TO_PEER_PERIPHERAL);
+		}
+
 		break;
 
 	case USB_BAM_EVENT_INACTIVITY:
@@ -1111,9 +1574,22 @@
 int usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
 	void *param)
 {
+	info.wake_cb = callback;
+	info.wake_param = param;
 	return __usb_bam_register_wake_cb(idx, callback, param, true);
 }
 
+int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param)
+{
+	info.start = start;
+	info.stop = stop;
+	info.start_stop_param = param;
+	return 0;
+}
+
 int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param)
 {
 	u32 ret = 0;
@@ -1156,78 +1632,29 @@
 		return 0;
 	}
 
-	spin_lock(&usb_bam_lock);
-
 	ret = disconnect_pipe(idx);
 	if (ret) {
 		pr_err("%s: src pipe disconnection failure\n", __func__);
-		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 0;
-
+	spin_lock(&usb_bam_lock);
 	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0)
 		pr_err("%s: wrong pipes enabled counter for bam_type=%d\n",
 			__func__, pipe_connect->bam_type);
 	else
 		ctx.pipes_enabled_per_bam[pipe_connect->bam_type] -= 1;
-
 	spin_unlock(&usb_bam_lock);
 
 	return 0;
 }
 
-static void usb_bam_start_lpm(void)
-{
-	struct usb_phy *trans = usb_get_transceiver();
-	BUG_ON(trans == NULL);
-	spin_lock(&usb_bam_lock);
-	lpm_wait_handshake = 0;
-	if (sched_lpm) {
-		pr_debug("%s: Going to LPM\n", __func__);
-		spin_unlock(&usb_bam_lock);
-		pm_runtime_resume(trans->dev);
-		pm_runtime_put_noidle(trans->dev);
-		pm_runtime_suspend(trans->dev);
-		return;
-	}
-	spin_unlock(&usb_bam_lock);
-}
-
-static void wait_for_prod_release(enum usb_bam cur_bam)
-{
-	int ret;
-
-	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
-		pr_debug("%s consumer already released\n", __func__);
-	 if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
-		pr_debug("%s producer already released\n", __func__);
-
-	init_completion(&prod_released[cur_bam]);
-	init_completion(&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]);
-	if (!ret) {
-		pr_debug("%s: Released without waiting\n", __func__);
-		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-		complete_all(&prod_released[cur_bam]);
-	} else if (ret == -EINPROGRESS) {
-		pr_debug("%s: Waiting for PROD_RELEASED\n", __func__);
-		if (!wait_for_completion_timeout(&prod_released[cur_bam],
-						USB_BAM_TIMEOUT))
-			pr_err("%s: Timeout waiting for PROD_RELEASED\n",
-			__func__);
-	} else
-		pr_err("%s: ipa_rm_request_resource ret =%d", __func__, ret);
-}
-
 static void wait_for_cons_release(enum usb_bam cur_bam)
 {
 	 pr_debug("%s: Waiting for CONS release\n", __func__);
-	 if (cur_prod_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
-		if (!wait_for_completion_timeout(&cons_released[cur_bam],
+	 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__);
@@ -1244,13 +1671,17 @@
 	struct sps_connect *sps_connection;
 	enum usb_bam cur_bam;
 
-
 	if (!ipa_params->prod_clnt_hdl && !ipa_params->cons_clnt_hdl) {
 		pr_err("%s: Both of the handles is missing\n", __func__);
 		return -EINVAL;
 	}
 
 	pr_debug("%s: Starting disconnect sequence\n", __func__);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.connect_complete = 0;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	mutex_lock(&info.suspend_resume_mutex);
 	/* Delay USB core to go into lpm before we finish our handshake */
 	if (ipa_params->prod_clnt_hdl) {
 		idx = ipa_params->dst_idx;
@@ -1258,12 +1689,15 @@
 
 		/* Do the release handshake with the A2 via RM */
 		cur_bam = pipe_connect->bam_type;
+		info.lpm_wait_pipes = 1;
 		wait_for_prod_release(cur_bam);
 		/* close USB -> IPA pipe */
+		usb_bam_resume_core(cur_bam);
 		ret = ipa_disconnect(ipa_params->prod_clnt_hdl);
 		if (ret) {
 			pr_err("%s: dst pipe disconnection failure\n",
 				__func__);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 		sps_connection = &ctx.usb_bam_sps.sps_connections[idx];
@@ -1274,6 +1708,7 @@
 		if (ret) {
 			pr_err("%s: failure to disconnect pipe %d\n",
 				__func__, idx);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 	}
@@ -1288,6 +1723,7 @@
 		if (ret) {
 			pr_err("%s: src pipe disconnection failure\n",
 				__func__);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 
@@ -1299,17 +1735,24 @@
 		if (ret) {
 			pr_err("%s: failure to disconnect pipe %d\n",
 				__func__, idx);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
-		pr_debug("%s: Notify CONS release\n", __func__);
 
-		if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pipe_connect->ipa_clnt_hdl = -1;
+
+		if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED) {
+			pr_debug("%s Notify CONS _RELEASED\n", __func__);
 			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
 				ipa_rm_resource_cons[cur_bam]);
+		}
 		pr_debug("%s Ended disconnect sequence\n", __func__);
-		usb_bam_start_lpm();
+		mutex_unlock(&info.suspend_resume_mutex);
+		usb_bam_start_lpm(1);
+		return 0;
 	}
 
+	mutex_unlock(&info.suspend_resume_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(usb_bam_disconnect_ipa);
@@ -1810,18 +2253,23 @@
 		ctx.pipes_enabled_per_bam[i] = 0;
 		ctx.inactivity_timer_ms[i] = 0;
 		ctx.is_bam_inactivity[i] = false;
-		init_completion(&prod_avail[i]);
-		complete(&prod_avail[i]);
-		init_completion(&cons_avail[i]);
-		complete(&cons_avail[i]);
-		init_completion(&cons_released[i]);
-		complete(&cons_released[i]);
-		init_completion(&prod_released[i]);
-		complete(&prod_released[i]);
-		cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
-		cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
+		init_completion(&info.prod_avail[i]);
+		complete(&info.prod_avail[i]);
+		init_completion(&info.cons_avail[i]);
+		complete(&info.cons_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;
+		info.cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
 	}
 
+	INIT_WORK(&info.resume_work, usb_bam_finish_resume);
+	INIT_WORK(&info.suspend_work, usb_bam_start_suspend);
+	INIT_WORK(&info.finish_suspend_work, usb_bam_finish_suspend_);
+	mutex_init(&info.suspend_resume_mutex);
+
 	spin_lock_init(&usb_bam_peer_handshake_info_lock);
 	INIT_WORK(&peer_handshake_info.reset_event.event_w, usb_bam_sm_work);
 
@@ -1837,8 +2285,8 @@
 		destroy_workqueue(ctx.usb_bam_wq);
 		return ret;
 	}
+	spin_lock_init(&usb_bam_ipa_handshake_info_lock);
 	usb_bam_ipa_create_resources();
-
 	spin_lock_init(&usb_bam_lock);
 
 	return ret;
@@ -1911,14 +2359,14 @@
 
 bool msm_bam_lpm_ok(void)
 {
-	spin_lock(&usb_bam_lock);
-	if (lpm_wait_handshake) {
-		sched_lpm = 1;
-		spin_unlock(&usb_bam_lock);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (info.lpm_wait_handshake || info.lpm_wait_pipes) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Scheduling LPM for later\n", __func__);
 		return 0;
 	} else {
-		spin_unlock(&usb_bam_lock);
+		info.in_lpm = 1;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Going to LPM now\n", __func__);
 		return 1;
 	}
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index eac8953..9a642d6 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -2503,6 +2503,8 @@
 		batt_data = &palladium_1500_data;
 	} else if (chip->batt_type == BATT_OEM) {
 		batt_data = &oem_batt_data;
+	} else if (chip->batt_type == BATT_QRD_4V35_2000MAH) {
+		batt_data = &QRD_4v35_2000mAh_data;
 	} else {
 		battery_id = read_battery_id(chip);
 		if (battery_id < 0) {
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 3d8a75d..624a42f 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -91,6 +91,7 @@
 #define BUCK_TEST_SMBC_MODES			0xE6
 #define SEC_ACCESS				0xD0
 #define BAT_IF_VREF_BAT_THM_CTRL		0x4A
+#define BAT_IF_BPD_CTRL				0x48
 
 #define REG_OFFSET_PERP_SUBTYPE			0x05
 /* SMBB peripheral subtype values */
@@ -126,7 +127,11 @@
 #define USB_VALID_DEB_20MS		0x03
 #define BUCK_VBAT_REG_NODE_SEL_BIT	BIT(0)
 #define VREF_BATT_THERM_FORCE_ON	0xC0
+#define BAT_IF_BPD_CTRL_SEL		0x03
 #define VREF_BAT_THM_ENABLED_FSM	0x80
+#define REV_BST_DETECTED		BIT(0)
+#define BAT_THM_EN			BIT(1)
+#define BAT_ID_EN			BIT(0)
 
 /* Interrupt definitions */
 /* smbb_chg_interrupts */
@@ -179,6 +184,11 @@
 /* Workaround flags */
 #define CHG_FLAGS_VCP_WA		BIT(0)
 
+struct qpnp_chg_irq {
+	unsigned int		irq;
+	unsigned long		disabled;
+};
+
 /**
  * struct qpnp_chg_chip - device information
  * @dev:			device pointer to access the parent
@@ -237,14 +247,14 @@
 	u16				boost_base;
 	u16				misc_base;
 	u16				freq_base;
-	unsigned int			usbin_valid_irq;
-	unsigned int			dcin_valid_irq;
-	unsigned int			chg_gone_irq;
-	unsigned int			chg_fastchg_irq;
-	unsigned int			chg_trklchg_irq;
-	unsigned int			chg_failed_irq;
-	unsigned int			chg_vbatdet_lo_irq;
-	unsigned int			batt_pres_irq;
+	struct qpnp_chg_irq		usbin_valid;
+	struct qpnp_chg_irq		dcin_valid;
+	struct qpnp_chg_irq		chg_gone;
+	struct qpnp_chg_irq		chg_fastchg;
+	struct qpnp_chg_irq		chg_trklchg;
+	struct qpnp_chg_irq		chg_failed;
+	struct qpnp_chg_irq		chg_vbatdet_lo;
+	struct qpnp_chg_irq		batt_pres;
 	bool				bat_is_cool;
 	bool				bat_is_warm;
 	bool				chg_done;
@@ -253,6 +263,7 @@
 	bool				batt_present;
 	bool				charging_disabled;
 	bool				use_default_batt_values;
+	unsigned int			bpd_detection;
 	unsigned int			max_bat_chg_current;
 	unsigned int			warm_bat_chg_ma;
 	unsigned int			cool_bat_chg_ma;
@@ -286,11 +297,31 @@
 	struct wake_lock		eoc_wake_lock;
 };
 
+
 static struct of_device_id qpnp_charger_match_table[] = {
 	{ .compatible = QPNP_CHARGER_DEV_NAME, },
 	{}
 };
 
+#define BPD_MAX		3
+
+static const char *bpd_list[BPD_MAX] = {
+	"bpd_thm",
+	"bpd_id",
+	"bpd_thm_id",
+};
+
+static inline int
+get_bpd(const char *name)
+{
+	int i = 0;
+	for (i = 0 ; i < BPD_MAX; i++) {
+		if (strcmp(name, bpd_list[i]) == 0)
+			return i;
+	}
+	return -EINVAL;
+}
+
 static int
 qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
 			u16 base, int count)
@@ -354,6 +385,24 @@
 	return 0;
 }
 
+static void
+qpnp_chg_enable_irq(struct qpnp_chg_irq *irq)
+{
+	if (__test_and_clear_bit(0, &irq->disabled)) {
+		pr_debug("number = %d\n", irq->irq);
+		enable_irq(irq->irq);
+	}
+}
+
+static void
+qpnp_chg_disable_irq(struct qpnp_chg_irq *irq)
+{
+	if (!__test_and_set_bit(0, &irq->disabled)) {
+		pr_debug("number = %d\n", irq->irq);
+		disable_irq_nosync(irq->irq);
+	}
+}
+
 #define USB_OTG_EN_BIT	BIT(0)
 static int
 qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
@@ -649,14 +698,16 @@
 		schedule_delayed_work(&chip->eoc_work,
 			msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
 		wake_lock(&chip->eoc_wake_lock);
-		disable_irq_nosync(chip->chg_vbatdet_lo_irq);
+		qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
 	} else {
 		qpnp_chg_charge_en(chip, !chip->charging_disabled);
 	}
 
 	power_supply_changed(chip->usb_psy);
-	power_supply_changed(&chip->dc_psy);
-	power_supply_changed(&chip->batt_psy);
+	if (chip->dc_chgpth_base)
+		power_supply_changed(&chip->dc_psy);
+	if (chip->bat_if_base)
+		power_supply_changed(&chip->batt_psy);
 	return IRQ_HANDLED;
 }
 
@@ -771,9 +822,11 @@
 	if (rc)
 		pr_err("Failed to write chg_fail clear bit!\n");
 
-	power_supply_changed(&chip->batt_psy);
+	if (chip->bat_if_base)
+		power_supply_changed(&chip->batt_psy);
 	power_supply_changed(chip->usb_psy);
-	power_supply_changed(&chip->dc_psy);
+	if (chip->dc_chgpth_base)
+		power_supply_changed(&chip->dc_psy);
 	return IRQ_HANDLED;
 }
 
@@ -785,7 +838,8 @@
 	pr_debug("TRKL IRQ triggered\n");
 
 	chip->chg_done = false;
-	power_supply_changed(&chip->batt_psy);
+	if (chip->bat_if_base)
+		power_supply_changed(&chip->batt_psy);
 
 	return IRQ_HANDLED;
 }
@@ -797,10 +851,12 @@
 
 	pr_debug("FAST_CHG IRQ triggered\n");
 	chip->chg_done = false;
-	power_supply_changed(&chip->batt_psy);
+	if (chip->bat_if_base)
+		power_supply_changed(&chip->batt_psy);
 	power_supply_changed(chip->usb_psy);
-	power_supply_changed(&chip->dc_psy);
-	enable_irq(chip->chg_vbatdet_lo_irq);
+	if (chip->dc_chgpth_base)
+		power_supply_changed(&chip->dc_psy);
+	qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
 
 	return IRQ_HANDLED;
 }
@@ -1523,7 +1579,7 @@
 				qpnp_chg_charge_en(chip, 0);
 				chip->chg_done = true;
 				power_supply_changed(&chip->batt_psy);
-				enable_irq(chip->chg_vbatdet_lo_irq);
+				qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
 				goto stop_eoc;
 			} else {
 				count += 1;
@@ -1532,7 +1588,7 @@
 		} else if ((!(chg_sts & VBAT_DET_LOW_IRQ)) && (vbat_mv <
 			(chip->max_voltage_mv - chip->resume_delta_mv))) {
 			pr_debug("woke up too early\n");
-			enable_irq(chip->chg_vbatdet_lo_irq);
+			qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
 			goto stop_eoc;
 		}
 	} else {
@@ -1689,157 +1745,157 @@
 		case SMBB_CHGR_SUBTYPE:
 		case SMBBP_CHGR_SUBTYPE:
 		case SMBCL_CHGR_SUBTYPE:
-			chip->chg_fastchg_irq = spmi_get_irq_byname(spmi,
+			chip->chg_fastchg.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "fast-chg-on");
-			if (chip->chg_fastchg_irq < 0) {
+			if (chip->chg_fastchg.irq < 0) {
 				pr_err("Unable to get fast-chg-on irq\n");
 				return rc;
 			}
 
-			chip->chg_trklchg_irq = spmi_get_irq_byname(spmi,
+			chip->chg_trklchg.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "trkl-chg-on");
-			if (chip->chg_trklchg_irq < 0) {
+			if (chip->chg_trklchg.irq < 0) {
 				pr_err("Unable to get trkl-chg-on irq\n");
 				return rc;
 			}
 
-			chip->chg_failed_irq = spmi_get_irq_byname(spmi,
+			chip->chg_failed.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "chg-failed");
-			if (chip->chg_failed_irq < 0) {
+			if (chip->chg_failed.irq < 0) {
 				pr_err("Unable to get chg_failed irq\n");
 				return rc;
 			}
 
-			chip->chg_vbatdet_lo_irq = spmi_get_irq_byname(spmi,
+			chip->chg_vbatdet_lo.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "vbat-det-lo");
-			if (chip->chg_vbatdet_lo_irq < 0) {
+			if (chip->chg_vbatdet_lo.irq < 0) {
 				pr_err("Unable to get fast-chg-on irq\n");
 				return rc;
 			}
 
-			rc |= devm_request_irq(chip->dev, chip->chg_failed_irq,
+			rc |= devm_request_irq(chip->dev, chip->chg_failed.irq,
 				qpnp_chg_chgr_chg_failed_irq_handler,
 				IRQF_TRIGGER_RISING, "chg-failed", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d chg-failed: %d\n",
-						chip->chg_failed_irq, rc);
+						chip->chg_failed.irq, rc);
 				return rc;
 			}
 
-			rc |= devm_request_irq(chip->dev, chip->chg_fastchg_irq,
+			rc |= devm_request_irq(chip->dev, chip->chg_fastchg.irq,
 					qpnp_chg_chgr_chg_fastchg_irq_handler,
 					IRQF_TRIGGER_RISING,
 					"fast-chg-on", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d fast-chg-on: %d\n",
-						chip->chg_fastchg_irq, rc);
+						chip->chg_fastchg.irq, rc);
 				return rc;
 			}
 
-			rc |= devm_request_irq(chip->dev, chip->chg_trklchg_irq,
+			rc |= devm_request_irq(chip->dev, chip->chg_trklchg.irq,
 				qpnp_chg_chgr_chg_trklchg_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				"trkl-chg-on", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d trkl-chg-on: %d\n",
-						chip->chg_trklchg_irq, rc);
+						chip->chg_trklchg.irq, rc);
 				return rc;
 			}
 
 			rc |= devm_request_irq(chip->dev,
-				chip->chg_vbatdet_lo_irq,
+				chip->chg_vbatdet_lo.irq,
 				qpnp_chg_vbatdet_lo_irq_handler,
 				IRQF_TRIGGER_RISING,
 				"vbat-det-lo", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d vbat-det-lo: %d\n",
-						chip->chg_vbatdet_lo_irq, rc);
+						chip->chg_vbatdet_lo.irq, rc);
 				return rc;
 			}
 
-			enable_irq_wake(chip->chg_fastchg_irq);
-			enable_irq_wake(chip->chg_trklchg_irq);
-			enable_irq_wake(chip->chg_failed_irq);
-			disable_irq_nosync(chip->chg_vbatdet_lo_irq);
-			enable_irq_wake(chip->chg_vbatdet_lo_irq);
+			enable_irq_wake(chip->chg_trklchg.irq);
+			enable_irq_wake(chip->chg_failed.irq);
+			qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
+			enable_irq_wake(chip->chg_vbatdet_lo.irq);
 
 			break;
 		case SMBB_BAT_IF_SUBTYPE:
 		case SMBBP_BAT_IF_SUBTYPE:
 		case SMBCL_BAT_IF_SUBTYPE:
-			chip->batt_pres_irq = spmi_get_irq_byname(spmi,
+			chip->batt_pres.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "batt-pres");
-			if (chip->batt_pres_irq < 0) {
+			if (chip->batt_pres.irq < 0) {
 				pr_err("Unable to get batt-pres irq\n");
 				return rc;
 			}
-			rc = devm_request_irq(chip->dev, chip->batt_pres_irq,
+			rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
 				qpnp_chg_bat_if_batt_pres_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				"batt-pres", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d batt-pres irq: %d\n",
-						chip->batt_pres_irq, rc);
+						chip->batt_pres.irq, rc);
 				return rc;
 			}
 
-			enable_irq_wake(chip->batt_pres_irq);
+			enable_irq_wake(chip->batt_pres.irq);
 			break;
 		case SMBB_USB_CHGPTH_SUBTYPE:
 		case SMBBP_USB_CHGPTH_SUBTYPE:
 		case SMBCL_USB_CHGPTH_SUBTYPE:
-			chip->usbin_valid_irq = spmi_get_irq_byname(spmi,
+			chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "usbin-valid");
-			if (chip->usbin_valid_irq < 0) {
+			if (chip->usbin_valid.irq < 0) {
 				pr_err("Unable to get usbin irq\n");
 				return rc;
 			}
-			rc = devm_request_irq(chip->dev, chip->usbin_valid_irq,
+			rc = devm_request_irq(chip->dev, chip->usbin_valid.irq,
 				qpnp_chg_usb_usbin_valid_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 					"usbin-valid", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d usbin-valid: %d\n",
-						chip->usbin_valid_irq, rc);
+						chip->usbin_valid.irq, rc);
 				return rc;
 			}
 
-			chip->chg_gone_irq = spmi_get_irq_byname(spmi,
+			chip->chg_gone.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "chg-gone");
-			if (chip->chg_gone_irq < 0) {
+			if (chip->chg_gone.irq < 0) {
 				pr_err("Unable to get chg-gone irq\n");
 				return rc;
 			}
-			rc = devm_request_irq(chip->dev, chip->chg_gone_irq,
+			rc = devm_request_irq(chip->dev, chip->chg_gone.irq,
 				qpnp_chg_usb_chg_gone_irq_handler,
 				IRQF_TRIGGER_RISING,
 					"chg-gone", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d chg-gone: %d\n",
-						chip->chg_gone_irq, rc);
+						chip->chg_gone.irq, rc);
 				return rc;
 			}
-			enable_irq_wake(chip->usbin_valid_irq);
-			enable_irq_wake(chip->chg_gone_irq);
+
+			enable_irq_wake(chip->usbin_valid.irq);
+			enable_irq_wake(chip->chg_gone.irq);
 			break;
 		case SMBB_DC_CHGPTH_SUBTYPE:
-			chip->dcin_valid_irq = spmi_get_irq_byname(spmi,
+			chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
 					spmi_resource, "dcin-valid");
-			if (chip->dcin_valid_irq < 0) {
+			if (chip->dcin_valid.irq < 0) {
 				pr_err("Unable to get dcin irq\n");
 				return -rc;
 			}
-			rc = devm_request_irq(chip->dev, chip->dcin_valid_irq,
+			rc = devm_request_irq(chip->dev, chip->dcin_valid.irq,
 				qpnp_chg_dc_dcin_valid_irq_handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				"dcin-valid", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d dcin-valid: %d\n",
-						chip->dcin_valid_irq, rc);
+						chip->dcin_valid.irq, rc);
 				return rc;
 			}
 
-			enable_irq_wake(chip->dcin_valid_irq);
+			enable_irq_wake(chip->dcin_valid.irq);
 			break;
 		}
 	}
@@ -1853,7 +1909,7 @@
 				struct spmi_resource *spmi_resource)
 {
 	int rc = 0;
-	u8 reg;
+	u8 reg = 0;
 
 	switch (subtype) {
 	case SMBB_CHGR_SUBTYPE:
@@ -1932,6 +1988,20 @@
 	case SMBB_BAT_IF_SUBTYPE:
 	case SMBBP_BAT_IF_SUBTYPE:
 	case SMBCL_BAT_IF_SUBTYPE:
+		/* Select battery presence detection */
+		if (chip->bpd_detection == 1)
+			reg = BAT_ID_EN;
+		else if (chip->bpd_detection == 2)
+			reg = BAT_ID_EN | BAT_THM_EN;
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->bat_if_base + BAT_IF_BPD_CTRL,
+			BAT_IF_BPD_CTRL_SEL,
+			reg, 1);
+		if (rc) {
+			pr_debug("failed to chose BPD rc=%d\n", rc);
+			return rc;
+		}
 		/* Force on VREF_BAT_THM */
 		rc = qpnp_chg_masked_write(chip,
 			chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
@@ -2031,6 +2101,7 @@
 qpnp_charger_read_dt_props(struct qpnp_chg_chip *chip)
 {
 	int rc = 0;
+	const char *bpd;
 
 	OF_PROP_READ(chip, max_voltage_mv, "vddmax-mv", rc, 0);
 	OF_PROP_READ(chip, min_voltage_mv, "vinmin-mv", rc, 0);
@@ -2050,6 +2121,18 @@
 	if (rc)
 		return rc;
 
+	rc = of_property_read_string(chip->spmi->dev.of_node,
+		"qcom,bpd-detection", &bpd);
+	if (rc) {
+		pr_debug("no bpd-detection specified, ignored\n");
+	} else {
+		chip->bpd_detection = get_bpd(bpd);
+		if (chip->bpd_detection < 0) {
+			pr_err("failed to determine bpd schema %d\n", rc);
+			return rc;
+		}
+	}
+
 	/* Look up JEITA compliance parameters if cool and warm temp provided */
 	if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
 		rc = qpnp_adc_tm_is_ready();
@@ -2361,8 +2444,9 @@
 	if (qpnp_chg_is_usb_chg_plugged_in(chip))
 		power_supply_set_online(chip->usb_psy, 1);
 
-	pr_info("success chg_dis = %d, usb = %d, dc = %d b_health = %d batt_present = %d\n",
+	pr_info("success chg_dis = %d, bpd = %d, usb = %d, dc = %d b_health = %d batt_present = %d\n",
 			chip->charging_disabled,
+			chip->bpd_detection,
 			qpnp_chg_is_usb_chg_plugged_in(chip),
 			qpnp_chg_is_dc_chg_plugged_in(chip),
 			get_prop_batt_present(chip),
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 814817b..ab59864 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -596,7 +596,14 @@
 		pr_info("%s: Max frequency reset for cpu%d\n",
 				KBUILD_MODNAME, cpu);
 
-	ret = cpufreq_update_policy(cpu);
+	if (cpu_online(cpu)) {
+		struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+		if (!policy)
+			return ret;
+		ret = cpufreq_driver_target(policy, policy->cur,
+				CPUFREQ_RELATION_H);
+		cpufreq_cpu_put(policy);
+	}
 
 	return ret;
 }
@@ -748,14 +755,56 @@
 	return ret;
 }
 
+static void __cpuinit do_freq_control(long temp)
+{
+	int ret = 0;
+	int cpu = 0;
+	uint32_t max_freq = limited_max_freq;
+
+	if (temp >= msm_thermal_info.limit_temp_degC) {
+		if (limit_idx == limit_idx_low)
+			return;
+
+		limit_idx -= msm_thermal_info.freq_step;
+		if (limit_idx < limit_idx_low)
+			limit_idx = limit_idx_low;
+		max_freq = table[limit_idx].frequency;
+	} else if (temp < msm_thermal_info.limit_temp_degC -
+		 msm_thermal_info.temp_hysteresis_degC) {
+		if (limit_idx == limit_idx_high)
+			return;
+
+		limit_idx += msm_thermal_info.freq_step;
+		if (limit_idx >= limit_idx_high) {
+			limit_idx = limit_idx_high;
+			max_freq = MSM_CPUFREQ_NO_LIMIT;
+		} else
+			max_freq = table[limit_idx].frequency;
+	}
+
+	if (max_freq == limited_max_freq)
+		return;
+
+	/* Update new limits */
+	for_each_possible_cpu(cpu) {
+		if (!(msm_thermal_info.freq_control_mask & BIT(cpu)))
+			continue;
+		ret = update_cpu_max_freq(cpu, max_freq);
+		if (ret)
+			pr_debug(
+			"%s: Unable to limit cpu%d max freq to %d\n",
+					KBUILD_MODNAME, cpu, max_freq);
+	}
+
+}
+
 static void __cpuinit check_temp(struct work_struct *work)
 {
 	static int limit_init;
 	struct tsens_device tsens_dev;
 	long temp = 0;
-	uint32_t max_freq = limited_max_freq;
-	int cpu = 0;
 	int ret = 0;
+
 	tsens_dev.sensor_num = msm_thermal_info.sensor_id;
 	ret = tsens_get_temp(&tsens_dev, &temp);
 	if (ret) {
@@ -775,38 +824,7 @@
 	do_core_control(temp);
 	do_vdd_restriction();
 	do_psm();
-
-	if (temp >= msm_thermal_info.limit_temp_degC) {
-		if (limit_idx == limit_idx_low)
-			goto reschedule;
-
-		limit_idx -= msm_thermal_info.freq_step;
-		if (limit_idx < limit_idx_low)
-			limit_idx = limit_idx_low;
-		max_freq = table[limit_idx].frequency;
-	} else if (temp < msm_thermal_info.limit_temp_degC -
-		 msm_thermal_info.temp_hysteresis_degC) {
-		if (limit_idx == limit_idx_high)
-			goto reschedule;
-
-		limit_idx += msm_thermal_info.freq_step;
-		if (limit_idx >= limit_idx_high) {
-			limit_idx = limit_idx_high;
-			max_freq = MSM_CPUFREQ_NO_LIMIT;
-		} else
-			max_freq = table[limit_idx].frequency;
-	}
-	if (max_freq == limited_max_freq)
-		goto reschedule;
-
-	/* Update new limits */
-	for_each_possible_cpu(cpu) {
-		ret = update_cpu_max_freq(cpu, max_freq);
-		if (ret)
-			pr_debug(
-			"%s: Unable to limit cpu%d max freq to %d\n",
-					KBUILD_MODNAME, cpu, max_freq);
-	}
+	do_freq_control(temp);
 
 reschedule:
 	if (enabled)
@@ -1599,6 +1617,9 @@
 	if (ret)
 		goto fail;
 
+	key = "qcom,freq-control-mask";
+	ret = of_property_read_u32(node, key, &data.freq_control_mask);
+
 	key = "qcom,core-limit-temp";
 	ret = of_property_read_u32(node, key, &data.core_limit_temp_degC);
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c08a259..1059a4d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1706,6 +1706,7 @@
 	int			ret = 0;
 	u32			reg;
 
+	pm_runtime_get_sync(dwc->dev);
 	spin_lock_irqsave(&dwc->lock, flags);
 
 	if (dwc->gadget_driver) {
@@ -1765,6 +1766,7 @@
 	dwc3_ep0_out_start(dwc);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
+	pm_runtime_put(dwc->dev);
 
 	return 0;
 
@@ -1773,6 +1775,7 @@
 
 err0:
 	spin_unlock_irqrestore(&dwc->lock, flags);
+	pm_runtime_put(dwc->dev);
 
 	return ret;
 }
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 38f08fc..80e9e87 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2325,7 +2325,7 @@
 
 	/*stop charging upon reset */
 	if (udc->transceiver)
-		usb_phy_set_power(udc->transceiver, 0);
+		usb_phy_set_power(udc->transceiver, 100);
 
 	retval = _gadget_stop_activity(&udc->gadget);
 	if (retval)
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index c05f683..b71f903 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -539,9 +539,12 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
-	if (!port->port_usb)
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
+	}
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
@@ -552,14 +555,69 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
-	if (!port->port_usb)
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
+	}
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
 }
 
+static void gbam_stop_endless_rx(struct gbam_port *port)
+{
+	struct bam_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
+		return;
+	}
+	pr_debug("%s: dequeue\n", __func__);
+
+	status = usb_ep_dequeue(port->port_usb->out, d->rx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+
+}
+static void gbam_stop_endless_tx(struct gbam_port *port)
+{
+	struct bam_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
+		return;
+	}
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->in, d->tx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+}
+
+static void gbam_start(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct gbam_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		gbam_start_endless_rx(port);
+	else
+		gbam_start_endless_tx(port);
+}
+
+static void gbam_stop(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct gbam_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		gbam_stop_endless_rx(port);
+	else
+		gbam_stop_endless_tx(port);
+}
+
 static void gbam_start_io(struct gbam_port *port)
 {
 	unsigned long		flags;
@@ -1409,6 +1467,10 @@
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 
 	usb_bam_register_wake_cb(d->dst_connection_idx, gbam_wake_cb, port);
+	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(gbam_start, gbam_stop, port);
+		usb_bam_suspend(&d->ipa_params);
+	}
 }
 
 void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans)
@@ -1426,4 +1488,6 @@
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 
 	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
+	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+		usb_bam_resume(&d->ipa_params);
 }
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 2abe2ef..081a09c 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -92,6 +92,7 @@
 	if (!port->port_usb)
 		return;
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
@@ -105,11 +106,40 @@
 	if (!port->port_usb)
 		return;
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
 }
 
+static void bam_data_stop_endless_rx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb)
+		return;
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->out, d->rx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+
+}
+static void bam_data_stop_endless_tx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb)
+		return;
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->in, d->tx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+}
+
 static int bam_data_peer_reset_cb(void *param)
 {
 	struct bam_data_port	*port = (struct bam_data_port *)param;
@@ -529,9 +559,28 @@
 	return usb_gadget_wakeup(d_port->cdev->gadget);
 }
 
+static void bam_data_start(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct bam_data_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		bam_data_start_endless_rx(port);
+	else
+		bam_data_start_endless_tx(port);
+}
+
+static void bam_data_stop(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct bam_data_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		bam_data_stop_endless_rx(port);
+	else
+		bam_data_stop_endless_tx(port);
+}
+
 void bam_data_suspend(u8 port_num)
 {
-
 	struct bam_data_port	*port;
 	struct bam_data_ch_info *d;
 
@@ -540,6 +589,11 @@
 
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->dst_connection_idx, bam_data_wake_cb, port);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(bam_data_start, bam_data_stop,
+									port);
+		usb_bam_suspend(&d->ipa_params);
+	}
 }
 
 void bam_data_resume(u8 port_num)
@@ -553,5 +607,6 @@
 
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+		usb_bam_resume(&d->ipa_params);
 }
-
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index ede8bdb..d1d0f91 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -2180,7 +2180,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int msm_hsic_pm_suspend(struct device *dev)
 {
-	int ret;
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
 
@@ -2188,15 +2187,16 @@
 
 	dbg_log_event(NULL, "PM Suspend", 0);
 
+	if (!atomic_read(&mehci->in_lpm)) {
+		dev_info(dev, "abort suspend\n");
+		dbg_log_event(NULL, "PM Suspend abort", 0);
+		return -EBUSY;
+	}
+
 	if (device_may_wakeup(dev) && !mehci->async_irq)
 		enable_irq_wake(hcd->irq);
 
-	ret = msm_hsic_suspend(mehci);
-
-	if (ret && device_may_wakeup(dev) && !mehci->async_irq)
-		disable_irq_wake(hcd->irq);
-
-	return ret;
+	return 0;
 }
 
 static int msm_hsic_pm_suspend_noirq(struct device *dev)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index d4d7ee9..44a7aee 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -861,7 +861,7 @@
 	struct usb_bus *bus = phy->otg->host;
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	int cnt = 0;
-	bool host_bus_suspend, device_bus_suspend, dcp;
+	bool host_bus_suspend, device_bus_suspend, dcp, prop_charger;
 	u32 phy_ctrl_val = 0, cmd_val;
 	unsigned ret;
 	u32 portsc;
@@ -870,7 +870,7 @@
 		return 0;
 
 	if (motg->pdata->delay_lpm_hndshk_on_disconnect && !msm_bam_lpm_ok())
-		return 0;
+		return -EBUSY;
 
 	disable_irq(motg->irq);
 	host_bus_suspend = !test_bit(MHL, &motg->inputs) && phy->otg->host &&
@@ -879,6 +879,7 @@
 		test_bit(A_BUS_SUSPEND, &motg->inputs) &&
 		motg->caps & ALLOW_LPM_ON_DEV_SUSPEND;
 	dcp = motg->chg_type == USB_DCP_CHARGER;
+	prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
 
 	/*
 	 * Abort suspend when,
@@ -887,7 +888,7 @@
 	 */
 
 	if ((test_bit(B_SESS_VLD, &motg->inputs) && !device_bus_suspend &&
-		!dcp) || test_bit(A_BUS_REQ, &motg->inputs)) {
+		!dcp && !prop_charger) || test_bit(A_BUS_REQ, &motg->inputs)) {
 		enable_irq(motg->irq);
 		return -EBUSY;
 	}
@@ -955,7 +956,7 @@
 	 */
 	cmd_val = readl_relaxed(USB_USBCMD);
 	if (host_bus_suspend || device_bus_suspend ||
-		(motg->pdata->otg_control == OTG_PHY_CONTROL && dcp))
+		(motg->pdata->otg_control == OTG_PHY_CONTROL))
 		cmd_val |= ASYNC_INTR_CTRL | ULPI_STP_CTRL;
 	else
 		cmd_val |= ULPI_STP_CTRL;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 3d990c2..b5134a7 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -24,6 +24,7 @@
 #include "mdp3.h"
 #include "mdp3_ppp.h"
 
+#define MDP_CORE_CLK_RATE	100000000
 #define MDP_VSYNC_CLK_RATE	19200000
 #define VSYNC_PERIOD 16
 
@@ -240,17 +241,8 @@
 {
 	int rc = 0;
 	if (status) {
-		struct mdss_panel_info *panel_info = mfd->panel_info;
-		unsigned long core_clk;
-		int vtotal;
-		vtotal = panel_info->lcdc.v_back_porch +
-			panel_info->lcdc.v_front_porch +
-			panel_info->lcdc.v_pulse_width +
-			panel_info->yres;
-		core_clk = panel_info->xres * panel_info->yres;
-		core_clk *= panel_info->mipi.frame_rate;
-		core_clk = (core_clk / panel_info->yres) * vtotal;
-		mdp3_clk_set_rate(MDP3_CLK_CORE, core_clk);
+
+		mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE);
 		mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE);
 
 		rc = mdp3_clk_enable(true);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index a09f503..fa2e9eb 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -218,7 +218,7 @@
 	 * NOTE: MDP_DMA_P_FETCH_CFG: max_burst_size need to use value 4, not
 	 * the default 16 for MDP hang issue workaround
 	 */
-	MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x10);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x20);
 	MDP3_REG_WRITE(MDP3_REG_PRIMARY_RD_PTR_IRQ, 0x10);
 
 	dma->source_config = *source_config;
@@ -809,6 +809,7 @@
 		temp |= BIT(2);
 	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_CTL_POLARITY, temp);
 
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_UNDERFLOW_CTL, 0x800000ff);
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index f726e79..1f0efd3 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -287,7 +287,7 @@
 	timeout_count = 100;
 	keys_state = (link0_status >> 28) & 0x7;
 	while ((keys_state != HDCP_KEYS_STATE_VALID) &&
-		timeout_count--) {
+		--timeout_count) {
 		link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
 		keys_state = (link0_status >> 28) & 0x7;
 		DEV_DBG("%s: %s: Keys not ready(%d). s=%d\n, l0=%0x08x",
@@ -320,7 +320,7 @@
 				link0_status);
 			msleep(20);
 		}
-	} while (!an_ready && timeout_count--);
+	} while (!an_ready && --timeout_count);
 
 	if (!timeout_count) {
 		rc = -ETIMEDOUT;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index aa1eba5..ce9e5b9 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -195,7 +195,7 @@
 	/* write pointer offset in bytes */
 	unsigned int write_offset;
 
-	/* non-zero if data error occured */
+	/* non-zero if data error occurred */
 	int error;
 };
 
@@ -237,7 +237,10 @@
 	 * (dmx_sct_filter_params) and no sections were
 	 * received for the given time.
 	 */
-	DMX_EVENT_SECTION_TIMEOUT = 0x00000400
+	DMX_EVENT_SECTION_TIMEOUT = 0x00000400,
+
+	/* Scrambling bits change between clear and scrambled */
+	DMX_EVENT_SCRAMBLING_STATUS_CHANGE = 0x00000800
 };
 
 enum dmx_oob_cmd {
@@ -256,7 +259,7 @@
 /* Discontinuity indicator was set */
 #define DMX_FILTER_DISCONTINUITY_INDICATOR	0x02
 
-/* PES legnth in PES header is not correct */
+/* PES length in PES header is not correct */
 #define DMX_FILTER_PES_LENGTH_ERROR		0x04
 
 
@@ -412,7 +415,7 @@
 	/*
 	 * The PID the index entry belongs to.
 	 * In case of recording filter, multiple PIDs may exist in the same
-	 * filter through DMX_ADD_PID ioctl and each can be indexed seperatly.
+	 * filter through DMX_ADD_PID ioctl and each can be indexed separately.
 	 */
 	__u16 pid;
 
@@ -423,7 +426,7 @@
 	__u64 match_tsp_num;
 
 	/*
-	 * The TS packet number in the recorded data preceeding
+	 * The TS packet number in the recorded data preceding
 	 * match_tsp_num and has PUSI set.
 	 */
 	__u64 last_pusi_tsp_num;
@@ -432,6 +435,23 @@
 	__u64 stc;
 };
 
+/* Scrambling information associated with DMX_EVENT_SCRAMBLING_STATUS_CHANGE */
+struct dmx_scrambling_status_event_info {
+	/*
+	 * The PID which its scrambling bit status changed.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have
+	 * different scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* old value of scrambling bits */
+	__u8 old_value;
+
+	/* new value of scrambling bits */
+	__u8 new_value;
+};
+
 /*
  * Filter's event returned through DMX_GET_EVENT.
  * poll with POLLPRI would block until events are available.
@@ -447,6 +467,7 @@
 		struct dmx_es_data_event_info es_data;
 		struct dmx_marker_event_info marker;
 		struct dmx_index_event_info index;
+		struct dmx_scrambling_status_event_info scrambling_status;
 	} params;
 };
 
@@ -754,6 +775,19 @@
 	__u32 identifier;
 };
 
+struct dmx_scrambling_bits {
+	/*
+	 * The PID to return its scrambling bit value.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have different
+	 * scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* Current value of scrambling bits: 0, 1, 2 or 3 */
+	__u8 value;
+};
+
 #define DMX_START                _IO('o', 41)
 #define DMX_STOP                 _IO('o', 42)
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
@@ -784,5 +818,6 @@
 #define DMX_SET_INDEXING_PARAMS _IOW('o', 69, struct dmx_indexing_params)
 #define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
 #define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
+#define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
index df9569b..47a2b7b 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -18,10 +18,10 @@
 #define FCC_CC_COLS		5
 #define FCC_TEMP_COLS		8
 
-#define PC_CC_ROWS             29
+#define PC_CC_ROWS             31
 #define PC_CC_COLS             13
 
-#define PC_TEMP_ROWS		29
+#define PC_TEMP_ROWS		31
 #define PC_TEMP_COLS		8
 
 #define MAX_SINGLE_LUT_COLS	20
@@ -74,6 +74,7 @@
 	BATT_PALLADIUM,
 	BATT_DESAY,
 	BATT_OEM,
+	BATT_QRD_4V35_2000MAH,
 };
 
 /**
@@ -114,6 +115,7 @@
 extern struct bms_battery_data  palladium_1500_data;
 extern struct bms_battery_data  desay_5200_data;
 extern struct bms_battery_data  oem_batt_data;
+extern struct bms_battery_data QRD_4v35_2000mAh_data;
 
 int interpolate_fcc(struct single_row_lut *fcc_temp_lut, int batt_temp);
 int interpolate_scalingfactor(struct sf_lut *sf_lut, int row_entry, int pc);
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index 3d159c4..a741107 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -72,6 +72,13 @@
 	uint16_t	gain;
 };
 
+enum msm_spkr_prot_states {
+	MSM_SPKR_PROT_CALIBRATED,
+	MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS,
+	MSM_SPKR_PROT_DISABLED,
+	MSM_SPKR_PROT_NOT_CALIBRATED
+};
+
 struct msm_spk_prot_cfg {
 	int r0;
 	int t0;
diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h
index f14cc52..2c1fa11 100644
--- a/include/linux/msm_thermal.h
+++ b/include/linux/msm_thermal.h
@@ -20,6 +20,7 @@
 	int32_t limit_temp_degC;
 	int32_t temp_hysteresis_degC;
 	uint32_t freq_step;
+	uint32_t freq_control_mask;
 	int32_t core_limit_temp_degC;
 	int32_t core_temp_hysteresis_degC;
 	uint32_t core_control_mask;
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index f551e75..6d7d178 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -3069,4 +3069,32 @@
 	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U =	1<<3,
 };
 
+/**
+ * enum nl80211_connect_failed_reason - connection request failed reasons
+ * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be
+ *  handled by the AP is reached.
+ * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL.
+ */
+enum nl80211_connect_failed_reason {
+	NL80211_CONN_FAIL_MAX_CLIENTS,
+	NL80211_CONN_FAIL_BLOCKED_CLIENT,
+};
+
+/**
+ * enum nl80211_acl_policy - access control policy
+ *
+ * Access control policy is applied on a MAC list set by
+ * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to
+ * be used with %NL80211_ATTR_ACL_POLICY.
+ *
+ * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
+ *   listed in ACL, i.e. allow all the stations which are not listed
+ *  in ACL to authenticate.
+ * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed
+ *    in ACL, i.e. deny all the stations which are not listed in ACL.
+ */
+enum nl80211_acl_policy {
+	NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
+	NL80211_ACL_POLICY_DENY_UNLESS_LISTED,
+};
 #endif /* __LINUX_NL80211_H */
diff --git a/include/linux/of_coresight.h b/include/linux/of_coresight.h
index 0943dda..eb20e80 100644
--- a/include/linux/of_coresight.h
+++ b/include/linux/of_coresight.h
@@ -13,7 +13,7 @@
 #ifndef __LINUX_OF_CORESIGHT_H
 #define __LINUX_OF_CORESIGHT_H
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_OF_CORESIGHT
 extern struct coresight_platform_data *of_get_coresight_platform_data(
 				struct device *dev, struct device_node *node);
 extern struct coresight_cti_data *of_get_coresight_cti_data(
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 67889bf..952bcb1 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2726,6 +2726,8 @@
 
 #endif /* CONFIG_SMP */
 
+extern struct atomic_notifier_head migration_notifier_head;
+
 extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
 extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
 
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index da56df6..4711ec8 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -67,6 +67,7 @@
 void wcnss_riva_log_debug_regs(void);
 void wcnss_pronto_log_debug_regs(void);
 int wcnss_device_ready(void);
+void wcnss_riva_dump_pmic_regs(void);
 
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index dc29eb9..fb2b57a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -416,6 +416,26 @@
 	size_t probe_resp_len;
 };
 
+struct mac_address {
+	u8 addr[ETH_ALEN];
+};
+
+/**
+ * struct cfg80211_acl_data - Access control list data
+ *
+ * @acl_policy: ACL policy to be applied on the station's
+ *	entry specified by mac_addr
+ * @n_acl_entries: Number of MAC address entries passed
+ * @mac_addrs: List of MAC addresses of stations to be used for ACL
+ */
+struct cfg80211_acl_data {
+	enum nl80211_acl_policy acl_policy;
+	int n_acl_entries;
+
+	/* Keep it last */
+	struct mac_address mac_addrs[];
+};
+
 /**
  * struct cfg80211_ap_settings - AP configuration
  *
@@ -432,6 +452,8 @@
  * @privacy: the BSS uses privacy
  * @auth_type: Authentication type (algorithm)
  * @inactivity_timeout: time in seconds to determine station's inactivity.
+ * @acl: ACL configuration used by the drivers which has support for
+ *	MAC address based access control
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_beacon_data beacon;
@@ -444,6 +466,7 @@
 	bool privacy;
 	enum nl80211_auth_type auth_type;
 	int inactivity_timeout;
+	const struct cfg80211_acl_data *acl;
 };
 
 /**
@@ -1559,6 +1582,13 @@
  *	later passes to cfg80211_probe_status().
  *
  * @set_noack_map: Set the NoAck Map for the TIDs.
+ * @set_mac_acl: Sets MAC address control list in AP and P2P GO mode.
+ *	Parameters include ACL policy, an array of MAC address of stations
+ *	and the number of MAC addresses. If there is already a list in driver
+ *	this new list replaces the existing one. Driver has to clear its ACL
+ *	when number of MAC addresses entries is passed as 0. Drivers which
+ *	advertise the support for MAC based ACL have to implement this callback.
+ *
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1757,6 +1787,9 @@
 	struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
 	int	(*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
 				 struct cfg80211_update_ft_ies_params *ftie);
+
+	int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev,
+			   const struct cfg80211_acl_data *params);
 };
 
 /*
@@ -1924,10 +1957,6 @@
 	bool beacon_int_infra_match;
 };
 
-struct mac_address {
-	u8 addr[ETH_ALEN];
-};
-
 struct ieee80211_txrx_stypes {
 	u16 tx, rx;
 };
@@ -2068,6 +2097,9 @@
  * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
  * @ht_capa_mod_mask:  Specify what ht_cap values can be over-ridden.
  *	If null, then none can be over-ridden.
+ *
+ * @max_acl_mac_addrs: Maximum number of MAC addresses that the device
+ *	supports for ACL.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -2089,6 +2121,8 @@
 	/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
 	u16 interface_modes;
 
+	u16 max_acl_mac_addrs;
+
 	u32 flags, features;
 
 	u32 ap_sme_capa;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 862e172..1a07d2e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -87,6 +87,8 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/sched.h>
 
+ATOMIC_NOTIFIER_HEAD(migration_notifier_head);
+
 void start_bandwidth_timer(struct hrtimer *period_timer, ktime_t period)
 {
 	unsigned long delta;
@@ -1589,15 +1591,17 @@
 try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 {
 	unsigned long flags;
-	int cpu, success = 0;
+	int cpu, src_cpu, success = 0;
 
 	smp_wmb();
 	raw_spin_lock_irqsave(&p->pi_lock, flags);
+	src_cpu = task_cpu(p);
+	cpu = src_cpu;
+
 	if (!(p->state & state))
 		goto out;
 
 	success = 1; /* we're going to change ->state */
-	cpu = task_cpu(p);
 
 	if (p->on_rq && ttwu_remote(p, wake_flags))
 		goto stat;
@@ -1634,7 +1638,7 @@
 		p->sched_class->task_waking(p);
 
 	cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
-	if (task_cpu(p) != cpu) {
+	if (src_cpu != cpu) {
 		wake_flags |= WF_MIGRATED;
 		set_task_cpu(p, cpu);
 	}
@@ -1646,6 +1650,9 @@
 out:
 	raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
+	if (src_cpu != cpu && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   cpu, (void *)src_cpu);
 	return success;
 }
 
@@ -5068,6 +5075,7 @@
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
 	struct rq *rq_dest, *rq_src;
+	bool moved = false;
 	int ret = 0;
 
 	if (unlikely(!cpu_active(dest_cpu)))
@@ -5094,12 +5102,16 @@
 		set_task_cpu(p, dest_cpu);
 		enqueue_task(rq_dest, p, 0);
 		check_preempt_curr(rq_dest, p, 0);
+		moved = true;
 	}
 done:
 	ret = 1;
 fail:
 	double_rq_unlock(rq_src, rq_dest);
 	raw_spin_unlock(&p->pi_lock);
+	if (moved && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   dest_cpu, (void *)src_cpu);
 	return ret;
 }
 
@@ -7731,6 +7743,24 @@
 	sched_move_task(task);
 }
 
+static u64 cpu_notify_on_migrate_read_u64(struct cgroup *cgrp,
+					  struct cftype *cft)
+{
+	struct task_group *tg = cgroup_tg(cgrp);
+
+	return tg->notify_on_migrate;
+}
+
+static int cpu_notify_on_migrate_write_u64(struct cgroup *cgrp,
+					   struct cftype *cft, u64 notify)
+{
+	struct task_group *tg = cgroup_tg(cgrp);
+
+	tg->notify_on_migrate = (notify > 0);
+
+	return 0;
+}
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static int cpu_shares_write_u64(struct cgroup *cgrp, struct cftype *cftype,
 				u64 shareval)
@@ -8002,6 +8032,11 @@
 #endif /* CONFIG_RT_GROUP_SCHED */
 
 static struct cftype cpu_files[] = {
+	{
+		.name = "notify_on_migrate",
+		.read_u64 = cpu_notify_on_migrate_read_u64,
+		.write_u64 = cpu_notify_on_migrate_write_u64,
+	},
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	{
 		.name = "shares",
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index a1bd252..103730d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3101,6 +3101,8 @@
 	unsigned int		loop_max;
 };
 
+static DEFINE_PER_CPU(bool, dbs_boost_needed);
+
 /*
  * move_task - move a task from one runqueue to another runqueue.
  * Both runqueues must be locked.
@@ -3111,6 +3113,8 @@
 	set_task_cpu(p, env->dst_cpu);
 	activate_task(env->dst_rq, p, 0);
 	check_preempt_curr(env->dst_rq, p, 0);
+	if (task_notify_on_migrate(p))
+		per_cpu(dbs_boost_needed, env->dst_cpu) = true;
 }
 
 /*
@@ -4541,9 +4545,15 @@
 			 */
 			sd->nr_balance_failed = sd->cache_nice_tries+1;
 		}
-	} else
+	} else {
 		sd->nr_balance_failed = 0;
-
+		if (per_cpu(dbs_boost_needed, this_cpu)) {
+			per_cpu(dbs_boost_needed, this_cpu) = false;
+			atomic_notifier_call_chain(&migration_notifier_head,
+						   this_cpu,
+						   (void *)cpu_of(busiest));
+		}
+	}
 	if (likely(!active_balance)) {
 		/* We were unbalanced, so reset the balancing interval */
 		sd->balance_interval = sd->min_interval;
@@ -4698,6 +4708,12 @@
 out_unlock:
 	busiest_rq->active_balance = 0;
 	raw_spin_unlock_irq(&busiest_rq->lock);
+	if (per_cpu(dbs_boost_needed, target_cpu)) {
+		per_cpu(dbs_boost_needed, target_cpu) = false;
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   target_cpu,
+					   (void *)cpu_of(busiest_rq));
+	}
 	return 0;
 }
 
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 8f32475..f8317df 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1604,6 +1604,7 @@
 	struct task_struct *next_task;
 	struct rq *lowest_rq;
 	int ret = 0;
+	bool moved = false;
 
 	if (!rq->rt.overloaded)
 		return 0;
@@ -1673,6 +1674,7 @@
 
 	deactivate_task(rq, next_task, 0);
 	set_task_cpu(next_task, lowest_rq->cpu);
+	moved = true;
 	activate_task(lowest_rq, next_task, 0);
 	ret = 1;
 
@@ -1683,6 +1685,11 @@
 out:
 	put_task_struct(next_task);
 
+	if (moved && task_notify_on_migrate(next_task))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   cpu_of(lowest_rq),
+					   (void *)cpu_of(rq));
+
 	return ret;
 }
 
@@ -1696,8 +1703,10 @@
 static int pull_rt_task(struct rq *this_rq)
 {
 	int this_cpu = this_rq->cpu, ret = 0, cpu;
-	struct task_struct *p;
+	struct task_struct *p = NULL;
 	struct rq *src_rq;
+	bool moved = false;
+	int src_cpu = 0;
 
 	if (likely(!rt_overloaded(this_rq)))
 		return 0;
@@ -1758,6 +1767,10 @@
 			deactivate_task(src_rq, p, 0);
 			set_task_cpu(p, this_cpu);
 			activate_task(this_rq, p, 0);
+
+			moved = true;
+			src_cpu = cpu_of(src_rq);
+
 			/*
 			 * We continue with the search, just in
 			 * case there's an even higher prio task
@@ -1769,6 +1782,11 @@
 		double_unlock_balance(this_rq, src_rq);
 	}
 
+	if (moved && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   this_cpu,
+					   (void *)src_cpu);
+
 	return ret;
 }
 
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 451bd4f..5370bcb 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -104,6 +104,8 @@
 struct task_group {
 	struct cgroup_subsys_state css;
 
+	bool notify_on_migrate;
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	/* schedulable entities of this group on each cpu */
 	struct sched_entity **se;
@@ -554,6 +556,11 @@
 	return autogroup_task_group(p, tg);
 }
 
+static inline bool task_notify_on_migrate(struct task_struct *p)
+{
+	return task_group(p)->notify_on_migrate;
+}
+
 /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
 static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
 {
@@ -579,7 +586,10 @@
 {
 	return NULL;
 }
-
+static inline bool task_notify_on_migrate(struct task_struct *p)
+{
+	return false;
+}
 #endif /* CONFIG_CGROUP_SCHED */
 
 static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 798c750..8a93508 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1661,6 +1661,7 @@
 	long min = mark;
 	long lowmem_reserve = z->lowmem_reserve[classzone_idx];
 	int o;
+	long free_cma = 0;
 
 	free_pages -= (1 << order) - 1;
 	if (alloc_flags & ALLOC_HIGH)
@@ -1670,9 +1671,10 @@
 #ifdef CONFIG_CMA
 	/* If allocation can't use CMA areas don't use free CMA pages */
 	if (!(alloc_flags & ALLOC_CMA))
-		free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES);
+		free_cma = zone_page_state(z, NR_FREE_CMA_PAGES);
 #endif
-	if (free_pages <= min + lowmem_reserve)
+
+	if (free_pages - free_cma <= min + lowmem_reserve)
 		return false;
 	for (o = 0; o < order; o++) {
 		/* At the next order, this order's pages become unavailable */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ccdfed8..674c1fa 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -505,6 +505,11 @@
 			   ETH_ALEN)))
 		return -EINVAL;
 
+	if (WARN_ON(wiphy->max_acl_mac_addrs &&
+		    (!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) ||
+		     !rdev->ops->set_mac_acl)))
+		return -EINVAL;
+
 	if (wiphy->addresses)
 		memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e1fa62e..6ed6d3e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -210,6 +210,8 @@
 	[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
 	[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
 	[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+	[NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
+	[NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
 	[NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
 	[NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
@@ -1066,6 +1068,11 @@
 			sizeof(*dev->wiphy.ht_capa_mod_mask),
 			dev->wiphy.ht_capa_mod_mask);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
+	    dev->wiphy.max_acl_mac_addrs)
+		NLA_PUT_U32(msg, NL80211_ATTR_MAC_ACL_MAX,
+			    dev->wiphy.max_acl_mac_addrs);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -2105,6 +2112,97 @@
 	return err;
 }
 
+/* This function returns an error or the number of nested attributes */
+static int validate_acl_mac_addrs(struct nlattr *nl_attr)
+{
+	struct nlattr *attr;
+	int n_entries = 0, tmp;
+
+	nla_for_each_nested(attr, nl_attr, tmp) {
+		if (nla_len(attr) != ETH_ALEN)
+			return -EINVAL;
+
+		n_entries++;
+	}
+
+	return n_entries;
+}
+
+/*
+ * This function parses ACL information and allocates memory for ACL data.
+ * On successful return, the calling function is responsible to free the
+ * ACL buffer returned by this function.
+ */
+static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
+						struct genl_info *info)
+{
+	enum nl80211_acl_policy acl_policy;
+	struct nlattr *attr;
+	struct cfg80211_acl_data *acl;
+	int i = 0, n_entries, tmp;
+
+	if (!wiphy->max_acl_mac_addrs)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	if (!info->attrs[NL80211_ATTR_ACL_POLICY])
+		return ERR_PTR(-EINVAL);
+
+	acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
+	if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
+	    acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
+		return ERR_PTR(-EINVAL);
+
+	if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
+		return ERR_PTR(-EINVAL);
+
+	n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
+	if (n_entries < 0)
+		return ERR_PTR(n_entries);
+
+	if (n_entries > wiphy->max_acl_mac_addrs)
+		return ERR_PTR(-ENOTSUPP);
+
+	acl = kzalloc(sizeof(*acl) + (sizeof(struct mac_address) * n_entries),
+		      GFP_KERNEL);
+	if (!acl)
+		return ERR_PTR(-ENOMEM);
+
+	nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
+		memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
+		i++;
+	}
+
+	acl->n_acl_entries = n_entries;
+	acl->acl_policy = acl_policy;
+
+	return acl;
+}
+
+static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct cfg80211_acl_data *acl;
+	int err;
+
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
+
+	if (!dev->ieee80211_ptr->beacon_interval)
+		return -EINVAL;
+
+	acl = parse_acl_data(&rdev->wiphy, info);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+
+	err = rdev->ops->set_mac_acl(&rdev->wiphy, dev, acl);
+
+	kfree(acl);
+
+	return err;
+}
+
 static int nl80211_parse_beacon(struct genl_info *info,
 				struct cfg80211_beacon_data *bcn)
 {
@@ -2251,9 +2349,18 @@
 			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
 	}
 
+	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
+		params.acl = parse_acl_data(&rdev->wiphy, info);
+		if (IS_ERR(params.acl))
+			return PTR_ERR(params.acl);
+	}
+
 	err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
 	if (!err)
 		wdev->beacon_interval = params.beacon_interval;
+
+	kfree(params.acl);
+
 	return err;
 }
 
@@ -7063,6 +7170,14 @@
 				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
+		.cmd = NL80211_CMD_SET_MAC_ACL,
+		.doit = nl80211_set_mac_acl,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
 		.cmd = NL80211_CMD_UPDATE_FT_IES,
 		.doit = nl80211_update_ft_ies,
 		.policy = nl80211_policy,
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 616f8d5..58ea22d 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -45,6 +45,7 @@
 #define NUM_DECIMATORS 4
 #define NUM_INTERPOLATORS 3
 #define BITS_PER_REG 8
+#define SITAR_RX_PORT_START_NUMBER 10
 
 enum {
 	AIF1_PB = 0,
@@ -53,11 +54,11 @@
 };
 
 struct wcd9xxx_ch sitar_rx_chs[SITAR_RX_MAX] = {
-	WCD9XXX_CH(10, 0),
-	WCD9XXX_CH(11, 1),
-	WCD9XXX_CH(12, 2),
-	WCD9XXX_CH(13, 3),
-	WCD9XXX_CH(14, 4)
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(SITAR_RX_PORT_START_NUMBER + 4, 4)
 };
 
 struct wcd9xxx_ch sitar_tx_chs[SITAR_TX_MAX] = {
@@ -1368,10 +1369,10 @@
 						vport_check_table[dai_id],
 						port_id,
 						sitar_p->dai)) {
-				pr_info("%s: TX%u is used by other virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 					__func__, port_id + 1);
 				mutex_unlock(&codec->mutex);
-				return -EINVAL;
+				return 0;
 			}
 			widget->value |= 1 << port_id;
 			list_add_tail(&core->tx_chs[port_id].list,
@@ -1381,10 +1382,10 @@
 			list_del_init(&core->tx_chs[port_id].list);
 		} else {
 			if (enable)
-				pr_info("%s: TX%u port is used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is used by this virtual port\n",
 					__func__, port_id + 1);
 			else
-				pr_info("%s: TX%u port is not used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is not used by this virtual port\n",
 					__func__, port_id + 1);
 			/* avoid update power function */
 			mutex_unlock(&codec->mutex);
@@ -1446,9 +1447,13 @@
 		list_del_init(&core->rx_chs[port_id].list);
 		break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&sitar_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			SITAR_RX_PORT_START_NUMBER,
+			&sitar_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &sitar_p->dai[AIF1_PB].wcd9xxx_ch_list);
 		break;
@@ -1458,14 +1463,10 @@
 		goto err;
 	}
 
-
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
-
 	mutex_unlock(&codec->mutex);
 	return 0;
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 err:
 	mutex_unlock(&codec->mutex);
 	return -EINVAL;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index b71dd65..669f8e3 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -60,6 +60,7 @@
 #define BITS_PER_REG 8
 /* This actual number of TX ports supported in slimbus slave */
 #define TAPAN_TX_PORT_NUMBER	16
+#define TAPAN_RX_PORT_START_NUMBER	16
 
 /* Nummer of TX ports actually connected from Slimbus slave to codec Digital */
 #define TAPAN_SLIM_CODEC_TX_PORTS 5
@@ -155,11 +156,11 @@
 static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 
 static const struct wcd9xxx_ch tapan_rx_chs[TAPAN_RX_MAX] = {
-	WCD9XXX_CH(16, 0),
-	WCD9XXX_CH(17, 1),
-	WCD9XXX_CH(18, 2),
-	WCD9XXX_CH(19, 3),
-	WCD9XXX_CH(20, 4),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(TAPAN_RX_PORT_START_NUMBER + 4, 4),
 };
 
 static const struct wcd9xxx_ch tapan_tx_chs[TAPAN_TX_MAX] = {
@@ -1410,7 +1411,7 @@
 				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 					__func__, port_id + 1);
 				mutex_unlock(&codec->mutex);
-				return -EINVAL;
+				return 0;
 			}
 			widget->value |= 1 << port_id;
 			list_add_tail(&core->tx_chs[port_id].list,
@@ -1495,23 +1496,35 @@
 		list_del_init(&core->rx_chs[port_id].list);
 	break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAPAN_RX_PORT_START_NUMBER,
+			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF1_PB].wcd9xxx_ch_list);
 	break;
 	case 2:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF2_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAPAN_RX_PORT_START_NUMBER,
+			&tapan_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
+				dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+					__func__, port_id + 1);
+				goto rtn;
+			}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tapan_p->dai[AIF3_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAPAN_RX_PORT_START_NUMBER,
+			&tapan_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
+				dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+					__func__, port_id + 1);
+				goto rtn;
+			}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tapan_p->dai[AIF3_PB].wcd9xxx_ch_list);
 	break;
@@ -1520,13 +1533,10 @@
 		goto err;
 	}
 
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
-
 	mutex_unlock(&codec->mutex);
 	return 0;
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 err:
 	mutex_unlock(&codec->mutex);
 	return -EINVAL;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 29703b9..69e4cca 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -129,6 +129,8 @@
 #define TABLA_GPIO_IRQ_DEBOUNCE_TIME_US 5000
 
 #define TABLA_MBHC_GND_MIC_SWAP_THRESHOLD 2
+#define TABLA_RX_PORT_START_NUMBER	10
+
 
 #define TABLA_ACQUIRE_LOCK(x) do { \
 	mutex_lock_nested(&x, SINGLE_DEPTH_NESTING); \
@@ -302,13 +304,13 @@
 static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 
 static const struct wcd9xxx_ch tabla_rx_chs[TABLA_RX_MAX] = {
-	WCD9XXX_CH(10, 0),
-	WCD9XXX_CH(11, 1),
-	WCD9XXX_CH(12, 2),
-	WCD9XXX_CH(13, 3),
-	WCD9XXX_CH(14, 4),
-	WCD9XXX_CH(15, 5),
-	WCD9XXX_CH(16, 6)
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 4, 4),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 5, 5),
+	WCD9XXX_CH(TABLA_RX_PORT_START_NUMBER + 6, 6)
 };
 
 static const struct wcd9xxx_ch tabla_tx_chs[TABLA_TX_MAX] = {
@@ -2031,10 +2033,10 @@
 						vtable,
 						port_id,
 						tabla_p->dai)) {
-				pr_info("%s: TX%u is used by other virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 					__func__, port_id + 1);
 				mutex_unlock(&codec->mutex);
-				return -EINVAL;
+				return 0;
 			}
 			widget->value |= 1 << port_id;
 			list_add_tail(&core->tx_chs[port_id].list,
@@ -2045,10 +2047,10 @@
 			list_del_init(&core->tx_chs[port_id].list);
 		} else {
 			if (enable)
-				pr_info("%s: TX%u port is used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is used by this virtual port\n",
 					__func__, port_id + 1);
 			else
-				pr_info("%s: TX%u port is not used by this virtual port\n",
+				dev_dbg(codec->dev, "%s: TX%u port is not used by this virtual port\n",
 					__func__, port_id + 1);
 			/* avoid update power function */
 			mutex_unlock(&codec->mutex);
@@ -2116,23 +2118,35 @@
 		list_del_init(&core->rx_chs[port_id].list);
 	break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TABLA_RX_PORT_START_NUMBER,
+			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tabla_p->dai[AIF1_PB].wcd9xxx_ch_list);
 	break;
 	case 2:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TABLA_RX_PORT_START_NUMBER,
+			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tabla_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TABLA_RX_PORT_START_NUMBER,
+			&tabla_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &tabla_p->dai[AIF3_PB].wcd9xxx_ch_list);
 	break;
@@ -2140,15 +2154,8 @@
 		pr_err("Unknown AIF %d\n", widget->value);
 		goto err;
 	}
-
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
-
-	mutex_unlock(&codec->mutex);
-	return 0;
-
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 	mutex_unlock(&codec->mutex);
 	return 0;
 err:
@@ -2703,7 +2710,7 @@
 	}
 
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
-	msleep(250);
+	msleep(20);
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 	pr_debug("%s: leave\n", __func__);
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 5d4f9e6..8946dce 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -41,6 +41,8 @@
 
 #define TAIKO_MAD_SLIMBUS_TX_PORT 12
 #define TAIKO_MAD_AUDIO_FIRMWARE_PATH "wcd9320/wcd9320_mad_audio.bin"
+#define TAIKO_VALIDATE_RX_SBPORT_RANGE(port) ((port >= 16) && (port <= 22))
+#define TAIKO_CONVERT_RX_SBPORT_ID(port) (port - 16) /* RX1 port ID = 0 */
 
 #define TAIKO_HPH_PA_SETTLE_COMP_ON 3000
 #define TAIKO_HPH_PA_SETTLE_COMP_OFF 13000
@@ -294,6 +296,7 @@
 #define NUM_INTERPOLATORS 7
 #define BITS_PER_REG 8
 #define TAIKO_TX_PORT_NUMBER	16
+#define TAIKO_RX_PORT_START_NUMBER	16
 
 #define TAIKO_I2S_MASTER_MODE_MASK 0x08
 
@@ -409,19 +412,19 @@
 static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 
 static const struct wcd9xxx_ch taiko_rx_chs[TAIKO_RX_MAX] = {
-	WCD9XXX_CH(16, 0),
-	WCD9XXX_CH(17, 1),
-	WCD9XXX_CH(18, 2),
-	WCD9XXX_CH(19, 3),
-	WCD9XXX_CH(20, 4),
-	WCD9XXX_CH(21, 5),
-	WCD9XXX_CH(22, 6),
-	WCD9XXX_CH(23, 7),
-	WCD9XXX_CH(24, 8),
-	WCD9XXX_CH(25, 9),
-	WCD9XXX_CH(26, 10),
-	WCD9XXX_CH(27, 11),
-	WCD9XXX_CH(28, 12),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER, 0),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 1, 1),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 2, 2),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 3, 3),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 4, 4),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 5, 5),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 6, 6),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 7, 7),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 8, 8),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 9, 9),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 10, 10),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 11, 11),
+	WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 12, 12),
 };
 
 static const struct wcd9xxx_ch taiko_tx_chs[TAIKO_TX_MAX] = {
@@ -2042,11 +2045,10 @@
 						vtable,
 						port_id,
 						taiko_p->dai)) {
-					pr_debug("%s: TX%u is used by other\n"
-						"virtual port\n",
+					dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
 						__func__, port_id + 1);
 					mutex_unlock(&codec->mutex);
-					return -EINVAL;
+					return 0;
 				}
 				widget->value |= 1 << port_id;
 				list_add_tail(&core->tx_chs[port_id].list,
@@ -2057,11 +2059,11 @@
 				list_del_init(&core->tx_chs[port_id].list);
 			} else {
 				if (enable)
-					pr_debug("%s: TX%u port is used by\n"
+					dev_dbg(codec->dev, "%s: TX%u port is used by\n"
 						"this virtual port\n",
 						__func__, port_id + 1);
 				else
-					pr_debug("%s: TX%u port is not used by\n"
+					dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
 						"this virtual port\n",
 						__func__, port_id + 1);
 				/* avoid update power function */
@@ -2130,23 +2132,35 @@
 		list_del_init(&core->rx_chs[port_id].list);
 	break;
 	case 1:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF1_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAIKO_RX_PORT_START_NUMBER,
+			&taiko_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list);
 	break;
 	case 2:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF2_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAIKO_RX_PORT_START_NUMBER,
+			&taiko_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list);
 	break;
 	case 3:
-		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
-			&taiko_p->dai[AIF3_PB].wcd9xxx_ch_list))
-			goto pr_err;
+		if (wcd9xxx_rx_vport_validation(port_id +
+			TAIKO_RX_PORT_START_NUMBER,
+			&taiko_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
+			dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
+				__func__, port_id + 1);
+			goto rtn;
+		}
 		list_add_tail(&core->rx_chs[port_id].list,
 			      &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list);
 	break;
@@ -2154,14 +2168,11 @@
 		pr_err("Unknown AIF %d\n", widget->value);
 		goto err;
 	}
-
+rtn:
 	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
 
 	mutex_unlock(&codec->mutex);
 	return 0;
-pr_err:
-	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
-		__func__, port_id + 1);
 err:
 	mutex_unlock(&codec->mutex);
 	return -EINVAL;
@@ -4266,6 +4277,65 @@
 	return 0;
 }
 
+static void taiko_set_rxsb_port_format(struct snd_pcm_hw_params *params,
+				       struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx_codec_dai_data *cdc_dai;
+	struct wcd9xxx_ch *ch;
+	int port;
+	u8 bit_sel;
+	u16 sb_ctl_reg, field_shift;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		bit_sel = 0x2;
+		taiko_p->dai[dai->id].bit_width = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		bit_sel = 0x0;
+		taiko_p->dai[dai->id].bit_width = 24;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid format\n");
+		return;
+	}
+
+	cdc_dai = &taiko_p->dai[dai->id];
+
+	list_for_each_entry(ch, &cdc_dai->wcd9xxx_ch_list, list) {
+		port = wcd9xxx_get_slave_port(ch->ch_num);
+
+		if (IS_ERR_VALUE(port) ||
+		    !TAIKO_VALIDATE_RX_SBPORT_RANGE(port)) {
+			dev_warn(codec->dev,
+				 "%s: invalid port ID %d returned for RX DAI\n",
+				 __func__, port);
+			return;
+		}
+
+		port = TAIKO_CONVERT_RX_SBPORT_ID(port);
+
+		if (port <= 3) {
+			sb_ctl_reg = TAIKO_A_CDC_CONN_RX_SB_B1_CTL;
+			field_shift = port << 1;
+		} else if (port <= 6) {
+			sb_ctl_reg = TAIKO_A_CDC_CONN_RX_SB_B2_CTL;
+			field_shift = (port - 4) << 1;
+		} else { /* should not happen */
+			dev_warn(codec->dev,
+				 "%s: bad port ID %d\n", __func__, port);
+			return;
+		}
+
+		dev_dbg(codec->dev, "%s: sb_ctl_reg %x field_shift %x\n",
+			__func__, sb_ctl_reg, field_shift);
+		snd_soc_update_bits(codec, sb_ctl_reg, 0x3 << field_shift,
+				    bit_sel << field_shift);
+	}
+}
+
 static int taiko_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
@@ -4380,29 +4450,7 @@
 			snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_I2S_CTL,
 					    0x03, (rx_fs_rate >> 0x05));
 		} else {
-			switch (params_format(params)) {
-			case SNDRV_PCM_FORMAT_S16_LE:
-				snd_soc_update_bits(codec,
-					TAIKO_A_CDC_CONN_RX_SB_B1_CTL,
-					0xFF, 0xAA);
-				snd_soc_update_bits(codec,
-					TAIKO_A_CDC_CONN_RX_SB_B2_CTL,
-					0xFF, 0x2A);
-				taiko->dai[dai->id].bit_width = 16;
-				break;
-			case SNDRV_PCM_FORMAT_S24_LE:
-				snd_soc_update_bits(codec,
-					TAIKO_A_CDC_CONN_RX_SB_B1_CTL,
-					0xFF, 0x00);
-				snd_soc_update_bits(codec,
-					TAIKO_A_CDC_CONN_RX_SB_B2_CTL,
-					0xFF, 0x00);
-				taiko->dai[dai->id].bit_width = 24;
-				break;
-			default:
-				dev_err(codec->dev, "Invalid format\n");
-				break;
-			}
+			taiko_set_rxsb_port_format(params, dai);
 			taiko->dai[dai->id].rate   = params_rate(params);
 		}
 		break;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 945840d..ae92ca4 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -1949,6 +1949,52 @@
 		.codec_name = "snd-soc-dummy",
 		.be_id = MSM_FRONTEND_DAI_LSM1,
 	},
+	/* Multiple Tunnel instances */
+	{
+		.name = "MSM8974 Compr2",
+		.stream_name = "COMPR2",
+		.cpu_dai_name	= "MultiMedia6",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+	},
+	{
+		.name = "MSM8974 Compr3",
+		.stream_name = "COMPR3",
+		.cpu_dai_name	= "MultiMedia7",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+	},
+	{
+		.name = "MSM8974 Compr4",
+		.stream_name = "COMPR4",
+		.cpu_dai_name	= "MultiMedia8",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index bb13695..60f4669 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -1058,7 +1058,9 @@
 	}
 	/* Set encoder properties. */
 	switch (common.mvs_info.media_type) {
-	case VSS_MEDIA_ID_EVRC_MODEM: {
+	case VSS_MEDIA_ID_EVRC_MODEM:
+	case VSS_MEDIA_ID_4GV_NB_MODEM:
+	case VSS_MEDIA_ID_4GV_WB_MODEM: {
 		struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate;
 
 		pr_debug("Setting EVRC min-max rate\n");
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index a2e0b87..3b6a415 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -1010,10 +1010,11 @@
 	case AUDIO_GET_SPEAKER_PROT:
 		mutex_lock(&acdb_data.acdb_mutex);
 		/*Indicates calibration was succesfull*/
-		if (!acdb_data.spk_prot_cfg.mode) {
+		if (acdb_data.spk_prot_cfg.mode == MSM_SPKR_PROT_CALIBRATED) {
 			prot_status.r0 = acdb_data.spk_prot_cfg.r0;
 			prot_status.status = 0;
-		} else if (acdb_data.spk_prot_cfg.mode == 1) {
+		} else if (acdb_data.spk_prot_cfg.mode ==
+				   MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS) {
 			/*Call AFE to query the status*/
 			acdb_spk_status.status = -EINVAL;
 			acdb_spk_status.r0 = -1;
@@ -1021,7 +1022,8 @@
 			prot_status.r0 = acdb_spk_status.r0;
 			prot_status.status = acdb_spk_status.status;
 			if (!acdb_spk_status.status) {
-				acdb_data.spk_prot_cfg.mode = 0;
+				acdb_data.spk_prot_cfg.mode =
+					MSM_SPKR_PROT_CALIBRATED;
 				acdb_data.spk_prot_cfg.r0 = prot_status.r0;
 			}
 		} else {
@@ -1206,7 +1208,7 @@
 {
 	memset(&acdb_data, 0, sizeof(acdb_data));
 	/*Speaker protection disabled*/
-	acdb_data.spk_prot_cfg.mode = -1;
+	acdb_data.spk_prot_cfg.mode = MSM_SPKR_PROT_DISABLED;
 	mutex_init(&acdb_data.acdb_mutex);
 	atomic_set(&usage_count, 0);
 	atomic_set(&acdb_data.valid_adm_custom_top, 1);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index ec5359c..620f667 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -497,6 +497,10 @@
 			if (!atomic_cmpxchg(&compressed_audio.audio_ocmem_req,
 									0, 1))
 				audio_ocmem_process_req(AUDIO, true);
+			else
+				atomic_inc(&compressed_audio.audio_ocmem_req);
+			pr_debug("%s: req: %d\n", __func__,
+			atomic_read(&compressed_audio.audio_ocmem_req));
 		}
 
 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -619,7 +623,6 @@
 	populate_codec_list(compr, runtime);
 	runtime->private_data = compr;
 	atomic_set(&prtd->eos, 0);
-	atomic_set(&compressed_audio.audio_ocmem_req, 0);
 	compressed_audio.prtd =  &compr->prtd;
 
 	return 0;
@@ -653,8 +656,14 @@
 
 	dir = IN;
 	atomic_set(&prtd->pending_buffer, 0);
-	if (atomic_cmpxchg(&compressed_audio.audio_ocmem_req, 1, 0))
+
+	if (atomic_read(&compressed_audio.audio_ocmem_req) > 1)
+		atomic_dec(&compressed_audio.audio_ocmem_req);
+	else if (atomic_cmpxchg(&compressed_audio.audio_ocmem_req, 1, 0))
 		audio_ocmem_process_req(AUDIO, false);
+
+	pr_debug("%s: req: %d\n", __func__,
+		atomic_read(&compressed_audio.audio_ocmem_req));
 	prtd->pcm_irq_pos = 0;
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 	compressed_audio.prtd = NULL;
@@ -1171,6 +1180,8 @@
 
 	dev_info(&pdev->dev, "%s: dev name %s\n",
 			 __func__, dev_name(&pdev->dev));
+
+	atomic_set(&compressed_audio.audio_ocmem_req, 0);
 	return snd_soc_register_platform(&pdev->dev,
 				   &msm_soc_platform);
 }
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 643f280..70db200 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -257,6 +257,12 @@
 	{INVALID_SESSION, INVALID_SESSION},
 	/* MULTIMEDIA5 */
 	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA6 */
+	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA7 */
+	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA8 */
+	{INVALID_SESSION, INVALID_SESSION},
 };
 
 static uint8_t is_be_dai_extproc(int be_dai)
@@ -379,6 +385,10 @@
 			else if (msm_bedais[i].format ==
 						SNDRV_PCM_FORMAT_S24_LE)
 				bits_per_sample = 24;
+
+			if (msm_bedais[i].port_id == VOICE_RECORD_RX ||
+			    msm_bedais[i].port_id == VOICE_RECORD_TX)
+				topology = DEFAULT_COPP_TOPOLOGY;
 			if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
 				(channels > 0))
 				adm_multi_ch_copp_open(msm_bedais[i].port_id,
@@ -508,6 +518,10 @@
 			if (msm_bedais[reg].format == SNDRV_PCM_FORMAT_S24_LE)
 				bits_per_sample = 24;
 
+			if (msm_bedais[reg].port_id == VOICE_RECORD_RX ||
+			    msm_bedais[reg].port_id == VOICE_RECORD_TX)
+				topology = DEFAULT_COPP_TOPOLOGY;
+
 			if ((session_type == SESSION_TYPE_RX) &&
 				(channels > 0)) {
 				perf_mode = test_bit(val,
@@ -1345,6 +1359,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
@@ -1363,6 +1386,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1381,6 +1413,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = {
@@ -1399,6 +1440,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = {
@@ -1417,6 +1467,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
@@ -1450,6 +1509,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_hl_mixer_controls[] = {
@@ -1477,6 +1545,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
@@ -1495,6 +1572,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 	/* incall music delivery mixer */
 static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = {
@@ -1531,6 +1617,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -1549,6 +1644,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT_FM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_INT_FM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_INT_FM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT_FM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
@@ -1567,6 +1671,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -1585,6 +1698,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
@@ -1603,6 +1725,15 @@
 	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
@@ -2555,6 +2686,9 @@
 	SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
@@ -2855,6 +2989,9 @@
 	{"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"PRI_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"PRI_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"PRI_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"PRI_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"PRI_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
 
 	{"SEC_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2862,6 +2999,9 @@
 	{"SEC_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"SEC_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"SEC_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"SEC_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"SEC_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"SEC_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
 
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2869,6 +3009,9 @@
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
 
 	{"HDMI Mixer", "MultiMedia1", "MM_DL1"},
@@ -2876,6 +3019,9 @@
 	{"HDMI Mixer", "MultiMedia3", "MM_DL3"},
 	{"HDMI Mixer", "MultiMedia4", "MM_DL4"},
 	{"HDMI Mixer", "MultiMedia5", "MM_DL5"},
+	{"HDMI Mixer", "MultiMedia6", "MM_DL6"},
+	{"HDMI Mixer", "MultiMedia7", "MM_DL7"},
+	{"HDMI Mixer", "MultiMedia8", "MM_DL8"},
 	{"HDMI", NULL, "HDMI Mixer"},
 
 		/* incall */
@@ -2896,6 +3042,9 @@
 	{"MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"MI2S_RX", NULL, "MI2S_RX Audio Mixer"},
 
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2948,6 +3097,9 @@
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
 
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2955,6 +3107,9 @@
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
 
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2962,6 +3117,9 @@
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"AFE_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"AFE_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"AFE_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -2982,6 +3140,9 @@
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"AUX_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"AUX_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"AUX_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2989,6 +3150,9 @@
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX Audio Mixer"},
 
 	{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3348,6 +3512,10 @@
 			if (bedai->format == SNDRV_PCM_FORMAT_S24_LE)
 				bits_per_sample = 24;
 
+			if (bedai->port_id == VOICE_RECORD_RX ||
+			    bedai->port_id == VOICE_RECORD_TX)
+				topology = DEFAULT_COPP_TOPOLOGY;
+
 			if ((playback) && (channels > 0)) {
 				perf_mode = test_bit(i, &(bedai->perf_mode));
 				adm_multi_ch_copp_open(bedai->port_id,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 4a58369..9750756 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -67,6 +67,9 @@
 	MSM_FRONTEND_DAI_MULTIMEDIA3,
 	MSM_FRONTEND_DAI_MULTIMEDIA4,
 	MSM_FRONTEND_DAI_MULTIMEDIA5,
+	MSM_FRONTEND_DAI_MULTIMEDIA6,
+	MSM_FRONTEND_DAI_MULTIMEDIA7,
+	MSM_FRONTEND_DAI_MULTIMEDIA8,
 	MSM_FRONTEND_DAI_CS_VOICE,
 	MSM_FRONTEND_DAI_VOIP,
 	MSM_FRONTEND_DAI_AFE_RX,
@@ -79,8 +82,8 @@
 	MSM_FRONTEND_DAI_MAX,
 };
 
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA5 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA5
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA8 + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA8
 
 enum {
 	MSM_BACKEND_DAI_PRI_I2S_RX = 0,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index b5ce28f..9b3cc8d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -1145,6 +1145,7 @@
 
 static const struct of_device_id msm_voip_dt_match[] = {
 	{.compatible = "qcom,msm-voip-dsp"},
+	{}
 };
 MODULE_DEVICE_TABLE(of, msm_voip_dt_match);
 
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 29c06cb..ed4e090 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1003,8 +1003,8 @@
 		} else if (channel_mode == 6) {
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
-			open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
-			open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_LFE;
 			open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
 			open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
 		} else if (channel_mode == 8) {
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index ce5e816..f05f772 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -56,6 +56,9 @@
 #define TIMEOUT_MS 1000
 #define Q6AFE_MAX_VOLUME 0x3FFF
 
+#define Q6AFE_MSM_SPKR_PROCESSING 0
+#define Q6AFE_MSM_SPKR_CALIBRATION 1
+
 static int pcm_afe_instance[2];
 static int proxy_afe_instance[2];
 bool afe_close_done[2] = {true, true};
@@ -515,25 +518,31 @@
 	/*Get spkr protection cfg data*/
 	get_spk_protection_cfg(&prot_cfg);
 
-	if ((!prot_cfg.mode || prot_cfg.mode == 1) &&
+	if ((prot_cfg.mode != MSM_SPKR_PROT_DISABLED) &&
 		(this_afe.vi_tx_port == port_id)) {
 		afe_spk_config.mode_rx_cfg.minor_version = 1;
-		afe_spk_config.mode_rx_cfg.mode =
-		(uint32_t)prot_cfg.mode;
+		if (prot_cfg.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
+			afe_spk_config.mode_rx_cfg.mode =
+			Q6AFE_MSM_SPKR_CALIBRATION;
+		else
+			afe_spk_config.mode_rx_cfg.mode =
+			Q6AFE_MSM_SPKR_PROCESSING;
 		if (afe_spk_prot_prepare(port_id,
 			AFE_PARAM_ID_MODE_VI_PROC_CFG,
 			&afe_spk_config))
 			pr_err("%s TX VI_PROC_CFG failed\n", __func__);
-		afe_spk_config.vi_proc_cfg.minor_version = 1;
-		afe_spk_config.vi_proc_cfg.r0_cali_q24 =
-		(uint32_t) prot_cfg.r0;
-		afe_spk_config.vi_proc_cfg.t0_cali_q6 =
-		(uint32_t) prot_cfg.t0;
-		if (afe_spk_prot_prepare(port_id,
-			AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG,
-			&afe_spk_config))
-			pr_err("%s SPKR_CALIB_VI_PROC_CFG failed\n",
-				__func__);
+		if (prot_cfg.mode != MSM_SPKR_PROT_NOT_CALIBRATED) {
+			afe_spk_config.vi_proc_cfg.minor_version = 1;
+			afe_spk_config.vi_proc_cfg.r0_cali_q24 =
+			(uint32_t) prot_cfg.r0;
+			afe_spk_config.vi_proc_cfg.t0_cali_q6 =
+			(uint32_t) prot_cfg.t0;
+			if (afe_spk_prot_prepare(port_id,
+				AFE_PARAM_ID_SPKR_CALIB_VI_PROC_CFG,
+				&afe_spk_config))
+				pr_err("%s SPKR_CALIB_VI_PROC_CFG failed\n",
+					__func__);
+		}
 	}
 }
 
@@ -545,9 +554,13 @@
 	/*Get spkr protection cfg data*/
 	get_spk_protection_cfg(&prot_cfg);
 
-	if (!prot_cfg.mode || prot_cfg.mode == 1) {
-		afe_spk_config.mode_rx_cfg.mode =
-		(uint32_t)prot_cfg.mode;
+	if (prot_cfg.mode != MSM_SPKR_PROT_DISABLED) {
+		if (prot_cfg.mode == MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS)
+			afe_spk_config.mode_rx_cfg.mode =
+			Q6AFE_MSM_SPKR_CALIBRATION;
+		else
+			afe_spk_config.mode_rx_cfg.mode =
+			Q6AFE_MSM_SPKR_PROCESSING;
 		afe_spk_config.mode_rx_cfg.minor_version = 1;
 		if (afe_spk_prot_prepare(port_id,
 			AFE_PARAM_ID_FBSP_MODE_RX_CFG,
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c2fd2d7..ac26d0c 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -3363,6 +3363,7 @@
 	u32 lbuf_addr_lsw;
 	u32 liomode;
 	u32 io_compressed;
+	int dir = 0;
 
 	if (!ac || ac->apr == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
@@ -3380,15 +3381,21 @@
 	read.seq_id = param->uid;
 	liomode = (NT_MODE | ASYNC_IO_MODE);
 	io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
-	if (ac->io_mode == liomode)
+	if (ac->io_mode == liomode) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 32);
-	else if (ac->io_mode == io_compressed)
+		/*legacy wma driver case*/
+		dir = IN;
+	} else if (ac->io_mode == io_compressed) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 64);
-	else
+		dir = OUT;
+	} else {
 		lbuf_addr_lsw = read.buf_addr_lsw;
+		dir = OUT;
+	}
 
-	list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
-		buf_node = list_entry(ptr, struct asm_buffer_node, list);
+	list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
+		buf_node = list_entry(ptr, struct asm_buffer_node,
+			list);
 			if (buf_node->buf_addr_lsw == lbuf_addr_lsw) {
 				read.mem_map_handle = buf_node->mmap_hdl;
 				break;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index e9d0a7e..5f89e4a 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1207,7 +1207,9 @@
 	}
 	/* Set encoder properties. */
 	switch (common.mvs_info.media_type) {
-	case VSS_MEDIA_ID_EVRC_MODEM: {
+	case VSS_MEDIA_ID_EVRC_MODEM:
+	case VSS_MEDIA_ID_4GV_NB_MODEM:
+	case VSS_MEDIA_ID_4GV_WB_MODEM: {
 		struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate;
 
 		pr_debug("Setting EVRC min-max rate\n");