Merge "msm8974: mhl_sii8334: init chip on discovery"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index d07eba6..3947f75 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -28,11 +28,21 @@
 			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
+- qcom,core-temp-hysteresis: Degrees C below which the cores will be brought
 			online in sequence.
 - qcom,core-control-mask: The cpu mask that will be used to determine if a
 			core can be controlled or not. A mask of 0 indicates
 			the feature is disabled.
+- qcom,hotplug-temp: Threshold temperature to start shutting down cores
+			in degC. This will be used when polling based
+			core control is disabled. The difference between hotplug-temp
+			and core-limit-temp is that core-limit-temp is used during
+			early boot prior to thermal_sys being available for hotplug.
+- qcom,hotplug-temp-hysteresis: Degrees C below which thermal will not force the
+			cores to be offlined. Cores can be brought online if needed.
+- qcpm,cpu-sensors:     List of type names in thermal zone device struct which maps
+			to cpu0, cpu1, cpu2, cpu3 in sequence depending on how many
+			cpus there are.
 - qcom,vdd-restriction-temp: When temperature is below this threshold, will
 			enable vdd restriction which will set higher voltage on
 			key voltage rails, in degC.
@@ -81,8 +91,12 @@
 		qcom,freq-step = <2>;
 		qcom,freq-control-mask = <0xf>
 		qcom,core-limit-temp = <90>;
-		qcom,core-temp-hysterisis = <10>;
+		qcom,core-temp-hysteresis = <10>;
 		qcom,core-control-mask = <7>;
+		qcom,hotplug-temp = <110>;
+		qcom,hotplug-temp-hysteresis = <20>;
+		qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor6",
+				"tsens_tz_sensor7", "tsens_tz_sensor8";
 		qcom,pmic-sw-mode-temp = <90>;
 		qcom,pmic-sw-mode-temp-hysteresis = <80>;
 		qcom,pmic-sw-mode-regs = "vdd-dig";
diff --git a/arch/arm/boot/dts/batterydata-qrd-4v2-1800mah.dtsi b/arch/arm/boot/dts/batterydata-qrd-4v2-1800mah.dtsi
new file mode 100644
index 0000000..e44e943
--- /dev/null
+++ b/arch/arm/boot/dts/batterydata-qrd-4v2-1800mah.dtsi
@@ -0,0 +1,105 @@
+/* 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.
+ */
+
+qcom,qrd-4v2-1800mah-data {
+	qcom,fcc-mah = <1800>;
+	qcom,default-rbatt-mohm = <146>;
+	qcom,rbatt-capacitive-mohm = <0>;
+	qcom,flat-ocv-threshold-uv = <3800000>;
+	qcom,max-voltage-uv = <4200000>;
+	qcom,v-cutoff-uv = <3400000>;
+	qcom,chg-term-ua = <100000>;
+	qcom,batt-id-kohm = <47>;
+
+	qcom,rbatt-sf-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-row-legend = <100 95 90 85 80>,
+				<75 70 65 60 55>,
+				<50 45 40 35 30>,
+				<25 20 15 10 9>,
+				<8 7 6 5 4>,
+				<3 2 1 0>;
+		qcom,lut-data = <904 234 100 85 80>,
+				<905 234 100 85 80>,
+				<934 244 102 86 81>,
+				<928 254 105 87 82>,
+				<933 268 109 89 84>,
+				<924 280 114 91 85>,
+				<913 283 123 96 88>,
+				<916 267 135 103 91>,
+				<930 252 137 110 95>,
+				<954 247 117 106 95>,
+				<990 247 103 88 85>,
+				<1036 253 104 86 84>,
+				<1101 264 108 89 85>,
+				<1211 286 112 93 88>,
+				<1366 340 120 95 87>,
+				<1601 394 128 95 87>,
+				<2178 402 128 97 89>,
+				<5419 423 126 97 89>,
+				<10789 528 128 97 91>,
+				<13463 589 132 100 91>,
+				<17695 678 137 102 92>,
+				<23046 814 145 104 93>,
+				<30725 1019 153 106 93>,
+				<41382 1359 156 106 93>,
+				<56311 1959 165 108 95>,
+				<77209 3523 189 117 99>,
+				<104609 6039 235 127 105>,
+				<138858 9711 352 141 112>,
+				<165825 15373 1069 246 226>;
+	};
+
+	qcom,fcc-temp-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-data = <1859 1868 1873 1861 1859>;
+	};
+
+	qcom,pc-temp-ocv-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-row-legend = <100 95 90 85 80>,
+				<75 70 65 60 55>,
+				<50 45 40 35 30>,
+				<25 20 15 10 9>,
+				<8 7 6 5 4>,
+				<3 2 1 0>;
+		qcom,lut-data = <4178 4176 4174 4169 4163>,
+				<4090 4100 4105 4101 4099>,
+				<4029 4049 4053 4050 4048>,
+				<3973 3998 4006 4004 4002>,
+				<3932 3959 3965 3962 3960>,
+				<3891 3920 3928 3925 3922>,
+				<3855 3882 3894 3891 3889>,
+				<3825 3844 3862 3862 3859>,
+				<3803 3813 3829 3834 3831>,
+				<3788 3792 3797 3802 3800>,
+				<3777 3780 3778 3776 3773>,
+				<3764 3775 3771 3767 3763>,
+				<3749 3769 3766 3763 3757>,
+				<3725 3756 3758 3755 3750>,
+				<3687 3727 3736 3735 3729>,
+				<3631 3675 3698 3698 3691>,
+				<3571 3607 3637 3642 3637>,
+				<3514 3548 3568 3572 3570>,
+				<3458 3506 3519 3522 3522>,
+				<3444 3498 3511 3516 3515>,
+				<3430 3489 3503 3509 3508>,
+				<3413 3477 3493 3500 3500>,
+				<3395 3461 3478 3488 3486>,
+				<3373 3433 3446 3463 3456>,
+				<3346 3394 3397 3418 3410>,
+				<3307 3341 3334 3361 3352>,
+				<3251 3270 3254 3287 3277>,
+				<3160 3167 3152 3183 3172>,
+				<3000 3000 3000 3000 3000>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index a2d80ec..43bd0c9 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -238,5 +238,28 @@
 				reg = <0x2b00 0x100>;
 			};
 		};
+
+		krait_regulator_pmic: qcom,krait-regulator-pmic@2000 {
+			spmi-dev-container;
+			compatible = "qcom,krait-regulator-pmic";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+
+			qcom,ctl@2000 {
+				status = "disabled";
+				reg = <0x2000 0x100>;
+			};
+
+			qcom,ps@2100 {
+				status = "disabled";
+				reg = <0x2100 0x100>;
+			};
+
+			qcom,freq@2200 {
+				status = "disabled";
+				reg = <0x2200 0x100>;
+			};
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm-pma8084.dtsi b/arch/arm/boot/dts/msm-pma8084.dtsi
index 3ff1b60..c070443 100644
--- a/arch/arm/boot/dts/msm-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm-pma8084.dtsi
@@ -814,5 +814,28 @@
 			compatible = "qcom,qpnp-regulator";
 			status = "disabled";
 		};
+
+		krait_regulator_pmic: qcom,krait-regulator-pmic@2900 {
+			spmi-dev-container;
+			compatible = "qcom,krait-regulator-pmic";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+
+			qcom,ctl@2900 {
+				reg = <0x2900 0x100>;
+				status = "disabled";
+			};
+
+			qcom,ps@2a00 {
+				reg = <0x2a00 0x100>;
+				status = "disabled";
+			};
+
+			qcom,freq@2b00 {
+				reg = <0x2b00 0x100>;
+				status = "disabled";
+			};
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index 0a3148b..9e98681 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -31,3 +31,7 @@
 		qcom,cont-splash-enabled;
         };
 };
+
+&pm8226_bms {
+        qcom,use-external-rsense;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 95af304..320cea1 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -160,3 +160,7 @@
 		qcom,fast-avg-setup = <0>;
 	};
 };
+
+&pm8226_iadc {
+	qcom,rsense = <10000000>;
+};
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
index cef04ef..6b72e66 100644
--- a/arch/arm/boot/dts/msm8610-bus.dtsi
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -952,6 +952,7 @@
 			cell-id = <2048>;
 			label = "fab_mmss_noc";
 			qcom,masterp = <1>;
+			qcom,gateway;
 			qcom,qport = <1>;
 			qcom,buswidth = <8>;
 			qcom,ws = <10000>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index f3470c2..5e533ee 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -52,7 +52,7 @@
 				/* Object 6, Instance = 0 */
 				00 00 00 00 00 00
 				/* Object 38, Instance = 0 */
-				1D 02 00 0A 06 0D 00 00
+				1D 03 00 1E 07 0D 00 00
 				/* Object 7, Instance = 0 */
 				20 08 32
 				/* Object 8, Instance = 0 */
@@ -60,7 +60,7 @@
 				/* Object 9, Instance = 0 */
 				83 00 00 13 0B 00 20 32 01 03
 				00 32 05 30 0A 05 0A 00 70 03
-				FC 01 00 36 2F D8 00 00 40 00
+				FC 01 04 2F F8 DC 00 00 40 00
 				00 0A 00 00 02
 				/* Object 18, Instance = 0 */
 				00 00
@@ -143,6 +143,10 @@
             "AMIC1", "MIC BIAS External",
             "AMIC2", "MIC BIAS Internal2";
     };
+
+	qcom,dsi_v2_truly_wvga_video {
+		qcom,cont-splash-enabled;
+	};
 };
 
 &i2c_cdc  {
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 2041bf6..98a99a7 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -16,6 +16,8 @@
 		reg = <0xfc326000 0x1000>,
 		      <0xfc37c000 0x3000>;
 		reg-names = "tmc-base", "bam-base";
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
 
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 0d4c174..a70f8dc 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -52,7 +52,7 @@
 				/* Object 6, Instance = 0 */
 				00 00 00 00 00 00
 				/* Object 38, Instance = 0 */
-				1D 02 00 0A 06 0D 00 00
+				1D 03 00 1E 07 0D 00 00
 				/* Object 7, Instance = 0 */
 				20 08 32
 				/* Object 8, Instance = 0 */
@@ -60,7 +60,7 @@
 				/* Object 9, Instance = 0 */
 				83 00 00 13 0B 00 20 32 01 03
 				00 32 05 30 0A 05 0A 00 70 03
-				FC 01 00 36 2F D8 00 00 40 00
+				FC 01 04 2F F8 DC 00 00 40 00
 				00 0A 00 00 02
 				/* Object 18, Instance = 0 */
 				00 00
@@ -181,6 +181,10 @@
             "AMIC1", "MIC BIAS External",
             "AMIC2", "MIC BIAS Internal2";
     };
+
+	qcom,dsi_v2_truly_wvga_video {
+		qcom,cont-splash-enabled;
+	};
 };
 
 &i2c_cdc  {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index d31a65c..b1ec4fe 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -208,45 +208,43 @@
 
 		qcom,gpio-parent = <&msmgpio>;
 		qcom,gpio-map = <3  1>,
-			<4  4 >,
-			<5  5 >,
-			<6  9 >,
-			<7  13>,
-			<8  17>,
-			<9  21>,
-			<10  27>,
-			<11  29>,
-			<12  31>,
-			<13  33>,
-			<14  35>,
-			<15  37>,
-			<16  38>,
-			<17  39>,
-			<18  41>,
-			<19  46>,
-			<20  48>,
-			<21  49>,
-			<22  50>,
-			<23  51>,
-			<24  52>,
-			<25  54>,
-			<26  62>,
-			<27  63>,
-			<28  64>,
-			<29  65>,
-			<30  66>,
-			<31  67>,
-			<32  68>,
-			<33  69>,
-			<34  71>,
-			<35  72>,
-			<36  106>,
-			<37  107>,
-			<38  108>,
-			<39  109>,
-			<40  110>,
-			<54  111>,
-			<55  113>;
+			<4  5 >,
+			<5  9 >,
+			<6  14>,
+			<7  15>,
+			<8  32>,
+			<9  33>,
+			<10  34>,
+			<11  35>,
+			<12  41>,
+			<13  42>,
+			<14  72>,
+			<15  73>,
+			<16  74>,
+			<17  75>,
+			<18  76>,
+			<19  77>,
+			<20  78>,
+			<21  79>,
+			<22  80>,
+			<23  81>,
+			<24  82>,
+			<25  83>,
+			<26  84>,
+			<27  85>,
+			<28  87>,
+			<29  90>,
+			<30  91>,
+			<31  92>,
+			<32  93>,
+			<33  94>,
+			<34  95>,
+			<35  96>,
+			<36  97>,
+			<37  98>,
+			<38  99>,
+			<39  100>,
+			<40  101>;
 	};
 
 	qcom,pm-8x60@fe805664 {
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
index aeaf8ca..e220e6f 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
@@ -45,3 +45,10 @@
 	status = "ok";
 	qcom,batt-type = <5>;
 };
+
+&pm8110_vadc {
+	chan@30 {
+		label = "batt_therm";
+		qcom,scale-function = <7>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index 947a312..2948dec 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -80,7 +80,30 @@
 		};
 	};
 
+	usb@f9a55000 {
+               qcom,hsusb-otg-phy-init-seq =
+                       <0x44 0x80 0x6a 0x81 0x34 0x82 0x23 0x83 0xffffffff>;
+	};
+
 	qcom,dsi_v2_otm8018b_fwvga_video {
 		status = "ok";
 	};
 };
+
+/ {
+	qrd_batterydata: qcom,battery-data {
+		qcom,rpull-up-kohm = <100>;
+		qcom,vref-batt-therm = <1800000>;
+
+		/include/ "batterydata-qrd-4v2-1800mah.dtsi"
+	};
+};
+
+&pm8110_bms {
+	status = "ok";
+	qcom,battery-data = <&qrd_batterydata>;
+};
+
+&pm8110_chg {
+	qcom,battery-data = <&qrd_batterydata>;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index bd1705f..d1bf471 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -344,3 +344,10 @@
 	mpp@a300 { /* MPP 4 */
 	};
 };
+
+&pm8110_vadc {
+	chan@30 {
+		label = "batt_therm";
+		qcom,scale-function = <6>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index c6104bf..b943932 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -929,10 +929,16 @@
 };
 
 &gdsc_vfe {
+	qcom,clock-names = "core_clk", "iface_clk", "bus_clk";
+	qcom,skip-logic-collapse;
+	qcom,retain-periph;
+	qcom,retain-mem;
 	status = "ok";
 };
 
 &gdsc_oxili_cx {
+	qcom,clock-names = "core_clk", "iface_clk", "mem_clk";
+	qcom,skip-logic-collapse;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 5afcb4e..9159ba2 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -78,6 +78,10 @@
 	qcom,slope = <2901 2846 3038 2955 2901 2846>;
 };
 
+&msmgpio {
+	ngpio = <120>;
+};
+
 &memory_hole {
 	qcom,memblock-remove = <0x08000000 0x7500000
 				0x0fa00000 0x500000>; /* Address and size of the hole */
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 63f6d59..455ed2d 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -55,5 +55,12 @@
 			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
 			qcom,memory-reservation-size = <0x614000>;
 		};
+
+		qcom,ion-heap@23 { /* OTHER PIL HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <23>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-fixed = <0x05d00000 0x1e00000>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index 86a61cd..249c963 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -165,3 +165,19 @@
 	qcom,retain-mem;
 	qcom,retain-periph;
 };
+
+&krait_regulator_pmic {
+	status = "ok";
+
+	qcom,ctl@2000 {
+		status = "ok";
+	};
+
+	qcom,ps@2100 {
+		status = "ok";
+	};
+
+	qcom,freq@2200 {
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 9d5e50b..af4030f 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -168,3 +168,19 @@
 &tspp {
 	vdd_cx-supply = <&pm8841_s2_corner>;
 };
+
+&krait_regulator_pmic {
+	status = "ok";
+
+	qcom,ctl@2000 {
+		status = "ok";
+	};
+
+	qcom,ps@2100 {
+		status = "ok";
+	};
+
+	qcom,freq@2200 {
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index c8e3d96..bcea24e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1504,6 +1504,10 @@
 		qcom,core-limit-temp = <80>;
 		qcom,core-temp-hysteresis = <10>;
 		qcom,core-control-mask = <0xe>;
+		qcom,hotplug-temp = <110>;
+		qcom,hotplug-temp-hysteresis = <20>;
+		qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor6",
+				"tsens_tz_sensor7", "tsens_tz_sensor8";
 		qcom,vdd-restriction-temp = <5>;
 		qcom,vdd-restriction-temp-hysteresis = <10>;
 		qcom,pmic-sw-mode-temp = <85>;
@@ -1540,7 +1544,7 @@
 
         memory_hole: qcom,msm-mem-hole {
                 compatible = "qcom,msm-mem-hole";
-                qcom,memblock-remove = <0x7b00000 0x8400000>; /* Address and Size of Hole */
+                qcom,memblock-remove = <0x5d00000 0xa200000>; /* Address and Size of Hole */
         };
 
 	uart7: uart@f995d000 { /*BLSP #2, UART #7 */
diff --git a/arch/arm/boot/dts/msm8974pro-ab.dtsi b/arch/arm/boot/dts/msm8974pro-ab.dtsi
index 88687bd..5809069 100644
--- a/arch/arm/boot/dts/msm8974pro-ab.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ab.dtsi
@@ -39,3 +39,19 @@
 &tspp {
 	vdd_cx-supply = <&pm8841_s2_corner>;
 };
+
+&krait_regulator_pmic {
+	status = "ok";
+
+	qcom,ctl@2000 {
+		status = "ok";
+	};
+
+	qcom,ps@2100 {
+		status = "ok";
+	};
+
+	qcom,freq@2200 {
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
index 250afd2..debf7fb 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
@@ -62,10 +62,6 @@
 		vbus_dwc3-supply = <&pm8941_mvs1>;
 	};
 
-	qcom,mdss_dsi_toshiba_720p_video {
-		qcom,rst-gpio = <&pma8084_gpios 20 0>;
-	};
-
 	gpio_keys {
 		camera_snapshot {
 			gpios = <&pma8084_gpios 3 0x1>;
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index 032c256..4c55169 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -52,6 +52,7 @@
 		vdd-supply = <&pma8084_l22>;
 		vddio-supply = <&pma8084_l12>;
 		vdda-supply = <&pma8084_l2>;
+		qcom,platform-reset-gpio = <&pma8084_gpios 20 0>;
 	};
 
 	qcom,mdss_dsi@fd922e00 {
@@ -188,3 +189,19 @@
 &tspp {
 	vdd_cx-supply = <&pma8084_s2_corner>;
 };
+
+&krait_regulator_pmic {
+	status = "ok";
+
+	qcom,ctl@2900 {
+		status = "ok";
+	};
+
+	qcom,ps@2a00 {
+		status = "ok";
+	};
+
+	qcom,freq@2b00 {
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
new file mode 100644
index 0000000..31bff88
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -0,0 +1,340 @@
+/* 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,spm@f9089000 {
+		compatible = "qcom,spm-v2";
+	#address-cells = <1>;
+	#size-cells = <1>;
+		reg = <0xf9089000 0x1000>;
+		qcom,core-id = <0>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x3C102800>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+
+	qcom,spm@f9099000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9099000 0x1000>;
+		qcom,core-id = <1>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x3C102800>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+
+	qcom,spm@f90a9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf90a9000 0x1000>;
+		qcom,core-id = <2>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x3C102800>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+
+	qcom,spm@f90b9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf90b9000 0x1000>;
+		qcom,core-id = <3>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x3C102800>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+
+	qcom,spm@f9012000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9012000 0x1000>;
+		qcom,core-id = <0xffff>; /* L2/APCS SAW */
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x14>;
+		qcom,saw2-avs-ctl = <0>;
+		qcom,saw2-avs-hysteresis = <0>;
+		qcom,saw2-avs-limit = <0>;
+		qcom,saw2-avs-dly= <0>;
+		qcom,saw2-spm-dly= <0x3C102800>;
+		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-pmic-data0 = <0x02030080>;
+		qcom,saw2-pmic-data1 = <0x00030000>;
+		qcom,vctl-timeout-us = <50>;
+		qcom,vctl-port = <0x0>;
+		qcom,phase-port = <0x1>;
+		qcom,pfm-port = <0x2>;
+		qcom,saw2-spm-cmd-ret = [1f 00 03 00 0f];
+		qcom,saw2-spm-cmd-gdhs = [00 32 42 07 44 50 02 32 50 0f];
+		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
+				50 02 32 50 0f];
+	};
+
+	qcom,lpm-levels {
+		compatible = "qcom,lpm-levels";
+		qcom,default-l2-state = "l2_cache_retention";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,lpm-level@0 {
+			reg = <0x0>;
+			qcom,mode = "wfi";
+			qcom,l2 = "l2_cache_retention";
+			qcom,latency-us = <1>;
+			qcom,ss-power = <715>;
+			qcom,energy-overhead = <17700>;
+			qcom,time-overhead = <2>;
+		};
+
+		qcom,lpm-level@1 {
+			reg = <0x1>;
+			qcom,mode = "retention";
+			qcom,l2 = "l2_cache_retention";
+			qcom,latency-us = <35>;
+			qcom,ss-power = <542>;
+			qcom,energy-overhead = <34920>;
+			qcom,time-overhead = <40>;
+		};
+
+
+		qcom,lpm-level@2 {
+			reg = <0x2>;
+			qcom,mode = "standalone_pc";
+			qcom,l2 = "l2_cache_retention";
+			qcom,latency-us = <300>;
+			qcom,ss-power = <476>;
+			qcom,energy-overhead = <225300>;
+			qcom,time-overhead = <350>;
+		};
+
+		qcom,lpm-level@3 {
+			reg = <0x3>;
+			qcom,mode = "pc";
+			qcom,l2 = "l2_cache_gdhs";
+			qcom,gpio-detectable;
+			qcom,latency-us = <20000>;
+			qcom,ss-power = <163>;
+			qcom,energy-overhead = <1577736>;
+			qcom,time-overhead = <5067>;
+		};
+
+		qcom,lpm-level@4 {
+			reg = <0x4>;
+			qcom,mode = "pc";
+			qcom,l2 = "l2_cache_pc";
+			qcom,latency-us = <30000>;
+			qcom,ss-power = <83>;
+			qcom,energy-overhead = <2274420>;
+			qcom,time-overhead = <6605>;
+		};
+	};
+
+	qcom,pm-boot {
+		compatible = "qcom,pm-boot";
+		qcom,mode = "tz";
+	};
+
+	qcom,mpm@fc4281d0 {
+		compatible = "qcom,mpm-v2";
+		reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+		    <0xf9011008 0x4>;   /* MSM_APCS_GCC_BASE 4K */
+		reg-names = "vmpm", "ipc";
+		interrupts = <0 171 1>;
+
+		qcom,ipc-bit-offset = <1>;
+
+		qcom,gic-parent = <&intc>;
+		qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
+			<47 165>, /* usb30_hs_phy_irq */
+			<50 172>, /* usb1_hs_async_wakeup_irq */
+			<53 104>, /* mdss_irq */
+			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 56>,  /* modem_watchdog */
+			<0xff 57>,  /* mss_to_apps_irq(0) */
+			<0xff 58>,  /* mss_to_apps_irq(1) */
+			<0xff 59>,  /* mss_to_apps_irq(2) */
+			<0xff 60>,  /* mss_to_apps_irq(3) */
+			<0xff 61>,  /* mss_a2_bam_irq */
+			<0xff 70>,  /* iommu_pmon_nonsecure_irq */
+			<0xff 97>,  /* iommu_nonsecure_irq */
+			<0xff 105>, /* iommu_pmon_nonsecure_irq */
+			<0xff 173>, /* o_wcss_apss_smd_hi */
+			<0xff 174>, /* o_wcss_apss_smd_med */
+			<0xff 175>, /* o_wcss_apss_smd_low */
+			<0xff 176>, /* o_wcss_apss_smsm_irq */
+			<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
+			<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
+			<0xff 179>, /* o_wcss_apss_asic_intr */
+
+			<0xff 181>, /* wcnss watchdog */
+			<0xff 188>, /* lpass_irq_out_apcs(0) */
+			<0xff 189>, /* lpass_irq_out_apcs(1) */
+			<0xff 190>, /* lpass_irq_out_apcs(2) */
+			<0xff 191>, /* lpass_irq_out_apcs(3) */
+			<0xff 192>, /* lpass_irq_out_apcs(4) */
+			<0xff 193>, /* lpass_irq_out_apcs(5) */
+			<0xff 194>, /* lpass_irq_out_apcs(6) */
+			<0xff 195>, /* lpass_irq_out_apcs(7) */
+			<0xff 196>, /* lpass_irq_out_apcs(8) */
+			<0xff 197>, /* lpass_irq_out_apcs(9) */
+			<0xff 200>, /* rpm_ipc(4) */
+			<0xff 201>, /* rpm_ipc(5) */
+			<0xff 202>, /* rpm_ipc(6) */
+			<0xff 203>, /* rpm_ipc(7) */
+			<0xff 204>, /* rpm_ipc(24) */
+			<0xff 205>, /* rpm_ipc(25) */
+			<0xff 206>, /* rpm_ipc(26) */
+			<0xff 207>, /* rpm_ipc(27) */
+			<0xff 211>, /* usb_dwc3_otg */
+			<0xff 240>; /* summary_irq_kpss */
+
+		qcom,gpio-parent = <&msmgpio>;
+		qcom,gpio-map = <3  102>,
+			<4  1 >,
+			<5  5 >,
+			<6  9 >,
+			<7  18>,
+			<8  20>,
+			<9  24>,
+			<10  27>,
+			<11  28>,
+			<12  34>,
+			<13  35>,
+			<14  37>,
+			<15  42>,
+			<16  44>,
+			<17  46>,
+			<18  50>,
+			<19  54>,
+			<20  59>,
+			<21  61>,
+			<22  62>,
+			<23  64>,
+			<24  65>,
+			<25  66>,
+			<26  67>,
+			<27  68>,
+			<28  71>,
+			<29  72>,
+			<30  73>,
+			<31  74>,
+			<32  75>,
+			<33  77>,
+			<34  79>,
+			<35  80>,
+			<36  82>,
+			<37  86>,
+			<38  92>,
+			<39  93>,
+			<40  95>,
+			<41  144>;
+	};
+
+	qcom,pm-8x60@fe805664 {
+		compatible = "qcom,pm-8x60";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0xfe805664 0x40>;
+		qcom,pc-mode = "tz_l2_int";
+		qcom,use-sync-timer;
+		qcom,cpus-as-clocks;
+
+		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>;
+		qcom,cpu-alias-addr = <0x10000>;
+		qcom,sleep-status-mask= <0x80000>;
+	};
+
+	qcom,rpm-log@fc19dc00 {
+		compatible = "qcom,rpm-log";
+		reg = <0xfc19dc00 0x4000>;
+		qcom,rpm-addr-phys = <0xfc000000>;
+		qcom,offset-version = <4>;
+		qcom,offset-page-buffer-addr = <36>;
+		qcom,offset-log-len = <40>;
+		qcom,offset-log-len-mask = <44>;
+		qcom,offset-page-indices = <56>;
+	};
+
+	qcom,rpm-stats@fc19dba0 {
+		compatible = "qcom,rpm-stats";
+		reg = <0xfc19dba0 0x1000>;
+		reg-names = "phys_addr_base";
+		qcom,sleep-stats-version = <2>;
+	};
+
+	qcom,rpm-rbcpr-stats@fc000000 {
+		compatible = "qcom,rpmrbcpr-stats";
+		reg = <0xfc000000 0x1a0000>;
+		qcom,start-offset = <0x190010>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index e7c6a48..7914a6a 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -19,7 +19,7 @@
 /include/ "msm8974.dtsi"
 /include/ "msm8974-v2-iommu.dtsi"
 /include/ "msm8974-v2-iommu-domains.dtsi"
-/include/ "msm8974-v2-pm.dtsi"
+/include/ "msm8974pro-pm.dtsi"
 /include/ "msm8974pro-ion.dtsi"
 
 &soc {
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 67ed35c..47b425c 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -1,6 +1,5 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
@@ -72,6 +71,7 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index d42d54d..97c3664 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -1,6 +1,5 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
@@ -73,6 +72,7 @@
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_XPU_ERR_FATAL=y
+CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index b9d37b8..b8dc0d7b 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -69,10 +69,9 @@
 CONFIG_MSM_OCMEM_NONSECURE=y
 CONFIG_MSM_OCMEM_POWER_DISABLE=y
 CONFIG_SENSORS_ADSP=y
-CONFIG_MSM_RTB=y
-CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index a5f0704..dd4274a 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -1,6 +1,5 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
@@ -71,6 +70,7 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index e4a647f..6078901 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -296,7 +296,7 @@
 obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
 obj-$(CONFIG_ARCH_MPQ8092) += gdsc.o
 obj-$(CONFIG_ARCH_APQ8084) += gdsc.o
-obj-$(CONFIG_KRAIT_REGULATOR) += krait-regulator.o
+obj-$(CONFIG_KRAIT_REGULATOR) += krait-regulator.o  krait-regulator-pmic.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
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 39916ef..f8c206b 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -240,6 +240,7 @@
 #define                 GFX3D_CMD_RCGR	    0x4000
 #define               OXILI_GFX3D_CBCR	    0x4028
 #define                OXILI_GFX3D_BCR	    0x4030
+#define                 GMEM_GFX3D_BCR	    0x4040
 #define                  OXILI_AHB_BCR	    0x4044
 #define                 OXILI_AHB_CBCR	    0x403C
 #define                   AHB_CMD_RCGR	    0x5000
@@ -2147,6 +2148,7 @@
 
 static struct branch_clk csi_vfe_clk = {
 	.cbcr_reg = CSI_VFE_CBCR,
+	.bcr_reg = CSI_VFE_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2217,6 +2219,7 @@
 
 static struct branch_clk gmem_gfx3d_clk = {
 	.cbcr_reg = GMEM_GFX3D_CBCR,
+	.bcr_reg = GMEM_GFX3D_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2358,6 +2361,7 @@
 
 static struct branch_clk oxili_ahb_clk = {
 	.cbcr_reg = OXILI_AHB_CBCR,
+	.bcr_reg = OXILI_AHB_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2369,6 +2373,7 @@
 
 static struct branch_clk oxili_gfx3d_clk = {
 	.cbcr_reg = OXILI_GFX3D_CBCR,
+	.bcr_reg = OXILI_GFX3D_BCR,
 	.has_sibling = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2381,6 +2386,7 @@
 
 static struct branch_clk vfe_clk = {
 	.cbcr_reg = VFE_CBCR,
+	.bcr_reg = VFE_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2393,6 +2399,7 @@
 
 static struct branch_clk vfe_ahb_clk = {
 	.cbcr_reg = VFE_AHB_CBCR,
+	.bcr_reg = VFE_AHB_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
@@ -2404,6 +2411,7 @@
 
 static struct branch_clk vfe_axi_clk = {
 	.cbcr_reg = VFE_AXI_CBCR,
+	.bcr_reg = VFE_AXI_BCR,
 	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	 /* FIXME: Remove this once simulation is fixed. */
@@ -3133,6 +3141,14 @@
 	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c, "fd404000.qcom,qcrypto"),
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c, "fd404000.qcom,qcrypto"),
 	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,     "fd404000.qcom,qcrypto"),
+
+	/* GDSC clocks */
+	CLK_LOOKUP("core_clk", vfe_clk.c,	"fd8c36a4.qcom,gdsc"),
+	CLK_LOOKUP("iface_clk", vfe_ahb_clk.c,	"fd8c36a4.qcom,gdsc"),
+	CLK_LOOKUP("bus_clk",  vfe_axi_clk.c,	"fd8c36a4.qcom,gdsc"),
+	CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fd8c4034.qcom,gdsc"),
+	CLK_LOOKUP("iface_clk", oxili_ahb_clk.c, "fd8c4034.qcom,gdsc"),
+	CLK_LOOKUP("mem_clk", gmem_gfx3d_clk.c, "fd8c4034.qcom,gdsc"),
 };
 
 static struct clk_lookup msm_clocks_8610_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index b7852fe..4488869 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -549,19 +549,21 @@
 	u32 cbcr_val;
 	unsigned long irq_flags;
 	struct branch_clk *branch = to_branch_clk(c);
-	int ret = 0;
+	int delay_us = 0, ret = 0;
 
 	spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
 	cbcr_val = readl_relaxed(CBCR_REG(branch));
 	switch (flags) {
 	case CLKFLAG_RETAIN_PERIPH:
 		cbcr_val |= BIT(13);
+		delay_us = 1;
 		break;
 	case CLKFLAG_NORETAIN_PERIPH:
 		cbcr_val &= ~BIT(13);
 		break;
 	case CLKFLAG_RETAIN_MEM:
 		cbcr_val |= BIT(14);
+		delay_us = 1;
 		break;
 	case CLKFLAG_NORETAIN_MEM:
 		cbcr_val &= ~BIT(14);
@@ -570,17 +572,11 @@
 		ret = -EINVAL;
 	}
 	writel_relaxed(cbcr_val, CBCR_REG(branch));
-	/*
-	 * 8974v2.2 has a requirement that writes to set bits 13 and 14 are
-	 * separated by at least 2 bus cycles. Cover one of these cycles by
-	 * performing an extra write here. The other cycle is covered by the
-	 * read-modify-write design of this function.
-	 */
-	writel_relaxed(cbcr_val, CBCR_REG(branch));
-	spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
-
-	/* Make sure write is issued before returning. */
+	/* Make sure power is enabled before returning. */
 	mb();
+	udelay(delay_us);
+
+	spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
 
 	return ret;
 }
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 774548c..ea4865d 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -111,6 +111,13 @@
 	uint32_t regval;
 	int i, ret = 0;
 
+	for (i = sc->clock_count-1; i >= 0; i--) {
+		if (sc->toggle_mem)
+			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
+		if (sc->toggle_periph)
+			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
+	}
+
 	if (sc->toggle_logic) {
 		regval = readl_relaxed(sc->gdscr);
 		regval |= SW_COLLAPSE_MASK;
@@ -123,18 +130,11 @@
 			dev_err(&rdev->dev, "%s disable timed out\n",
 				sc->rdesc.name);
 	} else {
-		for (i = 0; i < sc->clock_count; i++)
+		for (i = sc->clock_count-1; i >= 0; i--)
 			clk_reset(sc->clocks[i], CLK_RESET_ASSERT);
 		sc->resets_asserted = true;
 	}
 
-	for (i = 0; i < sc->clock_count; i++) {
-		if (sc->toggle_mem)
-			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
-		if (sc->toggle_periph)
-			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
-	}
-
 	return ret;
 }
 
@@ -225,20 +225,9 @@
 
 	retain_mem = of_property_read_bool(pdev->dev.of_node,
 					    "qcom,retain-mem");
+	sc->toggle_mem = !retain_mem;
 	retain_periph = of_property_read_bool(pdev->dev.of_node,
 					    "qcom,retain-periph");
-	for (i = 0; i < sc->clock_count; i++) {
-		if (retain_mem || (regval & PWR_ON_MASK))
-			clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_MEM);
-		else
-			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
-
-		if (retain_periph || (regval & PWR_ON_MASK))
-			clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_PERIPH);
-		else
-			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
-	}
-	sc->toggle_mem = !retain_mem;
 	sc->toggle_periph = !retain_periph;
 	sc->toggle_logic = !of_property_read_bool(pdev->dev.of_node,
 						"qcom,skip-logic-collapse");
@@ -255,6 +244,18 @@
 		}
 	}
 
+	for (i = 0; i < sc->clock_count; i++) {
+		if (retain_mem || (regval & PWR_ON_MASK))
+			clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_MEM);
+		else
+			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
+
+		if (retain_periph || (regval & PWR_ON_MASK))
+			clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_PERIPH);
+		else
+			clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
+	}
+
 	sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
 				      pdev->dev.of_node);
 	if (IS_ERR(sc->rdev)) {
diff --git a/arch/arm/mach-msm/krait-regulator-pmic.c b/arch/arm/mach-msm/krait-regulator-pmic.c
new file mode 100644
index 0000000..5081e7b
--- /dev/null
+++ b/arch/arm/mach-msm/krait-regulator-pmic.c
@@ -0,0 +1,403 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt)	"PMIC PDN %s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/spmi.h>
+#include <linux/delay.h>
+
+#define KRAIT_REG_PMIC_DEV_NAME "qcom,krait-regulator-pmic"
+
+#define REG_DIG_MAJOR		0x01
+#define REG_DIG_MINOR		0x00
+
+#define REG_PERPH_TYPE		0x04
+#define CTRL_TYPE_VAL		0x1C
+#define PS_TYPE_VAL		0x1C
+#define FREQ_TYPE_VAL		0x1D
+
+#define REG_PERPH_SUBTYPE	0x05
+#define CTRL_SUBTYPE_VAL	0x08
+#define PS_SUBTYPE_VAL		0x01
+#define FREQ_SUBTYPE_VAL	0x19
+
+#define REG_V_CTL1		0x40
+#define V_CTL1_VAL		0x00
+
+#define REG_MODE_CTL		0x45
+#define NPM_MODE_BIT		BIT(7)
+#define AUTO_MODE_BIT		BIT(6)
+
+#define REG_EN_CTL		0x46
+#define EN_BIT			BIT(7)
+
+#define REG_PD_CTL		0x48
+#define PD_CTL_VAL		0x08
+
+#define REG_MULTIPHASE_CTL	0x51
+#define MULTIPHASE_EN_BIT	BIT(7)
+
+#define REG_PHASE_CTL		0x52
+#define BALANCE_EN_BIT		BIT(7)
+
+#define REG_VS_CTL		0x61
+#define VS_CTL_VAL		0x85
+
+#define REG_GANG_CTL2		0xC1
+#define GANG_EN_BIT		BIT(7)
+
+#define REG_PWM_CL			0x60
+
+struct krait_vreg_pmic_chip {
+	struct spmi_device	*spmi;
+	u16			ctrl_base;
+	u16			ps_base;
+	u16			freq_base;
+	u8			ctrl_dig_major;
+	u8			ctrl_dig_minor;
+};
+
+static struct krait_vreg_pmic_chip *the_chip;
+
+static struct of_device_id krait_vreg_pmic_match_table[] = {
+	{ .compatible = KRAIT_REG_PMIC_DEV_NAME },
+	{}
+};
+
+static int read_byte(struct spmi_device *spmi, u16 addr, u8 *val)
+{
+	int rc;
+
+	rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, 1);
+	if (rc) {
+		pr_err("SPMI read failed [%d,0x%04x] rc=%d\n",
+							spmi->sid, addr, rc);
+		return rc;
+	}
+	return 0;
+}
+
+static int write_byte(struct spmi_device *spmi, u16 addr, u8 *val)
+{
+	int rc;
+
+	rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, 1);
+	if (rc) {
+		pr_err("SPMI write failed [%d,0x%04x] val = 0x%02x rc=%d\n",
+						spmi->sid, addr, *val, rc);
+		return rc;
+	}
+	return 0;
+}
+
+#define ISTEP_MA			500
+#define IOFFSET_MA			1000
+#define OVERSHOOT_DIG_MAJOR		1
+#define OVERSHOOT_DIG_MINOR		1
+static bool v_overshoot_fixed(void)
+{
+	if (the_chip->ctrl_dig_major > OVERSHOOT_DIG_MAJOR
+		|| (the_chip->ctrl_dig_major == OVERSHOOT_DIG_MAJOR
+		&& the_chip->ctrl_dig_minor > OVERSHOOT_DIG_MINOR)) {
+		pr_debug("fixed in h/w\n");
+		return true;
+	}
+	return false;
+}
+
+/**
+ * krait_pmic_is_ready - function to check if the driver is initialized
+ *
+ * CONTEXT: Can be called in atomic context
+ *
+ * RETURNS: true if this driver has initialized, false otherwise
+ */
+bool krait_pmic_is_ready(void)
+{
+	if (the_chip == NULL) {
+		pr_debug("kait_regulator_pmic not ready yet\n");
+		return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL(krait_pmic_is_ready);
+
+#define I_PFM_MA		2000
+
+/**
+ * krait_pmic_post_pfm_entry - workarounds after entering pfm mode
+ *
+ * CONTEXT: Can be called in atomic context
+ *
+ * RETURNS: 0 on success, error code on failure
+ */
+int krait_pmic_post_pfm_entry(void)
+{
+	u8 setpoint;
+	int rc;
+
+	if (the_chip == NULL) {
+		pr_debug("kait_regulator_pmic not ready yet\n");
+		return -ENXIO;
+	}
+
+	if (v_overshoot_fixed())
+		return 0;
+
+	setpoint = (I_PFM_MA - IOFFSET_MA) / ISTEP_MA;
+	rc = write_byte(the_chip->spmi,
+			the_chip->ps_base + REG_PWM_CL, &setpoint);
+	pr_debug("wrote 0x%02x->[%d 0x%04x] rc = %d\n", setpoint,
+			the_chip->spmi->sid,
+			the_chip->ps_base + REG_PWM_CL, rc);
+	return rc;
+}
+EXPORT_SYMBOL(krait_pmic_post_pfm_entry);
+
+#define I_PWM_MA		3500
+/**
+ * krait_pmic_post_pwm_entry - workarounds after entering pwm mode
+ *
+ * CONTEXT: Can be called in atomic context
+ *
+ * RETURNS: 0 on success, error code on failure
+ */
+int krait_pmic_post_pwm_entry(void)
+{
+	u8 setpoint;
+	int rc;
+
+	if (the_chip == NULL) {
+		pr_debug("kait_regulator_pmic not ready yet\n");
+		return -ENXIO;
+	}
+
+	if (v_overshoot_fixed())
+		return 0;
+
+	udelay(50);
+	setpoint = (I_PWM_MA - IOFFSET_MA) / ISTEP_MA;
+
+	rc = write_byte(the_chip->spmi,
+			the_chip->ps_base + REG_PWM_CL, &setpoint);
+	pr_debug("wrote 0x%02x->[%d 0x%04x] rc = %d\n", setpoint,
+			the_chip->spmi->sid,
+			the_chip->ps_base + REG_PWM_CL, rc);
+	return rc;
+}
+EXPORT_SYMBOL(krait_pmic_post_pwm_entry);
+
+#define READ_BYTE(chip, addr, val, rc)				\
+do {								\
+	rc = read_byte(chip->spmi, (addr), &val);		\
+	if (rc)						\
+		pr_err("register read failed rc=%d\n", rc);	\
+} while (0)
+
+#define GANGED_VREG_COUNT	4
+static int gang_configuration_check(struct krait_vreg_pmic_chip *chip)
+{
+	u8 val;
+	int rc;
+	int i;
+
+	return 0;
+
+	READ_BYTE(chip, chip->ctrl_base + REG_V_CTL1, val, rc);
+	if (rc)
+		return rc;
+	BUG_ON(val != V_CTL1_VAL);
+
+	READ_BYTE(chip, chip->ctrl_base + REG_MODE_CTL, val, rc);
+	if (rc)
+		return rc;
+	/* The Auto mode should be off */
+	BUG_ON(val & AUTO_MODE_BIT);
+	/* The NPM mode should be on */
+	BUG_ON(!(val & NPM_MODE_BIT));
+
+	READ_BYTE(chip, chip->ctrl_base + REG_EN_CTL, val, rc);
+	if (rc)
+		return rc;
+	/* The en bit should be set */
+	BUG_ON(val & EN_BIT);
+
+	READ_BYTE(chip, chip->ctrl_base + REG_PD_CTL, val, rc);
+	if (rc)
+		return rc;
+	BUG_ON(val != PD_CTL_VAL);
+
+	READ_BYTE(chip, chip->ctrl_base + REG_MULTIPHASE_CTL, val, rc);
+	if (rc)
+		return rc;
+	BUG_ON(!(val & MULTIPHASE_EN_BIT));
+
+	READ_BYTE(chip, chip->ctrl_base + REG_PHASE_CTL, val, rc);
+	if (rc)
+		return rc;
+	BUG_ON(!(val & BALANCE_EN_BIT));
+
+	READ_BYTE(chip, chip->ctrl_base + REG_VS_CTL, val, rc);
+	if (rc)
+		return rc;
+	BUG_ON(val != VS_CTL_VAL);
+
+	for (i = 0; i < GANGED_VREG_COUNT; i++) {
+		READ_BYTE(chip,
+			chip->ctrl_base + i * 0x300 + REG_GANG_CTL2, val, rc);
+		if (rc)
+			return rc;
+
+		if (!(val & GANG_EN_BIT)) {
+			pr_err("buck = %d, ctrl gang not enabled\n", i);
+			BUG();
+		}
+	}
+
+	for (i = 0; i < GANGED_VREG_COUNT; i++) {
+		READ_BYTE(chip,
+			chip->ps_base + i * 0x300 + REG_GANG_CTL2, val, rc);
+		if (rc)
+			return rc;
+
+		if (!(val & GANG_EN_BIT)) {
+			pr_err("buck = %d, ps gang not enabled\n", i);
+			BUG();
+		}
+	}
+
+	for (i = 0; i < GANGED_VREG_COUNT; i++) {
+		READ_BYTE(chip,
+			chip->freq_base + i * 0x300 + REG_GANG_CTL2, val, rc);
+		if (rc)
+			return rc;
+
+		if (!(val & GANG_EN_BIT)) {
+			pr_err("buck = %d, freq gang not enabled\n", i);
+			BUG();
+		}
+	}
+	return 0;
+}
+
+static int __devinit krait_vreg_pmic_probe(struct spmi_device *spmi)
+{
+	u8 type, subtype;
+	int rc;
+	struct krait_vreg_pmic_chip *chip;
+	struct spmi_resource *spmi_resource;
+	struct resource *resource;
+
+	chip = devm_kzalloc(&spmi->dev, sizeof *chip, GFP_KERNEL);
+	if (chip == NULL) {
+		pr_err("kzalloc() failed.\n");
+		return -ENOMEM;
+	}
+
+	chip->spmi = spmi;
+
+	spmi_for_each_container_dev(spmi_resource, spmi) {
+		if (!spmi_resource) {
+			pr_err("spmi resource absent\n");
+			return -ENXIO;
+		}
+
+		resource = spmi_get_resource(spmi, spmi_resource,
+							IORESOURCE_MEM, 0);
+		if (!(resource && resource->start)) {
+			pr_err("node %s IO resource absent!\n",
+					spmi->dev.of_node->full_name);
+			return -ENXIO;
+		}
+
+		rc = read_byte(chip->spmi,
+				resource->start + REG_PERPH_TYPE,
+				&type);
+		if (rc) {
+			pr_err("Peripheral type read failed rc=%d\n", rc);
+			return -ENXIO;
+		}
+
+		rc = read_byte(chip->spmi,
+				resource->start + REG_PERPH_SUBTYPE,
+				&subtype);
+		if (rc) {
+			pr_err("Peripheral subtype read failed rc=%d\n", rc);
+			return -ENXIO;
+		}
+
+		if (type == CTRL_TYPE_VAL && subtype == CTRL_SUBTYPE_VAL)
+			chip->ctrl_base = resource->start;
+		else if (type == PS_TYPE_VAL && subtype == PS_SUBTYPE_VAL)
+			chip->ps_base = resource->start;
+		else if (type == FREQ_TYPE_VAL && subtype == FREQ_SUBTYPE_VAL)
+			chip->freq_base = resource->start;
+	}
+
+	if (chip->ctrl_base == 0) {
+		pr_err("ctrl base address missing\n");
+		return -ENXIO;
+	}
+
+	if (chip->ps_base == 0) {
+		pr_err("ps base address missing\n");
+		return -ENXIO;
+	}
+
+	if (chip->freq_base == 0) {
+		pr_err("freq base address missing\n");
+		return -ENXIO;
+	}
+
+	READ_BYTE(chip, chip->ctrl_base + REG_DIG_MAJOR,
+			chip->ctrl_dig_major, rc);
+	if (rc)
+		return rc;
+
+	READ_BYTE(chip, chip->ctrl_base + REG_DIG_MINOR,
+			chip->ctrl_dig_minor, rc);
+	if (rc)
+		return rc;
+
+	gang_configuration_check(chip);
+
+	the_chip = chip;
+	return 0;
+}
+
+static struct spmi_driver qpnp_revid_driver = {
+	.probe	= krait_vreg_pmic_probe,
+	.driver	= {
+		.name		= KRAIT_REG_PMIC_DEV_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= krait_vreg_pmic_match_table,
+	},
+};
+
+static int __init qpnp_revid_init(void)
+{
+	return spmi_driver_register(&qpnp_revid_driver);
+}
+
+static void __exit qpnp_revid_exit(void)
+{
+	return spmi_driver_unregister(&qpnp_revid_driver);
+}
+
+module_init(qpnp_revid_init);
+module_exit(qpnp_revid_exit);
+
+MODULE_DESCRIPTION("KRAIT REGULATOR PMIC DRIVER");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/krait-regulator-pmic.h b/arch/arm/mach-msm/krait-regulator-pmic.h
new file mode 100644
index 0000000..06ca3ea
--- /dev/null
+++ b/arch/arm/mach-msm/krait-regulator-pmic.h
@@ -0,0 +1,18 @@
+/* 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_KRAIT_REGULATOR_PMIC_H
+#define __ARCH_ARM_MACH_MSM_KRAIT_REGULATOR_PMIC_H
+bool krait_pmic_is_ready(void);
+int krait_pmic_post_pfm_entry(void);
+int krait_pmic_post_pwm_entry(void);
+#endif
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 9c5f197..4b2259e 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -29,7 +29,9 @@
 #include <linux/regulator/krait-regulator.h>
 #include <linux/debugfs.h>
 #include <linux/syscore_ops.h>
+#include <linux/cpu.h>
 #include <mach/msm_iomap.h>
+#include "krait-regulator-pmic.h"
 
 #include "spm.h"
 #include "pm.h"
@@ -222,8 +224,9 @@
 	int				cpu_num;
 	int				coeff1;
 	int				coeff2;
-	bool				online;
+	bool				reg_en;
 	int				online_at_probe;
+	bool				force_bhs;
 };
 
 DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
@@ -372,7 +375,7 @@
 		phase_scaling_factor = pvreg->efuse_phase_scaling_factor;
 
 	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (!kvreg->online)
+		if (!kvreg->reg_en)
 			continue;
 
 		if (kvreg->mode == LDO_MODE) {
@@ -414,7 +417,7 @@
 	struct krait_power_vreg *kvreg;
 
 	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (kvreg->online)
+		if (kvreg->reg_en)
 			online_total++;
 	}
 	return online_total;
@@ -427,7 +430,7 @@
 	struct pmic_gang_vreg *pvreg = from->pvreg;
 
 	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (!kvreg->online)
+		if (!kvreg->reg_en)
 			continue;
 		load_total += kvreg->load;
 	}
@@ -474,16 +477,18 @@
 	}
 
 	/* First check if the coeff is low for PFM mode */
-	if (load_total <= pvreg->pfm_threshold && n_online == 1) {
+	if (load_total <= pvreg->pfm_threshold
+			&& n_online == 1
+			&& krait_pmic_is_ready()) {
 		if (!pvreg->pfm_mode) {
 			rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
 			if (rc) {
 				pr_err("%s PFM en failed load_t %d rc = %d\n",
 					from->name, load_total, rc);
 				return rc;
-			} else {
-				pvreg->pfm_mode = true;
 			}
+			krait_pmic_post_pfm_entry();
+			pvreg->pfm_mode = true;
 		}
 		return rc;
 	}
@@ -495,10 +500,10 @@
 			pr_err("%s PFM exit failed load %d rc = %d\n",
 				from->name, coeff_total, rc);
 			return rc;
-		} else {
-			pvreg->pfm_mode = false;
-			udelay(PWM_SETTLING_TIME_US);
 		}
+		pvreg->pfm_mode = false;
+		krait_pmic_post_pwm_entry();
+		udelay(PWM_SETTLING_TIME_US);
 	}
 
 	/* calculate phases */
@@ -565,7 +570,7 @@
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	kvreg->load = load_uA;
-	if (!kvreg->online) {
+	if (!kvreg->reg_en) {
 		mutex_unlock(&pvreg->krait_power_vregs_lock);
 		return kvreg->mode;
 	}
@@ -588,10 +593,10 @@
 	return kvreg->mode;
 }
 
-static int switch_to_using_hs(struct krait_power_vreg *kvreg)
+static void __switch_to_using_bhs(void *info)
 {
-	if (kvreg->mode == HS_MODE)
-		return 0;
+	struct krait_power_vreg *kvreg = info;
+
 	/* enable bhs */
 	if (version > KPSS_VERSION_2P0) {
 		krait_masked_write(kvreg, APC_PWR_GATE_MODE,
@@ -645,21 +650,18 @@
 
 	kvreg->mode = HS_MODE;
 	pr_debug("%s using BHS\n", kvreg->name);
-	return 0;
 }
 
-static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
+static void __switch_to_using_ldo(void *info)
 {
-	if (kvreg->mode == LDO_MODE
-		&& get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
-		return 0;
+	struct krait_power_vreg *kvreg = info;
 
 	/*
 	 * if the krait is in ldo mode and a voltage change is requested on the
 	 * ldo switch to using hs before changing ldo voltage
 	 */
 	if (kvreg->mode == LDO_MODE)
-		switch_to_using_hs(kvreg);
+		__switch_to_using_bhs(kvreg);
 
 	set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
 	if (version > KPSS_VERSION_2P0) {
@@ -698,7 +700,25 @@
 
 	kvreg->mode = LDO_MODE;
 	pr_debug("%s using LDO\n", kvreg->name);
-	return 0;
+}
+
+static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
+{
+	if (kvreg->mode == LDO_MODE
+		&& get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
+		return 0;
+
+	return smp_call_function_single(kvreg->cpu_num,
+			__switch_to_using_ldo, kvreg, 1);
+}
+
+static int switch_to_using_bhs(struct krait_power_vreg *kvreg)
+{
+	if (kvreg->mode == HS_MODE)
+		return 0;
+
+	return smp_call_function_single(kvreg->cpu_num,
+			__switch_to_using_bhs, kvreg, 1);
 }
 
 static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
@@ -750,6 +770,41 @@
 	return rc;
 }
 
+static int configure_ldo_or_hs_one(struct krait_power_vreg *kvreg, int vmax)
+{
+	int rc;
+
+	if (!kvreg->reg_en)
+		return 0;
+
+	if (kvreg->force_bhs)
+		/*
+		 * The cpu is in transitory phase where it is being
+		 * prepared to be offlined or onlined and is being
+		 * forced to run on BHS during that time
+		 */
+		return 0;
+
+	if (kvreg->uV <= kvreg->ldo_threshold_uV
+		&& kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
+			<= vmax) {
+		rc = switch_to_using_ldo(kvreg);
+		if (rc < 0) {
+			pr_err("could not switch %s to ldo rc = %d\n",
+						kvreg->name, rc);
+			return rc;
+		}
+	} else {
+		rc = switch_to_using_bhs(kvreg);
+		if (rc < 0) {
+			pr_err("could not switch %s to hs rc = %d\n",
+						kvreg->name, rc);
+			return rc;
+		}
+	}
+	return 0;
+}
+
 static int configure_ldo_or_hs_all(struct krait_power_vreg *from, int vmax)
 {
 	struct pmic_gang_vreg *pvreg = from->pvreg;
@@ -757,27 +812,12 @@
 	int rc = 0;
 
 	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (!kvreg->online)
-			continue;
-		if (kvreg->uV <= kvreg->ldo_threshold_uV
-			&& kvreg->uV - kvreg->ldo_delta_uV + kvreg->headroom_uV
-				<= vmax) {
-			rc = switch_to_using_ldo(kvreg);
-			if (rc < 0) {
-				pr_err("could not switch %s to ldo rc = %d\n",
-							kvreg->name, rc);
-				return rc;
-			}
-		} else {
-			rc = switch_to_using_hs(kvreg);
-			if (rc < 0) {
-				pr_err("could not switch %s to hs rc = %d\n",
-							kvreg->name, rc);
-				return rc;
-			}
+		rc = configure_ldo_or_hs_one(kvreg, vmax);
+		if (rc) {
+			pr_err("could not switch %s\n", kvreg->name);
+			break;
 		}
 	}
-
 	return rc;
 }
 
@@ -856,7 +896,7 @@
 	struct krait_power_vreg *kvreg;
 
 	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (!kvreg->online)
+		if (!kvreg->reg_en)
 			continue;
 
 		v = kvreg->uV;
@@ -896,7 +936,7 @@
 		rc = krait_voltage_decrease(kvreg, vmax);
 
 	if (rc < 0) {
-		dev_err(&rdev->dev, "%s failed to set %duV from %duV rc = %d\n",
+		pr_err("%s failed to set %duV from %duV rc = %d\n",
 				kvreg->name, requested_uV, orig_krait_uV, rc);
 	}
 
@@ -927,7 +967,7 @@
 	}
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
-	if (!kvreg->online) {
+	if (!kvreg->reg_en) {
 		kvreg->uV = min_uV;
 		mutex_unlock(&pvreg->krait_power_vregs_lock);
 		return 0;
@@ -943,7 +983,7 @@
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
 
-	return kvreg->online;
+	return kvreg->reg_en;
 }
 
 static int krait_power_enable(struct regulator_dev *rdev)
@@ -953,8 +993,9 @@
 	int rc;
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
+	pr_debug("enable %s\n", kvreg->name);
 	__krait_power_mdd_enable(kvreg, true);
-	kvreg->online = true;
+	kvreg->reg_en = true;
 	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
 		goto en_err;
@@ -975,7 +1016,8 @@
 	int rc;
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
-	kvreg->online = false;
+	pr_debug("disable %s\n", kvreg->name);
+	kvreg->reg_en = false;
 
 	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
@@ -999,6 +1041,69 @@
 	.is_enabled		= krait_power_is_enabled,
 };
 
+static int krait_regulator_cpu_callback(struct notifier_block *nfb,
+					    unsigned long action, void *hcpu)
+{
+	int cpu = (int)hcpu;
+	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, cpu);
+	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
+
+	pr_debug("start state=0x%02x, cpu=%d is_online=%d\n",
+			(int)action, cpu, cpu_online(cpu));
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_UP_PREPARE:
+		mutex_lock(&pvreg->krait_power_vregs_lock);
+		kvreg->force_bhs = true;
+		/*
+		 * cpu is offline at this point, force bhs on which ever cpu
+		 * this callback is running on
+		 */
+		pr_debug("%s force BHS locally\n", kvreg->name);
+		__switch_to_using_bhs(kvreg);
+		mutex_unlock(&pvreg->krait_power_vregs_lock);
+		break;
+	case CPU_UP_CANCELED:
+	case CPU_ONLINE:
+		mutex_lock(&pvreg->krait_power_vregs_lock);
+		kvreg->force_bhs = false;
+		/*
+		 * switch the cpu to proper bhs/ldo, the cpu is online at this
+		 * point. The gang voltage and mode votes for the cpu were
+		 * submitted in CPU_UP_PREPARE phase
+		 */
+		configure_ldo_or_hs_one(kvreg, pvreg->pmic_vmax_uV);
+		mutex_unlock(&pvreg->krait_power_vregs_lock);
+		break;
+	case CPU_DOWN_PREPARE:
+		mutex_lock(&pvreg->krait_power_vregs_lock);
+		kvreg->force_bhs = true;
+		/*
+		 * switch the cpu to run on bhs using smp function calls. Note
+		 * that the cpu is online at this point.
+		 */
+		pr_debug("%s force BHS remotely\n", kvreg->name);
+		switch_to_using_bhs(kvreg);
+		mutex_unlock(&pvreg->krait_power_vregs_lock);
+		break;
+	case CPU_DOWN_FAILED:
+		mutex_lock(&pvreg->krait_power_vregs_lock);
+		kvreg->force_bhs = false;
+		configure_ldo_or_hs_one(kvreg, pvreg->pmic_vmax_uV);
+		mutex_unlock(&pvreg->krait_power_vregs_lock);
+		break;
+	default:
+		break;
+	}
+
+	pr_debug("done state=0x%02x, cpu=%d is_online=%d\n",
+			(int)action, cpu, cpu_online(cpu));
+	return NOTIFY_OK;
+}
+
+static struct notifier_block krait_cpu_notifier = {
+	.notifier_call = krait_regulator_cpu_callback,
+};
+
 static struct dentry *dent;
 static int get_retention_dbg_uV(void *data, u64 *val)
 {
@@ -1481,11 +1586,14 @@
 				KRAIT_REGULATOR_DRIVER_NAME, rc);
 		return rc;
 	}
+
+	register_hotcpu_notifier(&krait_cpu_notifier);
 	return platform_driver_register(&krait_pdn_driver);
 }
 
 static void __exit krait_power_exit(void)
 {
+	unregister_hotcpu_notifier(&krait_cpu_notifier);
 	platform_driver_unregister(&krait_power_driver);
 	platform_driver_unregister(&krait_pdn_driver);
 }
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_id.c b/arch/arm/mach-msm/msm_bus/msm_bus_id.c
index 7e9883f..25a749a 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_id.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_id.c
@@ -35,16 +35,22 @@
 		if (!fabreg->info[i].gateway) {
 			fabreg->info[i].priv_id = fabid + fabreg->info[i].id;
 			if (fabreg->info[i].id < SLAVE_ID_KEY) {
-				WARN(fabreg->info[i].id >= MSM_BUS_MASTER_LAST,
-					"id %d exceeds array size!\n",
-					fabreg->info[i].id);
+				if (fabreg->info[i].id >= MSM_BUS_MASTER_LAST) {
+					WARN(1, "id %d exceeds array size!\n",
+						fabreg->info[i].id);
+					continue;
+				}
+
 				master_iids[fabreg->info[i].id] =
 					fabreg->info[i].priv_id;
 			} else {
-				WARN((fabreg->info[i].id - SLAVE_ID_KEY) >=
-					(MSM_BUS_SLAVE_LAST - SLAVE_ID_KEY),
-					"id %d exceeds array size!\n",
-					fabreg->info[i].id);
+				if ((fabreg->info[i].id - SLAVE_ID_KEY) >=
+					(MSM_BUS_SLAVE_LAST - SLAVE_ID_KEY)) {
+					WARN(1, "id %d exceeds array size!\n",
+						fabreg->info[i].id);
+					continue;
+				}
+
 				slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)]
 					= fabreg->info[i].priv_id;
 			}
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index a24fc54..aa88b37 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -350,19 +350,21 @@
 		bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
 			"i: %3d, cmd_code: %4x, subsys_id: %4x, "
 			"client: %2d, cmd_code_lo: %4x, "
-			"cmd_code_hi: %4x, process_id: %5d\n",
+			"cmd_code_hi: %4x, process_id: %5d %s\n",
 			i,
 			driver->table[i].cmd_code,
 			driver->table[i].subsys_id,
 			driver->table[i].client_id,
 			driver->table[i].cmd_code_lo,
 			driver->table[i].cmd_code_hi,
-			driver->table[i].process_id);
+			driver->table[i].process_id,
+			(diag_find_polling_reg(i) ? "<- Polling cmd reg" : ""));
 
 		bytes_in_buffer += bytes_written;
 
 		/* Check if there is room to add another table entry */
 		bytes_remaining = buf_size - bytes_in_buffer;
+
 		if (bytes_remaining < bytes_written)
 			break;
 	}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 7ef1d80..c341ef5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -412,5 +412,6 @@
 extern uint16_t wrap_count;
 
 void diag_get_timestamp(char *time_str);
+int diag_find_polling_reg(int i);
 
 #endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 24d7fac..6cc18da 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -327,17 +327,19 @@
 	subsys_id = driver->table[i].subsys_id;
 	cmd_code_lo = driver->table[i].cmd_code_lo;
 	cmd_code_hi = driver->table[i].cmd_code_hi;
-	if (driver->table[i].cmd_code == 0x0C)
-		return 1;
-	else if (driver->table[i].cmd_code == 0xFF) {
-		if (subsys_id == 0x04 && cmd_code_hi == 0x0E &&
-			 cmd_code_lo == 0x0E)
+
+	if (driver->table[i].cmd_code == 0xFF) {
+		if (subsys_id == 0xFF && cmd_code_hi >= 0x0C &&
+			 cmd_code_lo <= 0x0C)
 			return 1;
-		else if (subsys_id == 0x08 && cmd_code_hi == 0x02 &&
-			 cmd_code_lo == 0x02)
+		if (subsys_id == 0x04 && cmd_code_hi >= 0x0E &&
+			 cmd_code_lo <= 0x0E)
 			return 1;
-		else if (subsys_id == 0x32 && cmd_code_hi == 0x03  &&
-			 cmd_code_lo == 0x03)
+		else if (subsys_id == 0x08 && cmd_code_hi >= 0x02 &&
+			 cmd_code_lo <= 0x02)
+			return 1;
+		else if (subsys_id == 0x32 && cmd_code_hi >= 0x03  &&
+			 cmd_code_lo <= 0x03)
 			return 1;
 	}
 	return 0;
@@ -356,7 +358,8 @@
 	}
 	/* re-scan the registration table */
 	for (i = 0; i < diag_max_reg; i++) {
-		if (diag_find_polling_reg(i) == 1) {
+		if (driver->table[i].process_id != 0 &&
+				diag_find_polling_reg(i) == 1) {
 			driver->polling_reg_flag = 1;
 			break;
 		}
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index c501700..d500c0a 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1451,14 +1451,17 @@
 
 	if (!drvdata->byte_cntr_present) {
 		dev_info(&pdev->dev, "Byte Counter feature absent\n");
-		return 0;
+		goto out;
 	}
 
 	drvdata->byte_cntr_irq = platform_get_irq_byname(pdev,
 							"byte-cntr-irq");
 	if (drvdata->byte_cntr_irq < 0) {
+		/* Even though this is an error condition, we do not fail
+		 * the probe as the byte counter feature is optional
+		 */
 		dev_err(&pdev->dev, "Byte-cntr-irq not specified\n");
-		return 0;
+		goto err;
 	}
 	ret = devm_request_irq(&pdev->dev, drvdata->byte_cntr_irq,
 			tmc_etr_byte_cntr_irq,
@@ -1466,7 +1469,7 @@
 			node_name, drvdata);
 	if (ret) {
 		dev_err(&pdev->dev, "Request irq failed\n");
-		return ret;
+		goto err;
 	}
 	init_waitqueue_head(&drvdata->wq);
 	node_size += strlen(node_name);
@@ -1477,10 +1480,14 @@
 	ret = tmc_etr_byte_cntr_dev_register(drvdata);
 	if (ret) {
 		dev_err(&pdev->dev, "Byte cntr node not registered\n");
-		return ret;
+		goto err;
 	}
 	dev_info(&pdev->dev, "Byte Counter feature enabled\n");
 	return 0;
+err:
+	drvdata->byte_cntr_present = false;
+out:
+	return ret;
 }
 
 static void tmc_etr_byte_cntr_exit(struct tmc_drvdata *drvdata)
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 418c488..1f60c65 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -346,6 +346,7 @@
 	dbs_tuners_ins.sampling_rate = new_rate
 				     = max(new_rate, min_sampling_rate);
 
+	get_online_cpus();
 	for_each_online_cpu(cpu) {
 		struct cpufreq_policy *policy;
 		struct cpu_dbs_info_s *dbs_info;
@@ -380,6 +381,7 @@
 		}
 		mutex_unlock(&dbs_info->timer_mutex);
 	}
+	put_online_cpus();
 }
 
 static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index fdd19e9..2781a34 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2771,7 +2771,7 @@
 } kgsl_ioctl_funcs[] = {
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY,
 			kgsl_ioctl_device_getproperty,
-			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP,
 			kgsl_ioctl_device_waittimestamp,
 			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
@@ -2789,13 +2789,13 @@
 			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP,
 			kgsl_ioctl_cmdstream_freememontimestamp,
-			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID,
 			kgsl_ioctl_cmdstream_freememontimestamp_ctxtid,
-			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_CREATE,
 			kgsl_ioctl_drawctxt_create,
-			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY,
 			kgsl_ioctl_drawctxt_destroy,
 			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
@@ -2815,10 +2815,10 @@
 			kgsl_ioctl_cff_user_event, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
 			kgsl_ioctl_timestamp_event,
-			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY,
 			kgsl_ioctl_device_setproperty,
-			KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
+			KGSL_IOCTL_LOCK),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC_ID,
 			kgsl_ioctl_gpumem_alloc_id, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_FREE_ID,
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index e4f502a..9e8f6d0 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -252,7 +252,7 @@
 	 * Increase the active count on the device to avoid going into power
 	 * saving modes while events are pending
 	 */
-	ret = kgsl_active_count_get_light(device);
+	ret = kgsl_active_count_get(device);
 	if (ret < 0) {
 		kgsl_context_put(context);
 		kfree(event);
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 8b0fcf4..9e0be59 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -131,57 +131,111 @@
 };
 
 static const struct qpnp_vadc_map_pt adcmap_qrd_btm_threshold[] = {
-	{-200,	1672},
-	{-180,	1656},
-	{-160,	1639},
-	{-140,	1620},
-	{-120,	1599},
-	{-100,	1577},
-	{-80,	1553},
-	{-60,	1527},
-	{-40,	1550},
-	{-20,	1471},
-	{0,	1440},
-	{20,	1408},
-	{40,	1374},
-	{60,	1339},
-	{80,	1303},
-	{100,	1266},
-	{120,	1228},
-	{140,	1190},
-	{160,	1150},
-	{180,	1111},
-	{200,	1071},
-	{220,	1032},
-	{240,	992},
-	{260,	953},
-	{280,	915},
-	{300,	877},
-	{320,	841},
-	{340,	805},
-	{360,	770},
-	{380,	736},
-	{400,	704},
-	{420,	673},
-	{440,	643},
-	{460,	614},
-	{480,	587},
-	{500,	561},
-	{520,	536},
-	{540,	513},
-	{560,	491},
-	{580,	470},
-	{600,	450},
-	{620,	431},
-	{640,	414},
-	{660,	397},
-	{680,	382},
-	{700,	367},
-	{720,	353},
-	{740,	340},
-	{760,	328},
-	{780,	317},
-	{800,	306},
+	{-200,	1540},
+	{-180,	1517},
+	{-160,	1492},
+	{-140,	1467},
+	{-120,	1440},
+	{-100,	1412},
+	{-80,	1383},
+	{-60,	1353},
+	{-40,	1323},
+	{-20,	1292},
+	{0,	1260},
+	{20,	1228},
+	{40,	1196},
+	{60,	1163},
+	{80,	1131},
+	{100,	1098},
+	{120,	1066},
+	{140,	1034},
+	{160,	1002},
+	{180,	971},
+	{200,	941},
+	{220,	911},
+	{240,	882},
+	{260,	854},
+	{280,	826},
+	{300,	800},
+	{320,	774},
+	{340,	749},
+	{360,	726},
+	{380,	703},
+	{400,	681},
+	{420,	660},
+	{440,	640},
+	{460,	621},
+	{480,	602},
+	{500,	585},
+	{520,	568},
+	{540,	552},
+	{560,	537},
+	{580,	523},
+	{600,	510},
+	{620,	497},
+	{640,	485},
+	{660,	473},
+	{680,	462},
+	{700,	452},
+	{720,	442},
+	{740,	433},
+	{760,	424},
+	{780,	416},
+	{800,	408},
+};
+
+static const struct qpnp_vadc_map_pt adcmap_qrd_skuaa_btm_threshold[] = {
+	{-200,	1476},
+	{-180,	1450},
+	{-160,	1422},
+	{-140,	1394},
+	{-120,	1365},
+	{-100,	1336},
+	{-80,	1306},
+	{-60,	1276},
+	{-40,	1246},
+	{-20,	1216},
+	{0,	1185},
+	{20,	1155},
+	{40,	1126},
+	{60,	1096},
+	{80,	1068},
+	{100,	1040},
+	{120,	1012},
+	{140,	986},
+	{160,	960},
+	{180,	935},
+	{200,	911},
+	{220,	888},
+	{240,	866},
+	{260,	844},
+	{280,	824},
+	{300,	805},
+	{320,	786},
+	{340,	769},
+	{360,	752},
+	{380,	737},
+	{400,	722},
+	{420,	707},
+	{440,	694},
+	{460,	681},
+	{480,	669},
+	{500,	658},
+	{520,	648},
+	{540,	637},
+	{560,	628},
+	{580,	619},
+	{600,	611},
+	{620,	603},
+	{640,	595},
+	{660,	588},
+	{680,	582},
+	{700,	575},
+	{720,	569},
+	{740,	564},
+	{760,	559},
+	{780,	554},
+	{800,	549},
 };
 
 /* Voltage to temperature */
@@ -539,6 +593,25 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_qrd_batt_therm);
 
+int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t bat_voltage = 0;
+
+	bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+			adc_properties, chan_properties);
+
+	return qpnp_adc_map_temp_voltage(
+			adcmap_qrd_skuaa_btm_threshold,
+			ARRAY_SIZE(adcmap_qrd_skuaa_btm_threshold),
+			bat_voltage,
+			&adc_chan_result->physical);
+}
+EXPORT_SYMBOL(qpnp_adc_scale_qrd_skuaa_batt_therm);
+
 int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *chip,
 		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index c4a2567..548764f 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -126,6 +126,7 @@
 	[SCALE_THERM_100K_PULLUP] = {qpnp_adc_scale_therm_pu2},
 	[SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
 	[SCALE_QRD_BATT_THERM] = {qpnp_adc_scale_qrd_batt_therm},
+	[SCALE_QRD_SKUAA_BATT_THERM] = {qpnp_adc_scale_qrd_skuaa_batt_therm},
 };
 
 static int32_t qpnp_vadc_read_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index ded2b6e..e0d8a47 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -320,15 +320,19 @@
 		if (sensor->use_poll)
 			schedule_delayed_work(&sensor->input_work,
 				msecs_to_jiffies(sensor->poll_interval));
-		else
+		else {
 			i2c_smbus_write_byte_data(sensor->client,
 					MPU3050_INT_CFG,
 					MPU3050_ACTIVE_LOW |
 					MPU3050_OPEN_DRAIN |
 					MPU3050_RAW_RDY_EN);
+			enable_irq(sensor->client->irq);
+		}
 	} else {
 		if (sensor->use_poll)
 			cancel_delayed_work_sync(&sensor->input_work);
+		else
+			disable_irq(sensor->client->irq);
 		gpio_set_value(sensor->enable_gpio, 0);
 		pm_runtime_put(sensor->dev);
 	}
@@ -448,6 +452,7 @@
 		mpu3050_config_regulator(client, 1);
 		udelay(10);
 		gpio_set_value(sensor->enable_gpio, 1);
+		msleep(60);
 	}
 
 	value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
@@ -709,7 +714,6 @@
 	}
 
 	mpu3050_set_power_mode(client, 1);
-	msleep(10);
 
 	ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
 	if (ret < 0) {
@@ -864,6 +868,10 @@
 static int mpu3050_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+
+	if (!sensor->use_poll)
+		disable_irq(client->irq);
 
 	mpu3050_set_power_mode(client, 0);
 
@@ -879,9 +887,12 @@
 static int mpu3050_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
 
 	mpu3050_set_power_mode(client, 1);
-	msleep(100);  /* wait for gyro chip resume */
+
+	if (!sensor->use_poll)
+		enable_irq(client->irq);
 
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov8825.c b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
index 3256c5c..e17c94e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
@@ -21,55 +21,55 @@
 		.seq_type = SENSOR_VREG,
 		.seq_val = CAM_VIO,
 		.config_val = 0,
-		.delay = 5,
+		.delay = 1,
 	},
 	{
 		.seq_type = SENSOR_VREG,
 		.seq_val = CAM_VANA,
 		.config_val = 0,
-		.delay = 5,
+		.delay = 1,
 	},
 	{
 		.seq_type = SENSOR_VREG,
 		.seq_val = CAM_VDIG,
 		.config_val = 0,
-		.delay = 5,
+		.delay = 1,
 	},
 	{
 		.seq_type = SENSOR_VREG,
 		.seq_val = CAM_VAF,
 		.config_val = 0,
-		.delay = 15,
+		.delay = 5,
 	},
 	{
 		.seq_type = SENSOR_GPIO,
 		.seq_val = SENSOR_GPIO_STANDBY,
 		.config_val = GPIO_OUT_LOW,
-		.delay = 15,
+		.delay = 1,
 	},
 	{
 		.seq_type = SENSOR_GPIO,
 		.seq_val = SENSOR_GPIO_RESET,
 		.config_val = GPIO_OUT_LOW,
-		.delay = 40,
+		.delay = 5,
 	},
 	{
 		.seq_type = SENSOR_GPIO,
 		.seq_val = SENSOR_GPIO_STANDBY,
 		.config_val = GPIO_OUT_HIGH,
-		.delay = 40,
+		.delay = 5,
 	},
 	{
 		.seq_type = SENSOR_GPIO,
 		.seq_val = SENSOR_GPIO_RESET,
 		.config_val = GPIO_OUT_HIGH,
-		.delay = 40,
+		.delay = 10,
 	},
 	{
 		.seq_type = SENSOR_CLK,
 		.seq_val = SENSOR_CAM_MCLK,
 		.config_val = 24000000,
-		.delay = 5,
+		.delay = 10,
 	},
 	{
 		.seq_type = SENSOR_I2C_MUX,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov9724.c b/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
index 56af02b..99bf03a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
@@ -46,7 +46,7 @@
 		.seq_type = SENSOR_GPIO,
 		.seq_val = SENSOR_GPIO_RESET,
 		.config_val = GPIO_OUT_HIGH,
-		.delay = 30,
+		.delay = 5,
 	},
 	{
 		.seq_type = SENSOR_GPIO,
@@ -58,13 +58,13 @@
 		.seq_type = SENSOR_GPIO,
 		.seq_val = SENSOR_GPIO_STANDBY,
 		.config_val = GPIO_OUT_HIGH,
-		.delay = 30,
+		.delay = 10,
 	},
 	{
 		.seq_type = SENSOR_CLK,
 		.seq_val = SENSOR_CAM_MCLK,
 		.config_val = 24000000,
-		.delay = 5,
+		.delay = 10,
 	},
 	{
 		.seq_type = SENSOR_I2C_MUX,
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index bc3b93d..44c9613 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -381,7 +381,7 @@
 }
 
 static inline void q6_hfi_add_apr_hdr(struct q6_hfi_device *dev,
-			struct apr_hdr *hdr, u32 pkt_size, u32 opcode)
+			struct apr_hdr *hdr, u32 pkt_size)
 {
 	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(sizeof(struct apr_hdr)),
@@ -394,7 +394,7 @@
 	hdr->dest_port = 0;
 	hdr->pkt_size  = pkt_size;
 	hdr->token = 0;
-	hdr->opcode = opcode;
+	hdr->opcode = VIDEO_HFI_CMD_ID;
 }
 
 static int q6_hfi_apr_callback(struct apr_client_data *data, void *priv)
@@ -496,7 +496,7 @@
 		goto err_core_init;
 	}
 
-	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr), HFI_CMD_SYS_INIT);
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 	rc = create_pkt_cmd_sys_init(&apr.pkt, HFI_VIDEO_ARCH_OX);
 	if (rc) {
@@ -529,22 +529,6 @@
 	return 0;
 }
 
-static int q6_hfi_core_pc_prep(void *device)
-{
-	(void) device;
-
-	/* Q6 does not support core_pc_prep*/
-	return 0;
-}
-
-static int q6_hfi_core_ping(void *device)
-{
-	(void) device;
-
-	/* Q6 does not support cmd_sys_ping */
-	return 0;
-}
-
 static void *q6_hfi_session_init(void *device, u32 session_id,
 	enum hal_domain session_type, enum hal_video_codec codec_type)
 {
@@ -567,8 +551,7 @@
 		new_session->is_decoder = 1;
 	new_session->device = dev;
 
-	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
-				   HFI_CMD_SYS_SESSION_INIT);
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 	if (create_pkt_cmd_sys_session_init(&apr.pkt, (u32)new_session,
 					session_type, codec_type)) {
@@ -605,7 +588,7 @@
 	}
 	dev = session->device;
 
-	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr), pkt_type);
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 	rc = create_pkt_cmd_session_cmd(&apr.pkt, pkt_type, (u32)session);
 	if (rc) {
@@ -670,8 +653,7 @@
 		return 0;
 	apr = (struct q6_apr_cmd_session_set_buffers_packet *)packet;
 
-	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE,
-			HFI_CMD_SESSION_SET_BUFFERS);
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE);
 
 	rc = create_pkt_cmd_session_set_buffers(&apr->pkt,
 			(u32)session, buffer_info);
@@ -713,8 +695,7 @@
 
 	apr = (struct q6_apr_cmd_session_release_buffer_packet *) packet;
 
-	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE,
-					   HFI_CMD_SESSION_RELEASE_BUFFERS);
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE);
 
 	rc = create_pkt_cmd_session_release_buffers(&apr->pkt,
 					(u32)session, buffer_info);
@@ -788,8 +769,7 @@
 
 	if (session->is_decoder) {
 		struct q6_apr_cmd_session_empty_buffer_compressed_packet apr;
-		q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
-					   HFI_CMD_SESSION_EMPTY_BUFFER);
+		q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 		rc = create_pkt_cmd_session_etb_decoder(&apr.pkt,
 					(u32)session, input_frame);
@@ -811,8 +791,7 @@
 	} else {
 		struct
 		q6_apr_cmd_session_empty_buffer_uncompressed_plane0_packet apr;
-		q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
-				   HFI_CMD_SESSION_EMPTY_BUFFER);
+		q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 		rc =  create_pkt_cmd_session_etb_encoder(&apr.pkt,
 					(u32)session, input_frame);
@@ -848,8 +827,7 @@
 	}
 	dev = session->device;
 
-	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
-				   HFI_CMD_SESSION_FILL_BUFFER);
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 	rc = create_pkt_cmd_session_ftb(&apr.pkt, (u32)session, output_frame);
 	if (rc) {
@@ -886,8 +864,7 @@
 
 	apr = (struct q6_apr_cmd_session_parse_sequence_header_packet *) packet;
 
-	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_SMALL_PKT_SIZE,
-			   HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER);
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_SMALL_PKT_SIZE);
 
 	rc = create_pkt_cmd_session_parse_seq_header(&apr->pkt,
 					(u32)session, seq_hdr);
@@ -925,8 +902,7 @@
 
 	apr = (struct q6_apr_cmd_session_get_sequence_header_packet *) packet;
 
-	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_SMALL_PKT_SIZE,
-				   HFI_CMD_SESSION_GET_SEQUENCE_HEADER);
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_SMALL_PKT_SIZE);
 
 	rc = create_pkt_cmd_session_get_seq_hdr(&apr->pkt, (u32)session,
 						seq_hdr);
@@ -960,8 +936,7 @@
 	}
 	dev = session->device;
 
-	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
-				   HFI_CMD_SESSION_GET_PROPERTY);
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 	rc = create_pkt_cmd_session_get_buf_req(&apr.pkt, (u32)session);
 	if (rc) {
@@ -993,8 +968,7 @@
 	}
 	dev = session->device;
 
-	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr),
-				   HFI_CMD_SESSION_FLUSH);
+	q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr));
 
 	rc = create_pkt_cmd_session_flush(&apr.pkt, (u32)session, flush_mode);
 	if (rc) {
@@ -1031,8 +1005,7 @@
 	dev = session->device;
 	dprintk(VIDC_DBG, "in set_prop,with prop id: 0x%x", ptype);
 
-	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE,
-				 HFI_CMD_SESSION_SET_PROPERTY);
+	q6_hfi_add_apr_hdr(dev, &apr->hdr, VIDC_IFACEQ_VAR_LARGE_PKT_SIZE);
 
 	rc = create_pkt_cmd_session_set_property(&apr->pkt,
 				(u32)session, ptype, pdata);
@@ -1177,28 +1150,6 @@
 	return 0;
 }
 
-static int q6_hfi_scale_clocks(void *dev, int load)
-{
-	(void)dev;
-	(void)load;
-
-	/* Q6 does not support clocks scaling */
-	return 0;
-}
-
-static int q6_hfi_scale_bus(void *dev, int load,
-			enum session_type type, enum mem_type mtype)
-{
-	(void)dev;
-	(void)load;
-	(void)type;
-	(void)mtype;
-
-	/* Q6 does not support bus scaling */
-	return 0;
-
-}
-
 static int q6_hfi_unset_ocmem(void *dev)
 {
 	(void)dev;
@@ -1207,23 +1158,6 @@
 	return -EINVAL;
 }
 
-static int q6_hfi_alloc_ocmem(void *dev, unsigned long size)
-{
-	(void)dev;
-	(void)size;
-
-	/* Q6 does not support ocmem */
-	return 0;
-}
-
-static int q6_hfi_free_ocmem(void *dev)
-{
-	(void)dev;
-
-	/* Q6 does not support ocmem */
-	return 0;
-}
-
 static int q6_hfi_iommu_get_domain_partition(void *dev, u32 flags,
 	u32 buffer_type, int *domain, int *partition)
 {
@@ -1373,14 +1307,6 @@
 	}
 }
 
-static int q6_hfi_get_fw_info(void *dev, enum fw_info info)
-{
-	(void)dev;
-	(void)info;
-
-	return 0;
-}
-
 static int q6_hfi_get_stride_scanline(int color_fmt,
 	int width, int height, int *stride, int *scanlines) {
 	*stride = VENUS_Y_STRIDE(color_fmt, width);
@@ -1392,8 +1318,6 @@
 {
 	hdev->core_init = q6_hfi_core_init;
 	hdev->core_release = q6_hfi_core_release;
-	hdev->core_pc_prep = q6_hfi_core_pc_prep;
-	hdev->core_ping = q6_hfi_core_ping;
 	hdev->session_init = q6_hfi_session_init;
 	hdev->session_end = q6_hfi_session_end;
 	hdev->session_abort = q6_hfi_session_abort;
@@ -1414,15 +1338,10 @@
 	hdev->session_flush = q6_hfi_session_flush;
 	hdev->session_set_property = q6_hfi_session_set_property;
 	hdev->session_get_property = q6_hfi_session_get_property;
-	hdev->scale_clocks = q6_hfi_scale_clocks;
-	hdev->scale_bus = q6_hfi_scale_bus;
 	hdev->unset_ocmem = q6_hfi_unset_ocmem;
-	hdev->alloc_ocmem = q6_hfi_alloc_ocmem;
-	hdev->free_ocmem = q6_hfi_free_ocmem;
 	hdev->iommu_get_domain_partition = q6_hfi_iommu_get_domain_partition;
 	hdev->load_fw = q6_hfi_load_fw;
 	hdev->unload_fw = q6_hfi_unload_fw;
-	hdev->get_fw_info = q6_hfi_get_fw_info;
 	hdev->get_stride_scanline = q6_hfi_get_stride_scanline;
 }
 
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.h b/drivers/media/platform/msm/vidc/q6_hfi.h
index 3dc4607..67aed5a 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.h
+++ b/drivers/media/platform/msm/vidc/q6_hfi.h
@@ -20,6 +20,15 @@
 
 #define Q6_IFACEQ_QUEUE_SIZE (8 * 1024)
 
+/* client to Q6 communication path : forward path */
+#define VIDEO_HFI_CMD_ID  0x00012ECC
+
+/* Q6 to client ACK msg: reverse path*/
+#define VIDEO_HFI_MSG_ID  0x00012ECD
+
+/* Q6 to client event notifications */
+#define VIDEO_HFI_EVT_ID  0x00012ECE
+
 struct q6_resources {
 	struct msm_vidc_fw fw;
 };
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 249f54d..494242d 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -201,7 +201,7 @@
 	HAL_VIDEO_CODEC_VP6      = 0x00000400,
 	HAL_VIDEO_CODEC_VP7      = 0x00000800,
 	HAL_VIDEO_CODEC_VP8      = 0x00001000,
-	HAL_VIDEO_CODEC_HEVC     = 0x00010000,
+	HAL_VIDEO_CODEC_HEVC     = 0x00002000,
 	HAL_UNUSED_CODEC = 0x10000000,
 };
 
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 3f63357..61c6e15 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -79,7 +79,7 @@
 #define HFI_VIDEO_CODEC_VC1				0x00000100
 #define HFI_VIDEO_CODEC_SPARK				0x00000200
 #define HFI_VIDEO_CODEC_VP8				0x00001000
-#define HFI_VIDEO_CODEC_HEVC				0x00010000
+#define HFI_VIDEO_CODEC_HEVC				0x00002000
 
 #define HFI_H264_PROFILE_BASELINE			0x00000001
 #define HFI_H264_PROFILE_MAIN				0x00000002
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 69031dc..fcc5a8d 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -664,6 +664,15 @@
 			lower_thr = true;
 		}
 		if (upper_thr || lower_thr) {
+			unsigned long temp;
+			enum thermal_trip_type trip =
+					THERMAL_TRIP_CONFIGURABLE_LOW;
+
+			if (upper_thr)
+				trip = THERMAL_TRIP_CONFIGURABLE_HI;
+			tsens_tz_get_temp(tm->sensor[i].tz_dev, &temp);
+			thermal_sensor_trip(tm->sensor[i].tz_dev, trip, temp);
+
 			/* Notify user space */
 			queue_work(tm->tsens_wq, &tm->sensor[i].work);
 			rc = tsens_get_sw_id_mapping(
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 974cadc..00df613 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -14,9 +14,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/msm_tsens.h>
 #include <linux/workqueue.h>
+#include <linux/completion.h>
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/msm_tsens.h>
@@ -29,6 +31,7 @@
 #include <linux/sysfs.h>
 #include <linux/types.h>
 #include <linux/android_alarm.h>
+#include <linux/thermal.h>
 #include <mach/cpufreq.h>
 #include <mach/rpm-regulator.h>
 #include <mach/rpm-regulator-smd.h>
@@ -45,7 +48,10 @@
 static uint32_t wakeup_ms;
 static struct alarm thermal_rtc;
 static struct kobject *tt_kobj;
+static struct kobject *cc_kobj;
 static struct work_struct timer_work;
+static struct task_struct *hotplug_task;
+static struct completion hotplug_notify_complete;
 
 static int enabled;
 static int rails_cnt;
@@ -67,6 +73,14 @@
 static DEFINE_MUTEX(vdd_rstr_mutex);
 static DEFINE_MUTEX(psm_mutex);
 
+struct cpu_info {
+	uint32_t cpu;
+	bool offline;
+	bool user_offline;
+	const char *sensor_type;
+	struct sensor_threshold thresh[2];
+};
+
 struct rail {
 	const char *name;
 	uint32_t freq_req;
@@ -91,6 +105,7 @@
 
 static struct psm_rail *psm_rails;
 static struct rail *rails;
+static struct cpu_info cpus[NR_CPUS];
 
 struct vdd_rstr_enable {
 	struct kobj_attribute ko_attr;
@@ -658,11 +673,67 @@
 	}
 	mutex_unlock(&core_control_mutex);
 }
+/* Call with core_control_mutex locked */
+static int __ref update_offline_cores(int val)
+{
+	int cpu = 0;
+	int ret = 0;
+
+	if (!core_control_enabled)
+		return 0;
+
+	cpus_offlined = msm_thermal_info.core_control_mask & val;
+
+	for_each_possible_cpu(cpu) {
+		if (!(cpus_offlined & BIT(cpu)))
+			continue;
+		if (!cpu_online(cpu))
+			continue;
+		ret = cpu_down(cpu);
+		if (ret)
+			pr_err("%s: Unable to offline cpu%d\n",
+				KBUILD_MODNAME, cpu);
+	}
+	return ret;
+}
+
+static __ref int do_hotplug(void *data)
+{
+	int ret = 0;
+	int cpu = 0;
+	uint32_t mask = 0;
+
+	if (!core_control_enabled)
+		return -EINVAL;
+
+	while (!kthread_should_stop()) {
+		wait_for_completion(&hotplug_notify_complete);
+		INIT_COMPLETION(hotplug_notify_complete);
+		mask = 0;
+
+		mutex_lock(&core_control_mutex);
+		for_each_possible_cpu(cpu) {
+			if (cpus[cpu].offline || cpus[cpu].user_offline)
+				mask |= BIT(cpu);
+		}
+		if (mask != cpus_offlined)
+			update_offline_cores(mask);
+		mutex_unlock(&core_control_mutex);
+		sysfs_notify(cc_kobj, NULL, "cpus_offlined");
+	}
+
+	return ret;
+}
 #else
 static void do_core_control(long temp)
 {
 	return;
 }
+
+static __ref int do_hotplug(void *data)
+{
+	return 0;
+}
 #endif
 
 static int do_vdd_restriction(void)
@@ -848,7 +919,7 @@
 		if (core_control_enabled &&
 			(msm_thermal_info.core_control_mask & BIT(cpu)) &&
 			(cpus_offlined & BIT(cpu))) {
-			pr_info(
+			pr_debug(
 			"%s: Preventing cpu%d from coming online.\n",
 				KBUILD_MODNAME, cpu);
 			return NOTIFY_BAD;
@@ -896,6 +967,112 @@
 			ts.tv_sec, ts.tv_usec);
 }
 
+static int hotplug_notify(enum thermal_trip_type type, int temp, void *data)
+{
+	struct cpu_info *cpu_node = (struct cpu_info *)data;
+
+	pr_info("%s: %s reach temp threshold: %d\n", KBUILD_MODNAME,
+			cpu_node->sensor_type, temp);
+
+	if (!(msm_thermal_info.core_control_mask & BIT(cpu_node->cpu)))
+		return 0;
+	switch (type) {
+	case THERMAL_TRIP_CONFIGURABLE_HI:
+		if (!(cpu_node->offline))
+			cpu_node->offline = 1;
+		break;
+	case THERMAL_TRIP_CONFIGURABLE_LOW:
+		if (cpu_node->offline)
+			cpu_node->offline = 0;
+		break;
+	default:
+		break;
+	}
+	if (hotplug_task)
+		complete(&hotplug_notify_complete);
+	else
+		pr_err("%s: Hotplug task is not initialized\n", KBUILD_MODNAME);
+	return 0;
+}
+/* Adjust cpus offlined bit based on temperature reading. */
+static int hotplug_init_cpu_offlined(void)
+{
+	struct tsens_device tsens_dev;
+	long temp = 0;
+	int cpu = 0;
+
+	mutex_lock(&core_control_mutex);
+	for_each_possible_cpu(cpu) {
+		if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
+			continue;
+		tsens_dev.sensor_num = sensor_get_id(\
+				(char *)cpus[cpu].sensor_type);
+		if (tsens_get_temp(&tsens_dev, &temp)) {
+			pr_err("%s: Unable to read TSENS sensor %d\n",
+				KBUILD_MODNAME, tsens_dev.sensor_num);
+			return -EINVAL;
+		}
+
+		if (temp >= msm_thermal_info.hotplug_temp_degC)
+			cpus[cpu].offline = 1;
+		else if (temp <= (msm_thermal_info.hotplug_temp_degC -
+			msm_thermal_info.hotplug_temp_hysteresis_degC))
+			cpus[cpu].offline = 0;
+	}
+	mutex_unlock(&core_control_mutex);
+
+	if (hotplug_task)
+		complete(&hotplug_notify_complete);
+	else {
+		pr_err("%s: Hotplug task is not initialized\n",
+					KBUILD_MODNAME);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void hotplug_init(void)
+{
+	int cpu = 0;
+
+	if (hotplug_task)
+		return;
+
+	for_each_possible_cpu(cpu) {
+		if (!(msm_thermal_info.core_control_mask & BIT(cpus[cpu].cpu)))
+			continue;
+		cpus[cpu].cpu = (uint32_t)cpu;
+		cpus[cpu].thresh[0].temp = msm_thermal_info.hotplug_temp_degC;
+		cpus[cpu].thresh[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
+		cpus[cpu].thresh[0].notify = hotplug_notify;
+		cpus[cpu].thresh[0].data = (void *)&cpus[cpu];
+		sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
+				&cpus[cpu].thresh[0]);
+
+		cpus[cpu].thresh[1].temp = msm_thermal_info.hotplug_temp_degC -
+				msm_thermal_info.hotplug_temp_hysteresis_degC;
+		cpus[cpu].thresh[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
+		cpus[cpu].thresh[1].notify = hotplug_notify;
+		cpus[cpu].thresh[1].data = (void *)&cpus[cpu];
+		sensor_set_trip(sensor_get_id((char *)cpus[cpu].sensor_type),
+				&cpus[cpu].thresh[1]);
+
+	}
+	init_completion(&hotplug_notify_complete);
+	hotplug_task = kthread_run(do_hotplug, NULL, "msm_thermal:hotplug");
+	if (IS_ERR(hotplug_task)) {
+		pr_err("%s: Failed to create do_hotplug thread\n",
+				KBUILD_MODNAME);
+		return;
+	}
+	/*
+	 * Adjust cpus offlined bit when hotplug intitializes so that the new
+	 * cpus offlined state is based on hotplug threshold range
+	 */
+	if (hotplug_init_cpu_offlined())
+		kthread_stop(hotplug_task);
+}
+
 /*
  * We will reset the cpu frequencies limits here. The core online/offline
  * status will be carried over to the process stopping the msm_thermal, as
@@ -922,9 +1099,10 @@
 	int ret = 0;
 
 	ret = param_set_bool(val, kp);
-	if (!enabled)
+	if (!enabled) {
 		disable_msm_thermal();
-	else
+		hotplug_init();
+	} else
 		pr_info("%s: no action for enabled = %d\n",
 				KBUILD_MODNAME, enabled);
 
@@ -941,37 +1119,6 @@
 module_param_cb(enabled, &module_ops, &enabled, 0644);
 MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu");
 
-
-#ifdef CONFIG_SMP
-/* Call with core_control_mutex locked */
-static int __ref update_offline_cores(int val)
-{
-	int cpu = 0;
-	int ret = 0;
-
-	cpus_offlined = msm_thermal_info.core_control_mask & val;
-	if (!core_control_enabled)
-		return 0;
-
-	for_each_possible_cpu(cpu) {
-		if (!(cpus_offlined & BIT(cpu)))
-			continue;
-		if (!cpu_online(cpu))
-			continue;
-		ret = cpu_down(cpu);
-		if (ret)
-			pr_err("%s: Unable to offline cpu%d\n",
-				KBUILD_MODNAME, cpu);
-	}
-	return ret;
-}
-#else
-static int update_offline_cores(int val)
-{
-	return 0;
-}
-#endif
-
 static ssize_t show_cc_enabled(struct kobject *kobj,
 		struct kobj_attribute *attr, char *buf)
 {
@@ -984,7 +1131,6 @@
 	int ret = 0;
 	int val = 0;
 
-	mutex_lock(&core_control_mutex);
 	ret = kstrtoint(buf, 10, &val);
 	if (ret) {
 		pr_err("%s: Invalid input %s\n", KBUILD_MODNAME, buf);
@@ -998,14 +1144,17 @@
 	if (core_control_enabled) {
 		pr_info("%s: Core control enabled\n", KBUILD_MODNAME);
 		register_cpu_notifier(&msm_thermal_cpu_notifier);
-		update_offline_cores(cpus_offlined);
+		if (hotplug_task)
+			complete(&hotplug_notify_complete);
+		else
+			pr_err("%s: Hotplug task is not initialized\n",
+					KBUILD_MODNAME);
 	} else {
 		pr_info("%s: Core control disabled\n", KBUILD_MODNAME);
 		unregister_cpu_notifier(&msm_thermal_cpu_notifier);
 	}
 
 done_store_cc:
-	mutex_unlock(&core_control_mutex);
 	return count;
 }
 
@@ -1020,6 +1169,7 @@
 {
 	int ret = 0;
 	uint32_t val = 0;
+	int cpu;
 
 	mutex_lock(&core_control_mutex);
 	ret = kstrtouint(buf, 10, &val);
@@ -1034,10 +1184,16 @@
 		goto done_cc;
 	}
 
-	if (cpus_offlined == val)
-		goto done_cc;
+	for_each_possible_cpu(cpu) {
+		if (!(msm_thermal_info.core_control_mask & BIT(cpu)))
+			continue;
+		cpus[cpu].user_offline = !!(val & BIT(cpu));
+	}
 
-	update_offline_cores(val);
+	if (hotplug_task)
+		complete(&hotplug_notify_complete);
+	else
+		pr_err("%s: Hotplug task is not initialized\n", KBUILD_MODNAME);
 done_cc:
 	mutex_unlock(&core_control_mutex);
 	return count;
@@ -1108,7 +1264,6 @@
 static __init int msm_thermal_add_cc_nodes(void)
 {
 	struct kobject *module_kobj = NULL;
-	struct kobject *cc_kobj = NULL;
 	int ret = 0;
 
 	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
@@ -1190,8 +1345,7 @@
 		return -EINVAL;
 
 	enabled = 1;
-	if (num_possible_cpus() > 1)
-		core_control_enabled = 1;
+
 	INIT_DELAYED_WORK(&check_temp_work, check_temp);
 	schedule_delayed_work(&check_temp_work, 0);
 
@@ -1602,12 +1756,76 @@
 	return ret;
 }
 
+static int probe_cc(struct device_node *node, struct msm_thermal_data *data,
+		struct platform_device *pdev)
+{
+	char *key = NULL;
+	int cpu_cnt = 0;
+	int ret = 0;
+	int cpu = 0;
+
+	key = "qcom,core-limit-temp";
+	ret = of_property_read_u32(node, key, &data->core_limit_temp_degC);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,core-temp-hysteresis";
+	ret = of_property_read_u32(node, key, &data->core_temp_hysteresis_degC);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,core-control-mask";
+	ret = of_property_read_u32(node, key, &data->core_control_mask);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,hotplug-temp";
+	ret = of_property_read_u32(node, key, &data->hotplug_temp_degC);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,hotplug-temp-hysteresis";
+	ret = of_property_read_u32(node, key,
+			&data->hotplug_temp_hysteresis_degC);
+	if (ret)
+		goto read_node_fail;
+
+	key = "qcom,cpu-sensors";
+	cpu_cnt = of_property_count_strings(node, key);
+	if (cpu_cnt != num_possible_cpus()) {
+		pr_err("%s: Wrong number of cpu\n", KBUILD_MODNAME);
+		goto read_node_fail;
+	}
+
+	for_each_possible_cpu(cpu) {
+		cpus[cpu].cpu = cpu;
+		cpus[cpu].offline = 0;
+		cpus[cpu].user_offline = 0;
+		ret = of_property_read_string_index(node, key, cpu,
+				&cpus[cpu].sensor_type);
+		if (ret)
+			goto read_node_fail;
+	}
+
+	if (num_possible_cpus() > 1)
+		core_control_enabled = 1;
+
+read_node_fail:
+	if (ret) {
+		dev_info(&pdev->dev,
+			"%s:Failed reading node=%s, key=%s. KTM continues\n",
+			KBUILD_MODNAME, node->full_name, key);
+		core_control_enabled = 0;
+	}
+
+	return ret;
+}
+
 static int __devinit msm_thermal_dev_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	char *key = NULL;
 	struct device_node *node = pdev->dev.of_node;
-
 	struct msm_thermal_data data;
 
 	memset(&data, 0, sizeof(struct msm_thermal_data));
@@ -1640,15 +1858,7 @@
 	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);
-
-	key = "qcom,core-temp-hysteresis";
-	ret = of_property_read_u32(node, key, &data.core_temp_hysteresis_degC);
-
-	key = "qcom,core-control-mask";
-	ret = of_property_read_u32(node, key, &data.core_control_mask);
-
+	ret = probe_cc(node, &data, pdev);
 	/*
 	 * Probe optional properties below. Call probe_psm before
 	 * probe_vdd_rstr because rpm_regulator_get has to be called
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index fd1a2fc..1cf901e 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -4,6 +4,7 @@
  *  Copyright (C) 2008 Intel Corp
  *  Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
  *  Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
+ *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
  *
  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -60,6 +61,273 @@
 static LIST_HEAD(thermal_cdev_list);
 static DEFINE_MUTEX(thermal_list_lock);
 
+static LIST_HEAD(sensor_info_list);
+static DEFINE_MUTEX(sensor_list_lock);
+
+static struct sensor_info *get_sensor(uint32_t sensor_id)
+{
+	struct sensor_info *pos, *var;
+
+	list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
+		if (pos->sensor_id == sensor_id)
+			break;
+	}
+
+	return pos;
+}
+
+int sensor_get_id(char *name)
+{
+	struct sensor_info *pos, *var;
+
+	list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
+		if (!strcmp(pos->tz->type, name))
+			return pos->sensor_id;
+	}
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(sensor_get_id);
+
+static void __update_sensor_thresholds(struct sensor_info *sensor)
+{
+	int min = INT_MIN;
+	int max = INT_MAX;
+	struct sensor_threshold *pos, *var;
+	enum thermal_trip_type type;
+	int i;
+	unsigned long curr_temp;
+
+	for (i = 0; ((sensor->max_idx == -1) || (sensor->min_idx == -1)) &&
+		(sensor->tz->ops->get_trip_type) && (i < sensor->tz->trips);
+		i++) {
+		sensor->tz->ops->get_trip_type(sensor->tz, i, &type);
+		if (type == THERMAL_TRIP_CONFIGURABLE_HI)
+			sensor->max_idx = i;
+		if (type == THERMAL_TRIP_CONFIGURABLE_LOW)
+			sensor->min_idx = i;
+	}
+
+	get_cpu();
+	sensor->tz->ops->get_temp(sensor->tz, &curr_temp);
+	list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+		if ((pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
+				(pos->temp < (int)curr_temp))
+			if (pos->temp > min)
+				min = pos->temp;
+		if ((pos->trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
+				(pos->temp > (int)curr_temp))
+			if (pos->temp < max)
+				max = pos->temp;
+	}
+	put_cpu();
+
+	if (sensor->tz->ops->set_trip_temp) {
+		if (max != INT_MAX) {
+			sensor->tz->ops->set_trip_temp(sensor->tz,
+				sensor->max_idx, max);
+			sensor->threshold_max = max;
+		}
+		if (min != INT_MIN) {
+			sensor->tz->ops->set_trip_temp(sensor->tz,
+				sensor->min_idx, min);
+			sensor->threshold_min = min;
+		}
+	}
+
+	pr_debug("sensor %d, min: %d, max %d\n", sensor->sensor_id, min, max);
+}
+
+static void sensor_update_work(struct work_struct *work)
+{
+	struct sensor_info *sensor = container_of(work, struct sensor_info,
+						work);
+	mutex_lock(&sensor->lock);
+	__update_sensor_thresholds(sensor);
+	mutex_unlock(&sensor->lock);
+}
+
+/* May be called in an interrupt context.
+ * Do NOT call sensor_set_trip from this function
+ */
+int thermal_sensor_trip(struct thermal_zone_device *tz,
+		enum thermal_trip_type trip, unsigned long temp)
+{
+	struct sensor_threshold *pos, *var;
+	int ret = -ENODEV;
+
+	if (trip != THERMAL_TRIP_CONFIGURABLE_HI &&
+			trip != THERMAL_TRIP_CONFIGURABLE_LOW)
+		return 0;
+
+	if (list_empty(&tz->sensor.threshold_list))
+		return 0;
+
+	list_for_each_entry_safe(pos, var, &tz->sensor.threshold_list, list) {
+		if (pos->trip != trip)
+			continue;
+		if (((trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
+			(pos->temp <= tz->sensor.threshold_min) &&
+			(pos->temp >= (int) temp)) ||
+			((trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
+				(pos->temp >= tz->sensor.threshold_max) &&
+				(pos->temp <= (int)temp))) {
+			pos->notify(trip, temp, pos->data);
+		}
+	}
+
+	schedule_work(&tz->sensor.work);
+
+	return ret;
+}
+EXPORT_SYMBOL(thermal_sensor_trip);
+
+int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
+{
+	struct sensor_threshold *pos, *var;
+	struct sensor_info *sensor = get_sensor(sensor_id);
+
+	if (!sensor)
+		return -ENODEV;
+
+	if (!threshold || !threshold->notify)
+		return -EFAULT;
+
+	mutex_lock(&sensor->lock);
+	list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+		if (pos == threshold)
+			break;
+	}
+
+	if (pos != threshold) {
+		INIT_LIST_HEAD(&threshold->list);
+		list_add(&threshold->list, &sensor->threshold_list);
+	}
+
+	__update_sensor_thresholds(sensor);
+	mutex_unlock(&sensor->lock);
+
+	return 0;
+
+}
+EXPORT_SYMBOL(sensor_set_trip);
+
+int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
+{
+	struct sensor_threshold *pos, *var;
+	struct sensor_info *sensor = get_sensor(sensor_id);
+
+	if (!sensor)
+		return -ENODEV;
+
+	mutex_lock(&sensor->lock);
+	list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+		if (pos == threshold) {
+			list_del(&pos->list);
+			break;
+		}
+	}
+
+	__update_sensor_thresholds(sensor);
+	mutex_unlock(&sensor->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(sensor_cancel_trip);
+
+static int sensor_get_trip_temp(struct thermal_zone_device *tz,
+		int type, unsigned long *temp)
+{
+	struct sensor_info *sensor = get_sensor(tz->id);
+
+	if (!sensor)
+		return -EFAULT;
+
+	switch (type) {
+	case THERMAL_TRIP_CONFIGURABLE_HI:
+		*temp = tz->sensor.threshold_max;
+		break;
+	case THERMAL_TRIP_CONFIGURABLE_LOW:
+		*temp = tz->sensor.threshold_min;
+		break;
+	default:
+		tz->ops->get_trip_temp(tz, type, temp);
+		break;
+	}
+
+	return 0;
+}
+
+static int tz_notify_trip(enum thermal_trip_type type, int temp, void *data)
+{
+	struct thermal_zone_device *tz = (struct thermal_zone_device *)data;
+
+	pr_debug("sensor %d tripped: type %d temp %d\n",
+			tz->sensor.sensor_id, type, temp);
+
+	return 0;
+}
+
+int sensor_set_trip_temp(struct thermal_zone_device *tz,
+		int trip, long temp)
+{
+	int ret = 0;
+	enum thermal_trip_type type;
+
+	if (!tz->ops->get_trip_type)
+		return -EPERM;
+
+	tz->ops->get_trip_type(tz, trip, &type);
+	switch (type) {
+	case THERMAL_TRIP_CONFIGURABLE_HI:
+		tz->tz_threshold[0].temp = temp;
+		tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
+		tz->tz_threshold[0].notify = tz_notify_trip;
+		tz->tz_threshold[0].data = tz;
+		ret = sensor_set_trip(tz->sensor.sensor_id,
+					&tz->tz_threshold[0]);
+		break;
+	case THERMAL_TRIP_CONFIGURABLE_LOW:
+		tz->tz_threshold[1].temp = temp;
+		tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
+		tz->tz_threshold[1].notify = tz_notify_trip;
+		tz->tz_threshold[1].data = tz;
+		ret = sensor_set_trip(tz->sensor.sensor_id,
+					&tz->tz_threshold[1]);
+		break;
+	default:
+		ret = tz->ops->set_trip_temp(tz, trip, temp);
+		break;
+	}
+
+	return ret;
+}
+
+int sensor_init(struct thermal_zone_device *tz)
+{
+	struct sensor_info *sensor = &tz->sensor;
+
+	sensor->sensor_id = tz->id;
+	sensor->tz = tz;
+	sensor->threshold_min = 0;
+	sensor->threshold_max = INT_MAX;
+	sensor->max_idx = -1;
+	sensor->min_idx = -1;
+	mutex_init(&sensor->lock);
+	INIT_LIST_HEAD(&sensor->sensor_list);
+	INIT_LIST_HEAD(&sensor->threshold_list);
+	INIT_LIST_HEAD(&tz->tz_threshold[0].list);
+	INIT_LIST_HEAD(&tz->tz_threshold[1].list);
+	tz->tz_threshold[0].notify = NULL;
+	tz->tz_threshold[0].data = NULL;
+	tz->tz_threshold[1].notify = NULL;
+	tz->tz_threshold[1].data = NULL;
+	list_add(&sensor->sensor_list, &sensor_info_list);
+	INIT_WORK(&sensor->work, sensor_update_work);
+
+	return 0;
+}
+
 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
 {
 	int err;
@@ -243,7 +511,7 @@
 	if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
 		return -EINVAL;
 
-	ret = tz->ops->get_trip_temp(tz, trip, &temperature);
+	ret = sensor_get_trip_temp(tz, trip, &temperature);
 
 	if (ret)
 		return ret;
@@ -268,7 +536,8 @@
 	if (!sscanf(buf, "%ld", &temperature))
 		return -EINVAL;
 
-	ret = tz->ops->set_trip_temp(tz, trip, temperature);
+	ret = sensor_set_trip_temp(tz, trip, temperature);
+
 	if (ret)
 		return ret;
 
@@ -1313,6 +1582,7 @@
 		if (result)
 			break;
 		}
+	sensor_init(tz);
 	mutex_unlock(&thermal_list_lock);
 
 	INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
@@ -1372,6 +1642,10 @@
 				   &trip_point_attrs[count * 2 + 1]);
 	}
 	thermal_remove_hwmon_sysfs(tz);
+	flush_work(&tz->sensor.work);
+	mutex_lock(&thermal_list_lock);
+	list_del(&tz->sensor.sensor_list);
+	mutex_unlock(&thermal_list_lock);
 	release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
 	idr_destroy(&tz->idr);
 	mutex_destroy(&tz->lock);
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index db6fec9..98c6884 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -111,7 +111,33 @@
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
 	reg |= DWC3_GCTL_PRTCAPDIR(mode);
+	/*
+	 * Set this bit so that device attempts three more times at SS, even
+	 * if it failed previously to operate in SS mode.
+	 */
+	reg |= DWC3_GCTL_U2RSTECN;
+	if (mode == DWC3_GCTL_PRTCAP_HOST) {
+		/*
+		 * Allow ITP generated off of ref clk based counter instead
+		 * of UTMI/ULPI clk based counter, when superspeed only is
+		 * active so that UTMI/ULPI PHY can be suspened.
+		 */
+		reg |= DWC3_GCTL_SOFITPSYNC;
+		reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+		reg |= DWC3_GCTL_PWRDNSCALE(2);
+	} else if (mode == DWC3_GCTL_PRTCAP_DEVICE) {
+		reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+		reg |= DWC3_GCTL_PWRDNSCALE(2);
+		reg &= ~(DWC3_GCTL_SOFITPSYNC);
+	}
+	reg |= DWC3_GCTL_U2EXIT_LFPS;
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+	reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+	reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 }
 
 /**
@@ -127,6 +153,9 @@
 	reg |= DWC3_GCTL_CORESOFTRESET;
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
+	if (dwc->revision >= DWC3_REVISION_230A)
+		dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT);
+
 	/* Assert USB3 PHY reset */
 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 	reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
@@ -155,6 +184,9 @@
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg &= ~DWC3_GCTL_CORESOFTRESET;
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+
+	if (dwc->revision >= DWC3_REVISION_230A)
+		dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT);
 }
 
 /**
@@ -473,6 +505,20 @@
 	dwc3_gadget_restart(dwc);
 }
 
+static void (*notify_event) (struct dwc3 *, unsigned);
+void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned))
+{
+	notify_event = notify;
+}
+EXPORT_SYMBOL(dwc3_set_notifier);
+
+void dwc3_notify_event(struct dwc3 *dwc, unsigned event)
+{
+	if (dwc->notify_event)
+		dwc->notify_event(dwc, event);
+}
+EXPORT_SYMBOL(dwc3_notify_event);
+
 #define DWC3_ALIGN_MASK		(16 - 1)
 
 static u64 dwc3_dma_mask = DMA_BIT_MASK(64);
@@ -504,6 +550,7 @@
 	if (!dev->coherent_dma_mask)
 		dev->coherent_dma_mask = DMA_BIT_MASK(64);
 
+	dwc->notify_event = notify_event;
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(dev, "missing IRQ\n");
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 2064c13..328f6f4 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -163,7 +163,10 @@
 
 /* Global Configuration Register */
 #define DWC3_GCTL_PWRDNSCALE(n)	((n) << 19)
+#define DWC3_GCTL_PWRDNSCALEMASK (0xFFF80000)
 #define DWC3_GCTL_U2RSTECN	(1 << 16)
+#define DWC3_GCTL_SOFITPSYNC	(1 << 10)
+#define DWC3_GCTL_U2EXIT_LFPS	(1 << 2)
 #define DWC3_GCTL_RAMCLKSEL(x)	(((x) & DWC3_GCTL_CLK_MASK) << 6)
 #define DWC3_GCTL_CLK_BUS	(0)
 #define DWC3_GCTL_CLK_PIPE	(1)
@@ -643,6 +646,9 @@
 	__le64	dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
 };
 
+#define DWC3_CONTROLLER_ERROR_EVENT			0
+#define DWC3_CONTROLLER_RESET_EVENT			1
+#define DWC3_CONTROLLER_POST_RESET_EVENT		2
 /**
  * struct dwc3 - representation of our controller
  * @ctrl_req: usb control request which is used for ep0
@@ -771,6 +777,7 @@
 
 	/* Indicate if software connect was issued by the usb_gadget_driver */
 	bool			softconnect;
+	void (*notify_event) (struct dwc3 *, unsigned);
 };
 
 /* -------------------------------------------------------------------------- */
@@ -922,6 +929,9 @@
 void dwc3_post_host_reset_core_init(struct dwc3 *dwc);
 int dwc3_event_buffers_setup(struct dwc3 *dwc);
 
+extern void dwc3_set_notifier(
+		void (*notify) (struct dwc3 *dwc3, unsigned event));
+extern void dwc3_notify_event(struct dwc3 *dwc3, unsigned event);
 extern int dwc3_get_device_id(void);
 extern void dwc3_put_device_id(int id);
 
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index b156c5f..4901f4b 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -46,6 +46,7 @@
 extern void dbg_setup(u8, const struct usb_ctrlrequest*);
 extern int dwc3_debugfs_init(struct dwc3 *);
 extern void dwc3_debugfs_exit(struct dwc3 *);
+extern void dbg_print_reg(const char *name, int reg);
 #else
 static inline void dbg_event(u8, const char*, int)
 {  }
@@ -57,6 +58,8 @@
 {  }
 static inline void dbg_setup(u8, const struct usb_ctrlrequest*)
 {  }
+static inline void dbg_print_reg(const char *name, int reg)
+{  }
 static inline int dwc3_debugfs_init(struct dwc3 *d)
 {  return 0;  }
 static inline void dwc3_debugfs_exit(struct dwc3 *d)
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index df95646..a2580fc 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -972,6 +972,28 @@
 }
 
 /**
+ * dbg_print_reg: prints a reg value
+ * @name:   reg name
+ * @reg: reg value to be printed
+ */
+void dbg_print_reg(const char *name, int reg)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&dbg_dwc3_data.lck, flags);
+
+	scnprintf(dbg_dwc3_data.buf[dbg_dwc3_data.idx], DBG_DATA_MSG,
+		  "%s = 0x%08x\n", name, reg);
+
+	dbg_inc(&dbg_dwc3_data.idx);
+
+	write_unlock_irqrestore(&dbg_dwc3_data.lck, flags);
+
+	if (dbg_dwc3_data.tty != 0)
+		pr_notice("%s = 0x%08x\n", name, reg);
+}
+
+/**
  * store_events: configure if events are going to be also printed to console
  *
  */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index d3ea3be..d7721dc 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -50,6 +50,7 @@
 #include "dwc3_otg.h"
 #include "core.h"
 #include "gadget.h"
+#include "debug.h"
 
 /* ADC threshold values */
 static int adc_low_threshold = 700;
@@ -140,6 +141,7 @@
 #define QSCRATCH_REG_OFFSET	(0x000F8800)
 #define QSCRATCH_CTRL_REG      (QSCRATCH_REG_OFFSET + 0x04)
 #define QSCRATCH_GENERAL_CFG	(QSCRATCH_REG_OFFSET + 0x08)
+#define QSCRATCH_RAM1_REG	(QSCRATCH_REG_OFFSET + 0x0C)
 #define HS_PHY_CTRL_REG		(QSCRATCH_REG_OFFSET + 0x10)
 #define PARAMETER_OVERRIDE_X_REG (QSCRATCH_REG_OFFSET + 0x14)
 #define CHARGING_DET_CTRL_REG	(QSCRATCH_REG_OFFSET + 0x18)
@@ -156,6 +158,8 @@
 #define SS_CR_PROTOCOL_CAP_DATA_REG (QSCRATCH_REG_OFFSET + 0x48)
 #define SS_CR_PROTOCOL_READ_REG     (QSCRATCH_REG_OFFSET + 0x4C)
 #define SS_CR_PROTOCOL_WRITE_REG    (QSCRATCH_REG_OFFSET + 0x50)
+#define PWR_EVNT_IRQ_STAT_REG    (QSCRATCH_REG_OFFSET + 0x58)
+#define PWR_EVNT_IRQ_MASK_REG    (QSCRATCH_REG_OFFSET + 0x5C)
 
 struct dwc3_msm_req_complete {
 	struct list_head list_item;
@@ -223,7 +227,7 @@
 	bool			ext_inuse;
 	enum dwc3_id_state	id_state;
 	unsigned long		lpm_flags;
-#define MDWC3_CORECLK_OFF		BIT(0)
+#define MDWC3_PHY_REF_AND_CORECLK_OFF	BIT(0)
 #define MDWC3_TCXO_SHUTDOWN		BIT(1)
 
 	u32 qscratch_ctl_val;
@@ -410,6 +414,37 @@
 }
 
 /**
+ * Dump all QSCRATCH registers.
+ *
+ */
+static void dwc3_msm_dump_phy_info(struct dwc3_msm *mdwc)
+{
+
+	dbg_print_reg("SSPHY_CTRL_REG", dwc3_msm_read_reg(mdwc->base,
+						SS_PHY_CTRL_REG));
+	dbg_print_reg("HSPHY_CTRL_REG", dwc3_msm_read_reg(mdwc->base,
+						HS_PHY_CTRL_REG));
+	dbg_print_reg("QSCRATCH_CTRL_REG", dwc3_msm_read_reg(mdwc->base,
+						QSCRATCH_CTRL_REG));
+	dbg_print_reg("QSCRATCH_GENERAL_CFG", dwc3_msm_read_reg(mdwc->base,
+						QSCRATCH_GENERAL_CFG));
+	dbg_print_reg("PARAMETER_OVERRIDE_X_REG", dwc3_msm_read_reg(mdwc->base,
+						PARAMETER_OVERRIDE_X_REG));
+	dbg_print_reg("HS_PHY_IRQ_STAT_REG", dwc3_msm_read_reg(mdwc->base,
+						HS_PHY_IRQ_STAT_REG));
+	dbg_print_reg("SS_PHY_PARAM_CTRL_1", dwc3_msm_read_reg(mdwc->base,
+						SS_PHY_PARAM_CTRL_1));
+	dbg_print_reg("SS_PHY_PARAM_CTRL_2", dwc3_msm_read_reg(mdwc->base,
+						SS_PHY_PARAM_CTRL_2));
+	dbg_print_reg("QSCRATCH_RAM1_REG", dwc3_msm_read_reg(mdwc->base,
+						QSCRATCH_RAM1_REG));
+	dbg_print_reg("PWR_EVNT_IRQ_STAT_REG", dwc3_msm_read_reg(mdwc->base,
+						PWR_EVNT_IRQ_STAT_REG));
+	dbg_print_reg("PWR_EVNT_IRQ_MASK_REG", dwc3_msm_read_reg(mdwc->base,
+						PWR_EVNT_IRQ_MASK_REG));
+}
+
+/**
  * Return DBM EP number according to usb endpoint number.
  *
  */
@@ -1381,8 +1416,14 @@
 }
 
 /* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc,
+						unsigned event_status)
 {
+	if (event_status == DWC3_CONTROLLER_POST_RESET_EVENT) {
+		dwc3_msm_ss_phy_reg_init(mdwc);
+		return;
+	}
+
 	/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
 	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
 	msleep(30);
@@ -1393,7 +1434,7 @@
 	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
 	usleep_range(2000, 2200);
 	/* Ref clock must be stable now, enable ref clock for HS mode */
-	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210102);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x11210102);
 	usleep_range(2000, 2200);
 	/*
 	 * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
@@ -1401,8 +1442,8 @@
 	 */
 	dwc3_msm_write_reg(mdwc->base, HS_PHY_CTRL_REG, 0x5220bb2);
 	usleep_range(2000, 2200);
-	/* Disable (bypass) VBUS and ID filters */
-	dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x78);
+	/* Set XHCI_REV bit (2) to 1 - XHCI version 1.0 */
+	dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x4);
 	/*
 	 * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
 	 * VBUS valid threshold, disconnect valid threshold, DC voltage level,
@@ -1415,14 +1456,14 @@
 					PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
 					mdwc->hsphy_init_seq & 0x03FFFFFF);
 
-	/* Enable master clock for RAMs to allow BAM to access RAMs when
-	 * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
+	/*
+	 * Enable master clock for RAMs to allow BAM to access RAMs when
+	 * RAM clock gating is enabled via DWC3's GCTL. Otherwise issues
 	 * are seen where RAM clocks get turned OFF in SS mode
 	 */
 	dwc3_msm_write_reg(mdwc->base, CGCTL_REG,
 		dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18);
 
-	dwc3_msm_ss_phy_reg_init(mdwc);
 	/*
 	 * This is required to restore the POR value after userspace
 	 * is done with charger detection.
@@ -1431,6 +1472,31 @@
 		dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG);
 }
 
+static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
+{
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+	switch (event) {
+	case DWC3_CONTROLLER_ERROR_EVENT:
+		dev_info(mdwc->dev, "DWC3_CONTROLLER_ERROR_EVENT received\n");
+		dwc3_msm_dump_phy_info(mdwc);
+		break;
+	case DWC3_CONTROLLER_RESET_EVENT:
+		dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESET_EVENT received\n");
+		dwc3_msm_qscratch_reg_init(mdwc, DWC3_CONTROLLER_RESET_EVENT);
+		break;
+	case DWC3_CONTROLLER_POST_RESET_EVENT:
+		dev_dbg(mdwc->dev,
+				"DWC3_CONTROLLER_POST_RESET_EVENT received\n");
+		dwc3_msm_qscratch_reg_init(mdwc,
+					DWC3_CONTROLLER_POST_RESET_EVENT);
+		break;
+	default:
+		dev_dbg(mdwc->dev, "unknown dwc3 event\n");
+		break;
+	}
+}
+
 static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
 {
 	struct dwc3_msm *mdwc = container_of(xceiv, struct dwc3_msm, ext_xceiv);
@@ -1447,9 +1513,6 @@
 			return;
 
 		usleep_range(10000, 12000);
-
-		/* Reinitialize QSCRATCH registers after block reset */
-		dwc3_msm_qscratch_reg_init(mdwc);
 	}
 
 	/* Reset the DBM */
@@ -1687,6 +1750,7 @@
 	bool dcp;
 	bool host_bus_suspend;
 	bool host_ss_active;
+	bool host_ss_suspend;
 
 	dev_dbg(mdwc->dev, "%s: entering lpm\n", __func__);
 
@@ -1713,6 +1777,7 @@
 	      (mdwc->charger.chg_type == DWC3_PROPRIETARY_CHARGER) ||
 	      (mdwc->charger.chg_type == DWC3_FLOATED_CHARGER));
 	host_bus_suspend = mdwc->host_mode == 1;
+	host_ss_suspend = host_bus_suspend && host_ss_active;
 
 	if (!dcp && !host_bus_suspend)
 		dwc3_msm_write_reg(mdwc->base, QSCRATCH_CTRL_REG,
@@ -1724,13 +1789,17 @@
 	 * 3. Set TEST_POWERED_DOWN in SS_PHY_CTRL_REG to enable PHY retention
 	 * 4. Disable SSPHY ref clk
 	 */
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8), 0x0);
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28), 0x0);
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26),
+	if (!host_ss_suspend) {
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8),
+									0x0);
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28),
+									0x0);
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26),
 								(1 << 26));
-
+	}
 	usleep_range(1000, 1200);
-	clk_disable_unprepare(mdwc->ref_clk);
+	if (!host_ss_suspend)
+		clk_disable_unprepare(mdwc->ref_clk);
 
 	if (host_bus_suspend) {
 		/* Sequence for host bus suspend case:
@@ -1775,9 +1844,9 @@
 	if (!host_bus_suspend)
 		dwc3_msm_config_gdsc(mdwc, 0);
 
-	if (!host_bus_suspend || !host_ss_active) {
+	if (!host_ss_suspend) {
 		clk_disable_unprepare(mdwc->core_clk);
-		mdwc->lpm_flags |= MDWC3_CORECLK_OFF;
+		mdwc->lpm_flags |= MDWC3_PHY_REF_AND_CORECLK_OFF;
 	}
 	clk_disable_unprepare(mdwc->iface_clk);
 
@@ -1825,6 +1894,7 @@
 	int ret;
 	bool dcp;
 	bool host_bus_suspend;
+	bool resume_from_core_clk_off = false;
 
 	dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
 
@@ -1835,6 +1905,9 @@
 
 	pm_stay_awake(mdwc->dev);
 
+	if (mdwc->lpm_flags & MDWC3_PHY_REF_AND_CORECLK_OFF)
+		resume_from_core_clk_off = true;
+
 	if (mdwc->bus_perf_client) {
 		ret = msm_bus_scale_client_update_request(
 						mdwc->bus_perf_client, 1);
@@ -1873,13 +1946,14 @@
 	if (!host_bus_suspend && !dcp)
 		dwc3_hsusb_config_vddcx(mdwc, 1);
 
-	clk_prepare_enable(mdwc->ref_clk);
+	if (mdwc->lpm_flags & MDWC3_PHY_REF_AND_CORECLK_OFF)
+		clk_prepare_enable(mdwc->ref_clk);
 	usleep_range(1000, 1200);
 
 	clk_prepare_enable(mdwc->iface_clk);
-	if (mdwc->lpm_flags & MDWC3_CORECLK_OFF) {
+	if (mdwc->lpm_flags & MDWC3_PHY_REF_AND_CORECLK_OFF) {
 		clk_prepare_enable(mdwc->core_clk);
-		mdwc->lpm_flags &= ~MDWC3_CORECLK_OFF;
+		mdwc->lpm_flags &= ~MDWC3_PHY_REF_AND_CORECLK_OFF;
 	}
 
 	if (host_bus_suspend) {
@@ -1892,10 +1966,6 @@
 
 		/* Disable DP and DM HV interrupt */
 		dwc3_msm_write_reg(mdwc->base, ALT_INTERRUPT_EN_REG, 0x000);
-
-		/* Clear suspend bit in GUSB2PHYCONFIG register */
-		dwc3_msm_write_readback(mdwc->base, DWC3_GUSB2PHYCFG(0),
-								0x40, 0x0);
 	} else {
 		/* Disable HV interrupt */
 		if (mdwc->otg_xceiv && (!mdwc->ext_xceiv.otg_capability))
@@ -1919,23 +1989,27 @@
 
 	}
 
-	/* Assert SS PHY RESET */
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7),
+	if (resume_from_core_clk_off) {
+		/* Assert SS PHY RESET */
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7),
 								(1 << 7));
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28),
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 28),
 								(1 << 28));
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8),
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 8),
 								(1 << 8));
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26), 0x0);
-	/* 10usec delay required before de-asserting SS PHY RESET */
-	udelay(10);
-	dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7), 0x0);
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 26),
+									0x0);
+		/* 10usec delay required before de-asserting SS PHY RESET */
+		udelay(10);
+		dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7),
+									0x0);
 
-	/*
-	 * Reinitilize SSPHY parameters as SS_PHY RESET will reset
-	 * the internal registers to default values.
-	 */
-	dwc3_msm_ss_phy_reg_init(mdwc);
+		/*
+		 * Reinitilize SSPHY parameters as SS_PHY RESET will reset
+		 * the internal registers to default values.
+		 */
+		dwc3_msm_ss_phy_reg_init(mdwc);
+	}
 	atomic_set(&mdwc->in_lpm, 0);
 
 	/* match disable_irq call from isr */
@@ -2072,7 +2146,7 @@
 
 static struct dentry *dwc3_debugfs_root;
 
-static void dwc3_debugfs_init(struct dwc3_msm *mdwc)
+static void dwc3_msm_debugfs_init(struct dwc3_msm *mdwc)
 {
 	dwc3_debugfs_root = debugfs_create_dir("msm_dwc3", NULL);
 
@@ -2871,8 +2945,6 @@
 	else if (!mdwc->hsphy_init_seq)
 		dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
 
-	dwc3_msm_qscratch_reg_init(mdwc);
-
 	pm_runtime_set_active(mdwc->dev);
 	pm_runtime_enable(mdwc->dev);
 
@@ -2891,7 +2963,7 @@
 		ret = -ENODEV;
 		goto disable_hs_ldo;
 	}
-
+	dwc3_set_notifier(&dwc3_msm_notify_event);
 	/* usb_psy required only for vbus_notifications or charging support */
 	if (mdwc->ext_xceiv.otg_capability ||
 			!mdwc->charger.charging_disabled) {
@@ -2990,7 +3062,7 @@
 
 	device_init_wakeup(mdwc->dev, 1);
 	pm_stay_awake(mdwc->dev);
-	dwc3_debugfs_init(mdwc);
+	dwc3_msm_debugfs_init(mdwc);
 
 	return 0;
 
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index d0d9d34..e912e86 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -56,6 +56,19 @@
 		reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 		reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
 		reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST);
+		/*
+		 * Allow ITP generated off of ref clk based counter instead
+		 * of UTMI/ULPI clk based counter, when superspeed only is
+		 * active so that UTMI/ULPI can be suspened.
+		 */
+		reg |= DWC3_GCTL_SOFITPSYNC;
+		/*
+		 * Set this bit so that device attempts three more times at SS,
+		 * even if it failed previously to operate in SS mode.
+		 */
+		reg |= DWC3_GCTL_U2RSTECN;
+		reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+		reg |= DWC3_GCTL_PWRDNSCALE(2);
 		dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 	}
 }
@@ -126,6 +139,14 @@
 		reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 		reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
 		reg |= DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_DEVICE);
+		/*
+		 * Set this bit so that device attempts three more times at SS,
+		 * even if it failed previously to operate in SS mode.
+	 */
+		reg |= DWC3_GCTL_U2RSTECN;
+		reg &= ~(DWC3_GCTL_PWRDNSCALEMASK);
+		reg |= DWC3_GCTL_PWRDNSCALE(2);
+		reg &= ~(DWC3_GCTL_SOFITPSYNC);
 		dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 	}
 }
@@ -847,7 +868,8 @@
 	 * OCFG[1] - HNPCap = 0
 	 * OCFG[0] - SRPCap = 0
 	 */
-	dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);
+	if (ext_xceiv && !ext_xceiv->otg_capability)
+		dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);
 
 	/*
 	 * OCTL[6] - PeriMode = 1
@@ -859,7 +881,8 @@
 	 * OCTL[0] - HstSetHNPEn = 0
 	 */
 	if (!once) {
-		dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
+		if (ext_xceiv && !ext_xceiv->otg_capability)
+			dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
 		once++;
 	}
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index acda980..8cf8a6d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -63,6 +63,9 @@
 MODULE_PARM_DESC(tx_fifo_resize_enable,
 			"Enable allocating Tx fifo for endpoints");
 
+static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend);
+static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
+
 /**
  * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
  * @dwc: pointer to our context structure
@@ -322,6 +325,16 @@
 {
 	u32		timeout = 500;
 	u32		reg;
+	bool hsphy_suspend_enabled;
+	int ret;
+
+	/* Commands to controller will work only if PHY is not suspended */
+	hsphy_suspend_enabled = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
+						DWC3_GUSB2PHYCFG_SUSPHY);
+
+	/* Disable suspend of the USB2 PHY */
+	if (hsphy_suspend_enabled)
+		dwc3_gadget_usb2_phy_suspend(dwc, false);
 
 	dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
 	dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
@@ -331,7 +344,8 @@
 		if (!(reg & DWC3_DGCMD_CMDACT)) {
 			dev_vdbg(dwc->dev, "Command Complete --> %d\n",
 					DWC3_DGCMD_STATUS(reg));
-			return 0;
+			ret = 0;
+			break;
 		}
 
 		/*
@@ -339,10 +353,18 @@
 		 * interrupt context.
 		 */
 		timeout--;
-		if (!timeout)
-			return -ETIMEDOUT;
+		if (!timeout) {
+			ret = -ETIMEDOUT;
+			break;
+		}
 		udelay(1);
 	} while (1);
+
+	/* Enable suspend of the USB2 PHY */
+	if (hsphy_suspend_enabled)
+		dwc3_gadget_usb2_phy_suspend(dwc, true);
+
+	return ret;
 }
 
 int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
@@ -351,12 +373,22 @@
 	struct dwc3_ep		*dep = dwc->eps[ep];
 	u32			timeout = 500;
 	u32			reg;
+	bool hsphy_suspend_enabled;
+	int ret;
 
 	dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n",
 			dep->name,
 			dwc3_gadget_ep_cmd_string(cmd), params->param0,
 			params->param1, params->param2);
 
+	/* Commands to controller will work only if PHY is not suspended */
+	hsphy_suspend_enabled = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
+						DWC3_GUSB2PHYCFG_SUSPHY);
+
+	/* Disable suspend of the USB2 PHY */
+	if (hsphy_suspend_enabled)
+		dwc3_gadget_usb2_phy_suspend(dwc, false);
+
 	dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
 	dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(ep), params->param1);
 	dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(ep), params->param2);
@@ -374,9 +406,10 @@
 			 * event. Hence return error in this case.
 			 */
 			if (reg & 0x2000)
-				return -EAGAIN;
+				ret = -EAGAIN;
 			else
-				return 0;
+				ret = 0;
+			break;
 		}
 
 		/*
@@ -384,11 +417,19 @@
 		 * interrupt context.
 		 */
 		timeout--;
-		if (!timeout)
-			return -ETIMEDOUT;
+		if (!timeout) {
+			ret = -ETIMEDOUT;
+			break;
+		}
 
 		udelay(1);
 	} while (1);
+
+	/* Enable suspend of the USB2 PHY */
+	if (hsphy_suspend_enabled)
+		dwc3_gadget_usb2_phy_suspend(dwc, true);
+
+	return ret;
 }
 
 dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
@@ -1677,6 +1718,9 @@
 		reg |= DWC3_DCTL_HIRD_THRES(28);
 
 		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+		dwc3_gadget_usb2_phy_suspend(dwc, true);
+		dwc3_gadget_usb3_phy_suspend(dwc, true);
 	}
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
@@ -2572,6 +2616,35 @@
 	dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
 }
 
+static void dwc3_dump_reg_info(struct dwc3 *dwc)
+{
+	dbg_event(0xFF, "REGDUMP", 0);
+
+	dbg_print_reg("GUSB3PIPCTL", dwc3_readl(dwc->regs,
+							DWC3_GUSB3PIPECTL(0)));
+	dbg_print_reg("GUSB2PHYCONFIG", dwc3_readl(dwc->regs,
+							DWC3_GUSB2PHYCFG(0)));
+	dbg_print_reg("GCTL", dwc3_readl(dwc->regs, DWC3_GCTL));
+	dbg_print_reg("GUCTL", dwc3_readl(dwc->regs, DWC3_GUCTL));
+	dbg_print_reg("GDBGLTSSM", dwc3_readl(dwc->regs, DWC3_GDBGLTSSM));
+	dbg_print_reg("DCFG", dwc3_readl(dwc->regs, DWC3_DCFG));
+	dbg_print_reg("DCTL", dwc3_readl(dwc->regs, DWC3_DCTL));
+	dbg_print_reg("DEVTEN", dwc3_readl(dwc->regs, DWC3_DEVTEN));
+	dbg_print_reg("DSTS", dwc3_readl(dwc->regs, DWC3_DSTS));
+	dbg_print_reg("DALPENA", dwc3_readl(dwc->regs, DWC3_DALEPENA));
+	dbg_print_reg("DGCMD", dwc3_readl(dwc->regs, DWC3_DGCMD));
+
+	dbg_print_reg("OCFG", dwc3_readl(dwc->regs, DWC3_OCFG));
+	dbg_print_reg("OCTL", dwc3_readl(dwc->regs, DWC3_OCTL));
+	dbg_print_reg("OEVT", dwc3_readl(dwc->regs, DWC3_OEVT));
+	dbg_print_reg("OSTS", dwc3_readl(dwc->regs, DWC3_OSTS));
+
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT);
+
+	panic("DWC3 Erratic error\n");
+
+}
+
 static void dwc3_gadget_interrupt(struct dwc3 *dwc,
 		const struct dwc3_event_devt *event)
 {
@@ -2600,6 +2673,7 @@
 	case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
 		dbg_event(0xFF, "ERROR", 0);
 		dev_vdbg(dwc->dev, "Erratic Error\n");
+		dwc3_dump_reg_info(dwc);
 		break;
 	case DWC3_DEVICE_EVENT_CMD_CMPL:
 		dev_vdbg(dwc->dev, "Command Complete\n");
@@ -2824,8 +2898,8 @@
 
 		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
-		dwc3_gadget_usb2_phy_suspend(dwc, false);
-		dwc3_gadget_usb3_phy_suspend(dwc, false);
+		dwc3_gadget_usb2_phy_suspend(dwc, true);
+		dwc3_gadget_usb3_phy_suspend(dwc, true);
 	}
 
 	ret = device_register(&dwc->gadget.dev);
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index f90967f..44dd3c5 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -463,6 +463,11 @@
 	pr_debug("qdss_disable\n");
 
 	spin_lock_irqsave(&qdss->lock, flags);
+	if (!qdss->usb_connected) {
+		spin_unlock_irqrestore(&qdss->lock, flags);
+		return;
+	}
+
 	qdss->usb_connected = 0;
 	spin_unlock_irqrestore(&qdss->lock, flags);
 
@@ -521,6 +526,7 @@
 	if (gadget->speed != USB_SPEED_SUPER &&
 		gadget->speed != USB_SPEED_HIGH) {
 			pr_err("qdss_st_alt: qdss supportes HS or SS only\n");
+			ret = -EINVAL;
 			goto fail;
 	}
 
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index f2de17d..7f731d2 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -320,7 +320,7 @@
 	wmb();
 }
 
-void msm_dsi_set_tx_power_mode(int mode)
+void dsi_set_tx_power_mode(int mode)
 {
 	u32 data;
 	unsigned char *ctrl_base = dsi_host_private->dsi_base;
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index 022d911..b1a4293 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -143,6 +143,29 @@
 	return 0;
 }
 
+static char led_pwm1[2] = {0x51, 0x0};	/* DTYPE_DCS_WRITE1 */
+static struct dsi_cmd_desc backlight_cmd = {
+	DTYPE_DCS_WRITE1, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
+
+static void dsi_panel_bklt_dcs(struct mdss_panel_data *pdata, int level)
+{
+	struct mipi_panel_info *mipi;
+
+	mipi  = &pdata->panel_info.mipi;
+
+	pr_debug("%s: dcs level=%d\n", __func__, level);
+
+	led_pwm1[1] = (unsigned char)level;
+
+	if (DSI_VIDEO_MODE == mipi->mode) {
+		dsi_set_tx_power_mode(0);
+		dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+					&backlight_cmd,
+					1);
+		dsi_set_tx_power_mode(1);
+	}
+}
+
 void dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
 {
 	if (pdata == NULL) {
@@ -166,13 +189,21 @@
 	if (enable == 2) {
 		dsi_panel_power(1);
 		gpio_request(panel_private->rst_gpio, "panel_reset");
+		gpio_set_value(panel_private->rst_gpio, 1);
 		if (gpio_is_valid(panel_private->disp_en_gpio)) {
 			gpio_request(panel_private->disp_en_gpio,
 					"panel_enable");
+			gpio_set_value(panel_private->disp_en_gpio, 1);
 		}
 		if (gpio_is_valid(panel_private->video_mode_gpio)) {
 			gpio_request(panel_private->video_mode_gpio,
 					"panel_video_mdoe");
+			if (pdata->panel_info.mipi.mode == DSI_VIDEO_MODE)
+				gpio_set_value(panel_private->video_mode_gpio,
+						1);
+			else
+				gpio_set_value(panel_private->video_mode_gpio,
+						0);
 		}
 		if (gpio_is_valid(panel_private->te_gpio))
 			gpio_request(panel_private->te_gpio, "panel_te");
@@ -233,6 +264,10 @@
 			led_trigger_event(bl_led_trigger, bl_level);
 			break;
 
+		case BL_DCS_CMD:
+			dsi_panel_bklt_dcs(pdata, bl_level);
+			break;
+
 		default:
 			pr_err("%s: Unknown bl_ctrl configuration\n",
 				__func__);
@@ -605,8 +640,11 @@
 		led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
 		pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
 		*bl_ctrl = BL_WLED;
+	} else if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type,
+				"bl_ctrl_dcs", 11))) {
+		pr_debug("%s: SUCCESS-> DCS COMMAND register\n", __func__);
+		*bl_ctrl = BL_DCS_CMD;
 	}
-
 	rc = of_property_read_u32_array(pdev->dev.of_node,
 		"qcom,mdss-pan-bl-levels", res, 2);
 	panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
@@ -620,6 +658,7 @@
 	const char *pdest;
 	u32 tmp;
 	int rc;
+	bool cont_splash_enabled = false;
 
 	pdest = of_get_property(pdev->dev.of_node,
 				"qcom,mdss-pan-dest", NULL);
@@ -641,6 +680,17 @@
 		"qcom,mdss-pan-underflow-clr", &tmp);
 	panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
 
+	cont_splash_enabled = of_property_read_bool(pdev->dev.of_node,
+		"qcom,cont-splash-enabled");
+	if (!cont_splash_enabled) {
+		pr_debug("%s:%d Continuous splash flag not found.\n",
+				__func__, __LINE__);
+		panel_data->panel_info.cont_splash_enabled = 0;
+	} else {
+		pr_debug("%s:%d Continuous splash flag enabled.\n",
+				__func__, __LINE__);
+		panel_data->panel_info.cont_splash_enabled = 1;
+	}
 	return rc;
 }
 
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index 96dd390..73df790 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -235,4 +235,6 @@
 
 int dsi_long_read_resp(struct dsi_buf *rp);
 
+void dsi_set_tx_power_mode(int mode);
+
 #endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index f6f722e..e899fa3 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -1173,6 +1173,11 @@
 	size_t size;
 	int rc;
 
+	if (pdata->panel_info.type != MIPI_VIDEO_PANEL) {
+		pr_debug("cmd mode panel, no need to copy splash image\n");
+		return 0;
+	}
+
 	rgb_size = MDP3_REG_READ(MDP3_REG_DMA_P_SIZE);
 	stride = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_Y_STRIDE);
 	stride = stride & 0x3FFF;
@@ -1210,8 +1215,8 @@
 		status = MDP3_REG_READ(MDP3_REG_DSI_VIDEO_EN);
 		rc = status & 0x1;
 	} else {
-		status = MDP3_REG_READ(MDP3_REG_DMA_P_START);
-		rc = status & 01;
+		status = MDP3_REG_READ(MDP3_REG_DMA_P_CONFIG);
+		rc = status & 0x80000;
 	}
 
 	mdp3_clk_update(MDP3_CLK_AHB, 0);
@@ -1285,7 +1290,13 @@
 			return 0;
 		}
 		rc = mdp3_continuous_splash_on(pdata);
+	} else {
+		if (mdp3_is_display_on(pdata)) {
+			pr_err("lk continuous splash, but kerenl not\n");
+			rc = mdp3_continuous_splash_on(pdata);
+		}
 	}
+
 	return rc;
 }
 
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index f77a2b3..0a0c272 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -88,20 +88,11 @@
 	return bufq->count;
 }
 
-static void mdp3_dispatch_vsync(struct work_struct *work)
-{
-	struct mdp3_session_data *mdp3_session;
-	mdp3_session = container_of(work, struct mdp3_session_data, vsync_work);
-	if (mdp3_session && mdp3_session->mfd)
-		sysfs_notify(&mdp3_session->mfd->fbi->dev->kobj, NULL,
-				"vsync_event");
-}
-
 void vsync_notify_handler(void *arg)
 {
 	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
 	session->vsync_time = ktime_get();
-	schedule_work(&session->vsync_work);
+	sysfs_notify_dirent(session->vsync_event_sd);
 }
 
 static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
@@ -370,6 +361,14 @@
 	struct mdp3_dma_output_config outputConfig;
 	struct mdp3_dma_source sourceConfig;
 	int frame_rate = mfd->panel_info->mipi.frame_rate;
+	int vbp, vfp, vspw;
+	int vtotal, vporch;
+
+	vbp = panel_info->lcdc.v_back_porch;
+	vfp = panel_info->lcdc.v_front_porch;
+	vspw = panel_info->lcdc.v_pulse_width;
+	vporch = vbp + vfp + vspw;
+	vtotal = vporch + panel_info->yres;
 
 	fix = &fbi->fix;
 	var = &fbi->var;
@@ -381,8 +380,9 @@
 	sourceConfig.y = 0;
 	sourceConfig.stride = fix->line_length;
 	sourceConfig.buf = (void *)mfd->iova;
+	sourceConfig.vporch = vporch;
 	sourceConfig.vsync_count =
-		MDP_VSYNC_CLK_RATE / (frame_rate * sourceConfig.width);
+		MDP_VSYNC_CLK_RATE / (frame_rate * vtotal);
 
 	outputConfig.dither_en = 0;
 	outputConfig.out_sel = mdp3_ctrl_get_intf_type(mfd);
@@ -475,9 +475,6 @@
 
 	mdp3_fbmem_clear();
 
-	if (panel->set_backlight)
-		panel->set_backlight(panel, panel->panel_info.bl_max);
-
 	pr_debug("mdp3_ctrl_on dma start\n");
 	if (mfd->fbi->screen_base) {
 		rc = mdp3_session->dma->start(mdp3_session->dma,
@@ -520,18 +517,16 @@
 
 	mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);
 
-	pr_debug("mdp3_ctrl_off turn panel off\n");
-	if (panel->set_backlight)
-		panel->set_backlight(panel, 0);
+	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+	if (rc)
+		pr_debug("fail to stop the MDP3 dma\n");
 
 	if (panel->event_handler)
 		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
 	if (rc)
 		pr_err("fail to turn off the panel\n");
 
-	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
-	if (rc)
-		pr_err("fail to stop the MDP3 dma\n");
+
 
 	mdp3_irq_deregister();
 
@@ -789,6 +784,64 @@
 	return ret;
 }
 
+int mdp3_validate_start_req(struct mdp_histogram_start_req *req)
+{
+	if (req->frame_cnt >= MDP_HISTOGRAM_FRAME_COUNT_MAX) {
+		pr_err("%s invalid req frame_cnt\n", __func__);
+		return -EINVAL;
+	}
+	if (req->bit_mask >= MDP_HISTOGRAM_BIT_MASK_MAX) {
+		pr_err("%s invalid req bit mask\n", __func__);
+		return -EINVAL;
+	}
+	if (req->block != MDP_BLOCK_DMA_P ||
+		req->num_bins != MDP_HISTOGRAM_BIN_NUM) {
+		pr_err("mdp3_histogram_start invalid request\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int mdp3_validate_scale_config(struct mdp_bl_scale_data *data)
+{
+	if (data->scale > MDP_HISTOGRAM_BL_SCALE_MAX) {
+		pr_err("%s invalid bl_scale\n", __func__);
+		return -EINVAL;
+	}
+	if (data->min_lvl > MDP_HISTOGRAM_BL_LEVEL_MAX) {
+		pr_err("%s invalid bl_min_lvl\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int mdp3_validate_csc_data(struct mdp_csc_cfg_data *data)
+{
+	int i;
+	for (i = 0; i < 9; i++) {
+		if (data->csc_data.csc_mv[i] >=
+				MDP_HISTOGRAM_CSC_MATRIX_MAX)
+			return -EINVAL;
+	}
+	for (i = 0; i < 3; i++) {
+		if (data->csc_data.csc_pre_bv[i] >=
+				MDP_HISTOGRAM_CSC_VECTOR_MAX)
+			return -EINVAL;
+		if (data->csc_data.csc_post_bv[i] >=
+				MDP_HISTOGRAM_CSC_VECTOR_MAX)
+			return -EINVAL;
+	}
+	for (i = 0; i < 6; i++) {
+		if (data->csc_data.csc_pre_lv[i] >=
+				MDP_HISTOGRAM_CSC_VECTOR_MAX)
+			return -EINVAL;
+		if (data->csc_data.csc_post_lv[i] >=
+				MDP_HISTOGRAM_CSC_VECTOR_MAX)
+			return -EINVAL;
+	}
+	return 0;
+}
+
 static int mdp3_histogram_start(struct mdp3_session_data *session,
 					struct mdp_histogram_start_req *req)
 {
@@ -796,11 +849,10 @@
 	struct mdp3_dma_histogram_config histo_config;
 
 	pr_debug("mdp3_histogram_start\n");
-	if (req->block != MDP_BLOCK_DMA_P ||
-		req->num_bins != MDP_HISTOGRAM_BIN_NUM) {
-		pr_err("mdp3_histogram_start invalid request\n");
-		return -EINVAL;
-	}
+
+	ret = mdp3_validate_start_req(req);
+	if (ret)
+		return ret;
 
 	if (!session->dma->histo_op ||
 		!session->dma->config_histo) {
@@ -1000,10 +1052,20 @@
 
 	switch (mdp_pp.op) {
 	case mdp_bl_scale_cfg:
+		ret = mdp3_validate_scale_config(&mdp_pp.data.bl_scale_data);
+		if (ret) {
+			pr_err("%s: invalid scale config\n", __func__);
+			break;
+		}
 		ret = mdp3_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
 						&mdp_pp.data.bl_scale_data);
 		break;
 	case mdp_op_csc_cfg:
+		ret = mdp3_validate_csc_data(&(mdp_pp.data.csc_cfg_data));
+		if (ret) {
+			pr_err("%s: invalid csc data\n", __func__);
+			break;
+		}
 		ret = mdp3_csc_config(mdp3_session,
 						&(mdp_pp.data.csc_cfg_data));
 		break;
@@ -1235,7 +1297,6 @@
 	}
 	memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
 	mutex_init(&mdp3_session->lock);
-	INIT_WORK(&mdp3_session->vsync_work, mdp3_dispatch_vsync);
 	mutex_init(&mdp3_session->histo_lock);
 	mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
 	if (!mdp3_session->dma) {
@@ -1261,6 +1322,7 @@
 		goto init_done;
 	}
 
+	mdp3_session->dma->output_config.out_sel = intf_type;
 	mdp3_session->mfd = mfd;
 	mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
 	mdp3_session->status = 0;
@@ -1282,6 +1344,14 @@
 		goto init_done;
 	}
 
+	mdp3_session->vsync_event_sd = sysfs_get_dirent(dev->kobj.sd, NULL,
+							"vsync_event");
+	if (!mdp3_session->vsync_event_sd) {
+		pr_err("vsync_event sysfs lookup failed\n");
+		rc = -ENODEV;
+		goto init_done;
+	}
+
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
 
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 9ea1c91..eb32797 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -43,10 +43,10 @@
 	ktime_t vsync_time;
 	struct timer_list vsync_timer;
 	int vsync_period;
+	struct sysfs_dirent *vsync_event_sd;
 	struct mdp_overlay overlay;
 	struct mdp3_buffer_queue bufq_in;
 	struct mdp3_buffer_queue bufq_out;
-	struct work_struct vsync_work;
 	int histo_status;
 	struct mutex histo_lock;
 	int lut_sel;
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 88eedb9..f4421f2 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -247,16 +247,22 @@
 	pr_debug("mdp3_dma_sync_config\n");
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
-		sync_config = (source_config->height - 1) << 21;
+		int porch = source_config->vporch;
+		int height = source_config->height;
+		int vtotal = height + porch;
+		sync_config = vtotal << 21;
 		sync_config |= source_config->vsync_count;
 		sync_config |= BIT(19);
 		sync_config |= BIT(20);
 
 		MDP3_REG_WRITE(MDP3_REG_SYNC_CONFIG_0 + dma_sel, sync_config);
 		MDP3_REG_WRITE(MDP3_REG_VSYNC_SEL, 0x024);
-		MDP3_REG_WRITE(MDP3_REG_PRIMARY_VSYNC_INIT_VAL + dma_sel, 0);
-		MDP3_REG_WRITE(MDP3_REG_SYNC_THRESH_0 + dma_sel, 0x00100000);
-		MDP3_REG_WRITE(MDP3_REG_PRIMARY_START_P0S + dma_sel, 0x0);
+		MDP3_REG_WRITE(MDP3_REG_PRIMARY_VSYNC_INIT_VAL + dma_sel,
+				height);
+		MDP3_REG_WRITE(MDP3_REG_PRIMARY_RD_PTR_IRQ, 0x5);
+		MDP3_REG_WRITE(MDP3_REG_SYNC_THRESH_0 + dma_sel, (4 << 16 | 2));
+		MDP3_REG_WRITE(MDP3_REG_PRIMARY_START_P0S + dma_sel, porch);
+		MDP3_REG_WRITE(MDP3_REG_TEAR_CHECK_EN, 0x1);
 	}
 	return 0;
 }
@@ -291,7 +297,7 @@
 	 * the default 16 for MDP hang issue workaround
 	 */
 	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;
 	dma->output_config = *output_config;
@@ -497,7 +503,7 @@
 			struct mdp3_dma_histogram_config *histo_config)
 {
 	unsigned long flag;
-	u32 histo_bit_mask, histo_control;
+	u32 histo_bit_mask = 0, histo_control = 0;
 	u32 histo_isr_mask = MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT |
 			MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT;
 
@@ -530,7 +536,7 @@
 	pr_debug("mdp3_dmap_update\n");
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
-		cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+		cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
 		if (intf->active)
 			wait_for_completion_killable(&dma->dma_comp);
 	}
@@ -553,7 +559,8 @@
 
 	mdp3_dma_callback_enable(dma, cb_type);
 	pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
-	wait_for_completion_killable(&dma->vsync_comp);
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
+		wait_for_completion_killable(&dma->vsync_comp);
 	pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
 	return 0;
 }
@@ -565,7 +572,7 @@
 	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
-		cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+		cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
 		if (intf->active)
 			wait_for_completion_killable(&dma->dma_comp);
 	}
@@ -586,7 +593,8 @@
 	spin_unlock_irqrestore(&dma->dma_lock, flag);
 
 	mdp3_dma_callback_enable(dma, cb_type);
-	wait_for_completion_killable(&dma->vsync_comp);
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
+		wait_for_completion_killable(&dma->vsync_comp);
 	return 0;
 }
 
@@ -631,7 +639,7 @@
 		return ret;
 
 	if (dma->histo_state != MDP3_DMA_HISTO_STATE_READY) {
-		pr_err("mdp3_dmap_histo_get after dma shut down\n");
+		pr_debug("mdp3_dmap_histo_get after dma shut down\n");
 		return -EPERM;
 	}
 
@@ -694,9 +702,6 @@
 	unsigned long flag;
 	int ret;
 
-	if (dma->histo_state == MDP3_DMA_HISTO_STATE_START)
-		return -EINVAL;
-
 	spin_lock_irqsave(&dma->histo_lock, flag);
 
 	init_completion(&dma->histo_comp);
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index e4a28dc..6983e55 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -16,6 +16,12 @@
 
 #include <linux/sched.h>
 
+#define MDP_HISTOGRAM_BL_SCALE_MAX 1024
+#define MDP_HISTOGRAM_BL_LEVEL_MAX 255
+#define MDP_HISTOGRAM_FRAME_COUNT_MAX 0x20
+#define MDP_HISTOGRAM_BIT_MASK_MAX 0x4
+#define MDP_HISTOGRAM_CSC_MATRIX_MAX 0x2000
+#define MDP_HISTOGRAM_CSC_VECTOR_MAX 0x200
 #define MDP_HISTOGRAM_BIN_NUM	32
 #define MDP_LUT_SIZE 256
 
@@ -145,6 +151,7 @@
 	void *buf;
 	int stride;
 	int vsync_count;
+	int vporch;
 };
 
 struct mdp3_dma_output_config {
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 924ec5a..8e1dd66 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -344,7 +344,7 @@
 int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off)
 {
 	struct mdss_panel_info *panel_info = mfd->panel_info;
-	int ab = 0, ib = 0;
+	uint64_t ab = 0, ib = 0;
 	int rate = 0;
 
 	if (on_off) {
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 717241d..9c4e43a 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -364,6 +364,7 @@
 struct mdss_overlay_private {
 	int vsync_pending;
 	ktime_t vsync_time;
+	struct sysfs_dirent *vsync_event_sd;
 	int borderfill_enable;
 	int overlay_play_enable;
 	int hw_refresh;
@@ -376,7 +377,6 @@
 	struct list_head overlay_list;
 	struct list_head pipes_used;
 	struct list_head pipes_cleanup;
-	struct work_struct vsync_work;
 	bool mixer_swap;
 };
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 6252e17..938cb1f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1351,15 +1351,6 @@
 	mutex_unlock(&mdp5_data->ov_lock);
 }
 
-static void mdss_mdp_overlay_dispatch_vsync(struct work_struct *work)
-{
-	struct mdss_overlay_private *mdp5_data;
-	mdp5_data = container_of(work, struct mdss_overlay_private, vsync_work);
-	if (mdp5_data->ctl && mdp5_data->ctl->mfd)
-		sysfs_notify(&mdp5_data->ctl->mfd->fbi->dev->kobj, NULL,
-				"vsync_event");
-}
-
 /* function is called in irq context should have minimum processing */
 static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
 						ktime_t t)
@@ -1376,7 +1367,7 @@
 	pr_debug("vsync on fb%d play_cnt=%d\n", mfd->index, ctl->play_cnt);
 
 	mdp5_data->vsync_time = t;
-	schedule_work(&mdp5_data->vsync_work);
+	sysfs_notify_dirent(mdp5_data->vsync_event_sd);
 }
 
 int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
@@ -2130,7 +2121,6 @@
 
 	INIT_LIST_HEAD(&mdp5_data->pipes_used);
 	INIT_LIST_HEAD(&mdp5_data->pipes_cleanup);
-	INIT_WORK(&mdp5_data->vsync_work, mdss_mdp_overlay_dispatch_vsync);
 	mutex_init(&mdp5_data->ov_lock);
 	mdp5_data->hw_refresh = true;
 	mdp5_data->overlay_play_enable = true;
@@ -2153,6 +2143,14 @@
 		goto init_fail;
 	}
 
+	mdp5_data->vsync_event_sd = sysfs_get_dirent(dev->kobj.sd, NULL,
+						     "vsync_event");
+	if (!mdp5_data->vsync_event_sd) {
+		pr_err("vsync_event sysfs lookup failed\n");
+		rc = -ENODEV;
+		goto init_fail;
+	}
+
 	pm_runtime_set_suspended(&mfd->pdev->dev);
 	pm_runtime_enable(&mfd->pdev->dev);
 
diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h
index 2c1fa11..2ca9900 100644
--- a/include/linux/msm_thermal.h
+++ b/include/linux/msm_thermal.h
@@ -23,6 +23,8 @@
 	uint32_t freq_control_mask;
 	int32_t core_limit_temp_degC;
 	int32_t core_temp_hysteresis_degC;
+	int32_t hotplug_temp_degC;
+	int32_t hotplug_temp_hysteresis_degC;
 	uint32_t core_control_mask;
 	int32_t vdd_rstr_temp_degC;
 	int32_t vdd_rstr_temp_hyst_degC;
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 4f39eaa..9a49c5e 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -218,6 +218,8 @@
  *				 Uses a mapping table with 150K pullup.
  * %SCALE_QRD_BATT_THERM: Conversion to temperature(decidegC) based on
  *			btm parameters.
+ * %SCALE_QRD_SKUAA_BATT_THERM: Conversion to temperature(decidegC) based on
+ *          btm parametersi for SKUAA.
  * %SCALE_NONE: Do not use this scaling type.
  */
 enum qpnp_adc_scale_fn_type {
@@ -228,6 +230,7 @@
 	SCALE_XOTHERM,
 	SCALE_THERM_150K_PULLUP,
 	SCALE_QRD_BATT_THERM,
+	SCALE_QRD_SKUAA_BATT_THERM,
 	SCALE_NONE,
 };
 
@@ -1121,6 +1124,23 @@
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
 /**
+ * qpnp_adc_scale_qrd_skuaa_batt_therm() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. Returns the temperature in decidegC.
+ * @dev:	Structure device for qpnp vadc
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(struct qpnp_vadc_chip *dev,
+			int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
  * qpnp_adc_scale_batt_id() - Scales the pre-calibrated digital output
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset.
@@ -1366,7 +1386,13 @@
 			struct qpnp_vadc_chip *vadc, int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
 			const struct qpnp_vadc_chan_properties *chan_prop,
-			struct qpnp_vadc_result *chan_rslt);
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(
+			struct qpnp_vadc_chip *vadc, int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *vadc,
 			int32_t adc_code,
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index f740640..1bb3b06 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -97,6 +97,27 @@
 				((long)t-2732+5)/10 : ((long)t-2732-5)/10)
 #define CELSIUS_TO_KELVIN(t)	((t)*10+2732)
 
+struct sensor_threshold {
+	int temp;
+	enum thermal_trip_type trip;
+	int (*notify)(enum thermal_trip_type type, int temp, void *data);
+	void *data;
+	struct list_head list;
+};
+
+struct sensor_info {
+	uint32_t sensor_id;
+	struct thermal_zone_device *tz;
+	int threshold_min;
+	int threshold_max;
+	int max_idx;
+	int min_idx;
+	struct list_head sensor_list;
+	struct list_head threshold_list;
+	struct mutex lock;
+	struct work_struct work;
+};
+
 struct thermal_zone_device {
 	int id;
 	char type[THERMAL_NAME_LENGTH];
@@ -116,6 +137,8 @@
 	struct mutex lock;	/* protect cooling devices list */
 	struct list_head node;
 	struct delayed_work poll_queue;
+	struct sensor_threshold tz_threshold[2];
+	struct sensor_info sensor;
 };
 /* Adding event notification support elements */
 #define THERMAL_GENL_FAMILY_NAME                "thermal_event"
@@ -163,6 +186,12 @@
 		const struct thermal_cooling_device_ops *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 
+int sensor_get_id(char *name);
+int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
+int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
+int thermal_sensor_trip(struct thermal_zone_device *tz,
+		enum thermal_trip_type trip, unsigned long temp);
+
 #ifdef CONFIG_NET
 extern int thermal_generate_netlink_event(u32 orig, enum events event);
 #else
diff --git a/kernel/exit.c b/kernel/exit.c
index f01ca74..6096e80 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -880,7 +880,6 @@
 	static DEFINE_SPINLOCK(low_water_lock);
 	static int lowest_to_date = THREAD_SIZE;
 	unsigned long free;
-	int islower = false;
 
 	free = stack_not_used(current);
 
@@ -889,16 +888,12 @@
 
 	spin_lock(&low_water_lock);
 	if (free < lowest_to_date) {
-		lowest_to_date = free;
-		islower = true;
-	}
-	spin_unlock(&low_water_lock);
-
-	if (islower) {
 		printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
 				"left\n",
 				current->comm, free);
+		lowest_to_date = free;
 	}
+	spin_unlock(&low_water_lock);
 }
 #else
 static inline void check_stack_usage(void) {}
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 170dbe7..66b0094 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -126,6 +126,16 @@
 	ON_DEMAND_SUPPLIES_MAX,
 };
 
+/*
+ * The delay list is per codec HW specification.
+ * Please add delay in the list in the future instead
+ * of magic number
+ */
+enum {
+	CODEC_DELAY_1_MS = 1000,
+	CODEC_DELAY_1_1_MS  = 1100,
+};
+
 struct hpf_work {
 	struct msm8x10_wcd_priv *msm8x10_wcd;
 	u32 decimator;
@@ -1148,13 +1158,8 @@
 	"ZERO", "ADC1", "ADC2", "DMIC1", "DMIC2"
 };
 
-static const char * const anc_mux_text[] = {
-	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
-		"RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
-};
-
-static const char * const anc1_fb_mux_text[] = {
-	"ZERO", "EAR_HPH_L", "EAR_LINE_1",
+static const char * const adc2_mux_text[] = {
+	"ZERO", "INP2", "INP3"
 };
 
 static const char * const iir1_inp1_text[] = {
@@ -1212,6 +1217,9 @@
 	SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL, 0, 3,
 	rx_rdac4_text);
 
+static const struct soc_enum adc2_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
+
 static const struct snd_kcontrol_new rx_mix1_inp1_mux =
 	SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
 
@@ -1242,6 +1250,9 @@
 static const struct snd_kcontrol_new rx_dac4_mux =
 	SOC_DAPM_ENUM("RDAC4 MUX Mux", rx_rdac4_enum);
 
+static const struct snd_kcontrol_new tx_adc2_mux =
+	SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
+
 static int msm8x10_wcd_put_dec_enum(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
@@ -1370,7 +1381,8 @@
 
 	if (w->reg == MSM8X10_WCD_A_TX_1_EN)
 		init_bit_shift = 7;
-	else if (w->reg == MSM8X10_WCD_A_TX_2_EN)
+	else if ((w->reg == MSM8X10_WCD_A_TX_2_EN) ||
+		 (w->reg == MSM8X10_WCD_A_TX_3_EN))
 		init_bit_shift = 6;
 	else {
 		dev_err(codec->dev, "%s: Error, invalid adc register\n",
@@ -1383,9 +1395,11 @@
 		msm8x10_wcd_codec_enable_adc_block(codec, 1);
 		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
 				1 << init_bit_shift);
+		usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+		usleep_range(CODEC_DELAY_1_MS, CODEC_DELAY_1_1_MS);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		msm8x10_wcd_codec_enable_adc_block(codec, 0);
@@ -1930,9 +1944,14 @@
 	{"DEC2 MUX", "ADC2", "ADC2"},
 	{"DEC2 MUX", NULL, "CDC_CONN"},
 
+	{"ADC2", NULL, "ADC2 MUX"},
+	{"ADC2 MUX", "INP2", "ADC2_INP2"},
+	{"ADC2 MUX", "INP3", "ADC2_INP3"},
+
 	/* ADC Connections */
 	{"ADC1", NULL, "AMIC1"},
-	{"ADC2", NULL, "AMIC2"},
+	{"ADC2_INP2", NULL, "AMIC2"},
+	{"ADC2_INP3", NULL, "AMIC3"},
 
 	{"IIR1", NULL, "IIR1 INP1 MUX"},
 	{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
@@ -2406,9 +2425,17 @@
 	SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
 		msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_ADC_E("ADC2", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
+	SND_SOC_DAPM_ADC_E("ADC2_INP2", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
 		msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC2_INP3", NULL, MSM8X10_WCD_A_TX_3_EN, 7, 0,
+		msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
+		&tx_adc2_mux),
 
 	SND_SOC_DAPM_MICBIAS("MIC BIAS External", MSM8X10_WCD_A_MICB_1_CTL,
 			     7, 0),
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index b49b1e3..e1f1efc 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -52,6 +52,9 @@
 static void __iomem *pcbcr;
 static void __iomem *prcgr;
 
+static int msm_sec_mi2s_rx_ch = 1;
+static int msm_pri_mi2s_tx_ch = 1;
+
 /*
  * There is limitation for the clock root selection from
  * either MI2S or DIG_CODEC.
@@ -182,10 +185,43 @@
 	return 0;
 }
 
+static int msm_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s(): channel:%d\n", __func__, msm_pri_mi2s_tx_ch);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = msm_sec_mi2s_rx_ch;
+
+	return 0;
+}
+
+static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s(), channel:%d\n", __func__, msm_pri_mi2s_tx_ch);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = msm_pri_mi2s_tx_ch;
+
+	return 0;
+}
+
+
 static const char *const btsco_rate_text[] = {"8000", "16000"};
 static const struct soc_enum msm_btsco_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
 };
+static const char *const sec_mi2s_rx_ch_text[] = {"One", "Two"};
+static const char *const pri_mi2s_tx_ch_text[] = {"One", "Two"};
 
 static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
@@ -215,6 +251,43 @@
 	return 0;
 }
 
+static int msm_sec_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_sec_mi2s_rx_ch  = %d\n", __func__,
+		 msm_sec_mi2s_rx_ch);
+	ucontrol->value.integer.value[0] = msm_sec_mi2s_rx_ch - 1;
+	return 0;
+}
+
+static int msm_sec_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_sec_mi2s_rx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm_sec_mi2s_rx_ch = %d\n", __func__,
+		 msm_sec_mi2s_rx_ch);
+	return 1;
+}
+
+static int msm_pri_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_pri_mi2s_tx_ch  = %d\n", __func__,
+		 msm_pri_mi2s_tx_ch);
+	ucontrol->value.integer.value[0] = msm_pri_mi2s_tx_ch - 1;
+	return 0;
+}
+
+static int msm_pri_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_pri_mi2s_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm_pri_mi2s_tx_ch = %d\n", __func__, msm_pri_mi2s_tx_ch);
+	return 1;
+}
+
 static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -353,9 +426,18 @@
 	return ret;
 }
 
+static const struct soc_enum msm_snd_enum[] = {
+	SOC_ENUM_SINGLE_EXT(2, sec_mi2s_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(2, pri_mi2s_tx_ch_text),
+};
+
 static const struct snd_kcontrol_new msm_snd_controls[] = {
 	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
 		     msm_btsco_rate_get, msm_btsco_rate_put),
+	SOC_ENUM_EXT("MI2S_RX Channels", msm_snd_enum[0],
+			msm_sec_mi2s_rx_ch_get, msm_sec_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("MI2S_TX Channels", msm_snd_enum[1],
+			msm_pri_mi2s_tx_ch_get, msm_pri_mi2s_tx_ch_put),
 };
 
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -637,7 +719,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
 		.init = &msm_audrx_init,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_rx_be_hw_params_fixup,
 		.ops = &msm8x10_mi2s_be_ops,
 		.ignore_suspend = 1,
 	},
@@ -650,7 +732,7 @@
 		.codec_dai_name = "msm8x10_wcd_i2s_tx1",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
-		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_tx_be_hw_params_fixup,
 		.ops = &msm8x10_mi2s_be_ops,
 		.ignore_suspend = 1,
 	},