Merge "msm: ocmem: Handle shrinking of memory after passive evictions"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 6ef2b77..d07eba6 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -85,19 +85,19 @@
 		qcom,core-control-mask = <7>;
 		qcom,pmic-sw-mode-temp = <90>;
 		qcom,pmic-sw-mode-temp-hysteresis = <80>;
-		qcom,pmic-sw-mode-regs = "vdd_dig";
+		qcom,pmic-sw-mode-regs = "vdd-dig";
 		qcom,vdd-restriction-temp = <5>;
 		qcom,vdd-restriction-temp-hysteresis = <10>;
-		vdd_dig-supply=<&pm8841_s2_floor_corner>
+		vdd-dig-supply=<&pm8841_s2_floor_corner>
 
 		qcom,vdd-dig-rstr{
-			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,vdd-rstr-reg = "vdd-dig";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-apps-rstr{
-			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,vdd-rstr-reg = "vdd-apps";
 			qcom,levels = <1881600 1958400 2265600>;
 			qcom,freq-req;
 		};
diff --git a/Documentation/devicetree/bindings/input/misc/bmp180.txt b/Documentation/devicetree/bindings/input/misc/bmp180.txt
new file mode 100644
index 0000000..13e0839
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/bmp180.txt
@@ -0,0 +1,35 @@
+Bosch BMP18x-series altimeter driver
+
+Required properties:
+
+ - compatible			: Should be "bosch,bmp180".
+ - reg					: i2c slave address of the device.
+ - vdd-supply		: Analog power supply needed to power device.
+ - vddio-supply		: Digital IO power supply needed for IO and I2C.
+ - bosch,chip-id		: Chip id for the bmp18x altimeter sensor.
+ - bosch,oversample	: Sensor default oversampling value.
+				Default oversampling value to be used at startup.
+				Value range is 0-3 with rising sensitivity.
+ - bosch,period	: Temperature measurement period (milliseconds).
+				Set to zero if unsure.
+
+Optional properties:
+
+ - bosch,sw-oversample	: Boolean to enable software oversampling if
+				this property is defined. Only take effect when
+				default_oversampling is 3.
+
+Example:
+	i2c@f9925000 {
+		bmp180@77 {
+			status = "okay";
+			reg = <0x77>;
+			compatible = "bosch,bmp180";
+			vdd-supply = <&pm8110_l19>;
+			vddio-supply = <&pm8110_l14>;
+			bosch,chip-id = <0x55>;
+			bosch,oversample = <3>;
+			bosch,period = <1000>;
+			bosch,sw-oversample;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/input/misc/mma8x5x.txt b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
new file mode 100644
index 0000000..854939c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
@@ -0,0 +1,39 @@
+Freescale MMA8x5x 3-Axis Orientation/Motion Detection Sensor series
+(MMA8451/MMA8452/MMA8453/MMA8652/MMA8653)
+
+The Freescale 3-Axis Orientation/Motion Detection Sensor is
+connected to host processor via i2c.
+The sensor can be polling for acceleration data or configure to
+generates interrupts when a motion is detected.
+
+Required properties:
+
+ - compatible		: should be "fsl,mma8x5x"
+ - reg			: i2c slave address of the device
+ - vdd-supply : power supply needed to power up the device.
+ - vio-supply	: power supply needed for device IO and to pullup i2c bus.
+ - fsl,sensors-position	: select from 0 to 7 depends on how the sensor is
+				 mounting on the board, this will decide how the 3-axis reading
+				 of data will be translated to X/Y/Z axis of acceleration data.
+
+Optional properties:
+ Sensor can work on polling mode or interrupt mode, following interrupt
+ is required if the sensor need to work on interrupt mode.
+ - interrupt-parent	: parent of interrupt.
+ - interrupts		: sensor signal interrupt to indicate new data ready or
+				 a motion is detected.
+ - fsl,irq-gpio	: First irq gpio which is to provide interrupts to host, same
+				 as "interrupts" node. It will also contain active low or active
+				 high information.
+
+Example:
+	fsl@1c {
+		compatible = "fsl,mma8x5x";
+		reg = <0x1c>;
+		interrupt-parent = <&msmgpio>;
+		interrupts = <81 0x2>;
+		vdd-supply = <&pm8110_l19>;
+		vio-supply = <&pm8110_l14>;
+		fsl,sensors-position = <5>;
+		fsl,irq-gpio = <&msmgpio 0x81 0x02>;
+	};
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index ff95d43..e9c5061 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -81,7 +81,9 @@
 - qcom,source-sel: select power source, default 1 (enabled)
 - qcom,mode-ctrl: select operation mode, default 0x60 = Mode Sink
 - qcom,mode: mode the led should operate in, options "pwm", "lpg" and "manual"
+- qcom,vin-ctrl: select input source, supported values are 0 to 3
 - qcom,use-blink: Use blink sysfs entry for switching into lpg mode.  For optimal use, set default mode to pwm.  All required lpg parameters must be supplied.
+- qcom,min-brightness - Lowest possible brightness supported on this LED other than 0.
 
 Required properties for PWM mode only:
 - qcom,pwm-channel: pwm channel the led will operate on
@@ -136,6 +138,8 @@
 			qcom,id = <6>;
 			qcom,source-sel = <1>;
 			qcom,mode-ctrl = <0x10>;
+			qcom,vin-ctrl = <0x03>;
+			qcom,min-brightness = <20>;
 		};
 	};
 
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 583fbfa..8e988be 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -95,6 +95,11 @@
     #gpio-cells specifying specific gpio (controller specific)
 - qcom,gpio-reset : should contain index to gpio used by sensors reset_n
 - qcom,gpio-standby : should contain index to gpio used by sensors standby_n
+- qcom,gpio-vio : should contain index to gpio used by sensors io vreg enable
+- qcom,gpio-vana : should contain index to gpio used by sensors analog vreg enable
+- qcom,gpio-vdig : should contain index to gpio used by sensors digital vreg enable
+- qcom,gpio-vaf : should contain index to gpio used by sensors af vreg enable
+- qcom,gpio-af-pwdm : should contain index to gpio used by sensors af pwdm_n
 - qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
 - qcom,gpio-req-tbl-flags : should contain direction of gpios present in
     qcom,gpio-req-tbl-num property (in the same order)
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 3cac311..3e7a578 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -77,6 +77,10 @@
 			number of the FCC measurement cycles required to
 			generate an FCC update. This is applicable only
 			if the FCC learning is enabled.
+- qcom,fcc-resolution:	An integer which defines the fcc resolution used
+			for storing the FCC(mAh) in the 8-bit BMS register.
+			For example - A value of 10 indicates:
+			FCC value (in mAh) = (8-bit register value) * 10.
 
 Parent node optional properties:
 - qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b4bcaf6..a3a3807 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -8,6 +8,7 @@
 apm	Applied Micro Circuits Corporation (APM)
 arm	ARM Ltd.
 atmel	Atmel Corporation
+bosch	Bosch Sensortec GmbH
 cavium	Cavium, Inc.
 chrp	Common Hardware Reference Platform
 cortina	Cortina Systems, Inc.
diff --git a/arch/arm/boot/dts/apq8026-v1.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
index f15a96f..7fbfcb5 100644
--- a/arch/arm/boot/dts/apq8026-v1.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -22,3 +22,8 @@
 	model = "Qualcomm APQ 8026";
 	compatible = "qcom,apq8026";
 };
+
+&tsens {
+	qcom,sensors = <4>;
+	qcom,slope = <2901 2846 3038 2955>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v2.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
index d87b500..4c0d3ce 100644
--- a/arch/arm/boot/dts/apq8026-v2.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -22,3 +22,8 @@
 	model = "Qualcomm APQ 8026";
 	compatible = "qcom,apq8026";
 };
+
+&tsens {
+	qcom,sensors = <6>;
+	qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 350257c..3014813 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -198,7 +198,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <11>;
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
new file mode 100644
index 0000000..f57a7bd
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
@@ -0,0 +1,124 @@
+/* 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,dsi_v2_truly_wvga_video {
+		compatible = "qcom,dsi-panel-v2";
+		label = "Truly WVGA command mode dsi panel";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 41 0>;
+		qcom,mode-selection-gpio = <&msmgpio 7 0>;
+		qcom,te-gpio = <&msmgpio 12 0>;
+		vdda-supply = <&pm8110_l19>;
+		vddio-supply=<&pm8110_l14>;
+		qcom,mdss-pan-res = <480 800>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <40 8 160 10 2 12>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-dsi-mode = <1>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <1>;
+		qcom,mdss-pan-dsi-dst-format = <8>;
+		qcom,mdss-pan-insert-dcs-cmd = <1>;
+		qcom,mdss-pan-wr-mem-continue = <0x3c>;
+		qcom,mdss-pan-wr-mem-start = <0x2c>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x02>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
+		qcom,panel-phy-timingSettings = [5D 12 0C  00 33 38
+						 10 16 1E 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+		qcom,panel-phy-laneConfig =
+					[80 45 00 00 01 66 /*lane0**/
+					80 45 00 00 01 66 /*lane1*/
+					80 45 00 00 01 66 /*lane2*/
+					80 45 00 00 01 66 /*lane3*/
+					40 67 00 00 01 88]; /*Clk*/
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-on-cmds = [
+					05 01 00 00 00 02
+						01 00
+					23 01 00 00 00 02
+						b0 04
+					29 01 00 00 00 03
+						b3 02 00
+					23 01 00 00 00 02
+						bd 00
+					29 01 00 00 00 03
+						c0 18 66
+					29 01 00 00 00 10
+						c1 23 31 99 21 20 00 30 28 0c 0c
+						00 00 00 21 01
+					29 01 00 00 00 07
+						c2 00 06 06 01 03 00
+					29 01 00 00 00 19
+						c8 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 19
+						c9 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 19
+						ca 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 11
+						d0 29 03 ce a6 00 43 20 10 01 00
+						01 01 00 03 01 00
+					29 01 00 00 00 08
+						d1 18 0C 23 03 75 02 50
+					23 01 00 00 00 02
+						d3 11
+					29 01 00 00 00 03
+						d5 2a 2a
+					29 01 00 00 00 03
+						de 01 51
+					23 01 00 00 00 02
+						e6 51
+					23 01 00 00 00 02
+						fa 03
+					23 01 00 00 64 02
+						d6 28
+					15 01 00 00 00 02
+						36 41
+					39 01 00 00 00 05
+						2a 00 00 01 df
+					39 01 00 00 00 05
+						2b 00 00 03 1f
+					15 01 00 00 00 02
+						35 00
+					39 01 00 00 00 03
+						44 00 50
+					15 01 00 00 00 02
+						3a 77
+					05 01 00 00 7D 02
+						11 00
+					05 01 00 00 14 02
+						29 00
+					];
+		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+					05 01 00 00 78 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
index 5693ccd..8be8d71 100644
--- a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
@@ -69,7 +69,7 @@
 						c1 23 31 99 21 20 00 30 28 0c 0c
 						00 00 00 21 01
 					29 01 00 00 00 07
-						c2 10 06 06 01 03 00
+						c2 00 06 06 01 03 00
 					29 01 00 00 00 19
 						c8 04 10 18 20 2e 46 3c 28 1f 18
 						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
@@ -89,7 +89,7 @@
 					29 01 00 00 00 03
 						d5 2a 2a
 					29 01 00 00 00 03
-						de 01 41
+						de 01 51
 					23 01 00 00 00 02
 						e6 51
 					23 01 00 00 00 02
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
index 4fb2b24..3a86814 100644
--- a/arch/arm/boot/dts/mpq8092-iommu.dtsi
+++ b/arch/arm/boot/dts/mpq8092-iommu.dtsi
@@ -212,3 +212,7 @@
 				0x10
 				0x0>;
 };
+
+&vpu_iommu {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 2eaa32f..04f0945 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -140,6 +140,38 @@
                 reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
 	};
 
+	usb@f9a55000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0xf9a55000 0x400>;
+		interrupts = <0 134 0>, <0 140 0>;
+		interrupt-names = "core_irq", "async_irq";
+
+		HSUSB_VDDCX-supply = <&pma8084_s8>;
+		HSUSB_1p8-supply = <&pma8084_l22>;
+		HSUSB_3p3-supply = <&pma8084_l24>;
+		qcom,vdd-voltage-level = <1050000 1050000>;
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-disable-reset;
+
+		qcom,msm_bus,name = "usb_otg";
+		qcom,msm_bus,num_cases = <3>;
+		qcom,msm_bus,active_only = <0>;
+		qcom,msm_bus,num_paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<87 512 0 0>,
+				<87 512 60000 960000>,
+				<87 512 6000  6000>;
+	};
+
+	android_usb@fe8050c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
+	};
+
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
@@ -259,6 +291,10 @@
 	status = "ok";
 };
 
+&gdsc_vpu {
+	status = "ok";
+};
+
 &gdsc_oxili_gx {
 	status = "ok";
 };
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index e5683fb..259dfdb 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -227,6 +227,16 @@
 	status = "ok";
 };
 
+&sdcc3 {
+	qcom,sup-voltages = <1800 1800>;
+	status = "disabled";
+};
+
+&sdhc_3 {
+	qcom,sup-voltages = <1800 1800>;
+	status = "disabled";
+};
+
 &spmi_bus {
 	qcom,pm8226@0 {
 		qcom,leds@a100 {
@@ -261,8 +271,12 @@
 				qcom,mode-ctrl = <0x60>;
 				qcom,pwm-channel = <0>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
@@ -283,8 +297,12 @@
 				qcom,source-sel = <10>;
 				qcom,pwm-channel = <5>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 0df3feb..4b2a4ad 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -275,8 +275,12 @@
 				qcom,mode-ctrl = <0x60>;
 				qcom,pwm-channel = <0>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
@@ -297,8 +301,12 @@
 				qcom,source-sel = <10>;
 				qcom,pwm-channel = <5>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index db0620f..8af5ef5 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -180,7 +180,7 @@
 &sdcc2 {
 	vdd-supply = <&pm8226_l18>;
 	qcom,vdd-voltage-level = <2950000 2950000>;
-	qcom,vdd-current-level = <9000 800000>;
+	qcom,vdd-current-level = <9000 400000>;
 
 	vdd-io-supply = <&pm8226_l21>;
 	qcom,vdd-io-voltage-level = <1800000 2950000>;
@@ -196,7 +196,7 @@
 
 	qcom,xpc;
 	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-	qcom,current-limit = <600>;
+	qcom,current-limit = <400>;
 
 	#address-cells = <0>;
 	interrupt-parent = <&sdcc2>;
@@ -215,7 +215,7 @@
 &sdhc_2 {
 	vdd-supply = <&pm8226_l18>;
 	qcom,vdd-voltage-level = <2950000 2950000>;
-	qcom,vdd-current-level = <9000 800000>;
+	qcom,vdd-current-level = <9000 400000>;
 
 	vdd-io-supply = <&pm8226_l21>;
 	qcom,vdd-io-voltage-level = <1800000 2950000>;
@@ -265,7 +265,7 @@
 			qcom,led_mpp_4 {
 				label = "mpp";
 				linux,name = "green";
-				linux,default-trigger = "none";
+				linux,default-trigger = "battery-full";
 				qcom,default-state = "off";
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
@@ -276,8 +276,12 @@
 				qcom,mode-ctrl = <0x60>;
 				qcom,pwm-channel = <0>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
@@ -287,7 +291,7 @@
 			qcom,led_mpp_6 {
 				label = "mpp";
 				linux,name = "red";
-				linux,default-trigger = "none";
+				linux,default-trigger = "battery-charging";
 				qcom,default-state = "off";
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
@@ -298,8 +302,12 @@
 				qcom,source-sel = <10>;
 				qcom,pwm-channel = <5>;
 				qcom,start-idx = <1>;
-				qcom,duty-pcts = [00 00 00 00 64
-						 64 00 00 00 00];
+				qcom,ramp-step-ms = <120>;
+				qcom,duty-pcts = [00 00 00 00 00
+						  00 00 00 00 00
+						  50 00 00 00 00
+						  00 00 00 00 00
+						  00];
 				qcom,use-blink;
 			};
 		};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 3e89c3a..571ddc3 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -44,8 +44,8 @@
 		qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
 					2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
 		qcom,pvs-corner-ceiling-slow = <1155000 1160000 1275000>;
-		qcom,pvs-corner-ceiling-nom  =  <975000 1075000 1200000>;
-		qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+		qcom,pvs-corner-ceiling-nom  = <1050000 1075000 1200000>;
+		qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
 		vdd-apc-supply = <&pm8226_s2>;
 
 		vdd-mx-supply = <&pm8226_l3_ao>;
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index d471bec..1db1f12 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -17,3 +17,8 @@
  */
 
 /include/ "msm8226.dtsi"
+
+&tsens {
+	qcom,sensors = <4>;
+	qcom,slope = <2901 2846 3038 2955>;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index 2148e1d..b44cb681 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -43,8 +43,8 @@
 	qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
 				2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
 	qcom,pvs-corner-ceiling-slow = <1160000 1160000 1280000>;
-	qcom,pvs-corner-ceiling-nom  =  <980000 1080000 1200000>;
-	qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+	qcom,pvs-corner-ceiling-nom  = <1050000 1080000 1200000>;
+	qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
 	qcom,cpr-step-quotient = <30>;
 	qcom,cpr-up-threshold = <0>;
 	qcom,cpr-down-threshold = <5>;
@@ -63,3 +63,8 @@
 		reg-names = "rcg_base", "pte_efuse";
 	};
 };
+
+&tsens {
+	qcom,sensors = <6>;
+	qcom,slope = <2901 2846 3038 2955 2901 2846>;
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 42c1247..b836100 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -21,6 +21,7 @@
 		spi0 = &spi_0;
 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
 		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+		sdhc3 = &sdhc_3; /* SDC3 SDIO slot */
 	};
 
 	memory {
@@ -762,6 +763,95 @@
 		status = "disabled";
 	};
 
+	sdcc3: qcom,sdcc@f9864000 {
+		cell-index = <3>;
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf9864000 0x800>,
+			<0xf9864800 0x100>,
+			<0xf9844000 0x7000>;
+		reg-names = "core_mem", "dml_mem", "bam_mem";
+
+		qcom,bus-width = <4>;
+		gpios = <&msmgpio 44 0>, /* CLK */
+			<&msmgpio 43 0>, /* CMD */
+			<&msmgpio 42 0>, /* DATA0 */
+			<&msmgpio 41 0>, /* DATA1 */
+			<&msmgpio 40 0>, /* DATA2 */
+			<&msmgpio 39 0>; /* DATA3 */
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+		qcom,msm-bus,name = "sdcc3";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+				<79 512 1600 3200>,    /* 400 KB/s*/
+				<79 512 80000 160000>, /* 20 MB/s */
+				<79 512 100000 200000>, /* 25 MB/s */
+				<79 512 200000 400000>, /* 50 MB/s */
+				<79 512 400000 800000>, /* 100 MB/s */
+				<79 512 400000 800000>, /* 200 MB/s */
+				<79 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
+		#address-cells = <0>;
+		interrupt-parent = <&sdcc3>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 127 0
+			      1 &intc 0 223 0
+			      2 &msmgpio 41 0x8>;
+		interrupt-names = "core_irq", "bam_irq", "sdiowakeup_irq";
+
+		status = "disabled";
+	};
+
+	sdhc_3: sdhci@f9864900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0xf9864900 0x11c>, <0xf9864000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		qcom,bus-width = <4>;
+		gpios = <&msmgpio 44 0>, /* CLK */
+			<&msmgpio 43 0>, /* CMD */
+			<&msmgpio 42 0>, /* DATA0 */
+			<&msmgpio 41 0>, /* DATA1 */
+			<&msmgpio 40 0>, /* DATA2 */
+			<&msmgpio 39 0>; /* DATA3 */
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+		qcom,msm-bus,name = "sdhc3";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+				<79 512 1600 3200>,    /* 400 KB/s*/
+				<79 512 80000 160000>, /* 20 MB/s */
+				<79 512 100000 200000>, /* 25 MB/s */
+				<79 512 200000 400000>, /* 50 MB/s */
+				<79 512 400000 800000>, /* 100 MB/s */
+				<79 512 400000 800000>, /* 200 MB/s */
+				<79 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
+		#address-cells = <0>;
+		interrupt-parent = <&sdhc_3>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 127 0
+			      1 &intc 0 224 0
+			      2 &msmgpio 41 0x8>;
+		interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+		status = "disabled";
+	};
+
 	spmi_bus: qcom,spmi@fc4c0000 {
 		cell-index = <0>;
 		compatible = "qcom,spmi-pmic-arb";
@@ -935,7 +1025,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <4>;
@@ -954,6 +1044,21 @@
 		qcom,core-limit-temp = <80>;
 		qcom,core-temp-hysteresis = <10>;
 		qcom,core-control-mask = <0xe>;
+		qcom,vdd-restriction-temp = <5>;
+		qcom,vdd-restriction-temp-hysteresis = <10>;
+		vdd-dig-supply = <&pm8226_s1_floor_corner>;
+
+		qcom,vdd-dig-rstr{
+			qcom,vdd-rstr-reg = "vdd-dig";
+			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+			qcom,min-level = <1>; /* No Request */
+		};
+
+		qcom,vdd-apps-rstr{
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <600000 787200 998400>;
+			qcom,freq-req;
+		};
 	};
 
 	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6b61317..a62a53c 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -222,9 +222,13 @@
 				qcom,default-state = "on";
 				qcom,max-current = <40>;
 				qcom,id = <6>;
-				qcom,source-sel = <1>;
+				qcom,source-sel = <8>;
 				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
+				qcom,pwm-channel = <0>;
+				qcom,pwm-us = <14>;
+				qcom,vin-ctrl = <0x03>;
+				qcom,mode = "pwm";
+				qcom,min-brightness = <19>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 352ccf1..3013058 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -105,6 +105,16 @@
 			invn,gpio-en = <&pm8110_gpios 2 0x2>;
 			invn,poll-interval = <200>;
 		};
+
+		bmp180@77 {
+			reg = <0x77>;
+			compatible = "bosch,bmp18x";
+			vdd-supply = <&pm8110_l19>;
+			vddio-supply = <&pm8110_l14>;
+			bosch,chip-id = <0x55>;
+			bosch,oversample = <3>;
+			bosch,period = <1000>;
+		};
 	};
 
 	gen-vkeys {
@@ -171,7 +181,7 @@
 
 		cdc-vdda-h-supply = <&pm8110_l6>;
 		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
-		qcom,cdc-vdda-h-current = <250000>;
+		qcom,cdc-vdda-h-current = <25000>;
 
 		cdc-vdd-px-supply = <&pm8110_l6>;
 		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
@@ -239,9 +249,13 @@
 				qcom,default-state = "on";
 				qcom,max-current = <40>;
 				qcom,id = <6>;
-				qcom,source-sel = <1>;
+				qcom,source-sel = <8>;
 				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
+				qcom,pwm-channel = <0>;
+				qcom,pwm-us = <14>;
+				qcom,vin-ctrl = <0x03>;
+				qcom,mode = "pwm";
+				qcom,min-brightness = <19>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index c46e9d2..62ef933 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 
 /include/ "msm8610-qrd.dtsi"
+/include/ "msm8612-qrd-camera-sensor.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 QRD";
@@ -37,4 +38,16 @@
 
         qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
     };
+    i2c@f9925000 {
+		fsl@1c {
+			compatible = "fsl,mma8x5x";
+			reg = <0x1c>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			fsl,irq-gpio = <&msmgpio 81 0x00>;
+			fsl,sensors-position = <5>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 7a93c49..bd1705f 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -124,51 +124,6 @@
 		};
 	};
 
-	i2c@f9927000  {
-                        msm8x10_wcd_codec@0d{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x0d>;
-                        cdc-vdda-cp-supply = <&pm8110_s4>;
-                        qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
-                        qcom,cdc-vdda-cp-current = <650000>;
-
-                        cdc-vdda-h-supply = <&pm8110_l6>;
-                        qcom,cdc-vdda-h-voltage = <1800000 1800000>;
-                        qcom,cdc-vdda-h-current = <250000>;
-
-                        cdc-vdd-px-supply = <&pm8110_l6>;
-                        qcom,cdc-vdd-px-voltage = <1800000 1800000>;
-                        qcom,cdc-vdd-px-current = <10000>;
-
-                        cdc-vdd-1p2v-supply = <&pm8110_l4>;
-                        qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
-                        qcom,cdc-vdd-1p2v-current = <5000>;
-
-                        cdc-vdd-mic-bias-supply = <&pm8110_l20>;
-                        qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
-                        qcom,cdc-vdd-mic-bias-current = <25000>;
-
-                        qcom,cdc-micbias-cfilt-sel = <0x0>;
-                        qcom,cdc-micbias-cfilt-mv = <1800000>;
-                        qcom,cdc-mclk-clk-rate = <12288000>;
-                };
-
-                msm8x10_wcd_codec@77{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x77>;
-                };
-
-                msm8x10_wcd_codec@66{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x66>;
-                };
-
-                msm8x10_wcd_codec@55{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x55>;
-                };
-	};
-
     sound {
         qcom,audio-routing =
             "RX_BIAS", "MCLK",
@@ -180,6 +135,58 @@
     };
 };
 
+&i2c_cdc  {
+	msm8x10_wcd_codec@0d{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x0d>;
+		cdc-vdda-cp-supply = <&pm8110_s4>;
+		qcom,cdc-vdda-cp-voltage = <1800000 2150000>;
+		qcom,cdc-vdda-cp-current = <650000>;
+
+		cdc-vdda-h-supply = <&pm8110_l6>;
+		qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdda-h-current = <25000>;
+
+		cdc-vdd-px-supply = <&pm8110_l6>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <10000>;
+
+		cdc-vdd-1p2v-supply = <&pm8110_l4>;
+		qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+		qcom,cdc-vdd-1p2v-current = <5000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <25000>;
+
+		qcom,cdc-micbias-cfilt-sel = <0x0>;
+		qcom,cdc-micbias-cfilt-mv = <1800000>;
+		qcom,cdc-mclk-clk-rate = <12288000>;
+
+		qcom,cdc-static-supplies = "cdc-vdda-h",
+						"cdc-vdd-px",
+						"cdc-vdd-1p2v";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdda-cp",
+						"cdc-vdd-mic-bias";
+	};
+
+	msm8x10_wcd_codec@77{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x77>;
+	};
+
+	msm8x10_wcd_codec@66{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x66>;
+	};
+
+	msm8x10_wcd_codec@55{
+		compatible = "qcom,msm8x10-wcd-i2c";
+		reg = <0x55>;
+	};
+};
+
 &spmi_bus {
 	qcom,pm8110@0 {
 		qcom,leds@a100 {
@@ -206,9 +213,13 @@
 				qcom,default-state = "on";
 				qcom,max-current = <40>;
 				qcom,id = <6>;
-				qcom,source-sel = <1>;
+				qcom,source-sel = <8>;
 				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
+				qcom,pwm-channel = <0>;
+				qcom,pwm-us = <14>;
+				qcom,vin-ctrl = <0x03>;
+				qcom,mode = "pwm";
+				qcom,min-brightness = <19>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 38f587b..cf54098 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -197,6 +197,7 @@
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
 			qcom,init-voltage = <1200000>;
+			regulator-always-on;
 			status = "okay";
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 15214dd..053e9bc 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -755,7 +755,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <2>;
@@ -777,16 +777,16 @@
 		qcom,core-control-mask = <0xe>;
 		qcom,vdd-restriction-temp = <5>;
 		qcom,vdd-restriction-temp-hysteresis = <10>;
-		vdd_dig-supply = <&pm8110_s1_floor_corner>;
+		vdd-dig-supply = <&pm8110_s1_floor_corner>;
 
 		qcom,vdd-dig-rstr{
-			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,vdd-rstr-reg = "vdd-dig";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-apps-rstr{
-			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,vdd-rstr-reg = "vdd-apps";
 			qcom,levels = <600000 787200 998400>;
 			qcom,freq-req;
 		};
diff --git a/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
new file mode 100644
index 0000000..25554eb
--- /dev/null
+++ b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+&i2c {
+
+	qcom,camera@20 {
+		compatible = "shinetech,s5k4e1";
+		reg = <0x20>;
+		qcom,slave-id = <0x20 0x0000 0x4e10>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "SKUAB_ST_s5k4e1";
+		cam_vdig-supply = <&pm8110_l2>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 0 0>;
+		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 8000 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 13 0>,
+			<&msmgpio 21 0>,
+			<&msmgpio 20 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY";
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,sensor-type = <0>;
+		qcom,cci-master = <0>;
+	};
+	qcom,camera@78 {
+		compatible = "shinetech,gc0339";
+		reg = <0x78>;
+		qcom,slave-id = <0x42 0x00 0xc8>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "skuab_shinetech_gc0339";
+		cam_vdig-supply = <&pm8110_l14>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 1 0>;
+		qcom,cam-vreg-min-voltage = <1800000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 14 0>,
+				<&msmgpio 15 0>,
+				<&msmgpio 85 0>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+				"CAM_RESET",
+				"CAM_STANDBY";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 57ce130..af21e43 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -406,6 +406,7 @@
 	qcom,min-fcc-learning-soc = <20>;
 	qcom,min-fcc-ocv-pc = <30>;
 	qcom,min-fcc-learning-samples = <5>;
+	qcom,fcc-resolution = <10>;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 7b43d9b..8e3b7cc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -355,6 +355,7 @@
 	qcom,min-fcc-learning-soc = <20>;
 	qcom,min-fcc-ocv-pc = <30>;
 	qcom,min-fcc-learning-samples = <5>;
+	qcom,fcc-resolution = <10>;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm8974-v2-2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
new file mode 100644
index 0000000..cb8895f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-cdp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 CDP";
+	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
+	qcom,msm-id = <126 1 0x20002>,
+		      <185 1 0x20002>,
+		      <186 1 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
new file mode 100644
index 0000000..8e04c18
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-fluid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 FLUID";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+	qcom,msm-id = <126 3 0x20002>,
+		      <185 3 0x20002>,
+		      <186 3 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
new file mode 100644
index 0000000..7128abe
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-liquid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 LIQUID";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
+	qcom,msm-id = <126 9 0x20002>,
+		      <185 9 0x20002>,
+		      <186 9 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
new file mode 100644
index 0000000..b7e35cf
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-mtp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+	qcom,msm-id = <126 8 0x20002>,
+		      <185 8 0x20002>,
+		      <186 8 0x20002>;
+};
+
+&pm8941_chg {
+	qcom,bpd-detection = "bpd_thm";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2.dtsi b/arch/arm/boot/dts/msm8974-v2-2.dtsi
new file mode 100644
index 0000000..09455b1
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2.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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974-v2.dtsi"
+
+/* GPU overrides */
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x03030001>;
+
+	qcom,initial-pwrlevel = <4>;
+
+	/* Updated bus bandwidth requirements */
+	qcom,msm-bus,vectors-KBps =
+		/* Off */
+		<26 512 0 0>, <89 604 0 0>,
+		/* SVS */
+		<26 512 0 2400000>, <89 604 0 3000000>,
+		/* Nominal / SVS */
+		<26 512 0 4656000>, <89 604 0 3000000>,
+		/* Nominal */
+		<26 512 0 4656000>, <89 604 0 5120000>,
+		/* Turbo / Nominal */
+		<26 512 0 7464000>, <89 604 0 5120000>,
+		/* Turbo */
+		<26 512 0 7464000>, <89 604 0 6400000>;
+
+	qcom,gpu-pwrlevels {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "qcom,gpu-pwrlevels";
+
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <450000000>;
+			qcom,bus-freq = <5>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@1 {
+			reg = <1>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@2 {
+			reg = <2>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@3 {
+			reg = <3>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@4 {
+			reg = <4>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@5 {
+			reg = <5>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <2>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@6 {
+			reg = <6>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <1>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@7 {
+			reg = <7>;
+			qcom,gpu-freq = <27000000>;
+			qcom,bus-freq = <0>;
+			qcom,io-fraction = <0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 4564c6a..aaa5f3e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1364,7 +1364,7 @@
 	tsens: tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <11>;
@@ -1487,24 +1487,24 @@
 		qcom,vdd-restriction-temp-hysteresis = <10>;
 		qcom,pmic-sw-mode-temp = <85>;
 		qcom,pmic-sw-mode-temp-hysteresis = <75>;
-		qcom,pmic-sw-mode-regs = "vdd_dig";
-		vdd_dig-supply = <&pm8841_s2_floor_corner>;
-		vdd_gfx-supply = <&pm8841_s4_floor_corner>;
+		qcom,pmic-sw-mode-regs = "vdd-dig";
+		vdd-dig-supply = <&pm8841_s2_floor_corner>;
+		vdd-gfx-supply = <&pm8841_s4_floor_corner>;
 
 		qcom,vdd-dig-rstr{
-			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,vdd-rstr-reg = "vdd-dig";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-gfx-rstr{
-			qcom,vdd-rstr-reg = "vdd_gfx";
+			qcom,vdd-rstr-reg = "vdd-gfx";
 			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
 			qcom,min-level = <1>; /* No Request */
 		};
 
 		qcom,vdd-apps-rstr{
-			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,vdd-rstr-reg = "vdd-apps";
 			qcom,levels = <1881600 1958400 2265600>;
 			qcom,freq-req;
 		};
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index cca34fb..032c256 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -158,8 +158,8 @@
 	};
 
 	qcom,msm-thermal {
-		vdd_dig-supply = <&pma8084_s2_floor_corner>;
-		vdd_gfx-supply = <&pma8084_s7_floor_corner>;
+		vdd-dig-supply = <&pma8084_s2_floor_corner>;
+		vdd-gfx-supply = <&pma8084_s7_floor_corner>;
 	};
 
 	qcom,lpm-resources {
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 24c6143..e18e143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -271,8 +271,9 @@
 			<37 71>;
 	};
 
-	qcom,pm-8x60 {
+	qcom,pm-8x60@fe805664 {
 		compatible = "qcom,pm-8x60";
+		reg = <0xfe805664 0x40>;
 		qcom,pc-mode = "tz_l2_ext";
 		qcom,use-sync-timer;
 	};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index f5e930d..5520401 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -511,7 +511,7 @@
 	tsens@fc4a8000 {
 		compatible = "qcom,msm-tsens";
 		reg = <0xfc4a8000 0x2000>,
-		      <0xfc4b8000 0x1000>;
+		      <0xfc4bc000 0x1000>;
 		reg-names = "tsens_physical", "tsens_eeprom_physical";
 		interrupts = <0 184 0>;
 		qcom,sensors = <5>;
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 35d6d2a..3743c54 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -128,6 +128,15 @@
 		status = "disabled";
 	};
 
+	qcom,sps@f9980000 {
+		compatible = "qcom,msm_sps";
+		reg = <0xf9984000 0x15000>,
+		      <0xf9999000 0xb000>,
+		      <0xfe803000 0xd000>,
+			  <0xfe805000 0x1000>;
+		interrupts = <0 94 0>;
+	};
+
 	spi_6: spi@f9928000 { /* BLSP1 QUP6 */
 		cell-index = <0>;
 		compatible = "qcom,spi-qup-v2";
diff --git a/arch/arm/configs/mpq8092_defconfig b/arch/arm/configs/mpq8092_defconfig
index c870208..0ee406a 100644
--- a/arch/arm/configs/mpq8092_defconfig
+++ b/arch/arm/configs/mpq8092_defconfig
@@ -239,6 +239,7 @@
 CONFIG_INPUT_UINPUT=y
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
 CONFIG_I2C=y
@@ -285,6 +286,7 @@
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
 CONFIG_USB=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
@@ -304,6 +306,11 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index fa86cc8..6c59c38 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -71,6 +71,7 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_XPU_ERR_FATAL=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 894b0b9..5e39b1f 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -242,6 +242,8 @@
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
 CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
 CONFIG_MSM_BUSPM_DEV=m
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 505e883..0305580 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -240,6 +240,8 @@
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
 CONFIG_INPUT_MPU3050=y
+CONFIG_BMP18X=y
+CONFIG_BMP18X_I2C=y
 CONFIG_MSM_BUSPM_DEV=m
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
index f073d2b..6609c32 100644
--- a/arch/arm/configs/msmkrypton_defconfig
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -104,6 +104,9 @@
 CONFIG_SPI_SPIDEV=m
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index b5a7552..21a940d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -232,6 +232,7 @@
 /* A2 power collaspe */
 #define UL_TIMEOUT_DELAY 1000	/* in ms */
 #define ENABLE_DISCONNECT_ACK	0x1
+#define SHUTDOWN_TIMEOUT_MS	500
 static void toggle_apps_ack(void);
 static void reconnect_to_bam(void);
 static void disconnect_to_bam(void);
@@ -272,6 +273,7 @@
 static int power_management_only_mode;
 static int in_ssr;
 static int ssr_skipped_disconnect;
+static struct completion shutdown_completion;
 
 struct outside_notify_func {
 	void (*notify)(void *, int, unsigned long);
@@ -1066,6 +1068,7 @@
 		goto fail;
 	}
 	polling_mode = 0;
+	complete_all(&shutdown_completion);
 	release_wakelock();
 
 	/* handle any rx packets before interrupt was enabled */
@@ -1266,6 +1269,7 @@
 					" not disabled\n", __func__, ret);
 				break;
 			}
+			INIT_COMPLETION(shutdown_completion);
 			grab_wakelock();
 			polling_mode = 1;
 			/*
@@ -1745,6 +1749,14 @@
 	struct list_head *node;
 	struct rx_pkt_info *info;
 	unsigned long flags;
+	unsigned long time_remaining;
+
+	time_remaining = wait_for_completion_timeout(&shutdown_completion,
+			msecs_to_jiffies(SHUTDOWN_TIMEOUT_MS));
+	if (time_remaining == 0) {
+		pr_err("%s: shutdown completion timed out\n", __func__);
+		ssrestart_check();
+	}
 
 	bam_connection_is_active = 0;
 
@@ -2365,6 +2377,8 @@
 	init_completion(&ul_wakeup_ack_completion);
 	init_completion(&bam_connection_completion);
 	init_completion(&dfab_unvote_completion);
+	init_completion(&shutdown_completion);
+	complete_all(&shutdown_completion);
 	INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
 	INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
 	wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index 56826c7..500731c 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -73,6 +73,8 @@
 }
 
 static struct of_dev_auxdata mpq8092_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
+			"msm_otg", NULL),
 	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
 			"msm_serial_hsl.0", NULL),
 	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF9922000, \
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index a32031d..fd831fc 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -468,6 +468,91 @@
 	},
 };
 
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+static struct gpiomux_setting sdc3_clk_actv_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdc3_cmd_data_0_3_actv_cfg = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdc3_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdc3_data_1_suspend_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config msm8226_sdc3_configs[] __initdata = {
+	{
+		/* DAT3 */
+		.gpio      = 39,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* DAT2 */
+		.gpio      = 40,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* DAT1 */
+		.gpio      = 41,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_data_1_suspend_cfg,
+		},
+	},
+	{
+		/* DAT0 */
+		.gpio      = 42,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* CMD */
+		.gpio      = 43,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_cmd_data_0_3_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+	{
+		/* CLK */
+		.gpio      = 44,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &sdc3_clk_actv_cfg,
+			[GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+		},
+	},
+};
+
+static void msm_gpiomux_sdc3_install(void)
+{
+	msm_gpiomux_install(msm8226_sdc3_configs,
+			    ARRAY_SIZE(msm8226_sdc3_configs));
+}
+#else
+static void msm_gpiomux_sdc3_install(void) {}
+#endif /* CONFIG_MMC_MSM_SDC3_SUPPORT */
+
 void __init msm8226_init_gpiomux(void)
 {
 	int rc;
@@ -500,4 +585,6 @@
 	if (of_board_is_cdp() || of_board_is_mtp() || of_board_is_xpm())
 		msm_gpiomux_install(usb_otg_sw_configs,
 					ARRAY_SIZE(usb_otg_sw_configs));
+
+	msm_gpiomux_sdc3_install();
 }
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 5ad6175..0d62b7a 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -75,10 +75,14 @@
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
 			"msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9864000, \
+			"msm_sdcc.3", NULL),
 	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9824900, \
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
 			"msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+			"msm_sdcc.3", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6432c93..66f2cd3 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -180,6 +180,12 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting gpio_epm_marker_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv  = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv  = GPIOMUX_DRV_2MA,
@@ -526,6 +532,18 @@
 			[GPIOMUX_SUSPENDED] = &gpio_epm_config,
 		},
 	},
+	{
+		.gpio      = 85,		/* EPM MARKER2 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+		},
+	},
+	{
+		.gpio      = 96,		/* EPM MARKER1 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
@@ -825,6 +843,135 @@
 	},
 };
 
+static struct msm_gpiomux_config msm_sensor_configs_dragonboard[] __initdata = {
+	{
+		.gpio = 15, /* CAM_MCLK0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 16, /* CAM_MCLK1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 17, /* CAM_MCLK2 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 18, /* WEBCAM1_RESET_N / CAM_MCLK3 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &cam_settings[4],
+		},
+	},
+	{
+		.gpio = 19, /* CCI_I2C_SDA0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 20, /* CCI_I2C_SCL0 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 21, /* CCI_I2C_SDA1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 22, /* CCI_I2C_SCL1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+		},
+	},
+	{
+		.gpio = 23, /* FLASH_LED_EN */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 24, /* FLASH_LED_NOW */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 25, /* WEBCAM2_RESET_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 26, /* CAM_IRQ */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &cam_settings[1],
+		},
+	},
+	{
+		.gpio = 27, /* OIS_SYNC */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[0],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 28, /* WEBCAM1_STANDBY */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 89, /* CAM1_STANDBY_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 90, /* CAM1_RST_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 91, /* CAM2_STANDBY_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+	{
+		.gpio = 94, /* CAM2_RST_N */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &cam_settings[3],
+			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+		},
+	},
+};
+
 static struct gpiomux_setting auxpcm_act_cfg = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
@@ -1198,7 +1345,9 @@
 	}
 
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
-	msm_gpiomux_install(msm_eth_configs, ARRAY_SIZE(msm_eth_configs));
+	if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+		msm_gpiomux_install(msm_eth_configs, \
+			ARRAY_SIZE(msm_eth_configs));
 #endif
 	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
 	msm_gpiomux_install(msm_blsp2_uart7_configs,
@@ -1215,7 +1364,12 @@
 		msm_gpiomux_install(hap_lvl_shft_config,
 				ARRAY_SIZE(hap_lvl_shft_config));
 
-	msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
+	if (of_board_is_dragonboard() && machine_is_apq8074())
+		msm_gpiomux_install(msm_sensor_configs_dragonboard, \
+				ARRAY_SIZE(msm_sensor_configs_dragonboard));
+	else
+		msm_gpiomux_install(msm_sensor_configs, \
+				ARRAY_SIZE(msm_sensor_configs));
 
 	msm_gpiomux_install(&sd_card_det, 1);
 
@@ -1223,7 +1377,8 @@
 	    of_board_is_dragonboard()))
 		msm_gpiomux_sdc3_install();
 
-	msm_gpiomux_sdc4_install();
+	if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+		msm_gpiomux_sdc4_install();
 
 	msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
 
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index fad2efc..36ad755 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -117,6 +117,10 @@
 			"usb_bam", NULL),
 	OF_DEV_AUXDATA("qcom,hsic-host", 0xF9A15000, \
 			"msm_hsic_host", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
+		       "msm_sdcc.2", NULL),
+	OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+		       "msm_sdcc.3", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index 605a7ae..184338e 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -137,7 +137,8 @@
 	CLK_DUMMY("",	gcc_lpass_mport_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_lpass_q6_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_lpass_sway_clk.c,	"", OFF),
-	CLK_DUMMY("",	gcc_mmss_bimc_gfx_clk.c,	"", OFF),
+	CLK_DUMMY("mem_iface_clk",	gcc_mmss_bimc_gfx_clk.c,
+				     "fdb00000.qcom,kgsl-3d0", OFF),
 	CLK_DUMMY("",	gcc_mmss_vpu_maple_sys_noc_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_ocmem_noc_cfg_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_msg_ram_ahb_clk.c,	"", OFF),
@@ -310,20 +311,24 @@
 	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
-	CLK_DUMMY("",	mdss_byte0_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_byte1_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edpaux_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edplink_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edppixel_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_esc0_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_esc1_clk.c,	"", OFF),
+	CLK_DUMMY("byte_clk", mdss_byte0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("byte_clk", mdss_byte1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("core_clk", mdss_esc1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+	CLK_DUMMY("pixel_clk", mdss_pclk1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
 	CLK_DUMMY("",	mdss_extpclk_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_clk.c,	"", OFF),
 	CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
-	CLK_DUMMY("",	mdss_pclk0_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_pclk1_clk.c,	"", OFF),
 	CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mmss_misc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_ahb_clk.c,	"", OFF),
@@ -333,9 +338,11 @@
 	CLK_DUMMY("iface_clk",	ocmemcx_ocmemnoc_clk.c,
 						"fdd00000.qcom,ocmem", OFF),
 	CLK_DUMMY("",	oxili_ocmemgx_clk.c,	"", OFF),
-	CLK_DUMMY("",	oxili_gfx3d_clk.c,	"", OFF),
+	CLK_DUMMY("core_clk",	oxili_gfx3d_clk.c,
+				     "fdb00000.qcom,kgsl-3d0", OFF),
 	CLK_DUMMY("",	oxili_rbbmtimer_clk.c,	"", OFF),
-	CLK_DUMMY("",	oxilicx_ahb_clk.c,	"", OFF),
+	CLK_DUMMY("iface_clk",	oxilicx_ahb_clk.c,
+				     "fdb00000.qcom,kgsl-3d0", OFF),
 	CLK_DUMMY("",	venus0_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	venus0_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	venus0_core0_vcodec_clk.c,	"", OFF),
diff --git a/arch/arm/mach-msm/clock-8092.c b/arch/arm/mach-msm/clock-8092.c
index f8150c4..bb46c4a 100644
--- a/arch/arm/mach-msm/clock-8092.c
+++ b/arch/arm/mach-msm/clock-8092.c
@@ -329,6 +329,11 @@
 	CLK_DUMMY("",	nidaq_out_clk.c,	"", OFF),
 	CLK_DUMMY("",	gcc_bcss_axi_clk.c,	"", OFF),
 	CLK_DUMMY("",	bcc_lnb_core_clk.c,	"", OFF),
+
+	/* USB */
+	CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
+	CLK_DUMMY("iface_clk", NULL, "msm_otg", OFF),
+	CLK_DUMMY("xo", NULL, "msm_otg", OFF),
 };
 
 struct clock_init_data mpq8092_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-krypton.c b/arch/arm/mach-msm/clock-krypton.c
index aaee003..0b615cc 100644
--- a/arch/arm/mach-msm/clock-krypton.c
+++ b/arch/arm/mach-msm/clock-krypton.c
@@ -46,6 +46,8 @@
 	CLK_DUMMY("mem_clk", bimc_msmbus_clk.c, "msm_bimc", OFF),
 	CLK_DUMMY("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc", OFF),
 	CLK_DUMMY("mem_clk", bimc_acpu_a_clk.c, "", OFF),
+	CLK_DUMMY("dfab_clk",	DFAB_CLK,	"msm_sps", OFF),
+	CLK_DUMMY("dma_bam_pclk",	DMA_BAM_P_CLK,	"msm_sps", OFF),
 
 	CLK_DUMMY("clktype", gcc_imem_axi_clk         , "drivername", OFF),
 	CLK_DUMMY("clktype", gcc_imem_cfg_ahb_clk     , "drivername", OFF),
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 8356207..1d7a5e2 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -42,7 +42,7 @@
 	int rc;
 	struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
 	rc = msm_rpm_get_status(&iv, 1);
-	return (rc < 0) ? rc : iv.value * r->factor;
+	return (rc < 0) ? rc : iv.value * 1000;
 }
 
 static int clk_rpmrs_handoff(struct rpm_clk *r)
@@ -54,7 +54,7 @@
 		return rc;
 
 	if (!r->branch)
-		r->c.rate = iv.value * r->factor;
+		r->c.rate = iv.value * 1000;
 
 	return 0;
 }
@@ -122,7 +122,7 @@
 			unsigned long *active_khz, unsigned long *sleep_khz)
 {
 	/* Convert the rate (hz) to khz */
-	*active_khz = DIV_ROUND_UP(rate, r->factor);
+	*active_khz = DIV_ROUND_UP(rate, 1000);
 
 	/*
 	 * Active-only clocks don't care what the rate is during sleep. So,
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b20c3d6..d283861 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,9 +39,7 @@
 	const bool active_only;
 	bool enabled;
 	bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
-	unsigned factor;
 	struct clk_rpmrs_data *rpmrs_data;
-
 	struct rpm_clk *peer;
 	struct clk c;
 };
@@ -69,7 +67,6 @@
 		.rpm_status_id = (stat_id), \
 		.rpm_key = (key), \
 		.peer = &active, \
-		.factor = 1000, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm, \
@@ -85,7 +82,6 @@
 		.rpm_key = (key), \
 		.peer = &name, \
 		.active_only = true, \
-		.factor = 1000, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
 			.ops = &clk_ops_rpm, \
@@ -104,7 +100,6 @@
 		.rpm_status_id = (stat_id), \
 		.rpm_key = (key), \
 		.peer = &active, \
-		.factor = 1000, \
 		.branch = true, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
@@ -121,7 +116,6 @@
 		.rpm_key = (key), \
 		.peer = &name, \
 		.active_only = true, \
-		.factor = 1000, \
 		.branch = true, \
 		.rpmrs_data = (rpmrsdata),\
 		.c = { \
@@ -132,46 +126,13 @@
 		}, \
 	};
 
-#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, \
-				key, rpmrsdata) \
-	static struct rpm_clk active; \
-	static struct rpm_clk name = { \
-		.rpm_res_type = (type), \
-		.rpm_clk_id = (r_id), \
-		.rpm_status_id = (stat_id), \
-		.rpm_key = (key), \
-		.peer = &active, \
-		.factor = 1, \
-		.rpmrs_data = (rpmrsdata),\
-		.c = { \
-			.ops = &clk_ops_rpm, \
-			.dbg_name = #name, \
-			CLK_INIT(name.c), \
-		}, \
-	}; \
-	static struct rpm_clk active = { \
-		.rpm_res_type = (type), \
-		.rpm_clk_id = (r_id), \
-		.rpm_status_id = (stat_id), \
-		.rpm_key = (key), \
-		.peer = &name, \
-		.active_only = true, \
-		.factor = 1, \
-		.rpmrs_data = (rpmrsdata),\
-		.c = { \
-			.ops = &clk_ops_rpm, \
-			.dbg_name = #active, \
-			CLK_INIT(active.c), \
-		}, \
-	};
-
 #define DEFINE_CLK_RPM(name, active, r_id, dep) \
 	__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
 		MSM_RPM_STATUS_ID_##r_id##_CLK, dep, 0, &clk_rpmrs_data)
 
 #define DEFINE_CLK_RPM_QDSS(name, active) \
-	__DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
-		MSM_RPM_STATUS_ID_QDSS_CLK, 0, &clk_rpmrs_data)
+	__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
+		MSM_RPM_STATUS_ID_QDSS_CLK, 0, 0, &clk_rpmrs_data)
 
 #define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
 	__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
@@ -186,8 +147,8 @@
 				RPM_SMD_KEY_ENABLE, &clk_rpmrs_data_smd)
 
 #define DEFINE_CLK_RPM_SMD_QDSS(name, active, type, r_id) \
-	__DEFINE_CLK_RPM_QDSS(name, active, type, r_id, \
-		0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
+	__DEFINE_CLK_RPM(name, active, type, r_id, \
+		0, 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
 /*
  * The RPM XO buffer clock management code aggregates votes for pin-control mode
  * and software mode separately. Software-enable has higher priority over pin-
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 5d25134..f8a32b4 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -25,6 +25,7 @@
 #ifdef CONFIG_MSM_SCM
 #define SCM_SVC_BOOT 0x1
 #define SCM_CMD_TERMINATE_PC 0x2
+#define SCM_CMD_CORE_HOTPLUGGED 0x10
 #endif
 
 ENTRY(msm_arch_idle)
@@ -99,7 +100,7 @@
 #ifdef CONFIG_MSM_SCM
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
-	mov	r2, #0
+	ldr	r2, =SCM_CMD_CORE_HOTPLUGGED
 	bl	scm_call_atomic1
 #else
 	mrc     p15, 0, r3, c1, c0, 0    /* read current CR    */
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 7b26bd6..6370bd4 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -183,7 +183,7 @@
 };
 
 struct msm_camera_gpio_num_info {
-	uint16_t gpio_num[2];
+	uint16_t gpio_num[7];
 };
 
 struct msm_camera_gpio_conf {
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
index 95f33d5..ff3da11 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,7 +25,8 @@
 
 struct msm_hdmi_audio_codec_ops {
 	int (*audio_info_setup)(struct platform_device *pdev,
-		u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+		u32 sample_rate, u32 num_of_channels,
+		u32 channel_allocation, u32 level_shift,
 		bool down_mix);
 	int (*get_audio_edid_blk) (struct platform_device *pdev,
 		struct msm_hdmi_audio_edid_blk *blk);
diff --git a/arch/arm/mach-msm/include/mach/msm_tspp.h b/arch/arm/mach-msm/include/mach/msm_tspp.h
index ddc99f3..2c40d83 100644
--- a/arch/arm/mach-msm/include/mach/msm_tspp.h
+++ b/arch/arm/mach-msm/include/mach/msm_tspp.h
@@ -25,7 +25,7 @@
 
 struct tspp_data_descriptor {
 	void *virt_base;   /* logical address of the actual data */
-	u32 phys_base;     /* physical address of the actual data */
+	phys_addr_t phys_base; /* physical address of the actual data */
 	u32 size;          /* size of buffer in bytes */
 	int id;            /* unique identifier */
 	void *user;        /* user-defined data */
@@ -33,9 +33,9 @@
 
 typedef void (tspp_notifier)(int channel_id, void *user);
 typedef void* (tspp_allocator)(int channel_id, u32 size,
-	u32 *phys_base, void *user);
+	phys_addr_t *phys_base, void *user);
 typedef void (tspp_memfree)(int channel_id, u32 size,
-	void *virt_base, u32 phys_base, void *user);
+	void *virt_base, phys_addr_t phys_base, void *user);
 
 /* Kernel API functions */
 int tspp_open_stream(u32 dev, u32 channel_id,
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 73b58ab..f0a5ebf 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -23,6 +23,7 @@
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -317,6 +318,8 @@
 		goto err_subsys;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = smsm_state_cb_register(SMSM_DSPS_STATE, SMSM_RESET,
 				     dsps_smsm_state_cb, drv);
 	if (ret)
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 840c90f..b209a25 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -571,6 +571,8 @@
 		goto err_smem;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
 			IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
 	if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 8398206..f6a853e 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -25,6 +25,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
 
 #include "modem_notifier.h"
 #include "peripheral-loader.h"
@@ -490,6 +491,8 @@
 		goto err_ramdump;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, modem_wdog_bite_irq,
 			IRQF_TRIGGER_RISING, "modem_watchdog", drv);
 	if (ret)
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 80c0862..6e4aa02 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -31,6 +31,7 @@
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -504,6 +505,8 @@
 	if (IS_ERR(drv->cxo))
 		return PTR_ERR(drv->cxo);
 
+	scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
 	ret = pil_desc_init(desc);
 	if (ret)
 		return ret;
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index a369878..58d4301 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -24,6 +24,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/scm.h>
 #include <mach/ramdump.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -393,6 +394,8 @@
 		goto err_subsys;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
 			       IRQF_TRIGGER_RISING, "lpass_wdog", drv);
 	if (ret) {
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 7acb599..6ec8430 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -26,6 +26,7 @@
 #include <mach/subsystem_notif.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "smd_private.h"
 #include "sysmon.h"
@@ -356,6 +357,8 @@
 		goto err_notif_riva;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	drv->modem_notif_hdle = subsys_notif_register_notifier("modem", &mnb);
 	if (IS_ERR(drv->modem_notif_hdle)) {
 		ret = PTR_ERR(drv->modem_notif_hdle);
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index c4b6038..6ee5965 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -24,6 +24,7 @@
 #include <mach/msm_smsm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "smd_private.h"
 #include "peripheral-loader.h"
@@ -462,6 +463,8 @@
 	if (ret)
 		goto err_irq;
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
 			smsm_state_cb, drv);
 	if (ret)
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 6cd6ffe..3b88b10 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -30,6 +30,7 @@
 #include <mach/scm.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
@@ -472,6 +473,8 @@
 		dev_info(&pdev->dev, "using non-secure boot\n");
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
 	ret = pil_desc_init(desc);
 	if (ret)
 		return ret;
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index bf7438b..9a364b7 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -25,6 +25,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/ramdump.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -534,6 +535,8 @@
 		goto err_subsys;
 	}
 
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
 			IRQF_TRIGGER_RISING, "riva_wdog", drv);
 	if (ret < 0)
diff --git a/arch/arm/mach-msm/pil-tzapps.c b/arch/arm/mach-msm/pil-tzapps.c
index 1410117..d9f5700 100644
--- a/arch/arm/mach-msm/pil-tzapps.c
+++ b/arch/arm/mach-msm/pil-tzapps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 
 #include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -97,6 +98,9 @@
 		pil_desc_release(desc);
 		return PTR_ERR(drv->subsys);
 	}
+
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 4e9e54b..a7ebbf7 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -605,6 +605,8 @@
 	if (!drv->ramdump_dev)
 		return -ENOMEM;
 
+	scm_pas_init(MSM_BUS_MASTER_CRYPTO_CORE0);
+
 	rc = pil_desc_init(desc);
 	if (rc)
 		goto err_ramdump;
diff --git a/arch/arm/mach-msm/pil-vidc.c b/arch/arm/mach-msm/pil-vidc.c
index 629907f..3dbddae 100644
--- a/arch/arm/mach-msm/pil-vidc.c
+++ b/arch/arm/mach-msm/pil-vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 
 #include <mach/subsystem_restart.h>
+#include <mach/msm_bus_board.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
@@ -122,6 +123,9 @@
 		pil_desc_release(desc);
 		return PTR_ERR(drv->subsys);
 	}
+
+	scm_pas_init(MSM_BUS_MASTER_SPS);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index b244c6f..57acdc4 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -255,9 +255,14 @@
 }
 EXPORT_SYMBOL(pas_supported);
 
-static int __init scm_pas_init(void)
+void scm_pas_init(enum msm_bus_fabric_master_type id)
 {
 	int i, rate;
+	static int is_inited;
+
+	if (is_inited)
+		return;
+
 	for (i = 0; i < NUM_CLKS; i++) {
 		scm_clocks[i] = clk_get_sys("scm", scm_clock_names[i]);
 		if (IS_ERR(scm_clocks[i]))
@@ -268,20 +273,14 @@
 	rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
 	clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
 
-	if (soc_class_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
-		scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
-		scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
-	} else {
-		if (!IS_ERR(scm_clocks[BUS_CLK]))
-			clk_set_rate(scm_clocks[BUS_CLK], 64000000);
-		else
-			pr_warn("unable to get bus clock\n");
-	}
+	scm_pas_bw_tbl[0].vectors[0].src = id;
+	scm_pas_bw_tbl[1].vectors[0].src = id;
+
+	clk_set_rate(scm_clocks[BUS_CLK], 64000000);
 
 	scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
 	if (!scm_perf_client)
 		pr_warn("unable to register bus client\n");
 
-	return 0;
+	is_inited = 1;
 }
-module_init(scm_pas_init);
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index f13757c..48bc558 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -9,6 +9,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
+#include <mach/msm_bus_board.h>
+
 #ifndef __MSM_SCM_PAS_H
 #define __MSM_SCM_PAS_H
 
@@ -31,6 +34,7 @@
 extern int pas_auth_and_reset(enum pas_id id);
 extern int pas_shutdown(enum pas_id id);
 extern int pas_supported(enum pas_id id);
+extern void scm_pas_init(enum msm_bus_fabric_master_type id);
 #else
 static inline int pas_init_image(enum pas_id id, const u8 *metadata,
 		size_t size)
@@ -53,6 +57,9 @@
 {
 	return 0;
 }
+static inline void scm_pas_init(enum msm_bus_fabric_master_type id)
+{
+}
 #endif
 
 #endif
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 0de37c9..58b0513 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -742,6 +742,16 @@
 
 	fd_install(ret, lock->file);
 
+	/*
+	 * Taking a reference for lock file.
+	 * This is required as now we have two file descriptor
+	 * pointing to same file. If one FD is closed, lock file
+	 * will be closed. Taking this reference will make sure
+	 * that file doesn't get close. This refrence will go
+	 * when client will call close on this FD.
+	 */
+	fget(ret);
+
 	return ret;
 }
 EXPORT_SYMBOL(genlock_get_fd_handle);
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index d01496e..0c67ed8 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -20,6 +20,8 @@
 #include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/spinlock.h>
 #include <asm/current.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <mach/usbdiag.h>
@@ -39,6 +41,12 @@
 struct mutex dci_event_mask_mutex;
 struct mutex dci_health_mutex;
 
+spinlock_t ws_lock;
+unsigned long ws_lock_flags;
+
+/* Number of milliseconds anticipated to process the DCI data */
+#define DCI_WAKEUP_TIMEOUT 1
+
 #define DCI_CHK_CAPACITY(entry, new_data_len)				\
 ((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0)	\
 
@@ -96,6 +104,11 @@
 		read_bytes += 5 + dci_pkt_len;
 		buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
 	}
+	/* Release wakeup source when there are no more clients to
+	   process DCI data */
+	if (driver->num_dci_client == 0)
+		diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
 	/* wake up all sleeping DCI clients which have some data */
 	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
 		if (driver->dci_client_tbl[i].client &&
@@ -1101,6 +1114,9 @@
 			diag_smd_notify);
 		driver->smd_dci[index].ch_save =
 			driver->smd_dci[index].ch;
+		driver->dci_device = &pdev->dev;
+		driver->dci_device->power.wakeup = wakeup_source_register
+							("DIAG_DCI_WS");
 		if (err)
 			pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
 				__func__, pdev->id, err);
@@ -1123,6 +1139,9 @@
 			diag_smd_notify);
 		driver->smd_dci_cmd[index].ch_save =
 			driver->smd_dci_cmd[index].ch;
+		driver->dci_cmd_device = &pdev->dev;
+		driver->dci_cmd_device->power.wakeup = wakeup_source_register
+							("DIAG_DCI_CMD_WS");
 		if (err)
 			pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
 				__func__, pdev->id, err);
@@ -1174,10 +1193,13 @@
 	driver->dci_tag = 0;
 	driver->dci_client_id = 0;
 	driver->num_dci_client = 0;
+	driver->dci_device = NULL;
+	driver->dci_cmd_device = NULL;
 	mutex_init(&driver->dci_mutex);
 	mutex_init(&dci_log_mask_mutex);
 	mutex_init(&dci_event_mask_mutex);
 	mutex_init(&dci_health_mutex);
+	spin_lock_init(&ws_lock);
 
 	for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 		success = diag_smd_constructor(&driver->smd_dci[i], i,
@@ -1408,3 +1430,26 @@
 		driver->dci_client_tbl[i].real_time = real_time;
 	return i;
 }
+
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel)
+{
+	spin_lock_irqsave(&ws_lock, ws_lock_flags);
+	if (channel == driver->smd_dci[MODEM_DATA].ch) {
+		pm_wakeup_event(driver->dci_device, DCI_WAKEUP_TIMEOUT);
+		pm_stay_awake(driver->dci_device);
+	} else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch) {
+		pm_wakeup_event(driver->dci_cmd_device, DCI_WAKEUP_TIMEOUT);
+		pm_stay_awake(driver->dci_cmd_device);
+	}
+	spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
+
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel)
+{
+	spin_lock_irqsave(&ws_lock, ws_lock_flags);
+	if (channel == driver->smd_dci[MODEM_DATA].ch)
+		pm_relax(driver->dci_device);
+	else if (channel == driver->smd_dci_cmd[MODEM_DATA].ch)
+		pm_relax(driver->dci_cmd_device);
+	spin_unlock_irqrestore(&ws_lock, ws_lock_flags);
+}
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2335d37..520995b 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -138,4 +138,7 @@
 void diag_dci_smd_record_info(int read_bytes);
 uint8_t diag_dci_get_cumulative_real_time(void);
 int diag_dci_set_real_time(int client_id, uint8_t real_time);
+/* Functions related to DCI wakeup sources */
+void diag_dci_try_activate_wakeup_source(smd_channel_t *channel);
+void diag_dci_try_deactivate_wakeup_source(smd_channel_t *channel);
 #endif
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 0badda6..3d1a6cd 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -176,6 +176,26 @@
 		bytes_in_buf += bytes_written;
 		bytes_remaining -= bytes_written;
 #endif
+		if (driver->dci_device) {
+			bytes_written = scnprintf(buf+bytes_in_buf,
+						  bytes_remaining,
+				"dci power active, relax: %lu, %lu\n",
+				driver->dci_device->power.wakeup->active_count,
+				driver->dci_device->power.wakeup->relax_count);
+			bytes_in_buf += bytes_written;
+			bytes_remaining -= bytes_written;
+		}
+		if (driver->dci_cmd_device) {
+			bytes_written = scnprintf(buf+bytes_in_buf,
+						  bytes_remaining,
+				"dci cmd power active, relax: %lu, %lu\n",
+				driver->dci_cmd_device->power.wakeup->
+						  active_count,
+				driver->dci_cmd_device->power.wakeup->
+						  relax_count);
+			bytes_in_buf += bytes_written;
+			bytes_remaining -= bytes_written;
+		}
 	}
 	temp_data += diag_dbgfs_dci_data_index;
 	for (i = diag_dbgfs_dci_data_index; i < DIAG_DCI_DEBUG_CNT; i++) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index b7784b5..3ae56c5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -333,6 +333,8 @@
 	unsigned hdlc_count;
 	unsigned hdlc_escape;
 	int in_busy_pktdata;
+	struct device *dci_device;
+	struct device *dci_cmd_device;
 	/* Variables for non real time mode */
 	int real_time_mode;
 	int real_time_update_busy;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 8df1b49..5e06f19 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1453,19 +1453,25 @@
 		driver->data_ready[index] ^= DCI_DATA_TYPE;
 		for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 			driver->smd_dci[i].in_busy_1 = 0;
-			if (driver->smd_dci[i].ch)
+			if (driver->smd_dci[i].ch) {
+				diag_dci_try_deactivate_wakeup_source(
+						driver->smd_dci[i].ch);
 				queue_work(driver->diag_dci_wq,
 				&(driver->smd_dci[i].diag_read_smd_work));
+			}
 		}
 		if (driver->supports_separate_cmdrsp) {
 			for (i = 0; i < NUM_SMD_DCI_CMD_CHANNELS; i++) {
 				if (!driver->separate_cmdrsp[i])
 					continue;
 				driver->smd_dci_cmd[i].in_busy_1 = 0;
-				if (driver->smd_dci_cmd[i].ch)
+				if (driver->smd_dci_cmd[i].ch) {
+					diag_dci_try_deactivate_wakeup_source(
+						driver->smd_dci_cmd[i].ch);
 					queue_work(driver->diag_dci_wq,
 						&(driver->smd_dci_cmd[i].
 							diag_read_smd_work));
+				}
 			}
 		}
 		goto exit;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6e7080e..de4433b 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -390,10 +390,18 @@
 			(smd_info->type == SMD_DATA_TYPE))
 		buf = smd_info->buf_in_2;
 
+	if (!buf && (smd_info->type == SMD_DCI_TYPE ||
+					smd_info->type == SMD_DCI_CMD_TYPE))
+		diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
 	if (smd_info->ch && buf) {
 		temp_buf = buf;
 		pkt_len = smd_cur_packet_size(smd_info->ch);
 
+		if (pkt_len == 0 && (smd_info->type == SMD_DCI_TYPE ||
+					smd_info->type == SMD_DCI_CMD_TYPE))
+			diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+
 		while (pkt_len && (pkt_len != total_recd)) {
 			loop_count++;
 			r = smd_read_avail(smd_info->ch);
@@ -412,7 +420,7 @@
 				} else {
 					pr_debug("diag: In %s, return from wait_event ch closed\n",
 						__func__);
-					return;
+					goto fail_return;
 				}
 			}
 			total_recd += r;
@@ -425,13 +433,13 @@
 				} else {
 					pr_err("diag: In %s, SMD sending in packets more than %d bytes\n",
 						__func__, MAX_IN_BUF_SIZE);
-					return;
+					goto fail_return;
 				}
 			}
 			if (pkt_len < r) {
 				pr_err("diag: In %s, SMD sending incorrect pkt\n",
 					__func__);
-				return;
+				goto fail_return;
 			}
 			if (pkt_len > r) {
 				pr_debug("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
@@ -462,6 +470,13 @@
 		(driver->logging_mode == MEMORY_DEVICE_MODE)) {
 			chk_logging_wakeup();
 	}
+	return;
+
+fail_return:
+	if (smd_info->type == SMD_DCI_TYPE ||
+					smd_info->type == SMD_DCI_CMD_TYPE)
+		diag_dci_try_deactivate_wakeup_source(smd_info->ch);
+	return;
 }
 
 void diag_read_smd_work_fn(struct work_struct *work)
@@ -1705,10 +1720,12 @@
 	wake_up(&driver->smd_wait_q);
 
 	if (smd_info->type == SMD_DCI_TYPE ||
-		smd_info->type == SMD_DCI_CMD_TYPE)
+					smd_info->type == SMD_DCI_CMD_TYPE) {
+		if (event == SMD_EVENT_DATA)
+			diag_dci_try_activate_wakeup_source(smd_info->ch);
 		queue_work(driver->diag_dci_wq,
 				&(smd_info->diag_read_smd_work));
-	else
+	} else
 		queue_work(driver->diag_wq, &(smd_info->diag_read_smd_work));
 }
 
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index d069f2e..0e4b309 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1937,7 +1937,7 @@
 	rc = misc_register(&podev->miscdevice);
 	qce_hw_support(podev->qce, &podev->ce_support);
 	if (podev->ce_support.bam) {
-		podev->platform_support.ce_shared = podev->ce_support.is_shared;
+		podev->platform_support.ce_shared = 0;
 		podev->platform_support.shared_ce_resource = 0;
 		podev->platform_support.hw_key_support =
 						podev->ce_support.hw_key;
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 64341e9..ed001f0 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -589,6 +589,9 @@
 	}
 	mutex_unlock(&qpnp_pin_chips_lock);
 
+	if (!q_spec)
+		return -ENODEV;
+
 	rc = _qpnp_pin_config(q_chip, q_spec, param);
 
 	return rc;
@@ -1225,6 +1228,8 @@
 		if (!res) {
 			dev_err(&spmi->dev, "%s: node %s is missing has no base address definition\n",
 				__func__, d_node->of_node->full_name);
+			rc = -EINVAL;
+			goto err_probe;
 		}
 
 		rc = of_property_read_u32(d_node->of_node,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index e316742..32a667f 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -109,6 +109,10 @@
 	.pm4_fw = NULL,
 	.wait_timeout = 0, /* in milliseconds, 0 means disabled */
 	.ib_check_level = 0,
+	.ft_policy = KGSL_FT_DEFAULT_POLICY,
+	.ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY,
+	.fast_hang_detect = 1,
+	.long_ib_detect = 1,
 };
 
 /* This set of registers are used for Hang detection
@@ -211,6 +215,8 @@
 		512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 },
 };
 
+static unsigned int adreno_isidle(struct kgsl_device *device);
+
 /**
  * adreno_perfcounter_init: Reserve kernel performance counters
  * @device: device to configure
@@ -818,6 +824,27 @@
 	return cmds - cmds_orig;
 }
 
+/**
+ * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu?
+ * @adreno_dev: the device
+ *
+ * In many cases it is preferable to poke the iommu or gpummu directly rather
+ * than using the GPU command stream. If we are idle or trying to go to a low
+ * power state, using the command stream will be slower and asynchronous, which
+ * needlessly complicates the power state transitions. Additionally,
+ * the hardware simulators do not support command stream MMU operations so
+ * the command stream can never be used if we are capturing CFF data.
+ *
+ */
+static bool adreno_use_default_setstate(struct adreno_device *adreno_dev)
+{
+	return (adreno_isidle(&adreno_dev->dev) ||
+		adreno_dev->drawctxt_active == NULL ||
+		KGSL_STATE_ACTIVE != adreno_dev->dev.state ||
+		atomic_read(&adreno_dev->dev.active_cnt) == 0 ||
+		adreno_dev->dev.cff_dump_enable);
+}
+
 static void adreno_iommu_setstate(struct kgsl_device *device,
 					unsigned int context_id,
 					uint32_t flags)
@@ -832,10 +859,7 @@
 	struct adreno_context *adreno_ctx = NULL;
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	if (!adreno_dev->drawctxt_active ||
-		KGSL_STATE_ACTIVE != device->state ||
-		!atomic_read(&device->active_cnt) ||
-		device->cff_dump_enable) {
+	if (adreno_use_default_setstate(adreno_dev)) {
 		kgsl_mmu_device_setstate(&device->mmu, flags);
 		return;
 	}
@@ -845,7 +869,7 @@
 	if (context == NULL)
 		return;
 
-	adreno_ctx = context->devctxt;
+	adreno_ctx = ADRENO_CONTEXT(context);
 
 	if (kgsl_mmu_enable_clk(&device->mmu,
 				KGSL_IOMMU_CONTEXT_USER))
@@ -886,8 +910,7 @@
 	adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE,
 			&link[0], sizedwords);
 
-	kgsl_mmu_disable_clk_on_ts(&device->mmu,
-		rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
+	kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts, true);
 	kgsl_context_put(context);
 }
 
@@ -915,11 +938,11 @@
 	 * writes For CFF dump we must idle and use the registers so that it is
 	 * easier to filter out the mmu accesses from the dump
 	 */
-	if (!device->cff_dump_enable && adreno_dev->drawctxt_active) {
+	if (!adreno_use_default_setstate(adreno_dev)) {
 		context = kgsl_context_get(device, context_id);
 		if (context == NULL)
 			return;
-		adreno_ctx = context->devctxt;
+		adreno_ctx = ADRENO_CONTEXT(context);
 
 		if (flags & KGSL_MMUFLAGS_PTUPDATE) {
 			/* wait for graphics pipe to be idle */
@@ -1663,6 +1686,8 @@
 
 	adreno_debugfs_init(device);
 
+	adreno_ft_init_sysfs(device);
+
 	kgsl_pwrscale_init(device);
 	kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY);
 
@@ -1703,7 +1728,6 @@
 static int adreno_init(struct kgsl_device *device)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int i;
 
 	if (KGSL_STATE_DUMP_AND_FT != device->state)
@@ -1744,8 +1768,6 @@
 		adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
 		device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
 
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-
 	/* Initialize ft detection register offsets */
 	ft_detect_regs[0] = adreno_getreg(adreno_dev,
 						ADRENO_REG_RBBM_STATUS);
@@ -1860,6 +1882,9 @@
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
+	if (adreno_dev->drawctxt_active)
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
 	adreno_dev->drawctxt_active = NULL;
 
 	adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
@@ -1892,7 +1917,7 @@
 {
 	unsigned int ft_status = *((unsigned int *) data);
 	struct kgsl_context *context = ptr;
-	struct adreno_context *adreno_context = context->devctxt;
+	struct adreno_context *adreno_context = ADRENO_CONTEXT(context);
 
 	if (ft_status) {
 		context->reset_status =
@@ -1930,20 +1955,16 @@
 static int _set_max_ts(int id, void *ptr, void *data)
 {
 	struct kgsl_device *device = data;
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	struct kgsl_context *context = ptr;
-	struct adreno_context *drawctxt = context->devctxt;
+	struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
 
-	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
+	if (drawctxt && drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
 		kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(context->id,
-			soptimestamp),
-			rb->timestamp[context->id]);
+			soptimestamp), drawctxt->timestamp);
 		kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(context->id,
-			eoptimestamp),
-			rb->timestamp[context->id]);
+			eoptimestamp), drawctxt->timestamp);
 	}
 
 	return 0;
@@ -2199,7 +2220,7 @@
 	}
 
 	if (context) {
-		adreno_context = context->devctxt;
+		adreno_context = ADRENO_CONTEXT(context);
 		if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
 			if (ft_data->ib1) {
 				ret = _find_hanging_ib_sequence(rb,
@@ -2266,6 +2287,9 @@
 		return -EINVAL;
 	}
 
+	if (adreno_dev->drawctxt_active)
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
 	adreno_dev->drawctxt_active = NULL;
 
 	/* Stop the ringbuffer */
@@ -2328,11 +2352,9 @@
 	}
 
 reset_done:
-	if (context) {
-		struct adreno_context *adreno_context = context->devctxt;
-		kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
-			KGSL_MEMSTORE_GLOBAL);
-	}
+	if (context)
+		kgsl_mmu_setstate(&device->mmu, context->pagetable,
+				KGSL_MEMSTORE_GLOBAL);
 
 	/* If iommu is used then we need to make sure that the iommu clocks
 	 * are on since there could be commands in pipeline that touch iommu */
@@ -2451,7 +2473,7 @@
 		}
 	} else {
 		no_context_ft = 0;
-		adreno_context = context->devctxt;
+		adreno_context = ADRENO_CONTEXT(context);
 		adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
 		/*
 		 * set the invalid ts flag to 0 for this context since we have
@@ -2507,16 +2529,16 @@
 		goto play_good_cmds;
 	}
 
-	/* Do not try the reply if hang is due to a pagefault */
-	if (adreno_context && adreno_context->pagefault) {
+	/* Do not try to replay if hang is due to a pagefault */
+	if (context && test_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv)) {
 		/* Resume MMU */
 		mmu->mmu_ops->mmu_pagefault_resume(mmu);
-		if ((ft_data->context_id == adreno_context->id) &&
-			(ft_data->global_eop == adreno_context->pagefault_ts)) {
+		if ((ft_data->context_id == context->id) &&
+			(ft_data->global_eop == context->pagefault_ts)) {
 			ft_data->ft_policy &= ~KGSL_FT_REPLAY;
 			KGSL_FT_ERR(device, "MMU fault skipping replay\n");
 		}
-		adreno_context->pagefault = 0;
+		clear_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
 	}
 
 	if (ft_data->ft_policy & KGSL_FT_REPLAY) {
@@ -2604,6 +2626,10 @@
 			adreno_context->flags = (adreno_context->flags &
 				~CTXT_FLAGS_GPU_HANG) | CTXT_FLAGS_GPU_HANG_FT;
 		}
+
+		if (last_active_ctx)
+			_kgsl_context_get(&last_active_ctx->base);
+
 		adreno_dev->drawctxt_active = last_active_ctx;
 	}
 
@@ -2631,10 +2657,7 @@
 		struct kgsl_context *last_ctx = kgsl_context_get(device,
 			ft_data->last_valid_ctx_id);
 
-		if (last_ctx)
-			adreno_dev->drawctxt_active = last_ctx->devctxt;
-
-		kgsl_context_put(last_ctx);
+		adreno_dev->drawctxt_active = ADRENO_CONTEXT(last_ctx);
 	}
 
 done:
@@ -2653,7 +2676,6 @@
 	int ret = 0;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	unsigned int timestamp;
 
 	/*
 	 * If GPU FT is turned off do not run FT.
@@ -2670,8 +2692,8 @@
 	"Bad context_id: %u, global_eop: 0x%x\n",
 	ft_data->ib1, ft_data->context_id, ft_data->global_eop);
 
-	timestamp = rb->timestamp[KGSL_MEMSTORE_GLOBAL];
-	KGSL_FT_INFO(device, "Last issued global timestamp: %x\n", timestamp);
+	KGSL_FT_INFO(device, "Last issued global timestamp: %x\n",
+			rb->global_ts);
 
 	/* We may need to replay commands multiple times based on whether
 	 * multiple contexts hang the GPU */
@@ -2700,14 +2722,12 @@
 	/* Restore correct states after fault tolerance */
 	if (adreno_dev->drawctxt_active)
 		device->mmu.hwpagetable =
-			adreno_dev->drawctxt_active->pagetable;
+			adreno_dev->drawctxt_active->base.pagetable;
 	else
 		device->mmu.hwpagetable = device->mmu.defaultpagetable;
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
 	kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
-			eoptimestamp),
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			eoptimestamp), rb->global_ts);
 
 	/* switch to NULL ctxt */
 	if (adreno_dev->drawctxt_active != NULL)
@@ -2798,6 +2818,264 @@
 }
 EXPORT_SYMBOL(adreno_dump_and_exec_ft);
 
+/**
+ * _ft_sysfs_store() -  Common routine to write to FT sysfs files
+ * @buf: value to write
+ * @count: size of the value to write
+ * @sysfs_cfg: KGSL FT sysfs config to write
+ *
+ * This is a common routine to write to FT sysfs files.
+ */
+static int _ft_sysfs_store(const char *buf, size_t count, unsigned int *ptr)
+{
+	char temp[20];
+	unsigned long val;
+	int rc;
+
+	snprintf(temp, sizeof(temp), "%.*s",
+			 (int)min(count, sizeof(temp) - 1), buf);
+	rc = kstrtoul(temp, 0, &val);
+	if (rc)
+		return rc;
+
+	*ptr = val;
+
+	return count;
+}
+
+/**
+ * _get_adreno_dev() -  Routine to get a pointer to adreno dev
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ */
+struct adreno_device *_get_adreno_dev(struct device *dev)
+{
+	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	return device ? ADRENO_DEVICE(device) : NULL;
+}
+
+/**
+ * _ft_policy_store() -  Routine to configure FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT policy can be set to any of the options below.
+ * KGSL_FT_DISABLE -> BIT(0) Set to disable FT
+ * KGSL_FT_REPLAY  -> BIT(1) Set to enable replay
+ * KGSL_FT_SKIPIB  -> BIT(2) Set to skip IB
+ * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
+ * by default set FT policy to KGSL_FT_DEFAULT_POLICY
+ */
+static int _ft_policy_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_policy);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+}
+
+/**
+ * _ft_policy_show() -  Routine to read FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT policy
+ */
+static int _ft_policy_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_policy);
+}
+
+/**
+ * _ft_pagefault_policy_store() -  Routine to configure FT
+ * pagefault policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT pagefault policy can be set to any of the options below.
+ * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
+ * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE  -> BIT(1) Set to enable GPU HALT on
+ * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE  -> BIT(2) Set to log only one
+ * pagefault per page.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
+ * pagefault per INT.
+ */
+static int _ft_pagefault_policy_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+}
+
+/**
+ * _ft_pagefault_policy_show() -  Routine to read FT pagefault
+ * policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT pagefault policy
+ */
+static int _ft_pagefault_policy_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_pf_policy);
+}
+
+/**
+ * _ft_fast_hang_detect_store() -  Routine to configure FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x1 - Enable fast hang detection
+ * 0x0 - Disable fast hang detection
+ */
+static int _ft_fast_hang_detect_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->fast_hang_detect);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+
+}
+
+/**
+ * _ft_fast_hang_detect_show() -  Routine to read FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_fast_hang_detect_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				(adreno_dev->fast_hang_detect ? 1 : 0));
+}
+
+/**
+ * _ft_long_ib_detect_store() -  Routine to configure FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x0 - Enable long IB detection
+ * 0x1 - Disable long IB detection
+ */
+static int _ft_long_ib_detect_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->long_ib_detect);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+
+}
+
+/**
+ * _ft_long_ib_detect_show() -  Routine to read FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_long_ib_detect_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				(adreno_dev->long_ib_detect ? 1 : 0));
+}
+
+
+#define FT_DEVICE_ATTR(name) \
+	DEVICE_ATTR(name, 0644,	_ ## name ## _show, _ ## name ## _store);
+
+FT_DEVICE_ATTR(ft_policy);
+FT_DEVICE_ATTR(ft_pagefault_policy);
+FT_DEVICE_ATTR(ft_fast_hang_detect);
+FT_DEVICE_ATTR(ft_long_ib_detect);
+
+
+const struct device_attribute *ft_attr_list[] = {
+	&dev_attr_ft_policy,
+	&dev_attr_ft_pagefault_policy,
+	&dev_attr_ft_fast_hang_detect,
+	&dev_attr_ft_long_ib_detect,
+	NULL,
+};
+
+int adreno_ft_init_sysfs(struct kgsl_device *device)
+{
+	return kgsl_create_device_sysfs_files(device->dev, ft_attr_list);
+}
+
+void adreno_ft_uninit_sysfs(struct kgsl_device *device)
+{
+	kgsl_remove_device_sysfs_files(device->dev, ft_attr_list);
+}
+
 static int adreno_getproperty(struct kgsl_device *device,
 				enum kgsl_property_type type,
 				void *value,
@@ -2942,20 +3220,15 @@
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	unsigned long wait;
+	unsigned long wait = jiffies;
 	unsigned long timeout = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
 	unsigned int rptr;
 
-	/*
-	 * The first time into the loop, wait for 100 msecs and kick wptr again
-	 * to ensure that the hardware has updated correctly.  After that, kick
-	 * it periodically every KGSL_TIMEOUT_PART msecs until the timeout
-	 * expires
-	 */
-
-	wait = jiffies + msecs_to_jiffies(100);
-
 	do {
+		/*
+		 * Wait is "jiffies" first time in the loop to start
+		 * GPU stall detection immediately.
+		 */
 		if (time_after(jiffies, wait)) {
 			/* Check to see if the core is hung */
 			if (adreno_ft_detect(device, regs))
@@ -2977,11 +3250,10 @@
 /* Caller must hold the device mutex. */
 int adreno_idle(struct kgsl_device *device)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	unsigned int rbbm_status;
 	unsigned long wait_time;
 	unsigned long wait_time_part;
 	unsigned int prev_reg_val[FT_DETECT_REGS_COUNT];
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
 	memset(prev_reg_val, 0, sizeof(prev_reg_val));
 
@@ -2999,23 +3271,15 @@
 	wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
 
 	while (time_before(jiffies, wait_time)) {
-		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
-					&rbbm_status);
-		if (adreno_is_a2xx(adreno_dev)) {
-			if (rbbm_status == 0x110)
-				return 0;
-		} else {
-			if (!(rbbm_status & 0x80000000))
-				return 0;
-		}
+		if (adreno_isidle(device))
+			return 0;
 
-		/* Dont wait for timeout, detect hang faster.
-		 */
+		/* Dont wait for timeout, detect hang faster.  */
 		if (time_after(jiffies, wait_time_part)) {
-				wait_time_part = jiffies +
-					msecs_to_jiffies(KGSL_TIMEOUT_PART);
-				if ((adreno_ft_detect(device, prev_reg_val)))
-					goto err;
+			wait_time_part = jiffies +
+				msecs_to_jiffies(KGSL_TIMEOUT_PART);
+			if ((adreno_ft_detect(device, prev_reg_val)))
+				goto err;
 		}
 
 	}
@@ -3064,9 +3328,8 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	WARN_ON(device->state == KGSL_STATE_INIT);
 	/* If the device isn't active, don't force it on. */
-	if (device->state == KGSL_STATE_ACTIVE) {
+	if (kgsl_pwrctrl_isenabled(device)) {
 		/* Is the ring buffer is empty? */
 		unsigned int rptr = adreno_get_rptr(rb);
 		if (rptr == rb->wptr) {
@@ -3109,21 +3372,20 @@
 	phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size)
 {
 	struct kgsl_context *context;
-	struct adreno_context *adreno_context = NULL;
 	int next = 0;
 	struct kgsl_memdesc *desc = NULL;
 
-
 	read_lock(&device->context_lock);
 	while (1) {
 		context = idr_get_next(&device->context_idr, &next);
 		if (context == NULL)
 			break;
 
-		adreno_context = (struct adreno_context *)context->devctxt;
-
-		if (kgsl_mmu_pt_equal(&device->mmu, adreno_context->pagetable,
+		if (kgsl_mmu_pt_equal(&device->mmu, context->pagetable,
 					pt_base)) {
+			struct adreno_context *adreno_context;
+
+			adreno_context = ADRENO_CONTEXT(context);
 			desc = &adreno_context->gpustate;
 			if (kgsl_gpuaddr_in_memdesc(desc, gpuaddr, size))
 				break;
@@ -3257,9 +3519,10 @@
 static unsigned int _get_context_id(struct kgsl_context *k_ctxt)
 {
 	unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
+
 	if (k_ctxt != NULL) {
-		struct adreno_context *a_ctxt = k_ctxt->devctxt;
-		if (k_ctxt->id == KGSL_CONTEXT_INVALID || a_ctxt == NULL)
+		struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+		if (kgsl_context_detached(k_ctxt))
 			context_id = KGSL_CONTEXT_INVALID;
 		else if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
 			context_id = k_ctxt->id;
@@ -3330,7 +3593,8 @@
 		 */
 
 		if (context && device->state != KGSL_STATE_SLUMBER) {
-			adreno_ringbuffer_issuecmds(device, context->devctxt,
+			adreno_ringbuffer_issuecmds(device,
+					ADRENO_CONTEXT(context),
 					KGSL_CMD_FLAGS_GET_INT, NULL, 0);
 		}
 	}
@@ -3390,6 +3654,7 @@
 	unsigned int curr_context_id = 0;
 	static struct adreno_context *curr_context;
 	static struct kgsl_context *context;
+	static char pid_name[TASK_COMM_LEN] = "unknown";
 
 	if (!adreno_dev->fast_hang_detect)
 		fast_hang_detected = 0;
@@ -3402,7 +3667,7 @@
 
 	if (is_adreno_rbbm_status_idle(device) &&
 		(kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED)
-		== rb->timestamp[KGSL_MEMSTORE_GLOBAL])) {
+		 == rb->global_ts)) {
 
 		/*
 		 * On A2XX if the RPTR != WPTR and the device is idle, then
@@ -3453,8 +3718,13 @@
 
 	if (curr_global_ts == prev_global_ts) {
 
-		/* Get the current context here */
-		if (context == NULL) {
+		/* If we don't already have a good context, get it. */
+		if (kgsl_context_detached(context)) {
+			kgsl_context_put(context);
+			context = NULL;
+			curr_context = NULL;
+			strlcpy(pid_name, "unknown", sizeof(pid_name));
+
 			kgsl_sharedmem_readl(&device->memstore,
 				&curr_context_id,
 				KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -3464,8 +3734,12 @@
 
 			context = kgsl_context_get(device, curr_context_id);
 			if (context != NULL) {
-				curr_context = context->devctxt;
+				struct task_struct *task;
+				curr_context = ADRENO_CONTEXT(context);
 				curr_context->ib_gpu_time_used = 0;
+				task = find_task_by_vpid(context->pid);
+				if (task)
+					get_task_comm(pid_name, task);
 			} else {
 				KGSL_DRV_ERR(device,
 					"Fault tolerance no context found\n");
@@ -3489,8 +3763,7 @@
 			KGSL_FT_ERR(device,
 				"Proc %s, ctxt_id %d ts %d triggered fault tolerance"
 				" on global ts %d\n",
-				curr_context ? curr_context->pid_name : "",
-				curr_context ? curr_context->id : 0,
+				pid_name, context ? context->id : 0,
 				(kgsl_readtimestamp(device, context,
 				KGSL_TIMESTAMP_RETIRED) + 1),
 				curr_global_ts + 1);
@@ -3502,7 +3775,7 @@
 			curr_context->ib_gpu_time_used += KGSL_TIMEOUT_PART;
 			KGSL_FT_INFO(device,
 			"Proc %s used GPU Time %d ms on timestamp 0x%X\n",
-			curr_context->pid_name, curr_context->ib_gpu_time_used,
+			pid_name, curr_context->ib_gpu_time_used,
 			curr_global_ts+1);
 
 			if ((long_ib_detected) &&
@@ -3518,8 +3791,7 @@
 						"Proc %s, ctxt_id %d ts %d"
 						"used GPU for %d ms long ib "
 						"detected on global ts %d\n",
-						curr_context->pid_name,
-						curr_context->id,
+						pid_name, context->id,
 						(kgsl_readtimestamp(device,
 						context,
 						KGSL_TIMESTAMP_RETIRED)+1),
@@ -3541,6 +3813,7 @@
 		kgsl_context_put(context);
 		context = NULL;
 		curr_context = NULL;
+		strlcpy(pid_name, "unknown", sizeof(pid_name));
 		adreno_dev->long_ib = 0;
 		adreno_dev->long_ib_ts = 0;
 	}
@@ -3563,7 +3836,7 @@
 	if (context_id == KGSL_CONTEXT_INVALID)
 		return -EINVAL;
 
-	ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
+	ts_issued = adreno_context_timestamp(context, &adreno_dev->ringbuffer);
 
 	if (timestamp_cmp(timestamp, ts_issued) <= 0)
 		return 0;
@@ -3598,7 +3871,8 @@
 				unsigned int msecs)
 {
 	static unsigned int io_cnt;
-	struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
+	struct adreno_context *adreno_ctx = context ? ADRENO_CONTEXT(context) :
+		NULL;
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	unsigned int context_id = _get_context_id(context);
 	unsigned int time_elapsed = 0;
@@ -3606,8 +3880,6 @@
 	int ts_compare = 1;
 	int io, ret = -ETIMEDOUT;
 
-	/* Get out early if the context has already been destroyed */
-
 	if (context_id == KGSL_CONTEXT_INVALID) {
 		KGSL_DRV_WARN(device, "context was detached");
 		return -EINVAL;
@@ -3745,9 +4017,9 @@
 	switch (type) {
 	case KGSL_TIMESTAMP_QUEUED: {
 		struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-		timestamp = rb->timestamp[context_id];
+		timestamp = adreno_context_timestamp(context,
+				&adreno_dev->ringbuffer);
 		break;
 	}
 	case KGSL_TIMESTAMP_CONSUMED:
@@ -3919,6 +4191,7 @@
 	/* Optional functions */
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
+	.drawctxt_detach = adreno_drawctxt_detach,
 	.drawctxt_destroy = adreno_drawctxt_destroy,
 	.setproperty = adreno_setproperty,
 	.postmortem_dump = adreno_dump,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index b53d16f..cb75b34 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -25,6 +25,9 @@
 #define ADRENO_DEVICE(device) \
 		KGSL_CONTAINER_OF(device, struct adreno_device, dev)
 
+#define ADRENO_CONTEXT(device) \
+		KGSL_CONTAINER_OF(device, struct adreno_context, base)
+
 #define ADRENO_CHIPID_CORE(_id) (((_id) >> 24) & 0xFF)
 #define ADRENO_CHIPID_MAJOR(_id) (((_id) >> 16) & 0xFF)
 #define ADRENO_CHIPID_MINOR(_id) (((_id) >> 8) & 0xFF)
@@ -337,10 +340,10 @@
 #define  KGSL_FT_DEFAULT_POLICY           (KGSL_FT_REPLAY + KGSL_FT_SKIPIB)
 
 /* Pagefault policy flags */
-#define KGSL_FT_PAGEFAULT_INT_ENABLE         0x00000001
-#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE     0x00000002
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE   0x00000004
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT    0x00000008
+#define KGSL_FT_PAGEFAULT_INT_ENABLE         BIT(0)
+#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE     BIT(1)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE   BIT(2)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT    BIT(3)
 #define KGSL_FT_PAGEFAULT_DEFAULT_POLICY     (KGSL_FT_PAGEFAULT_INT_ENABLE + \
 					KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
 
@@ -407,6 +410,9 @@
 unsigned int adreno_ft_detect(struct kgsl_device *device,
 						unsigned int *prev_reg_val);
 
+int adreno_ft_init_sysfs(struct kgsl_device *device);
+void adreno_ft_uninit_sysfs(struct kgsl_device *device);
+
 int adreno_perfcounter_get(struct adreno_device *adreno_dev,
 	unsigned int groupid, unsigned int countable, unsigned int *offset,
 	unsigned int flags);
@@ -501,6 +507,26 @@
 }
 
 /**
+ * adreno_context_timestamp() - Return the last queued timestamp for the context
+ * @k_ctxt: Pointer to the KGSL context to query
+ * @rb: Pointer to the ringbuffer structure for the GPU
+ *
+ * Return the last queued context for the given context. This is used to verify
+ * that incoming requests are not using an invalid (unsubmitted) timestamp
+ */
+static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt,
+		struct adreno_ringbuffer *rb)
+{
+	if (k_ctxt) {
+		struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+
+		if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+			return a_ctxt->timestamp;
+	}
+	return rb->global_ts;
+}
+
+/**
  * adreno_encode_istore_size - encode istore size in CP format
  * @adreno_dev - The 3D device.
  *
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 42137fe..3d72c5c 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1355,7 +1355,7 @@
 	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
-		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+		drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
 
 	if (result)
 		return result;
@@ -1364,7 +1364,7 @@
 	drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
 
 	/* blank out gmem shadow. */
-	kgsl_sharedmem_set(drawctxt->dev_priv->device,
+	kgsl_sharedmem_set(drawctxt->base.device,
 			&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
 			drawctxt->context_gmem_shadow.size);
 
@@ -1389,7 +1389,7 @@
 	kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
 			    KGSL_CACHE_OP_FLUSH);
 
-	kgsl_cffdump_syncmem(drawctxt->dev_priv,
+	kgsl_cffdump_syncmem(drawctxt->base.device,
 			&drawctxt->context_gmem_shadow.gmemshadow,
 			drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
 			drawctxt->context_gmem_shadow.gmemshadow.size, false);
@@ -1410,13 +1410,13 @@
 	 */
 
 	ret = kgsl_allocate(&drawctxt->gpustate,
-		drawctxt->pagetable, _context_size(adreno_dev));
+		drawctxt->base.pagetable, _context_size(adreno_dev));
 
 	if (ret)
 		return ret;
 
-	kgsl_sharedmem_set(drawctxt->dev_priv->device, &drawctxt->gpustate, 0,
-		0, _context_size(adreno_dev));
+	kgsl_sharedmem_set(drawctxt->base.device, &drawctxt->gpustate,
+		0, 0, _context_size(adreno_dev));
 
 	tmp_ctx.cmd = tmp_ctx.start
 	    = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
@@ -1440,8 +1440,8 @@
 	kgsl_cache_range_op(&drawctxt->gpustate,
 			    KGSL_CACHE_OP_FLUSH);
 
-	kgsl_cffdump_syncmem(drawctxt->dev_priv, &drawctxt->gpustate,
-			drawctxt->gpustate.gpuaddr,
+	kgsl_cffdump_syncmem(drawctxt->base.device,
+			&drawctxt->gpustate, drawctxt->gpustate.gpuaddr,
 			drawctxt->gpustate.size, false);
 
 done:
@@ -1516,7 +1516,7 @@
 			"Current active context has caused gpu hang\n");
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->reg_save[1],
 			context->reg_save[2] << 2, true);
 		/* save registers and constants. */
@@ -1525,7 +1525,7 @@
 			context->reg_save, 3);
 
 		if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_save[1],
 				context->shader_save[2] << 2, true);
@@ -1534,7 +1534,7 @@
 				KGSL_CMD_FLAGS_PMODE,
 				context->shader_save, 3);
 
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_fixup[1],
 				context->shader_fixup[2] << 2, true);
@@ -1552,7 +1552,7 @@
 
 	if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
 	    (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->context_gmem_shadow.gmem_save[1],
 			context->context_gmem_shadow.gmem_save[2] << 2, true);
 		/* save gmem.
@@ -1562,7 +1562,7 @@
 			KGSL_CMD_FLAGS_PMODE,
 			context->context_gmem_shadow.gmem_save, 3);
 
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->chicken_restore[1],
 			context->chicken_restore[2] << 2, true);
 
@@ -1586,9 +1586,18 @@
 	unsigned int cmds[5];
 
 	if (context == NULL) {
-		/* No context - set the default apgetable and thats it */
+		/* No context - set the default pagetable and thats it */
+		unsigned int id;
+		/*
+		 * If there isn't a current context, the kgsl_mmu_setstate
+		 * will use the CPU path so we don't need to give
+		 * it a valid context id.
+		 */
+		id = (adreno_dev->drawctxt_active != NULL)
+			? adreno_dev->drawctxt_active->base.id
+			: KGSL_CONTEXT_INVALID;
 		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
-				adreno_dev->drawctxt_active->id);
+				  id);
 		return;
 	}
 
@@ -1597,16 +1606,17 @@
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
 	cmds[3] = device->memstore.gpuaddr +
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
-	cmds[4] = context->id;
+	cmds[4] = context->base.id;
 	adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
 					cmds, 5);
-	kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+	kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+			context->base.id);
 
 	/* restore gmem.
 	 *  (note: changes shader. shader must not already be restored.)
 	 */
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->context_gmem_shadow.gmem_restore[1],
 			context->context_gmem_shadow.gmem_restore[2] << 2,
 			true);
@@ -1616,7 +1626,7 @@
 			context->context_gmem_shadow.gmem_restore, 3);
 
 		if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->chicken_restore[1],
 				context->chicken_restore[2] << 2, true);
@@ -1631,7 +1641,7 @@
 	}
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->reg_restore[1],
 			context->reg_restore[2] << 2, true);
 
@@ -1641,7 +1651,7 @@
 
 		/* restore shader instructions & partitioning. */
 		if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_restore[1],
 				context->shader_restore[2] << 2, true);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 7e5638c..670f0cf 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2321,7 +2321,7 @@
 	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
-		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+		drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
 
 	if (result)
 		return result;
@@ -2355,7 +2355,7 @@
 	 */
 
 	ret = kgsl_allocate(&drawctxt->gpustate,
-		drawctxt->pagetable, CONTEXT_SIZE);
+		drawctxt->base.pagetable, CONTEXT_SIZE);
 
 	if (ret)
 		return ret;
@@ -2420,7 +2420,7 @@
 		 * already be saved.)
 		 */
 
-		kgsl_cffdump_syncmem(context->dev_priv,
+		kgsl_cffdump_syncmem(context->base.device,
 			&context->gpustate,
 			context->context_gmem_shadow.gmem_save[1],
 			context->context_gmem_shadow.gmem_save[2] << 2, true);
@@ -2441,8 +2441,17 @@
 
 	if (context == NULL) {
 		/* No context - set the default pagetable and thats it */
+		unsigned int id;
+		/*
+		 * If there isn't a current context, the kgsl_mmu_setstate
+		 * will use the CPU path so we don't need to give
+		 * it a valid context id.
+		 */
+		id = (adreno_dev->drawctxt_active != NULL)
+			? adreno_dev->drawctxt_active->base.id
+			: KGSL_CONTEXT_INVALID;
 		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
-				adreno_dev->drawctxt_active->id);
+				  id);
 		return;
 	}
 
@@ -2451,10 +2460,11 @@
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
 	cmds[3] = device->memstore.gpuaddr +
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
-	cmds[4] = context->id;
+	cmds[4] = context->base.id;
 	adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
 					cmds, 5);
-	kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+	kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+			context->base.id);
 
 	/*
 	 * Restore GMEM.  (note: changes shader.
@@ -2462,7 +2472,7 @@
 	 */
 
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
-		kgsl_cffdump_syncmem(context->dev_priv,
+		kgsl_cffdump_syncmem(context->base.device,
 			&context->gpustate,
 			context->context_gmem_shadow.gmem_restore[1],
 			context->context_gmem_shadow.gmem_restore[2] << 2,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 90bd017..fc98d86 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -56,41 +56,6 @@
 		&adreno_dev->wait_timeout);
 	debugfs_create_u32("ib_check", 0644, device->d_debugfs,
 			   &adreno_dev->ib_check_level);
-	/* By Default enable fast hang detection */
-	adreno_dev->fast_hang_detect = 1;
-	debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
-			   &adreno_dev->fast_hang_detect);
-	/*
-	 * FT policy can be set to any of the options below.
-	 * KGSL_FT_OFF -> BIT(0) Set to turn off FT
-	 * KGSL_FT_REPLAY  -> BIT(1) Set to enable replay
-	 * KGSL_FT_SKIPIB  -> BIT(2) Set to skip IB
-	 * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
-	 * KGSL_FT_DISABLE -> BIT(4) Set to disable FT for faulting context
-	 * by default set FT policy to KGSL_FT_DEFAULT_POLICY
-	 */
-	adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
-	debugfs_create_u32("ft_policy", 0644, device->d_debugfs,
-			   &adreno_dev->ft_policy);
-	/* By default enable long IB detection */
-	adreno_dev->long_ib_detect = 1;
-	debugfs_create_u32("long_ib_detect", 0644, device->d_debugfs,
-			   &adreno_dev->long_ib_detect);
-
-	/*
-	 * FT pagefault policy can be set to any of the options below.
-	 * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
-	 * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE  -> BIT(1) Set to enable GPU HALT on
-	 * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
-	 * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE  -> BIT(2) Set to log only one
-	 * pagefault per page.
-	 * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
-	 * pagefault per INT.
-	 */
-	 adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
-	 debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
-			&adreno_dev->ft_pf_policy);
-
 	debugfs_create_file("active_cnt", 0444, device->d_debugfs, device,
 			    &_active_count_fops);
 }
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b32cdae..bf173a7 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -134,34 +134,32 @@
 
 /**
  * adreno_drawctxt_create - create a new adreno draw context
- * @device - KGSL device to create the context on
- * @pagetable - Pagetable for the context
- * @context- Generic KGSL context structure
- * @flags - flags for the context (passed from user space)
+ * @dev_priv: the owner of the context
+ * @flags: flags for the context (passed from user space)
  *
- * Create a new draw context for the 3D core.  Return 0 on success,
- * or error code on failure.
+ * Create and return a new draw context for the 3D core.
  */
-int adreno_drawctxt_create(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable,
-			struct kgsl_context *context, uint32_t *flags)
+struct kgsl_context *
+adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
+			uint32_t *flags)
 {
 	struct adreno_context *drawctxt;
+	struct kgsl_device *device = dev_priv->device;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int ret;
 
 	drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
-
 	if (drawctxt == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	drawctxt->pid = task_pid_nr(current);
-	strlcpy(drawctxt->pid_name, current->comm, TASK_COMM_LEN);
-	drawctxt->pagetable = pagetable;
+	ret = kgsl_context_init(dev_priv, &drawctxt->base);
+	if (ret != 0) {
+		kfree(drawctxt);
+		return ERR_PTR(ret);
+	}
+
 	drawctxt->bin_base_offset = 0;
-	drawctxt->id = context->id;
-	rb->timestamp[context->id] = 0;
+	drawctxt->timestamp = 0;
 
 	*flags &= (KGSL_CONTEXT_PREAMBLE |
 		KGSL_CONTEXT_NO_GMEM_ALLOC |
@@ -192,50 +190,47 @@
 
 	drawctxt->type =
 		(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
-	drawctxt->dev_priv = context->dev_priv;
 
 	ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
 	if (ret)
 		goto err;
 
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ref_wait_ts),
 			KGSL_INIT_REFTIMESTAMP);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, ts_cmp_enable), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ts_cmp_enable),
+			0);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, soptimestamp), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp),
+			0);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, eoptimestamp), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp),
+			0);
 
-	context->devctxt = drawctxt;
-	return 0;
+	return &drawctxt->base;
 err:
-	kfree(drawctxt);
-	return ret;
+	kgsl_context_put(&drawctxt->base);
+	return ERR_PTR(ret);
 }
 
 /**
- * adreno_drawctxt_destroy - destroy a draw context
- * @device - KGSL device that owns the context
- * @context- Generic KGSL context container for the context
+ * adreno_drawctxt_detach(): detach a context from the GPU
+ * @context: Generic KGSL context container for the context
  *
- * Destroy an existing context.  Return 0 on success or error
- * code on failure.
  */
-
-/* destroy a drawing context */
-
-void adreno_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context)
+void adreno_drawctxt_detach(struct kgsl_context *context)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct kgsl_device *device;
+	struct adreno_device *adreno_dev;
 	struct adreno_context *drawctxt;
 
-	if (context == NULL || context->devctxt == NULL)
+	if (context == NULL)
 		return;
 
-	drawctxt = context->devctxt;
+	device = context->device;
+	adreno_dev = ADRENO_DEVICE(device);
+	drawctxt = ADRENO_CONTEXT(context);
 	/* deactivate context */
 	if (adreno_dev->drawctxt_active == drawctxt) {
 		/* no need to save GMEM or shader, the context is
@@ -256,9 +251,17 @@
 
 	kgsl_sharedmem_free(&drawctxt->gpustate);
 	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
+}
 
+
+void adreno_drawctxt_destroy(struct kgsl_context *context)
+{
+	struct adreno_context *drawctxt;
+	if (context == NULL)
+		return;
+
+	drawctxt = ADRENO_CONTEXT(context);
 	kfree(drawctxt);
-	context->devctxt = NULL;
 }
 
 /**
@@ -274,10 +277,12 @@
 				      struct kgsl_context *context,
 				      unsigned int offset)
 {
-	struct adreno_context *drawctxt = context->devctxt;
+	struct adreno_context *drawctxt;
 
-	if (drawctxt)
-		drawctxt->bin_base_offset = offset;
+	if (context == NULL)
+		return;
+	drawctxt = ADRENO_CONTEXT(context);
+	drawctxt->bin_base_offset = offset;
 }
 
 /**
@@ -316,12 +321,22 @@
 
 	KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
 		adreno_dev->drawctxt_active ?
-		adreno_dev->drawctxt_active->id : 0,
-		drawctxt ? drawctxt->id : 0, flags);
+		adreno_dev->drawctxt_active->base.id : 0,
+		drawctxt ? drawctxt->base.id : 0, flags);
 
 	/* Save the old context */
 	adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
 
+	/* Put the old instance of the active drawctxt */
+	if (adreno_dev->drawctxt_active) {
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+		adreno_dev->drawctxt_active = NULL;
+	}
+
+	/* Get a refcount to the new instance */
+	if (drawctxt)
+		_kgsl_context_get(&drawctxt->base);
+
 	/* Set the new context */
 	adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
 	adreno_dev->drawctxt_active = drawctxt;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 2b8e600..88d1b8c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -13,8 +13,6 @@
 #ifndef __ADRENO_DRAWCTXT_H
 #define __ADRENO_DRAWCTXT_H
 
-#include <linux/sched.h>
-
 #include "adreno_pm4types.h"
 #include "a2xx_reg.h"
 
@@ -96,15 +94,11 @@
 };
 
 struct adreno_context {
-	pid_t pid;
-	char pid_name[TASK_COMM_LEN];
-	unsigned int id;
+	struct kgsl_context base;
 	unsigned int ib_gpu_time_used;
+	unsigned int timestamp;
 	uint32_t flags;
-	uint32_t pagefault;
-	unsigned long pagefault_ts;
 	unsigned int type;
-	struct kgsl_pagetable *pagetable;
 	struct kgsl_memdesc gpustate;
 	unsigned int reg_restore[3];
 	unsigned int shader_save[3];
@@ -131,16 +125,15 @@
 	struct kgsl_memdesc constant_load_commands[3];
 	struct kgsl_memdesc cond_execs[4];
 	struct kgsl_memdesc hlsqcontrol_restore_commands[1];
-	struct kgsl_device_private *dev_priv;
 };
 
-int adreno_drawctxt_create(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable,
-			struct kgsl_context *context,
+
+struct kgsl_context *adreno_drawctxt_create(struct kgsl_device_private *,
 			uint32_t *flags);
 
-void adreno_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context);
+void adreno_drawctxt_detach(struct kgsl_context *context);
+
+void adreno_drawctxt_destroy(struct kgsl_context *context);
 
 void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
 				struct adreno_context *drawctxt,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index f6c05b5..999b782 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -138,7 +138,7 @@
 			if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
 				KGSL_CTXT_WARN(rb->device,
 				"Context %p caused a gpu hang. Will not accept commands for context %d\n",
-				context, context->id);
+				context, context->base.id);
 				return -EDEADLK;
 			}
 			wait_time = jiffies + wait_timeout;
@@ -575,6 +575,8 @@
 	/* overlay structure on memptrs memory */
 	rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;
 
+	rb->global_ts = 0;
+
 	return 0;
 }
 
@@ -594,11 +596,11 @@
 	memset(rb, 0, sizeof(struct adreno_ringbuffer));
 }
 
-static uint32_t
+static int
 adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
 				struct adreno_context *context,
 				unsigned int flags, unsigned int *cmds,
-				int sizedwords, uint32_t timestamp)
+				int sizedwords)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
 	unsigned int *ringcmds;
@@ -607,6 +609,7 @@
 	unsigned int rcmd_gpu;
 	unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
 	unsigned int gpuaddr = rb->device->memstore.gpuaddr;
+	unsigned int timestamp;
 
 	/*
 	 * if the context was not created with per context timestamp
@@ -616,20 +619,7 @@
 	 */
 	if ((context && (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)) &&
 		!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE))
-		context_id = context->id;
-
-	if ((context && (context->flags & CTXT_FLAGS_USER_GENERATED_TS)) &&
-		!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
-		if (timestamp_cmp(rb->timestamp[context_id],
-						timestamp) >= 0) {
-			KGSL_DRV_ERR(rb->device,
-				"Invalid user generated ts <%d:0x%x>, "
-				"less than last issued ts <%d:0x%x>\n",
-				context_id, timestamp, context_id,
-				rb->timestamp[context_id]);
-			return -ERANGE;
-		}
-	}
+		context_id = context->base.id;
 
 	/* reserve space to temporarily turn off protected mode
 	*  error checking if needed
@@ -669,13 +659,8 @@
 		total_sizedwords += 2;
 
 	ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
-	if (!ringcmds) {
-		/*
-		 * We could not allocate space in ringbuffer, just return the
-		 * last timestamp
-		 */
-		return rb->timestamp[context_id];
-	}
+	if (!ringcmds)
+		return -ENOSPC;
 
 	rcmd_gpu = rb->buffer_desc.gpuaddr
 		+ sizeof(uint)*(rb->wptr-total_sizedwords);
@@ -690,26 +675,19 @@
 	}
 
 	/* always increment the global timestamp. once. */
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
+	rb->global_ts++;
 
-	/*
-	 * If global timestamp then we are not using per context ts for
-	 * this submission
-	 */
-	if (context_id != KGSL_MEMSTORE_GLOBAL) {
-		if (context->flags & CTXT_FLAGS_USER_GENERATED_TS)
-			rb->timestamp[context_id] = timestamp;
-		else
-			rb->timestamp[context_id]++;
-	}
-	timestamp = rb->timestamp[context_id];
+	if (KGSL_MEMSTORE_GLOBAL != context_id)
+		timestamp = context->timestamp;
+	else
+		timestamp = rb->global_ts;
 
 	/* scratchpad ts for fault tolerance */
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
 		cp_type0_packet(adreno_getreg(adreno_dev,
 			ADRENO_REG_CP_TIMESTAMP), 1));
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			rb->global_ts);
 
 	/* start-of-pipeline timestamp */
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
@@ -781,7 +759,7 @@
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 				eoptimestamp)));
 		GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			rb->global_ts);
 	}
 
 	if (adreno_is_a20x(adreno_dev)) {
@@ -857,7 +835,7 @@
 
 	adreno_ringbuffer_submit(rb);
 
-	return timestamp;
+	return 0;
 }
 
 unsigned int
@@ -877,7 +855,7 @@
 	flags |= KGSL_CMD_FLAGS_INTERNAL_ISSUE;
 
 	return adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds,
-							sizedwords, 0);
+							sizedwords);
 }
 
 static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
@@ -1097,12 +1075,9 @@
 		ret = -EINVAL;
 		goto done;
 	}
-	drawctxt = context->devctxt;
+	drawctxt = ADRENO_CONTEXT(context);
 
 	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
-		KGSL_CTXT_ERR(device, "proc %s failed fault tolerance"
-			" will not accept commands for context %d\n",
-			drawctxt->pid_name, drawctxt->id);
 		ret = -EDEADLK;
 		goto done;
 	}
@@ -1116,10 +1091,6 @@
 		start_index = 1;
 
 	if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) {
-		KGSL_CTXT_ERR(device,
-			"proc %s triggered fault tolerance"
-			" skipping commands for context till EOF %d\n",
-			drawctxt->pid_name, drawctxt->id);
 		if (flags & KGSL_CMD_FLAGS_EOF)
 			drawctxt->flags &= ~CTXT_FLAGS_SKIP_EOF;
 		if (start_index)
@@ -1172,10 +1143,30 @@
 
 	adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
 
-	*timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
+	if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
+		if (timestamp_cmp(drawctxt->timestamp, *timestamp) >= 0) {
+			KGSL_DRV_ERR(device,
+				"Invalid user generated ts <%d:0x%x>, "
+				"less than last issued ts <%d:0x%x>\n",
+				context->id, *timestamp, context->id,
+				drawctxt->timestamp);
+			return -ERANGE;
+		}
+		drawctxt->timestamp = *timestamp;
+	} else
+		drawctxt->timestamp++;
+
+	ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
 					drawctxt,
 					(flags & KGSL_CMD_FLAGS_EOF),
-					&link[0], (cmds - link), *timestamp);
+					&link[0], (cmds - link));
+	if (ret)
+		goto done;
+
+	if (drawctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+		*timestamp = drawctxt->timestamp;
+	else
+		*timestamp = adreno_dev->ringbuffer.global_ts;
 
 #ifdef CONFIG_MSM_KGSL_CFF_DUMP
 	/*
@@ -1282,7 +1273,7 @@
 	k_ctxt = kgsl_context_get(device, ft_data->context_id);
 
 	if (k_ctxt) {
-		a_ctxt = k_ctxt->devctxt;
+		a_ctxt = ADRENO_CONTEXT(k_ctxt);
 		if (a_ctxt->flags & CTXT_FLAGS_PREAMBLE)
 			_turn_preamble_on_for_ib_seq(rb, rb_rptr);
 		kgsl_context_put(k_ctxt);
@@ -1319,7 +1310,7 @@
 			k_ctxt = kgsl_context_get(rb->device, val2);
 
 			if (k_ctxt) {
-				a_ctxt = k_ctxt->devctxt;
+				a_ctxt = ADRENO_CONTEXT(k_ctxt);
 
 			/* If we are changing to a good context and were not
 			 * copying commands then copy over commands to the good
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e9fb050..9634e32 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -55,7 +55,7 @@
 
 	unsigned int wptr; /* write pointer offset in dwords from baseaddr */
 
-	unsigned int timestamp[KGSL_MEMSTORE_MAX];
+	unsigned int global_ts;
 };
 
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4c1ef54..966e035 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -448,20 +448,24 @@
 	entry->priv = NULL;
 }
 
-/* Allocate a new context id */
-
-static struct kgsl_context *
-kgsl_create_context(struct kgsl_device_private *dev_priv)
+/**
+ * kgsl_context_init() - helper to initialize kgsl_context members
+ * @dev_priv: the owner of the context
+ * @context: the newly created context struct, should be allocated by
+ * the device specific drawctxt_create function.
+ *
+ * This is a helper function for the device specific drawctxt_create
+ * function to initialize the common members of its context struct.
+ * If this function succeeds, reference counting is active in the context
+ * struct and the caller should kgsl_context_put() it on error.
+ * If it fails, the caller should just free the context structure
+ * it passed in.
+ */
+int kgsl_context_init(struct kgsl_device_private *dev_priv,
+			struct kgsl_context *context)
 {
+	int ret = 0, id;
 	struct kgsl_device *device = dev_priv->device;
-	struct kgsl_context *context;
-	int ret, id = 0;
-
-	context = kzalloc(sizeof(*context), GFP_KERNEL);
-
-	if (context == NULL)
-		return ERR_PTR(-ENOMEM);
-
 
 	while (1) {
 		if (idr_pre_get(&device->context_idr, GFP_KERNEL) == 0) {
@@ -480,30 +484,26 @@
 	}
 
 	if (ret)
-		goto func_end;
+		goto fail;
 
 	/* MAX - 1, there is one memdesc in memstore for device info */
 	if (id >= KGSL_MEMSTORE_MAX) {
 		KGSL_DRV_INFO(device, "cannot have more than %d "
 				"ctxts due to memstore limitation\n",
 				KGSL_MEMSTORE_MAX);
-		write_lock(&device->context_lock);
-		idr_remove(&device->context_idr, id);
-		write_unlock(&device->context_lock);
 		ret = -ENOSPC;
-		goto func_end;
+		goto fail_free_id;
 	}
 
 	kref_init(&context->refcount);
-	context->dev_priv = dev_priv;
+	context->device = dev_priv->device;
+	context->pagetable = dev_priv->process_priv->pagetable;
+
+	context->pid = dev_priv->process_priv->pid;
 
 	ret = kgsl_sync_timeline_create(context);
-	if (ret) {
-		write_lock(&device->context_lock);
-		idr_remove(&dev_priv->device->context_idr, id);
-		write_unlock(&device->context_lock);
-		goto func_end;
-	}
+	if (ret)
+		goto fail_free_id;
 
 	/* Initialize the pending event list */
 	INIT_LIST_HEAD(&context->events);
@@ -518,15 +518,15 @@
 	 */
 
 	INIT_LIST_HEAD(&context->events_list);
-
-func_end:
-	if (ret) {
-		kfree(context);
-		return ERR_PTR(ret);
-	}
-
-	return context;
+	return 0;
+fail_free_id:
+	write_lock(&device->context_lock);
+	idr_remove(&dev_priv->device->context_idr, id);
+	write_unlock(&device->context_lock);
+fail:
+	return ret;
 }
+EXPORT_SYMBOL(kgsl_context_init);
 
 /**
  * kgsl_context_detach - Release the "master" context reference
@@ -536,37 +536,36 @@
  * has requested for it to be destroyed. The context itself may
  * exist a bit longer until its reference count goes to zero.
  * Other code referencing the context can detect that it has been
- * detached because the context id will be set to KGSL_CONTEXT_INVALID.
+ * detached by checking the KGSL_CONTEXT_DETACHED bit in
+ * context->priv.
  */
 void
 kgsl_context_detach(struct kgsl_context *context)
 {
-	int id;
 	struct kgsl_device *device;
 	if (context == NULL)
 		return;
-	device = context->dev_priv->device;
-	trace_kgsl_context_detach(device, context);
-	id = context->id;
 
-	if (device->ftbl->drawctxt_destroy)
-		device->ftbl->drawctxt_destroy(device, context);
-	/*device specific drawctxt_destroy MUST clean up devctxt */
-	BUG_ON(context->devctxt);
+	device = context->device;
+
+	/*
+	 * Mark the context as detached to keep others from using
+	 * the context before it gets fully removed, and to make sure
+	 * we don't try to detach twice.
+	 */
+	if (test_and_set_bit(KGSL_CONTEXT_DETACHED, &context->priv))
+		return;
+
+	trace_kgsl_context_detach(device, context);
+
+	device->ftbl->drawctxt_detach(context);
 	/*
 	 * Cancel events after the device-specific context is
-	 * destroyed, to avoid possibly freeing memory while
+	 * detached, to avoid possibly freeing memory while
 	 * it is still in use by the GPU.
 	 */
 	kgsl_cancel_events_ctxt(device, context);
 
-	write_lock(&device->context_lock);
-	context->id = KGSL_CONTEXT_INVALID;
-	idr_remove(&device->context_idr, id);
-	write_unlock(&device->context_lock);
-
-	context->dev_priv = NULL;
-
 	kgsl_context_put(context);
 }
 
@@ -575,8 +574,19 @@
 {
 	struct kgsl_context *context = container_of(kref, struct kgsl_context,
 						    refcount);
+	struct kgsl_device *device = context->device;
+
+	trace_kgsl_context_destroy(device, context);
+
+	write_lock(&device->context_lock);
+	if (context->id != KGSL_CONTEXT_INVALID) {
+		idr_remove(&device->context_idr, context->id);
+		context->id = KGSL_CONTEXT_INVALID;
+	}
+	write_unlock(&device->context_lock);
 	kgsl_sync_timeline_destroy(context);
-	kfree(context);
+
+	device->ftbl->drawctxt_destroy(context);
 }
 
 struct kgsl_device *kgsl_get_device(int dev_idx)
@@ -975,7 +985,7 @@
 		if (context == NULL)
 			break;
 
-		if (context->dev_priv == dev_priv)
+		if (context->pid == private->pid)
 			kgsl_context_detach(context);
 
 		next = next + 1;
@@ -1623,27 +1633,16 @@
 	int result = 0;
 	struct kgsl_drawctxt_create *param = data;
 	struct kgsl_context *context = NULL;
+	struct kgsl_device *device = dev_priv->device;
 
-	context = kgsl_create_context(dev_priv);
-
+	context = device->ftbl->drawctxt_create(dev_priv, &param->flags);
 	if (IS_ERR(context)) {
 		result = PTR_ERR(context);
 		goto done;
 	}
-
-	if (dev_priv->device->ftbl->drawctxt_create) {
-		result = dev_priv->device->ftbl->drawctxt_create(
-			dev_priv->device, dev_priv->process_priv->pagetable,
-			context, &param->flags);
-		if (result)
-			goto done;
-	}
 	trace_kgsl_context_create(dev_priv->device, context, param->flags);
 	param->drawctxt_id = context->id;
 done:
-	if (result && !IS_ERR(context))
-		kgsl_context_detach(context);
-
 	return result;
 }
 
@@ -2600,7 +2599,7 @@
 	if (!entry)
 		return -EINVAL;
 
-	kgsl_cffdump_syncmem(dev_priv, &entry->memdesc, param->gpuaddr,
+	kgsl_cffdump_syncmem(dev_priv->device, &entry->memdesc, param->gpuaddr,
 			     param->len, true);
 
 	kgsl_mem_entry_put(entry);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index b07a1cad..43bcc30 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -410,29 +410,19 @@
 	cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5);
 }
 
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
-	struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
-	bool clean_cache)
+void kgsl_cffdump_syncmem(struct kgsl_device *device,
+			  struct kgsl_memdesc *memdesc, uint gpuaddr,
+			  uint sizebytes, bool clean_cache)
 {
-	struct kgsl_device *device = dev_priv->device;
 	const void *src;
 
 	if (!device->cff_dump_enable)
 		return;
 
+	BUG_ON(memdesc == NULL);
+
 	total_syncmem += sizebytes;
 
-	if (memdesc == NULL) {
-		struct kgsl_mem_entry *entry;
-		entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
-			gpuaddr, sizebytes);
-		if (entry == NULL) {
-			KGSL_CORE_ERR("did not find mapping "
-				"for gpuaddr: 0x%08x\n", gpuaddr);
-			return;
-		}
-		memdesc = &entry->memdesc;
-	}
 	src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
 	if (memdesc->hostptr == NULL) {
 		KGSL_CORE_ERR(
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index ab5a345..2852e0f 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -28,7 +28,7 @@
 void kgsl_cffdump_destroy(void);
 void kgsl_cffdump_open(struct kgsl_device *device);
 void kgsl_cffdump_close(struct kgsl_device *device);
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+void kgsl_cffdump_syncmem(struct kgsl_device *,
 	struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
 	bool clean_cache);
 void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr,
@@ -74,7 +74,7 @@
 	return;
 }
 
-static inline void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+static inline void kgsl_cffdump_syncmem(struct kgsl_device *device,
 		struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
 		bool clean_cache)
 {
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index d0e40db..1f8bcbe 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -15,6 +15,7 @@
 
 #include <linux/idr.h>
 #include <linux/pm_qos.h>
+#include <linux/sched.h>
 
 #include "kgsl.h"
 #include "kgsl_mmu.h"
@@ -103,11 +104,10 @@
 	   calling the hook */
 	void (*setstate) (struct kgsl_device *device, unsigned int context_id,
 			uint32_t flags);
-	int (*drawctxt_create) (struct kgsl_device *device,
-		struct kgsl_pagetable *pagetable, struct kgsl_context *context,
-		uint32_t *flags);
-	void (*drawctxt_destroy) (struct kgsl_device *device,
-		struct kgsl_context *context);
+	struct kgsl_context *(*drawctxt_create) (struct kgsl_device_private *,
+						uint32_t *flags);
+	void (*drawctxt_detach) (struct kgsl_context *context);
+	void (*drawctxt_destroy) (struct kgsl_context *context);
 	long (*ioctl) (struct kgsl_device_private *dev_priv,
 		unsigned int cmd, void *data);
 	int (*setproperty) (struct kgsl_device *device,
@@ -254,31 +254,44 @@
 	.ver_minor = DRIVER_VERSION_MINOR
 
 
+/* bits for struct kgsl_context.priv */
+/* the context has been destroyed by userspace and is no longer using the gpu */
+#define KGSL_CONTEXT_DETACHED 0
+/* the context has caused a pagefault */
+#define KGSL_CONTEXT_PAGEFAULT 1
+
 /**
  * struct kgsl_context - Master structure for a KGSL context object
- * @refcount - kref object for reference counting the context
- * @id - integer identifier for the context
- * @dev_priv - pointer to the owning device instance
- * @devctxt - pointer to the device specific context information
- * @reset_status - status indication whether a gpu reset occured and whether
+ * @refcount: kref object for reference counting the context
+ * @id: integer identifier for the context
+ * @priv: in-kernel context flags, use KGSL_CONTEXT_* values
+ * @dev_priv: pointer to the owning device instance
+ * @reset_status: status indication whether a gpu reset occured and whether
  * this context was responsible for causing it
- * @wait_on_invalid_ts - flag indicating if this context has tried to wait on a
+ * @wait_on_invalid_ts: flag indicating if this context has tried to wait on a
  * bad timestamp
- * @timeline - sync timeline used to create fences that can be signaled when a
+ * @timeline: sync timeline used to create fences that can be signaled when a
  * sync_pt timestamp expires
- * @events - list head of pending events for this context
- * @events_list - list node for the list of all contexts that have pending events
+ * @events: list head of pending events for this context
+ * @events_list: list node for the list of all contexts that have pending events
+ * @pid: process that owns this context.
+ * @pagefault: flag set if this context caused a pagefault.
+ * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
+ * is set.
  */
 struct kgsl_context {
 	struct kref refcount;
 	uint32_t id;
-	struct kgsl_device_private *dev_priv;
-	void *devctxt;
+	pid_t pid;
+	unsigned long priv;
+	struct kgsl_device *device;
+	struct kgsl_pagetable *pagetable;
 	unsigned int reset_status;
 	bool wait_on_invalid_ts;
 	struct sync_timeline *timeline;
 	struct list_head events;
 	struct list_head events_list;
+	unsigned int pagefault_ts;
 };
 
 struct kgsl_process_private {
@@ -429,6 +442,9 @@
 
 void kgsl_context_destroy(struct kref *kref);
 
+int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context
+		*context);
+
 /**
  * kgsl_context_put() - Release context reference count
  * @context: Pointer to the KGSL context to be released
@@ -442,6 +458,22 @@
 	if (context)
 		kref_put(&context->refcount, kgsl_context_destroy);
 }
+
+/**
+ * kgsl_context_detached() - check if a context is detached
+ * @context: the context
+ *
+ * Check if a context has been destroyed by userspace and is only waiting
+ * for reference counts to go away. This check is used to weed out
+ * contexts that shouldn't use the gpu so NULL is considered detached.
+ */
+static inline bool kgsl_context_detached(struct kgsl_context *context)
+{
+	return (context == NULL || test_bit(KGSL_CONTEXT_DETACHED,
+						&context->priv));
+}
+
+
 /**
  * kgsl_context_get() - get a pointer to a KGSL context
  * @device: Pointer to the KGSL device that owns the context
@@ -462,7 +494,10 @@
 
 	context = idr_find(&device->context_idr, id);
 
-	if (context)
+	/* Don't return a context that has been detached */
+	if (kgsl_context_detached(context))
+		context = NULL;
+	else
 		kref_get(&context->refcount);
 
 	read_unlock(&device->context_lock);
@@ -471,6 +506,20 @@
 }
 
 /**
+* _kgsl_context_get() - lightweight function to just increment the ref count
+* @context: Pointer to the KGSL context
+*
+* Get a reference to the specified KGSL context structure. This is a
+* lightweight way to just increase the refcount on a known context rather than
+* walking through kgsl_context_get and searching the iterator
+*/
+static inline void _kgsl_context_get(struct kgsl_context *context)
+{
+	if (context)
+		kref_get(&context->refcount);
+}
+
+/**
  * kgsl_context_get_owner() - get a pointer to a KGSL context in a specific
  * process
  * @dev_priv: Pointer to the process struct
@@ -489,8 +538,8 @@
 
 	context = kgsl_context_get(dev_priv->device, id);
 
-	/* Verify that the context belongs to the dev_priv instance */
-	if (context && context->dev_priv != dev_priv) {
+	/* Verify that the context belongs to current calling process. */
+	if (context != NULL && context->pid != dev_priv->process_priv->pid) {
 		kgsl_context_put(context);
 		return NULL;
 	}
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 0b75175..40974b0 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -147,7 +147,7 @@
 	 * Increment the refcount to avoid freeing the context while
 	 * cancelling its events
 	 */
-	kref_get(&context->refcount);
+	_kgsl_context_get(context);
 
 	/* Remove ourselves from the master pending list */
 	list_del_init(&context->events_list);
@@ -324,7 +324,7 @@
 		 * Increment the refcount to make sure that the list_del_init
 		 * is called with a valid context's list
 		 */
-		kref_get(&context->refcount);
+		_kgsl_context_get(context);
 		/*
 		 * If kgsl_timestamp_expired_context returns 0 then it no longer
 		 * has any pending events and can be removed from the list
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 7af4575..14aae9f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -327,7 +327,7 @@
 	unsigned int no_page_fault_log = 0;
 	unsigned int curr_context_id = 0;
 	unsigned int curr_global_ts = 0;
-	static struct kgsl_context *context;
+	struct kgsl_context *context;
 
 	ret = get_iommu_unit(dev, &mmu, &iommu_unit);
 	if (ret)
@@ -401,23 +401,16 @@
 	context = kgsl_context_get(device, curr_context_id);
 
 	if (context != NULL) {
-		struct adreno_context *drawctxt = context->devctxt;
-
 		kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 			eoptimestamp));
 
-		/*
-		 * Store pagefault's timestamp in adreno context,
-		 * this information will be used in GFT
-		 */
-
-		if (drawctxt != NULL) {
-			drawctxt->pagefault = 1;
-			drawctxt->pagefault_ts = curr_global_ts;
-		}
+		/* save pagefault timestamp for GFT */
+		set_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
+		context->pagefault_ts = curr_global_ts;
 
 		kgsl_context_put(context);
+		context = NULL;
 	}
 
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 5e6d24b..20391be 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1214,6 +1214,11 @@
 	}
 }
 
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device)
+{
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	return (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) != 0);
+}
 
 /**
  * kgsl_pre_hwaccess - Enforce preconditions for touching registers
@@ -1230,7 +1235,7 @@
 	/* In order to touch a register you must hold the device mutex...*/
 	BUG_ON(!mutex_is_locked(&device->mutex));
 	/* and have the clock on! */
-	BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags));
+	BUG_ON(!kgsl_pwrctrl_isenabled(device));
 }
 EXPORT_SYMBOL(kgsl_pre_hwaccess);
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 3bf65ee..b7d9226 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -110,6 +110,8 @@
 void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
 void kgsl_pwrctrl_enable(struct kgsl_device *device);
 void kgsl_pwrctrl_disable(struct kgsl_device *device);
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device);
+
 static inline unsigned long kgsl_get_clkrate(struct clk *clk)
 {
 	return (clk != NULL) ? clk_get_rate(clk) : 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 35f24d9..6094e04 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -109,7 +109,7 @@
 	struct kgsl_device *device;
 
 	if (context)
-		device = context->dev_priv->device;
+		device = context->device;
 	else
 		device = (struct kgsl_device *)data;
 
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 1853996c..62ecdeb 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -239,7 +239,7 @@
 	char ktimeline_name[sizeof(context->timeline->name)] = {};
 	snprintf(ktimeline_name, sizeof(ktimeline_name),
 		"%s_%.15s(%d)-%.15s(%d)-%d",
-		context->dev_priv->device->name,
+		context->device->name,
 		current->group_leader->comm, current->group_leader->pid,
 		current->comm, current->pid, context->id);
 
@@ -250,7 +250,7 @@
 
 	ktimeline = (struct kgsl_sync_timeline *) context->timeline;
 	ktimeline->last_timestamp = 0;
-	ktimeline->device = context->dev_priv->device;
+	ktimeline->device = context->device;
 	ktimeline->context_id = context->id;
 
 	return 0;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index abb7c35..5981163 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -678,6 +678,28 @@
 	)
 );
 
+TRACE_EVENT(kgsl_context_destroy,
+
+	TP_PROTO(struct kgsl_device *device, struct kgsl_context *context),
+
+	TP_ARGS(device, context),
+
+	TP_STRUCT__entry(
+		__string(device_name, device->name)
+		__field(unsigned int, id)
+	),
+
+	TP_fast_assign(
+		__assign_str(device_name, device->name);
+		__entry->id = context->id;
+	),
+
+	TP_printk(
+		"d_name=%s ctx=%u",
+		__get_str(device_name), __entry->id
+	)
+);
+
 TRACE_EVENT(kgsl_mmu_pagefault,
 
 	TP_PROTO(struct kgsl_device *device, unsigned int page,
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cc1819d..883417f 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -859,11 +859,30 @@
 	return status;
 }
 
-static void
-z180_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context)
+struct kgsl_context *
+z180_drawctxt_create(struct kgsl_device_private *dev_priv,
+			uint32_t *flags)
 {
-	struct z180_device *z180_dev = Z180_DEVICE(device);
+	int ret;
+	struct kgsl_context *context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (context == NULL)
+		return ERR_PTR(-ENOMEM);
+	ret = kgsl_context_init(dev_priv, context);
+	if (ret != 0) {
+		kfree(context);
+		return ERR_PTR(ret);
+	}
+	return context;
+}
+
+static void
+z180_drawctxt_detach(struct kgsl_context *context)
+{
+	struct kgsl_device *device;
+	struct z180_device *z180_dev;
+
+	device = context->device;
+	z180_dev = Z180_DEVICE(device);
 
 	z180_idle(device);
 
@@ -875,6 +894,12 @@
 	}
 }
 
+static void
+z180_drawctxt_destroy(struct kgsl_context *context)
+{
+	kfree(context);
+}
+
 static void z180_power_stats(struct kgsl_device *device,
 			    struct kgsl_power_stats *stats)
 {
@@ -941,7 +966,8 @@
 	.gpuid = z180_gpuid,
 	.irq_handler = z180_irq_handler,
 	/* Optional functions */
-	.drawctxt_create = NULL,
+	.drawctxt_create = z180_drawctxt_create,
+	.drawctxt_detach = z180_drawctxt_detach,
 	.drawctxt_destroy = z180_drawctxt_destroy,
 	.ioctl = NULL,
 	.postmortem_dump = z180_dump,
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index a587ed2..a309ceb 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -65,6 +65,8 @@
 #define EPM_ADC_MILLI_VOLTS_SOURCE	4750
 #define EPM_ADC_SCALE_FACTOR		64
 #define GPIO_EPM_GLOBAL_ENABLE		86
+#define GPIO_EPM_MARKER1		85
+#define GPIO_EPM_MARKER2		96
 #define EPM_ADC_CONVERSION_TIME_MIN	50000
 #define EPM_ADC_CONVERSION_TIME_MAX	51000
 /* PSoc Commands */
@@ -715,6 +717,56 @@
 	return 0;
 }
 
+static int epm_set_marker1(struct epm_marker_level *marker_init)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_EPM_MARKER1, "EPM_MARKER1");
+	if (!rc) {
+		gpio_direction_output(GPIO_EPM_MARKER1, 1);
+	} else {
+		pr_err("%s: Configure MARKER1 GPIO Failed\n",
+							__func__);
+		return rc;
+	}
+
+	gpio_set_value(GPIO_EPM_MARKER1, marker_init->level);
+
+	return 0;
+}
+
+static int epm_set_marker2(struct epm_marker_level *marker_init)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_EPM_MARKER2, "EPM_MARKER2");
+	if (!rc) {
+		gpio_direction_output(GPIO_EPM_MARKER2, 1);
+	} else {
+		pr_err("%s: Configure MARKER2 GPIO Failed\n",
+							__func__);
+		return rc;
+	}
+
+	gpio_set_value(GPIO_EPM_MARKER2, marker_init->level);
+
+	return 0;
+}
+
+static int epm_marker1_release(void)
+{
+	gpio_free(GPIO_EPM_MARKER1);
+
+	return 0;
+}
+
+static int epm_marker2_release(void)
+{
+	gpio_free(GPIO_EPM_MARKER2);
+
+	return 0;
+}
+
 static int epm_psoc_init(struct epm_adc_drv *epm_adc,
 					struct epm_psoc_init_resp *init_resp)
 {
@@ -1296,6 +1348,58 @@
 				return -EFAULT;
 			break;
 		}
+	case EPM_MARKER1_REQUEST:
+		{
+			struct epm_marker_level marker_init;
+			uint32_t result;
+
+			if (copy_from_user(&marker_init, (void __user *)arg,
+					sizeof(struct epm_marker_level)))
+				return -EFAULT;
+
+			result = epm_set_marker1(&marker_init);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER2_REQUEST:
+		{
+			struct epm_marker_level marker_init;
+			uint32_t result;
+
+			if (copy_from_user(&marker_init, (void __user *)arg,
+					sizeof(struct epm_marker_level)))
+				return -EFAULT;
+
+			result = epm_set_marker2(&marker_init);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER1_RELEASE:
+		{
+			uint32_t result;
+			result = epm_marker1_release();
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER2_RELEASE:
+		{
+			uint32_t result;
+			result = epm_marker2_release();
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
 	case EPM_PSOC_ADC_INIT:
 		{
 			struct epm_psoc_init_resp psoc_init;
@@ -1312,11 +1416,29 @@
 				return -EINVAL;
 			}
 
+			if (!rc) {
+				rc = epm_adc_psoc_gpio_init(true);
+				if (rc) {
+					pr_err("GPIO init failed\n");
+					return -EINVAL;
+				}
+			}
+
 			if (copy_to_user((void __user *)arg, &psoc_init,
 				sizeof(struct epm_psoc_init_resp)))
 				return -EFAULT;
 			break;
 		}
+	case EPM_PSOC_ADC_DEINIT:
+		{
+			uint32_t result;
+			result = epm_adc_psoc_gpio_init(false);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
 	case EPM_PSOC_ADC_CHANNEL_ENABLE:
 	case EPM_PSOC_ADC_CHANNEL_DISABLE:
 		{
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 8e350f0..4e77ca2 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -923,8 +923,12 @@
 			pr_err("Invalid channel fast average setup\n");
 			return -EINVAL;
 		}
-		calibration_param = of_get_property(child,
-				"qcom,calibration-type", NULL);
+		rc = of_property_read_string(child, "qcom,calibration-type",
+							&calibration_param);
+		if (rc) {
+			pr_err("Invalid calibration type\n");
+			return -EINVAL;
+		}
 		if (!strncmp(calibration_param, "absolute", 8))
 			calib_type = CALIB_ABSOLUTE;
 		else if (!strncmp(calibration_param, "ratiometric", 11))
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 9570327..27818b4 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -530,6 +530,9 @@
 	uint16_t raw_data;
 	uint32_t mode_sel = 0;
 
+	if (!iadc || !iadc->iadc_initialized)
+		return -EPROBE_DEFER;
+
 	mutex_lock(&iadc->adc->adc_lock);
 
 	rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
@@ -541,11 +544,22 @@
 
 	iadc->adc->calib.gain_raw = raw_data;
 
-	rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+	if (iadc->external_rsense) {
+		/* external offset calculation */
+		rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP_CSN,
 						&raw_data, mode_sel);
-	if (rc < 0) {
-		pr_err("qpnp adc result read failed with %d\n", rc);
-		goto fail;
+		if (rc < 0) {
+			pr_err("qpnp adc result read failed with %d\n", rc);
+			goto fail;
+		}
+	} else {
+		/* internal offset calculation */
+		rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+						&raw_data, mode_sel);
+		if (rc < 0) {
+			pr_err("qpnp adc result read failed with %d\n", rc);
+			goto fail;
+		}
 	}
 
 	iadc->adc->calib.offset_raw = raw_data;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 309944e..53e43d1 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -866,6 +866,11 @@
 	amux_prescaling =
 		vadc->adc->adc_channels[dt_index].chan_path_prescaling;
 
+	if (amux_prescaling >= PATH_SCALING_NONE) {
+		rc = -EINVAL;
+		goto fail_unlock;
+	}
+
 	vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
 		qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
 	vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
@@ -1016,6 +1021,11 @@
 	amux_prescaling =
 		vadc->adc->adc_channels[dt_index].chan_path_prescaling;
 
+	if (amux_prescaling >= PATH_SCALING_NONE) {
+		rc = -EINVAL;
+		goto fail;
+	}
+
 	vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
 		qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
 	vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index b96349e..74a252f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1385,7 +1385,8 @@
 	qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"qup_phys_addr");
 	if (!qup_mem) {
-		dev_err(&pdev->dev, "no qup mem resource?\n");
+		dev_err(&pdev->dev,
+			"platform_get_resource_byname(qup_phys_addr) failed\n");
 		ret = -ENODEV;
 		goto get_res_failed;
 	}
@@ -1655,11 +1656,22 @@
 	return ret;
 }
 
+static void qup_i2c_mem_release(struct platform_device *pdev, const char *name)
+{
+	struct resource *res =
+		platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+
+	if (res)
+		release_mem_region(res->start, resource_size(res));
+	else
+		dev_dbg(&pdev->dev,
+			"platform_get_resource_byname(%s) failed\n", name);
+}
+
 static int __devexit
 qup_i2c_remove(struct platform_device *pdev)
 {
-	struct qup_i2c_dev	*dev = platform_get_drvdata(pdev);
-	struct resource		*qup_mem, *gsbi_mem;
+	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
 
 	/* Grab mutex to ensure ongoing transaction is over */
 	mutex_lock(&dev->mlock);
@@ -1693,14 +1705,11 @@
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
-	if (!(dev->pdata->use_gsbi_shared_mode)) {
-		gsbi_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-							"gsbi_qup_i2c_addr");
-		release_mem_region(gsbi_mem->start, resource_size(gsbi_mem));
-	}
-	qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						"qup_phys_addr");
-	release_mem_region(qup_mem->start, resource_size(qup_mem));
+	if (!(dev->pdata->use_gsbi_shared_mode))
+		qup_i2c_mem_release(pdev, "gsbi_qup_i2c_addr");
+
+	qup_i2c_mem_release(pdev, "qup_phys_addr");
+
 	if (dev->dev->of_node)
 		kfree(dev->pdata);
 	kfree(dev);
diff --git a/drivers/input/misc/bmp18x-core.c b/drivers/input/misc/bmp18x-core.c
index bac9059..4b5b710 100644
--- a/drivers/input/misc/bmp18x-core.c
+++ b/drivers/input/misc/bmp18x-core.c
@@ -441,7 +441,7 @@
 		mutex_unlock(&data->lock);
 
 	}
-	return success;
+	return count;
 }
 static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
 				show_enable, set_enable);
@@ -573,7 +573,7 @@
 	int err = 0;
 
 	if (pdata && pdata->init_hw) {
-		err = pdata->init_hw();
+		err = pdata->init_hw(data_bus);
 		if (err) {
 			printk(KERN_ERR "%s: init_hw failed!\n",
 				BMP18X_NAME);
@@ -633,7 +633,7 @@
 	kfree(data);
 exit:
 	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw();
+		pdata->deinit_hw(data_bus);
 	return err;
 }
 EXPORT_SYMBOL(bmp18x_probe);
@@ -655,9 +655,9 @@
 int bmp18x_disable(struct device *dev)
 {
 	struct bmp18x_platform_data *pdata = dev->platform_data;
-
+	struct bmp18x_data *data = dev_get_drvdata(dev);
 	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw();
+		pdata->deinit_hw(&data->data_bus);
 
 	return 0;
 }
@@ -666,9 +666,9 @@
 int bmp18x_enable(struct device *dev)
 {
 	struct bmp18x_platform_data *pdata = dev->platform_data;
-
+	struct bmp18x_data *data = dev_get_drvdata(dev);
 	if (pdata && pdata->init_hw)
-		return pdata->init_hw();
+		return pdata->init_hw(&data->data_bus);
 
 	return 0;
 }
diff --git a/drivers/input/misc/bmp18x-i2c.c b/drivers/input/misc/bmp18x-i2c.c
index 6c01ad3..abbe6e5 100644
--- a/drivers/input/misc/bmp18x-i2c.c
+++ b/drivers/input/misc/bmp18x-i2c.c
@@ -22,8 +22,137 @@
 
 #include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
 #include "bmp18x.h"
 
+struct sensor_regulator {
+	struct regulator *vreg;
+	const char *name;
+	u32	min_uV;
+	u32	max_uV;
+};
+
+struct sensor_regulator bmp_vreg[] = {
+	{NULL, "vdd", 2850000, 2850000},
+	{NULL, "vddio", 1800000, 1800000},
+};
+
+
+static int bmp18x_config_regulator(struct i2c_client *client, bool on)
+{
+	int rc = 0, i;
+	int num_vreg = ARRAY_SIZE(bmp_vreg);
+
+	if (on) {
+		for (i = 0; i < num_vreg; i++) {
+			bmp_vreg[i].vreg = regulator_get(&client->dev,
+					bmp_vreg[i].name);
+			if (IS_ERR(bmp_vreg[i].vreg)) {
+				rc = PTR_ERR(bmp_vreg[i].vreg);
+				dev_err(&client->dev, "%s:regulator get failed rc=%d\n",
+						__func__, rc);
+				bmp_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+			if (regulator_count_voltages(bmp_vreg[i].vreg) > 0) {
+				rc = regulator_set_voltage(bmp_vreg[i].vreg,
+					bmp_vreg[i].min_uV, bmp_vreg[i].max_uV);
+				if (rc) {
+					dev_err(&client->dev, "%s:set_voltage failed rc=%d\n",
+							__func__, rc);
+					regulator_put(bmp_vreg[i].vreg);
+					bmp_vreg[i].vreg = NULL;
+					goto error_vdd;
+				}
+			}
+			rc = regulator_enable(bmp_vreg[i].vreg);
+			if (rc) {
+				dev_err(&client->dev, "%s: regulator_enable failed rc =%d\n",
+						__func__, rc);
+				if (regulator_count_voltages(bmp_vreg[i].vreg)
+						> 0) {
+					regulator_set_voltage(bmp_vreg[i].vreg,
+							0, bmp_vreg[i].max_uV);
+				}
+				regulator_put(bmp_vreg[i].vreg);
+				bmp_vreg[i].vreg = NULL;
+				goto error_vdd;
+			}
+		}
+		return rc;
+	} else {
+		i = num_vreg;
+	}
+error_vdd:
+	while (--i >= 0) {
+		if (!IS_ERR_OR_NULL(bmp_vreg[i].vreg)) {
+			if (regulator_count_voltages(
+				bmp_vreg[i].vreg) > 0) {
+				regulator_set_voltage(bmp_vreg[i].vreg, 0,
+						bmp_vreg[i].max_uV);
+			}
+			regulator_disable(bmp_vreg[i].vreg);
+			regulator_put(bmp_vreg[i].vreg);
+			bmp_vreg[i].vreg = NULL;
+		}
+	}
+	return rc;
+}
+
+static int bmp18x_init_hw(struct bmp18x_data_bus *data_bus)
+{
+	if (data_bus->client)
+		return bmp18x_config_regulator(data_bus->client, 1);
+	return 0;
+}
+
+static void bmp18x_deinit_hw(struct bmp18x_data_bus *data_bus)
+{
+	if (data_bus->client)
+		bmp18x_config_regulator(data_bus->client, 0);
+}
+
+#ifdef CONFIG_OF
+static int bmp18x_parse_dt(struct device *dev,
+			struct bmp18x_platform_data *pdata)
+{
+	int ret = 0;
+	u32 val;
+
+	ret = of_property_read_u32(dev->of_node, "bosch,chip-id", &val);
+	if (ret) {
+		dev_err(dev, "no chip_id from dt\n");
+		return ret;
+	}
+	pdata->chip_id = (u8)val;
+
+	ret = of_property_read_u32(dev->of_node, "bosch,oversample", &val);
+	if (ret) {
+		dev_err(dev, "no default_oversampling from dt\n");
+		return ret;
+	}
+	pdata->default_oversampling = (u8)val;
+
+	ret = of_property_read_u32(dev->of_node, "bosch,period",
+				&pdata->temp_measurement_period);
+	if (ret) {
+		dev_err(dev, "no temp_measurement_period from dt\n");
+		return ret;
+	}
+
+	pdata->default_sw_oversampling = of_property_read_bool(dev->of_node,
+			"bosch,sw-oversample");
+	return 0;
+}
+#else
+static int bmp18x_parse_dt(struct device *dev,
+			struct bmp18x_platform_data *pdata)
+{
+	return -EINVAL;
+}
+#endif
+
 static int bmp18x_i2c_read_block(void *client, u8 reg, int len, char *buf)
 {
 	return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
@@ -52,7 +181,25 @@
 		.bops = &bmp18x_i2c_bus_ops,
 		.client = client
 	};
+	struct bmp18x_platform_data *pdata;
+	int ret;
 
+	if (client->dev.of_node) {
+		pdata = devm_kzalloc(&client->dev,
+			sizeof(struct bmp18x_platform_data), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&client->dev, "Failed to allocate memory\n");
+			return -ENOMEM;
+		}
+		ret =  bmp18x_parse_dt(&client->dev, pdata);
+		if (ret) {
+			dev_err(&client->dev, "Failed to parse device tree\n");
+			return ret;
+		}
+		pdata->init_hw = bmp18x_init_hw;
+		pdata->deinit_hw = bmp18x_deinit_hw;
+		client->dev.platform_data = pdata;
+	}
 	return bmp18x_probe(&client->dev, &data_bus);
 }
 
@@ -89,6 +236,11 @@
 };
 MODULE_DEVICE_TABLE(i2c, bmp18x_id);
 
+static const struct of_device_id bmp18x_of_match[] = {
+	{ .compatible = "bosch,bmp180", },
+	{ },
+};
+
 static struct i2c_driver bmp18x_i2c_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
@@ -96,6 +248,7 @@
 #ifdef CONFIG_PM
 		.pm	= &bmp18x_i2c_pm_ops,
 #endif
+		.of_match_table = bmp18x_of_match,
 	},
 	.id_table	= bmp18x_id,
 	.probe		= bmp18x_i2c_probe,
diff --git a/drivers/input/misc/bmp18x.h b/drivers/input/misc/bmp18x.h
index f9d55ec..d1b1ee7 100644
--- a/drivers/input/misc/bmp18x.h
+++ b/drivers/input/misc/bmp18x.h
@@ -34,14 +34,6 @@
  * @init_hw: Callback for hw specific startup
  * @deinit_hw: Callback for hw specific shutdown
  */
-struct bmp18x_platform_data {
-	u8	chip_id;
-	u8	default_oversampling;
-	u8	default_sw_oversampling;
-	u32	temp_measurement_period;
-	int	(*init_hw)(void);
-	void	(*deinit_hw)(void);
-};
 
 struct bmp18x_bus_ops {
 	int	(*read_block)(void *client, u8 reg, int len, char *buf);
@@ -50,10 +42,19 @@
 };
 
 struct bmp18x_data_bus {
-	const struct bmp18x_bus_ops	*bops;
+	const struct bmp18x_bus_ops *bops;
 	void	*client;
 };
 
+struct bmp18x_platform_data {
+	u8	chip_id;
+	u8	default_oversampling;
+	u8	default_sw_oversampling;
+	u32	temp_measurement_period;
+	int	(*init_hw)(struct bmp18x_data_bus *);
+	void	(*deinit_hw)(struct bmp18x_data_bus *);
+};
+
 int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
 int bmp18x_remove(struct device *dev);
 #ifdef CONFIG_PM
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index dd2e5d8..f879d78 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -756,7 +756,10 @@
 
 	kxtj9_pdata->negate_z = of_property_read_bool(np, "kionix,negate-z");
 
-	kxtj9_pdata->res_12bit = of_property_read_bool(np, "kionix,res-12bit");
+	if (of_property_read_bool(np, "kionix,res-12bit"))
+		kxtj9_pdata->res_ctl = RES_12BIT;
+	else
+		kxtj9_pdata->res_ctl = RES_8BIT;
 
 	return 0;
 }
@@ -834,7 +837,7 @@
 
 	i2c_set_clientdata(client, tj9);
 
-	tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
+	tj9->ctrl_reg1 = tj9->pdata.res_ctl | tj9->pdata.g_range;
 	tj9->last_poll_interval = tj9->pdata.init_interval;
 
 	if (client->irq) {
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index 8a0d4ab..f1ea705 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -2,6 +2,9 @@
  *  mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
  *  Detection Sensor MMA8451/MMA8452/MMA8453
  *
+ *  Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
+ *  Linux Foundation chooses to take subject only to the GPLv2 license
+ *  terms, and distributes only under these terms.
  *  Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -18,23 +21,16 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/pm.h>
-#include <linux/mutex.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/hwmon.h>
+#include <linux/i2c.h>
 #include <linux/input-polldev.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
 
-#define MMA8X5X_I2C_ADDR	0x1D
+#define ACCEL_INPUT_DEV_NAME		"accelerometer"
 #define MMA8451_ID			0x1A
 #define MMA8452_ID			0x2A
 #define MMA8453_ID			0x3A
@@ -151,6 +147,8 @@
 	int position;
 	u8 chip_id;
 	int mode;
+	int int_pin;
+	u32 int_flags;
 };
 /* Addresses scanned */
 static const unsigned short normal_i2c[] = {0x1c, 0x1d, I2C_CLIENT_END};
@@ -391,7 +389,8 @@
 				MMA8X5X_CTRL_REG1, val|0x01);
 		if (!ret) {
 			pdata->active = MMA_ACTIVED;
-			printk(KERN_INFO "mma enable setting active\n");
+			dev_dbg(dev,
+				"%s:mma enable setting active.\n", __func__);
 		}
 	} else if (enable == 0  && pdata->active == MMA_ACTIVED) {
 		val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
@@ -399,7 +398,8 @@
 			MMA8X5X_CTRL_REG1, val & 0xFE);
 		if (!ret) {
 			pdata->active = MMA_STANDBY;
-			printk(KERN_INFO "mma enable setting inactive\n");
+			dev_dbg(dev,
+				"%s:mma enable setting inactive.\n", __func__);
 		}
 	}
 	mutex_unlock(&pdata->data_lock);
@@ -458,11 +458,36 @@
 	chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
 	if (!mma8x5x_check_id(chip_id))
 		return -ENODEV;
-	printk(KERN_INFO "check %s i2c address 0x%x\n",
-		mma8x5x_id2name(chip_id), client->addr);
+	dev_dbg(&client->dev, "%s,check %s i2c address 0x%x.\n",
+		__func__, mma8x5x_id2name(chip_id), client->addr);
 	strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
 	return 0;
 }
+
+static int mma8x5x_parse_dt(struct device *dev, struct mma8x5x_data *data)
+{
+	int rc;
+	struct device_node *np = dev->of_node;
+	u32 temp_val;
+
+	data->int_pin = of_get_named_gpio_flags(np, "fsl,irq-gpio",
+				0, &data->int_flags);
+	if (data->int_pin < 0) {
+		dev_err(dev, "Unable to read irq-gpio\n");
+		return data->int_pin;
+	}
+
+	rc = of_property_read_u32(np, "fsl,sensors-position", &temp_val);
+	if (!rc)
+		data->position = temp_val;
+	else {
+		dev_err(dev, "Unable to read sensors-position\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int __devinit mma8x5x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
@@ -500,11 +525,22 @@
 		dev_err(&client->dev, "alloc data memory error!\n");
 		goto err_out;
 	}
+
+	if (client->dev.of_node) {
+		result = mma8x5x_parse_dt(&client->dev, pdata);
+		if (result)
+			return result;
+	} else {
+		pdata->position = CONFIG_SENSORS_MMA_POSITION;
+		pdata->int_pin = -1;
+		pdata->int_flags = 0;
+	}
+
 	/* Initialize the MMA8X5X chip */
 	pdata->client = client;
 	pdata->chip_id = chip_id;
 	pdata->mode = MODE_2G;
-	pdata->position = CONFIG_SENSORS_MMA_POSITION;
+
 	mutex_init(&pdata->data_lock);
 	i2c_set_clientdata(client, pdata);
 	/* Initialize the MMA8X5X chip */
@@ -522,7 +558,7 @@
 	poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
 	poll_dev->private = pdata;
 	idev = poll_dev->input;
-	idev->name = "accelerometer";
+	idev->name = ACCEL_INPUT_DEV_NAME;
 	idev->uniq = mma8x5x_id2name(pdata->chip_id);
 	idev->id.bustype = BUS_I2C;
 	idev->evbit[0] = BIT_MASK(EV_ABS);
@@ -541,7 +577,10 @@
 		result = -EINVAL;
 		goto err_create_sysfs;
 	}
-	printk(KERN_INFO "mma8x5x device driver probe successfully\n");
+	dev_info(&client->dev,
+		"%s:mma8x5x device driver probe successfully, position =%d\n",
+		__func__, pdata->position);
+
 	return 0;
 err_create_sysfs:
 	input_unregister_polled_device(pdata->poll_dev);
@@ -626,7 +665,7 @@
 
 	res = i2c_add_driver(&mma8x5x_driver);
 	if (res < 0) {
-		printk(KERN_INFO "add mma8x5x i2c driver failed\n");
+		pr_info("%s:add mma8x5x i2c driver failed\n", __func__);
 		return -ENODEV;
 	}
 	return res;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index fbcc243..e84b477 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -170,11 +170,13 @@
 #define LED_MPP_SINK_CTRL(base)		(base + 0x4C)
 
 #define LED_MPP_CURRENT_DEFAULT		5
+#define LED_MPP_VIN_CTRL_DEFAULT	0
 #define LED_MPP_CURRENT_PER_SETTING	5
 #define LED_MPP_SOURCE_SEL_DEFAULT	LED_MPP_MODE_ENABLE
 
 #define LED_MPP_SINK_MASK		0x07
 #define LED_MPP_MODE_MASK		0x7F
+#define LED_MPP_VIN_MASK		0x03
 #define LED_MPP_EN_MASK			0x80
 #define LED_MPP_SRC_MASK		0x0F
 #define LED_MPP_MODE_CTRL_MASK		0x70
@@ -348,6 +350,8 @@
  *  @current_setting - current setting, 5ma-40ma in 5ma increments
  *  @source_sel - source selection
  *  @mode_ctrl - mode control
+ *  @vin_ctrl - input control
+ *  @min_brightness - minimum brightness supported
  *  @pwm_mode - pwm mode in use
  */
 struct mpp_config_data {
@@ -355,6 +359,8 @@
 	u8	current_setting;
 	u8	source_sel;
 	u8	mode_ctrl;
+	u8	vin_ctrl;
+	u8	min_brightness;
 	u8 pwm_mode;
 };
 
@@ -576,6 +582,13 @@
 	int duty_us;
 
 	if (led->cdev.brightness) {
+		if (led->cdev.brightness < led->mpp_cfg->min_brightness) {
+			dev_warn(&led->spmi_dev->dev,
+				"brightness is less than supported..." \
+				"set to minimum supported\n");
+			led->cdev.brightness = led->mpp_cfg->min_brightness;
+		}
+
 		if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
 			if (!led->mpp_cfg->pwm_cfg->blinking) {
 				led->mpp_cfg->pwm_cfg->mode =
@@ -2093,6 +2106,14 @@
 	if (val < 0)
 		val = 0;
 
+	rc = qpnp_led_masked_write(led, LED_MPP_VIN_CTRL(led->base),
+		LED_MPP_VIN_MASK, led->mpp_cfg->vin_ctrl);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Failed to write led vin control reg\n");
+		return rc;
+	}
+
 	rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
 		LED_MPP_SINK_MASK, val);
 	if (rc) {
@@ -2677,6 +2698,20 @@
 	else if (rc != -EINVAL)
 		return rc;
 
+	led->mpp_cfg->vin_ctrl = LED_MPP_VIN_CTRL_DEFAULT;
+	rc = of_property_read_u32(node, "qcom,vin-ctrl", &val);
+	if (!rc)
+		led->mpp_cfg->vin_ctrl = (u8) val;
+	else if (rc != -EINVAL)
+		return rc;
+
+	led->mpp_cfg->min_brightness = 0;
+	rc = of_property_read_u32(node, "qcom,min-brightness", &val);
+	if (!rc)
+		led->mpp_cfg->min_brightness = (u8) val;
+	else if (rc != -EINVAL)
+		return rc;
+
 	rc = of_property_read_string(node, "qcom,mode", &mode);
 	if (!rc) {
 		led_mode = qpnp_led_get_mode(mode);
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8d53e35..07f3b40 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -519,6 +519,7 @@
 	struct msm_session *session;
 	unsigned int session_id;
 	unsigned int stream_id;
+	unsigned long spin_flags = 0;
 
 	event_data = (struct msm_v4l2_event_data *)
 		((struct v4l2_event *)arg)->u.data;
@@ -564,9 +565,13 @@
 			break;
 		}
 
+		spin_lock_irqsave(&(session->command_ack_q.lock),
+		   spin_flags);
 		ret_cmd->event = *(struct v4l2_event *)arg;
 		msm_enqueue(&cmd_ack->command_q, &ret_cmd->list);
 		wake_up(&cmd_ack->wait);
+		spin_unlock_irqrestore(&(session->command_ack_q.lock),
+		   spin_flags);
 	}
 		break;
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/hi256.c b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
index f1df703..de651df 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/hi256.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
@@ -1000,15 +1000,25 @@
 	{0x30, 0x06},
 	{0x31, 0x40},
 	{0x03, 0x20},
-	{0x88, 0x05},
-	{0x89, 0x7e},
-	{0x8a, 0x40},
+	{0x88, 0x01},
+	{0x89, 0x5f},
+	{0x8a, 0x90},
 	{0x03, 0x20},
 	{0x10, 0x9c},
 	{0x03, 0x22},
 	{0x10, 0xe9},
 };
 
+static struct msm_camera_i2c_reg_conf hi256_sleep_settings[] = {
+	{0x03, 0x00},
+	{0x01, 0xf1},
+	{0x03, 0x02},
+	{0x55, 0x10},
+	{0x01, 0xf1},
+	{0x01, 0xf3},
+	{0x01, 0xf1},
+};
+
 
 static const struct i2c_device_id hi256_i2c_id[] = {
 	{HI256_SENSOR_NAME, (kernel_ulong_t)&hi256_s_ctrl},
@@ -1073,6 +1083,13 @@
 
 }
 
+static int32_t hi256_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+	hi256_i2c_write_table(s_ctrl, &hi256_sleep_settings[0],
+		ARRAY_SIZE(hi256_sleep_settings));
+	return msm_sensor_power_down(s_ctrl);
+}
+
 static int32_t hi256_platform_probe(struct platform_device *pdev)
 {
 	int32_t rc;
@@ -1393,7 +1410,7 @@
 static struct msm_sensor_fn_t hi256_sensor_func_tbl = {
 	.sensor_config = hi256_sensor_config,
 	.sensor_power_up = msm_sensor_power_up,
-	.sensor_power_down = msm_sensor_power_down,
+	.sensor_power_down = hi256_sensor_power_down,
 	.sensor_match_id = hi256_sensor_match_id,
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index 40d1155..3792247 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -338,17 +338,11 @@
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc;
-	int i;
 	S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
 		__func__, addr, data, data_type);
 
-	for (i = 0; i < I2C_POLL_MAX_ITERATION; i++) {
-		rc = msm_camera_cci_i2c_compare(client,
-			addr, data, data_type);
-		if (rc == 0 || rc < 0)
-			break;
-		usleep_range(10000, 11000);
-	}
+	rc = msm_camera_cci_i2c_compare(client,
+		addr, data, data_type);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 7f474bb..adbfbe7 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -569,7 +569,92 @@
 		CDBG("%s qcom,gpio-reset %d\n", __func__,
 			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
 	}
-	return rc;
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vio", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vio invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vio %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VIO]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vio failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vana invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vana %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VANA]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vana failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vdig", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vdig invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vdig %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VDIG]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vdig failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vaf", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vaf invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-vaf %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_VAF]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-vaf failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-af-pwdm", &val);
+	if (!rc) {
+		if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-af-pwdm invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-af-pwdm %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_AF_PWDM]);
+	} else if (rc != -EINVAL) {
+		pr_err("%s:%d read qcom,gpio-af-pwdm failed rc %d\n",
+			__func__, __LINE__, rc);
+		goto ERROR;
+	}
+	return 0;
 
 ERROR:
 	kfree(gconf->gpio_num_info);
@@ -1162,6 +1247,15 @@
 	return;
 }
 
+static int msm_sensor_get_af_status(struct msm_sensor_ctrl_t *s_ctrl,
+			void __user *argp)
+{
+	/* TO-DO: Need to set AF status register address and expected value
+	We need to check the AF status in the sensor register and
+	set the status in the *status variable accordingly*/
+	return 0;
+}
+
 static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
 			unsigned int cmd, void *arg)
 {
@@ -1174,6 +1268,8 @@
 	switch (cmd) {
 	case VIDIOC_MSM_SENSOR_CFG:
 		return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+	case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
+		return msm_sensor_get_af_status(s_ctrl, argp);
 	case VIDIOC_MSM_SENSOR_RELEASE:
 		msm_sensor_stop_stream(s_ctrl);
 		return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
index c1cf862..de4fcd0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/mt9m114.c
@@ -1424,8 +1424,51 @@
 			break;
 		}
 		break;
-	}
-	default:
+		}
+		case CFG_SET_SATURATION: {
+			int32_t sat_lev;
+			if (copy_from_user(&sat_lev, (void *)cdata->cfg.setting,
+				sizeof(int32_t))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+			}
+		pr_debug("%s: Saturation Value is %d", __func__, sat_lev);
+		break;
+		}
+		case CFG_SET_CONTRAST: {
+			int32_t con_lev;
+			if (copy_from_user(&con_lev, (void *)cdata->cfg.setting,
+				sizeof(int32_t))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+			}
+		pr_debug("%s: Contrast Value is %d", __func__, con_lev);
+		break;
+		}
+		case CFG_SET_SHARPNESS: {
+			int32_t shp_lev;
+			if (copy_from_user(&shp_lev, (void *)cdata->cfg.setting,
+				sizeof(int32_t))) {
+				pr_err("%s:%d failed\n", __func__, __LINE__);
+				rc = -EFAULT;
+				break;
+			}
+		pr_debug("%s: Sharpness Value is %d", __func__, shp_lev);
+		break;
+		}
+		case CFG_SET_AUTOFOCUS: {
+		/* TO-DO: set the Auto Focus */
+		pr_debug("%s: Setting Auto Focus", __func__);
+		break;
+		}
+		case CFG_CANCEL_AUTOFOCUS: {
+		/* TO-DO: Cancel the Auto Focus */
+		pr_debug("%s: Cancelling Auto Focus", __func__);
+		break;
+		}
+		default:
 		rc = -EFAULT;
 		break;
 	}
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 75b75ea..a3d6dd8 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -1635,7 +1635,17 @@
 			__func__, ret);
 		goto failed_unmap_metadata_buf;
 	}
-	metadata_buff_desc->base_addr = (void *)temp;
+
+	/*
+	 * NOTE: the following casting to u32 must be done
+	 * as long as TZ does not support LPAE. Once TZ supports
+	 * LPAE SDMX interface needs to be updated accordingly.
+	 */
+	if (temp > 0xFFFFFFFF)
+		MPQ_DVB_ERR_PRINT(
+			"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+			__func__, &temp);
+	metadata_buff_desc->base_addr = (void *)(u32)temp;
 
 	dvb_ringbuffer_init(&feed->metadata_buf, metadata_buff_base,
 		SDMX_METADATA_BUFFER_SIZE);
@@ -2273,7 +2283,16 @@
 		return ret;
 	}
 
-	buf_desc->base_addr = (void *)phys_addr;
+	/*
+	 * NOTE: the following casting to u32 must be done
+	 * as long as TZ does not support LPAE. Once TZ supports
+	 * LPAE SDMX interface needs to be updated accordingly.
+	 */
+	if (phys_addr > 0xFFFFFFFF)
+		MPQ_DVB_ERR_PRINT(
+			"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+			__func__, &phys_addr);
+	buf_desc->base_addr = (void *)(u32)phys_addr;
 	buf_desc->size = rbuf->size;
 
 	return 0;
@@ -3405,8 +3424,19 @@
 
 	sg = sg_ptr->sgl;
 	for (i = 0; i < sg_ptr->nents; i++) {
+		/*
+		 * NOTE: the following casting to u32 must be done
+		 * as long as TZ does not support LPAE. Once TZ supports
+		 * LPAE SDMX interface needs to be updated accordingly.
+		 */
+		if (sg_dma_address(sg) > 0xFFFFFFFF)
+			MPQ_DVB_ERR_PRINT(
+				"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+				__func__, &sg_dma_address(sg));
+
 		buff_chunks[i].base_addr =
-			(void *)sg_dma_address(sg);
+			(void *)(u32)sg_dma_address(sg);
+
 		if (sg->length > actual_buff_size)
 			chunk_size = actual_buff_size;
 		else
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 940a4bc..8179061 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -195,7 +195,7 @@
 } mpq_dmx_tspp_info;
 
 static void *tspp_mem_allocator(int channel_id, u32 size,
-				u32 *phys_base, void *user)
+				phys_addr_t *phys_base, void *user)
 {
 	void *virt_addr = NULL;
 	int i = TSPP_GET_TSIF_NUM(channel_id);
@@ -218,7 +218,7 @@
 }
 
 static void tspp_mem_free(int channel_id, u32 size,
-			void *virt_base, u32 phys_base, void *user)
+			void *virt_base, phys_addr_t phys_base, void *user)
 {
 	int i = TSPP_GET_TSIF_NUM(channel_id);
 
@@ -372,7 +372,18 @@
 
 	buff_start_addr_phys =
 		mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_phys_base;
-	input.base_addr = (void *)buff_start_addr_phys;
+
+	/*
+	 * NOTE: the following casting to u32 must be done
+	 * as long as TZ does not support LPAE. Once TZ supports
+	 * LPAE SDMX interface needs to be updated accordingly.
+	 */
+	if (buff_start_addr_phys > 0xFFFFFFFF)
+		MPQ_DVB_ERR_PRINT(
+			"%s: WARNNING - physical address %pa is larger than 32bits!\n",
+			__func__, &buff_start_addr_phys);
+
+	input.base_addr = (void *)(u32)buff_start_addr_phys;
 	input.size = mpq_dmx_tspp_info.tsif[tsif].buffer_count *
 		TSPP_DESCRIPTOR_SIZE;
 
@@ -381,7 +392,7 @@
 			"%s: SDMX Processing %d descriptors: %d bytes at start address 0x%x, read offset %d\n",
 			__func__, aggregate_count, aggregate_len,
 			(unsigned int)input.base_addr,
-			buff_current_addr_phys - buff_start_addr_phys);
+			(int)(buff_current_addr_phys - buff_start_addr_phys));
 
 		mpq_sdmx_process(mpq_demux, &input, aggregate_len,
 			buff_current_addr_phys - buff_start_addr_phys,
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 6e8c809..982e4d4 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1343,3 +1343,17 @@
 	pkt->trigger_type = get_hfi_ssr_type(type);
 	return 0;
 }
+
+int create_pkt_cmd_sys_image_version(
+		struct hfi_cmd_sys_get_property_packet *pkt)
+{
+	if (!pkt) {
+		dprintk(VIDC_ERR, "%s invalid param :%p\n", __func__, pkt);
+		return -EINVAL;
+	}
+	pkt->size = sizeof(struct hfi_cmd_sys_get_property_packet);
+	pkt->packet_type = HFI_CMD_SYS_GET_PROPERTY;
+	pkt->num_properties = 1;
+	pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION;
+	return 0;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi_packetization.h
index df93906..20619c0 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.h
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.h
@@ -89,4 +89,7 @@
 
 int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
 		struct hfi_cmd_sys_test_ssr_packet *pkt);
+
+int create_pkt_cmd_sys_image_version(
+		struct hfi_cmd_sys_get_property_packet *pkt);
 #endif
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 859345f..44105ad 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
+#include <mach/msm_smem.h>
 #include "vidc_hfi_helper.h"
 #include "vidc_hfi_io.h"
 #include "msm_vidc_debug.h"
@@ -1089,6 +1090,44 @@
 	callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
 }
 
+void hfi_process_sys_property_info(
+		struct hfi_property_sys_image_version_info_type *pkt)
+{
+	int i = 0;
+	u32 smem_block_size = 0;
+	u8 *smem_table_ptr;
+	char version[256];
+	const u32 smem_image_index_venus = 14 * 128;
+
+	if (!pkt || !pkt->string_size) {
+		dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
+		return;
+	}
+
+	if (pkt->string_size < sizeof(version)) {
+		/*
+		 * The version string returned by firmware includes null
+		 * characters at the start and in between. Replace the null
+		 * characters with space, to print the version info.
+		 */
+		for (i = 0; i < pkt->string_size; i++) {
+			if (pkt->str_image_version[i] != '\0')
+				version[i] = pkt->str_image_version[i];
+			else
+				version[i] = ' ';
+		}
+		version[i] = '\0';
+		dprintk(VIDC_INFO, "F/W version: %s\n", version);
+	}
+
+	smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+						&smem_block_size);
+	if (smem_table_ptr &&
+		((smem_image_index_venus + 128) <= smem_block_size))
+		memcpy(smem_table_ptr + smem_image_index_venus,
+			   (u8 *)pkt->str_image_version, 128);
+}
+
 u32 hfi_process_msg_packet(
 		msm_vidc_callback callback, u32 device_id,
 		struct vidc_hal_msg_pkt_hdr *msg_hdr)
@@ -1121,6 +1160,11 @@
 			(struct hfi_msg_sys_session_init_done_packet *)
 					msg_hdr);
 		break;
+	case HFI_MSG_SYS_PROPERTY_INFO:
+		hfi_process_sys_property_info(
+		   (struct hfi_property_sys_image_version_info_type *)
+			msg_hdr);
+		break;
 	case HFI_MSG_SYS_SESSION_END_DONE:
 		hfi_process_session_end_done(callback, device_id,
 			(struct hfi_msg_sys_session_end_done_packet *)
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 7547464..7039929 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -934,6 +934,8 @@
 	struct hal_buffer_requirements *bufreq;
 	int extra_idx = 0;
 	struct hfi_device *hdev;
+	struct hal_buffer_count_actual new_buf_count;
+	enum hal_property property_id;
 	if (!q || !num_buffers || !num_planes
 		|| !sizes || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n",
@@ -960,6 +962,16 @@
 					i, inst->capability.height.max,
 					inst->capability.width.max);
 		}
+		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+		new_buf_count.buffer_type = HAL_BUFFER_INPUT;
+		new_buf_count.buffer_count_actual = *num_buffers;
+		rc = call_hfi_op(hdev, session_set_property,
+				inst->session, property_id, &new_buf_count);
+		if (rc) {
+			dprintk(VIDC_WARN,
+				"Failed to set new buffer count(%d) on FW, err: %d\n",
+				new_buf_count.buffer_count_actual, rc);
+		}
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		dprintk(VIDC_DBG, "Getting bufreqs on capture plane\n");
@@ -987,15 +999,11 @@
 		}
 		if (*num_buffers && *num_buffers >
 			bufreq->buffer_count_actual) {
-			struct hal_buffer_count_actual new_buf_count;
-			enum hal_property property_id =
-				HAL_PARAM_BUFFER_COUNT_ACTUAL;
-
+			property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
 			new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
 			new_buf_count.buffer_count_actual = *num_buffers;
 			rc = call_hfi_op(hdev, session_set_property,
 				inst->session, property_id, &new_buf_count);
-
 		}
 		if (bufreq->buffer_count_actual > *num_buffers)
 			*num_buffers =  bufreq->buffer_count_actual;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 77f838c..3d2b3d8 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -69,6 +69,20 @@
 	return false;
 }
 
+static bool is_thumbnail_session(struct msm_vidc_inst *inst)
+{
+	if (inst->session_type == MSM_VIDC_DECODER) {
+		int rc = 0;
+		struct v4l2_control ctrl = {
+			.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE
+		};
+		rc = v4l2_g_ctrl(&inst->ctrl_handler, &ctrl);
+		if (!rc && ctrl.value)
+			return true;
+	}
+	return false;
+}
+
 static int msm_comm_get_load(struct msm_vidc_core *core,
 	enum session_type type)
 {
@@ -83,7 +97,9 @@
 		if (inst->session_type == type &&
 			inst->state >= MSM_VIDC_OPEN_DONE &&
 			inst->state < MSM_VIDC_STOP_DONE) {
-			num_mbs_per_sec += NUM_MBS_PER_SEC(inst->prop.height,
+			if (!is_thumbnail_session(inst))
+				num_mbs_per_sec += NUM_MBS_PER_SEC(
+					inst->prop.height,
 					inst->prop.width, inst->prop.fps);
 		}
 		mutex_unlock(&inst->lock);
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 28ea41a..8ee9c32 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1030,6 +1030,7 @@
 static int venus_hfi_core_init(void *device)
 {
 	struct hfi_cmd_sys_init_packet pkt;
+	struct hfi_cmd_sys_get_property_packet version_pkt;
 	int rc = 0;
 	struct venus_hfi_device *dev;
 
@@ -1088,6 +1089,10 @@
 		rc = -ENOTEMPTY;
 		goto err_core_init;
 	}
+	rc = create_pkt_cmd_sys_image_version(&version_pkt);
+	if (rc || venus_hfi_iface_cmdq_write(dev, &version_pkt))
+		dprintk(VIDC_WARN, "Failed to send image version pkt to f/w");
+
 	return rc;
 err_core_init:
 	disable_irq_nosync(dev->hal_data->irq);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index bb72da7..ac6cb02 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -335,7 +335,6 @@
 #define HFI_MSG_SYS_OX_START			\
 (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
 #define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
-#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
 #define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
 
 #define HFI_MSG_SESSION_OX_START		\
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 2b6d6bb..0f1e896 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -197,6 +197,10 @@
 	(HFI_PROPERTY_SYS_COMMON_START + 0x003)
 #define HFI_PROPERTY_SYS_IDLE_INDICATOR         \
 	(HFI_PROPERTY_SYS_COMMON_START + 0x004)
+#define  HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL     \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x005)
+#define  HFI_PROPERTY_SYS_IMAGE_VERSION    \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x006)
 
 #define HFI_PROPERTY_PARAM_COMMON_START	\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
@@ -615,6 +619,11 @@
 	struct hfi_resource_ocmem_requirement rg_requirements[1];
 };
 
+struct hfi_property_sys_image_version_info_type {
+	u32 string_size;
+	u8  str_image_version[1];
+};
+
 struct hfi_venc_config_advanced {
 	u8 pipe2d;
 	u8 hw_mode;
@@ -703,6 +712,7 @@
 #define HFI_MSG_SYS_SESSION_INIT_DONE	(HFI_MSG_SYS_COMMON_START + 0x6)
 #define HFI_MSG_SYS_SESSION_END_DONE	(HFI_MSG_SYS_COMMON_START + 0x7)
 #define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_COMMON_START + 0x8)
+#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_COMMON_START + 0xA)
 
 #define HFI_MSG_SESSION_COMMON_START		\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET +	\
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index eb8320f..24fd5c1 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -35,7 +35,7 @@
  */
 #define PM8XXX_LPG_V0_PWM_CHANNELS	8
 #define PM8XXX_LPG_V1_PWM_CHANNELS	6
-#define PM8XXX_LPG_CTL_REGS		7
+#define PM8XXX_LPG_CTL_REGS		8
 
 /* PM8XXX PWM */
 #define SSBI_REG_ADDR_PWM1_CTRL1	0x88
@@ -66,6 +66,7 @@
 #define SSBI_REG_ADDR_LPG_LUT_CFG0	0x145
 #define SSBI_REG_ADDR_LPG_LUT_CFG1	0x146
 #define SSBI_REG_ADDR_LPG_TEST		0x147
+#define SSBI_REG_ADDR_LPG_CTL_7		0x14D
 
 /* LPG Control 0 */
 #define PM8XXX_PWM_1KHZ_COUNT_MASK	0xF0
@@ -126,6 +127,7 @@
 
 #define PM8XXX_PWM_PAUSE_ENABLE_HIGH		0x02
 #define PM8XXX_PWM_SIZE_9_BIT			0x01
+#define PM8XXX_PWM_SIZE_7_BIT			0x04
 
 /* LPG Control 6 */
 #define PM8XXX_PWM_PAUSE_COUNT_LO_MASK		0xFC
@@ -369,17 +371,22 @@
 }
 
 static void pm8xxx_pwm_calc_period(unsigned int period_us,
-				   struct pm8xxx_pwm_period *period)
+				   struct pwm_device *pwm)
 {
 	int	n, m, clk, div;
 	int	best_m, best_div, best_clk;
 	unsigned int	last_err, cur_err, min_err;
 	unsigned int	tmp_p, period_n;
+	struct	pm8xxx_pwm_period *period = &pwm->period;
+
+	if (pwm->banks == PM_PWM_BANK_LO)
+		n = 7;
+	else
+		n = 6;
 
 	/* PWM Period / N */
 	if (period_us < ((unsigned)(-1) / NSEC_PER_USEC)) {
-		period_n = (period_us * NSEC_PER_USEC) >> 6;
-		n = 6;
+		period_n = (period_us * NSEC_PER_USEC) >> n;
 	} else {
 		period_n = (period_us >> 9) * NSEC_PER_USEC;
 		n = 9;
@@ -458,6 +465,9 @@
 	int	rc = 0;
 
 	pwm_size = (pwm->pwm_lpg_ctl[5] & PM8XXX_PWM_SIZE_9_BIT) ? 9 : 6;
+	if (pwm->period.pwm_size == 7)
+		pwm_size = 7;
+
 	max_pwm_value = (1 << pwm_size) - 1;
 	for (i = 0; i < len; i++) {
 		if (raw_value)
@@ -512,9 +522,16 @@
 			PM8XXX_LPG_PWM_PREDIVIDE_MASK | PM8XXX_LPG_PWM_M_MASK;
 		pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[4], mask, val);
 
-		val = (pwm->period.pwm_size > 6) ? PM8XXX_PWM_SIZE_9_BIT : 0;
-		mask = PM8XXX_PWM_SIZE_9_BIT;
-		pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[5], mask, val);
+		if (pwm->period.pwm_size == 7) {
+			val = PM8XXX_PWM_SIZE_7_BIT;
+			mask = PM8XXX_PWM_SIZE_7_BIT;
+			pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[7], mask, val);
+		} else {
+			val = (pwm->period.pwm_size > 6) ?
+					PM8XXX_PWM_SIZE_9_BIT : 0;
+			mask = PM8XXX_PWM_SIZE_9_BIT;
+			pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[5], mask, val);
+		}
 	} else {
 		val = ((pwm->period.clk + 1) << PM8XXX_PWM_CLK_SEL_SHIFT)
 			& PM8XXX_PWM_CLK_SEL_MASK;
@@ -639,8 +656,18 @@
 {
 	int	i, rc;
 
+	if (end == 7) {
+		rc = pm8xxx_writeb(pwm->chip->dev->parent,
+				SSBI_REG_ADDR_LPG_CTL_7,
+				pwm->pwm_lpg_ctl[end]);
+		if (rc) {
+			pr_err("pm8xxx_writeb(): rc=%d (PWM Ctl[7])\n", rc);
+			return rc;
+		}
+	}
+
 	/* Write in reverse way so 0 would be the last */
-	for (i = end - 1; i >= start; i--) {
+	for (i = end - 2; i >= start; i--) {
 		rc = pm8xxx_writeb(pwm->chip->dev->parent,
 				   SSBI_REG_ADDR_LPG_CTL(i),
 				   pwm->pwm_lpg_ctl[i]);
@@ -788,7 +815,7 @@
 	}
 
 	if (pwm->pwm_period != period_us) {
-		pm8xxx_pwm_calc_period(period_us, period);
+		pm8xxx_pwm_calc_period(period_us, pwm);
 		pm8xxx_pwm_save_period(pwm);
 		pwm->pwm_period = period_us;
 	}
@@ -801,7 +828,7 @@
 				PM8XXX_PWM_BYPASS_LUT, PM8XXX_PWM_BYPASS_LUT);
 
 		pm8xxx_pwm_bank_sel(pwm);
-		rc = pm8xxx_lpg_pwm_write(pwm, 1, 6);
+		rc = pm8xxx_lpg_pwm_write(pwm, 1, 7);
 	} else {
 		rc = pm8xxx_pwm_write(pwm);
 	}
@@ -851,7 +878,7 @@
 			 * PWM mode.
 			 */
 			if (pwm->chip->is_pwm_enable_sync_workaround_needed)
-				rc = pm8xxx_lpg_pwm_write(pwm, 3, 4);
+				rc = pm8xxx_lpg_pwm_write(pwm, 3, 5);
 
 		} else {
 			pm8xxx_pwm_enable(pwm);
@@ -921,7 +948,7 @@
 
 	if (pwm_chip->is_lpg_supported) {
 		pm8xxx_pwm_bank_sel(pwm);
-		rc = pm8xxx_lpg_pwm_write(pwm, 4, 6);
+		rc = pm8xxx_lpg_pwm_write(pwm, 4, 7);
 	} else {
 		rc = pm8xxx_pwm_write(pwm);
 	}
@@ -965,7 +992,7 @@
 		pm8xxx_pwm_save(&pwm->pwm_lpg_ctl[1],
 				PM8XXX_PWM_BYPASS_LUT, PM8XXX_PWM_BYPASS_LUT);
 		pm8xxx_pwm_bank_sel(pwm);
-		rc = pm8xxx_lpg_pwm_write(pwm, 1, 6);
+		rc = pm8xxx_lpg_pwm_write(pwm, 1, 7);
 	} else {
 		rc = pm8xxx_pwm_write(pwm);
 	}
@@ -996,7 +1023,6 @@
 			  int idx_len, int pause_lo, int pause_hi, int flags)
 {
 	struct pm8xxx_pwm_lut	lut;
-	struct pm8xxx_pwm_period *period;
 	int	len;
 	int	rc;
 
@@ -1032,7 +1058,6 @@
 		return -EINVAL;
 	}
 
-	period = &pwm->period;
 	mutex_lock(&pwm->chip->pwm_mutex);
 
 	if (flags & PM_PWM_BANK_HI)
@@ -1052,7 +1077,7 @@
 	}
 
 	if (pwm->pwm_period != period_us) {
-		pm8xxx_pwm_calc_period(period_us, period);
+		pm8xxx_pwm_calc_period(period_us, pwm);
 		pm8xxx_pwm_save_period(pwm);
 		pwm->pwm_period = period_us;
 	}
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index aa71b74..36bdf45 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -617,8 +617,8 @@
 				break;
 
 			if (iovec.addr != channel->waiting->sps.phys_base)
-				pr_err("tspp: buffer mismatch 0x%08x",
-					channel->waiting->sps.phys_base);
+				pr_err("tspp: buffer mismatch %pa",
+					&channel->waiting->sps.phys_base);
 
 			complete = 1;
 			channel->waiting->state = TSPP_BUF_STATE_DATA;
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 16012bd..7f02187 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -2229,7 +2229,8 @@
 	return err;
 }
 
-#define BAM_APPS_PIPE_LOCK_GRP 0
+#define BAM_APPS_PIPE_LOCK_GRP0 0
+#define BAM_APPS_PIPE_LOCK_GRP1 1
 /*
  * This function allocates, configures, connects an end point and
  * also registers event notification for an end point. It also allocates
@@ -2273,7 +2274,13 @@
 	}
 
 	sps_config->options = SPS_O_AUTO_ENABLE | SPS_O_DESC_DONE;
-	sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP;
+
+	if (pipe_index == SPS_DATA_PROD_PIPE_INDEX ||
+			pipe_index == SPS_DATA_CONS_PIPE_INDEX)
+		sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP0;
+	else if (pipe_index == SPS_CMD_CONS_PIPE_INDEX)
+		sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP1;
+
 	/*
 	 * Descriptor FIFO is a cyclic FIFO. If SPS_MAX_DESC_NUM descriptors
 	 * are allowed to be submitted before we get any ack for any of them,
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index f20f37f..3aaec07 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -45,7 +45,7 @@
 	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1) {
 		ipa_write_reg(ipa_ctx->mmio,
 				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
-		usleep(IPA_PKT_FLUSH_TO_US);
+		udelay(IPA_PKT_FLUSH_TO_US);
 		if (IPA_CLIENT_IS_CONS(ep->client) &&
 				ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
 				ep->cfg.aggr.aggr_time_limit)
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index dba4430..986892b 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -787,15 +787,11 @@
 				&producer->resource.state_lock, flags);
 			consumer_result = ipa_rm_resource_consumer_release(
 				(struct ipa_rm_resource_cons *)consumer);
-			if (consumer_result == -EINPROGRESS) {
-				result = -EINPROGRESS;
-			} else {
-				spin_lock_irqsave(
-					&producer->resource.state_lock, flags);
-				producer->pending_release--;
-				spin_unlock_irqrestore(
-					&producer->resource.state_lock, flags);
-			}
+			spin_lock_irqsave(
+				&producer->resource.state_lock, flags);
+			producer->pending_release--;
+			spin_unlock_irqrestore(
+				&producer->resource.state_lock, flags);
 		}
 	}
 	spin_lock_irqsave(&producer->resource.state_lock, flags);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index e38b796..4a5fa4d 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -1396,12 +1396,8 @@
 	if (__ratelimit(&_rs)) {
 		ipa_inc_client_enable_clks();
 		pr_err("IPA BAM START\n");
-		sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 1048575, 0, 0);
+		sps_get_bam_debug_info(ipa_ctx->bam_handle, 5, 479182, 0, 0);
 		sps_get_bam_debug_info(ipa_ctx->bam_handle, 93, 0, 0, 0);
-		pr_err("BAM-DMA BAM START\n");
-		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 5, 1044480,
-				0, 0);
-		sps_get_bam_debug_info(sps_dma_get_bam_handle(), 93, 0, 0, 0);
 		ipa_dec_client_disable_clks();
 	}
 }
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 1fd4434..a9af974 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -2118,6 +2118,10 @@
 	if (the_chip->start_percent == -EINVAL)
 		return prev_soc;
 
+	/* do not scale at 100 */
+	if (new_soc == 100)
+		return new_soc;
+
 	chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC);
 	catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC);
 	if (catch_up_sec == 0)
@@ -2501,7 +2505,7 @@
 	}
 
 	/* last_soc < soc  ... scale and catch up */
-	if (last_soc != -EINVAL && last_soc < soc && soc != 100)
+	if (last_soc != -EINVAL && last_soc < soc)
 		soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
 
 	if (last_soc != -EINVAL) {
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 14d5b6a..08995cc 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -64,11 +64,10 @@
 /* Extra bms registers */
 #define SOC_STORAGE_REG			0xB0
 #define IAVG_STORAGE_REG		0xB1
-#define BMS_BATT_REMOVED_REG		0xB2
-#define BMS1_BMS_DATA_REG_3		0xB3
-#define CHARGE_INCREASE_STORAGE		0xB4
-#define FCC_BATT_TEMP_STORAGE		0xB5
-#define FCC_STORAGE_LSB			0xBC /* LSB=0xBC, MSB=0xBD */
+#define BMS_FCC_COUNT			0xB2
+#define BMS_FCC_BASE_REG		0xB3 /* FCC updates - 0xB3 to 0xB7 */
+#define BMS_CHGCYL_BASE_REG		0xB8 /* FCC chgcyl - 0xB8 to 0xBC */
+#define CHARGE_INCREASE_STORAGE		0xBD
 #define CHARGE_CYCLE_STORAGE_LSB	0xBE /* LSB=0xBE, MSB=0xBF */
 
 /* IADC Channel Select */
@@ -84,8 +83,11 @@
 #define IAVG_SAMPLES 16
 
 /* FCC learning constants */
+#define MAX_FCC_CYCLES				5
 #define DELTA_FCC_PERCENT                       5
 #define VALID_FCC_CHGCYL_RANGE                  50
+#define CHGCYL_RESOLUTION			20
+#define FCC_DEFAULT_TEMP			250
 
 #define QPNP_BMS_DEV_NAME "qcom,qpnp-bms"
 
@@ -116,9 +118,8 @@
 	int		last_good_ocv_uv;
 };
 
-struct fcc_data {
+struct fcc_sample {
 	int fcc_new;
-	int batt_temp;
 	int chargecycles;
 };
 
@@ -244,7 +245,8 @@
 	int				ocv_low_threshold_uv;
 	unsigned long			last_recalc_time;
 
-	struct fcc_data			*fcc_table;
+	struct fcc_sample		*fcc_learning_samples;
+	u8				fcc_sample_count;
 	int				enable_fcc_learning;
 	int				min_fcc_learning_soc;
 	int				min_fcc_ocv_pc;
@@ -259,8 +261,8 @@
 	int				fcc_new_batt_temp;
 	uint16_t			charge_cycles;
 	u8				charge_increase;
-	int				fcc_new_sysfs;
-	int				fcc_update_complete;
+	int				fcc_resolution;
+	bool				battery_removed;
 	struct bms_irq			sw_cc_thr_irq;
 	struct bms_irq			ocv_thr_irq;
 };
@@ -285,45 +287,10 @@
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
 };
 
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip);
+static void backup_charge_cycle(struct qpnp_bms_chip *chip);
+
 static bool bms_reset;
-static int min_fcc_cycles = -EINVAL;
-static int last_fcc_update_count;
-static int battery_removed;
-
-static int
-bms_ro_ops_set(const char *val, const struct kernel_param *kp)
-{
-	return -EINVAL;
-}
-
-static int
-bms_last_fcc_count_set(const char *val, const struct kernel_param *kp)
-{
-	int rc;
-
-	if (battery_removed) {
-		last_fcc_update_count = 0;
-		return 0;
-	}
-	rc = param_set_int(val, kp);
-	if (rc)
-		pr_err("Failed to set last_fcc_update_count rc=%d\n", rc);
-
-	return rc;
-}
-
-static struct kernel_param_ops bms_ro_param_ops = {
-	.set = bms_ro_ops_set,
-	.get = param_get_int,
-};
-static struct kernel_param_ops bms_last_fcc_count_param_ops = {
-	.set = bms_last_fcc_count_set,
-	.get = param_get_int,
-};
-module_param_cb(min_fcc_cycles, &bms_ro_param_ops, &min_fcc_cycles, 0644);
-module_param_cb(battery_removed, &bms_ro_param_ops, &battery_removed, 0644);
-module_param_cb(last_fcc_update_count, &bms_last_fcc_count_param_ops,
-						&last_fcc_update_count, 0644);
 
 static int qpnp_read_wrapper(struct qpnp_bms_chip *chip, u8 *val,
 			u16 base, int count)
@@ -871,6 +838,19 @@
 	chip->last_cc_uah = INT_MIN;
 	chip->last_ocv_temp = batt_temp;
 	chip->prev_batt_terminal_uv = 0;
+	if (chip->enable_fcc_learning) {
+		chip->adjusted_fcc_temp_lut = NULL;
+		chip->fcc_new_mah = -EINVAL;
+		/* reset the charge-cycle and charge-increase registers */
+		chip->charge_increase = 0;
+		chip->charge_cycles = 0;
+		backup_charge_cycle(chip);
+		/* discard all the FCC learnt data and reset the local table */
+		discard_backup_fcc_data(chip);
+		memset(chip->fcc_learning_samples, 0,
+			chip->min_fcc_learning_samples *
+				sizeof(struct fcc_sample));
+	}
 }
 
 #define OCV_RAW_UNINITIALIZED	0xFFFF
@@ -2624,26 +2604,85 @@
 	kfree(old);
 }
 
-
-static void backup_fcc_new(struct qpnp_bms_chip *chip)
+static int read_fcc_data_from_backup(struct qpnp_bms_chip *chip)
 {
-	int rc = 0;
-	u8 temp = 0;
+	int rc, i;
+	u8 fcc = 0, chgcyl = 0;
 
-	if (chip->fcc_new_mah > 0) {
-		rc = qpnp_write_wrapper(chip, (u8 *)&chip->fcc_new_mah,
-					chip->base + FCC_STORAGE_LSB, 2);
-		if (rc)
-			pr_err("Unable to backup new_fcc\n");
-
-		temp = chip->fcc_new_batt_temp / 10;
-		rc = qpnp_write_wrapper(chip, &temp,
-				chip->base + FCC_BATT_TEMP_STORAGE, 1);
-		if (rc)
-			pr_err("Unable to backup fcc temp.\n");
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+		rc = qpnp_read_wrapper(chip, &fcc,
+			chip->base + BMS_FCC_BASE_REG + i, 1);
+		rc |= qpnp_read_wrapper(chip, &chgcyl,
+			chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+		if (rc) {
+			pr_err("Unable to read FCC data\n");
+			return rc;
+		}
+		if (fcc == 0 || (fcc == 0xFF && chgcyl == 0xFF)) {
+			/* FCC invalid/not present */
+			chip->fcc_learning_samples[i].fcc_new = 0;
+			chip->fcc_learning_samples[i].chargecycles = 0;
+		} else {
+			/* valid FCC data */
+			chip->fcc_sample_count++;
+			chip->fcc_learning_samples[i].fcc_new =
+						fcc * chip->fcc_resolution;
+			chip->fcc_learning_samples[i].chargecycles =
+						chgcyl * CHGCYL_RESOLUTION;
+		}
 	}
+
+	return 0;
 }
 
+static int discard_backup_fcc_data(struct qpnp_bms_chip *chip)
+{
+	int rc = 0, i;
+	u8 temp_u8 = 0;
+
+	chip->fcc_sample_count = 0;
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+		rc = qpnp_write_wrapper(chip, &temp_u8,
+			chip->base + BMS_FCC_BASE_REG + i, 1);
+		rc |= qpnp_write_wrapper(chip, &temp_u8,
+			chip->base + BMS_CHGCYL_BASE_REG + i, 1);
+		if (rc) {
+			pr_err("Unable to clear FCC data\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static void
+average_fcc_samples_and_readjust_fcc_table(struct qpnp_bms_chip *chip)
+{
+	int i, temp_fcc_avg = 0, temp_fcc_delta = 0, new_fcc_avg = 0;
+	struct fcc_sample *ft;
+
+	for (i = 0; i < chip->min_fcc_learning_samples; i++)
+		temp_fcc_avg += chip->fcc_learning_samples[i].fcc_new;
+
+	temp_fcc_avg /= chip->min_fcc_learning_samples;
+	temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
+
+	/* fix the fcc if its an outlier i.e. > 5% of the average */
+	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+		ft = &chip->fcc_learning_samples[i];
+		if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
+			new_fcc_avg += temp_fcc_avg;
+		else
+			new_fcc_avg += ft->fcc_new;
+	}
+	new_fcc_avg /= chip->min_fcc_learning_samples;
+
+	chip->fcc_new_mah = new_fcc_avg;
+	chip->fcc_new_batt_temp = FCC_DEFAULT_TEMP;
+	pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
+				new_fcc_avg, FCC_DEFAULT_TEMP);
+	readjust_fcc_table(chip);
+}
 
 static void backup_charge_cycle(struct qpnp_bms_chip *chip)
 {
@@ -2651,7 +2690,7 @@
 
 	if (chip->charge_increase >= 0) {
 		rc = qpnp_write_wrapper(chip, &chip->charge_increase,
-				chip->base + CHARGE_INCREASE_STORAGE, 1);
+			chip->base + CHARGE_INCREASE_STORAGE, 1);
 		if (rc)
 			pr_err("Unable to backup charge_increase\n");
 	}
@@ -2664,9 +2703,31 @@
 	}
 }
 
-static void restore_fcc_data(struct qpnp_bms_chip *chip)
+static bool chargecycles_in_range(struct qpnp_bms_chip *chip)
 {
-	int rc = 0;
+	int i, min_cycle, max_cycle, valid_range;
+
+	/* find the smallest and largest charge cycle */
+	max_cycle = min_cycle = chip->fcc_learning_samples[0].chargecycles;
+	for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+		if (min_cycle > chip->fcc_learning_samples[i].chargecycles)
+			min_cycle = chip->fcc_learning_samples[i].chargecycles;
+		if (max_cycle < chip->fcc_learning_samples[i].chargecycles)
+			max_cycle = chip->fcc_learning_samples[i].chargecycles;
+	}
+
+	/* check if chargecyles are in range to continue with FCC update */
+	valid_range = DIV_ROUND_UP(VALID_FCC_CHGCYL_RANGE,
+					CHGCYL_RESOLUTION) * CHGCYL_RESOLUTION;
+	if (abs(max_cycle - min_cycle) > valid_range)
+		return false;
+
+	return true;
+}
+
+static int read_chgcycle_data_from_backup(struct qpnp_bms_chip *chip)
+{
+	int rc;
 	uint16_t temp_u16 = 0;
 	u8 temp_u8 = 0;
 
@@ -2680,25 +2741,18 @@
 	if (!rc && temp_u16 != 0xFFFF)
 		chip->charge_cycles = temp_u16;
 
-	rc = qpnp_read_wrapper(chip, (u8 *)&temp_u16,
-				chip->base + FCC_STORAGE_LSB, 2);
-	if (!rc && temp_u16 != 0xFFFF) {
-		chip->fcc_new_mah = temp_u16;
-	} else {
-		pr_debug("Backed-up FCC not initialized, FCC not updated\n");
-		return;
-	}
+	return rc;
+}
 
-	rc = qpnp_read_wrapper(chip, &temp_u8,
-				chip->base + FCC_BATT_TEMP_STORAGE, 1);
-	if (!rc && temp_u8 != 0xFF) {
-		chip->fcc_new_batt_temp = (s8)temp_u8 * 10;
-	} else {
-		pr_debug("Backed-up temp. not initialized, FCC not updated\n");
-		return;
-	}
-	/* readjust the FCC table if fcc and temp are valid */
-	readjust_fcc_table(chip);
+static void
+attempt_learning_new_fcc(struct qpnp_bms_chip *chip)
+{
+	pr_debug("Total FCC sample count=%d\n", chip->fcc_sample_count);
+
+	/* update FCC if we have the required samples */
+	if ((chip->fcc_sample_count == chip->min_fcc_learning_samples) &&
+						chargecycles_in_range(chip))
+		average_fcc_samples_and_readjust_fcc_table(chip);
 }
 
 static int calculate_real_soc(struct qpnp_bms_chip *chip,
@@ -2712,82 +2766,80 @@
 	return ((rc_uah - cc_uah) * 100) / fcc_uah;
 }
 
-static void update_fcc_table_for_temp(struct qpnp_bms_chip *chip,
-						int batt_temp_final)
-{
-	int i, fcc_t1, fcc_t2, fcc_final;
-	struct fcc_data *ft;
+#define MAX_U8_VALUE		((u8)(~0U))
 
-	/* Interpolate all the FCC entries to the same temperature */
-	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
-		ft = &chip->fcc_table[i];
-		if (ft->batt_temp == batt_temp_final)
-			continue;
-		fcc_t1 = interpolate_fcc(chip->fcc_temp_lut, ft->batt_temp);
-		fcc_t2 = interpolate_fcc(chip->fcc_temp_lut, batt_temp_final);
-		fcc_final = (ft->fcc_new / fcc_t1) * fcc_t2;
-		ft->fcc_new = fcc_final;
-		ft->batt_temp = batt_temp_final;
+static int backup_new_fcc(struct qpnp_bms_chip *chip, int fcc_mah,
+							int chargecycles)
+{
+	int rc, min_cycle, i;
+	u8 fcc_new, chgcyl, pos = 0;
+	struct fcc_sample *ft;
+
+	if ((fcc_mah > (chip->fcc_resolution * MAX_U8_VALUE)) ||
+		(chargecycles > (CHGCYL_RESOLUTION * MAX_U8_VALUE))) {
+		pr_warn("FCC/Chgcyl beyond storage limit. FCC=%d, chgcyl=%d\n",
+							fcc_mah, chargecycles);
+		return -EINVAL;
 	}
+
+	if (chip->fcc_sample_count == chip->min_fcc_learning_samples) {
+		/* search best location - oldest entry */
+		min_cycle = chip->fcc_learning_samples[0].chargecycles;
+		for (i = 1; i < chip->min_fcc_learning_samples; i++) {
+			if (min_cycle >
+				chip->fcc_learning_samples[i].chargecycles)
+				pos = i;
+		}
+	} else {
+		/* find an empty location */
+		for (i = 0; i < chip->min_fcc_learning_samples; i++) {
+			ft = &chip->fcc_learning_samples[i];
+			if (ft->fcc_new == 0 || (ft->fcc_new == 0xFF &&
+						ft->chargecycles == 0xFF)) {
+				pos = i;
+				break;
+			}
+		}
+		chip->fcc_sample_count++;
+	}
+	chip->fcc_learning_samples[pos].fcc_new = fcc_mah;
+	chip->fcc_learning_samples[pos].chargecycles = chargecycles;
+
+	fcc_new = DIV_ROUND_UP(fcc_mah, chip->fcc_resolution);
+	rc = qpnp_write_wrapper(chip, (u8 *)&fcc_new,
+			chip->base + BMS_FCC_BASE_REG + pos, 1);
+	if (rc)
+		return rc;
+
+	chgcyl = DIV_ROUND_UP(chargecycles, CHGCYL_RESOLUTION);
+	rc = qpnp_write_wrapper(chip, (u8 *)&chgcyl,
+			chip->base + BMS_CHGCYL_BASE_REG + pos, 1);
+	if (rc)
+		return rc;
+
+	pr_debug("Backup new FCC: fcc_new=%d, chargecycle=%d, pos=%d\n",
+						fcc_new, chgcyl, pos);
+
+	return rc;
 }
 
 static void update_fcc_learning_table(struct qpnp_bms_chip *chip,
-		int fcc_uah, int new_fcc_uah, int chargecycles, int batt_temp)
+			int new_fcc_uah, int chargecycles, int batt_temp)
 {
-	int i, count, new_fcc_avg = 0, temp_fcc_avg = 0, temp_fcc_delta = 0;
-	struct fcc_data *ft;
+	int rc, fcc_default, fcc_temp;
 
-	count = last_fcc_update_count % chip->min_fcc_learning_samples;
-	ft = &chip->fcc_table[count];
-	ft->fcc_new = chip->fcc_new_sysfs = new_fcc_uah;
-	ft->batt_temp = batt_temp;
-	ft->chargecycles = chargecycles;
-	last_fcc_update_count++;
-	/* update userspace */
-	sysfs_notify(&chip->dev->kobj, NULL, "fcc_data");
+	/* convert the fcc at batt_temp to new fcc at FCC_DEFAULT_TEMP */
+	fcc_default = calculate_fcc(chip, FCC_DEFAULT_TEMP) / 1000;
+	fcc_temp = calculate_fcc(chip, batt_temp) / 1000;
+	new_fcc_uah = (new_fcc_uah / fcc_temp) * fcc_default;
 
-	pr_debug("Updated fcc table. new_fcc=%d, chargecycle=%d, temp=%d fcc_update_count=%d\n",
-		new_fcc_uah, chargecycles, batt_temp, last_fcc_update_count);
-
-	if (last_fcc_update_count < chip->min_fcc_learning_samples) {
-		pr_debug("Not enough FCC samples. Current count = %d\n",
-						last_fcc_update_count);
-		return; /* Not enough samples to update fcc */
+	rc = backup_new_fcc(chip, new_fcc_uah / 1000, chargecycles);
+	if (rc) {
+		pr_err("Unable to backup new FCC\n");
+		return;
 	}
-
-	/* reject entries if they are > 50 chargecycles apart */
-	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
-		if ((chip->fcc_table[i].chargecycles + VALID_FCC_CHGCYL_RANGE)
-							< chargecycles) {
-			pr_debug("Charge cycle too old (> %d cycles apart)\n",
-							VALID_FCC_CHGCYL_RANGE);
-			return; /* Samples old, > 50 cycles apart*/
-		}
-	}
-	/* update the fcc table for temperature difference*/
-	update_fcc_table_for_temp(chip, batt_temp);
-
-	for (i = 0; i < chip->min_fcc_learning_samples; i++)
-		temp_fcc_avg += chip->fcc_table[i].fcc_new;
-
-	temp_fcc_avg /= chip->min_fcc_learning_samples;
-	temp_fcc_delta = div_u64(temp_fcc_avg * DELTA_FCC_PERCENT, 100);
-
-	/* fix the fcc if its an outlier i.e. > 5% of the average */
-	for (i = 0; i < chip->min_fcc_learning_samples; i++) {
-		ft = &chip->fcc_table[i];
-		if (abs(ft->fcc_new - temp_fcc_avg) > temp_fcc_delta)
-			ft->fcc_new = temp_fcc_avg;
-		new_fcc_avg += ft->fcc_new;
-	}
-	new_fcc_avg /= chip->min_fcc_learning_samples;
-
-	chip->fcc_new_mah = new_fcc_avg / 1000;
-	chip->fcc_new_batt_temp = batt_temp;
-	pr_info("FCC update: New fcc_mah=%d, fcc_batt_temp=%d\n",
-					new_fcc_avg, batt_temp);
-	readjust_fcc_table(chip);
-	backup_fcc_new(chip);
+	/* check if FCC can be updated */
+	attempt_learning_new_fcc(chip);
 }
 
 static bool is_new_fcc_valid(int new_fcc_uah, int fcc_uah)
@@ -2841,8 +2893,8 @@
 			chip->start_cc_uah, chip->end_cc_uah, new_fcc_uah);
 
 		if (is_new_fcc_valid(new_fcc_uah, fcc_uah))
-			update_fcc_learning_table(chip, fcc_uah,
-				new_fcc_uah, chip->charge_cycles, batt_temp);
+			update_fcc_learning_table(chip, new_fcc_uah,
+					chip->charge_cycles, batt_temp);
 	}
 }
 
@@ -3013,123 +3065,6 @@
 	return 0;
 }
 
-static ssize_t fcc_data_set(struct device *dev, struct device_attribute *attr,
-						const char *buf, size_t count)
-{
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-	static int i;
-	int fcc_new = 0, rc;
-
-	if (chip->fcc_update_complete) {
-		pr_debug("Invalid FCC update\n");
-		return count;
-	}
-
-	i %= chip->min_fcc_learning_samples;
-	rc = sscanf(buf, "%d", &fcc_new);
-	if (rc != 1)
-		return -EINVAL;
-	chip->fcc_table[i].fcc_new = fcc_new;
-	pr_debug("Rcvd: [%d] fcc_new=%d\n", i, fcc_new);
-	i++;
-
-	return count;
-}
-
-static ssize_t fcc_data_get(struct device *dev, struct device_attribute *attr,
-								char *buf)
-{
-	int count = 0;
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
-	count = snprintf(buf, PAGE_SIZE, "%d", chip->fcc_new_sysfs);
-	pr_debug("Sent: fcc_new=%d\n", chip->fcc_new_sysfs);
-	chip->fcc_update_complete = 1;
-
-	return count;
-}
-
-static ssize_t fcc_temp_set(struct device *dev, struct device_attribute *attr,
-						const char *buf, size_t count)
-{
-	static int i;
-	int batt_temp = 0, rc;
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
-	if (chip->fcc_update_complete)
-		return count;
-
-	i %= chip->min_fcc_learning_samples;
-	rc = sscanf(buf, "%d", &batt_temp);
-	if (rc != 1)
-		return -EINVAL;
-	chip->fcc_table[i].batt_temp = batt_temp;
-	pr_debug("Rcvd: [%d] batt_temp=%d\n", i, batt_temp);
-	i++;
-
-	return count;
-}
-
-static ssize_t fcc_chgcyl_set(struct device *dev, struct device_attribute *attr,
-						const char *buf, size_t count)
-{
-	static int i;
-	int chargecycle = 0, rc;
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-
-	if (chip->fcc_update_complete)
-		return count;
-
-	i %= chip->min_fcc_learning_samples;
-	rc = sscanf(buf, "%d", &chargecycle);
-	if (rc != 1)
-		return -EINVAL;
-	chip->fcc_table[i].chargecycles = chargecycle;
-	pr_debug("Rcvd: [%d] chargecycle=%d\n", i, chargecycle);
-	i++;
-
-	return count;
-}
-
-static ssize_t fcc_list_get(struct device *dev, struct device_attribute *attr,
-								char *buf)
-{
-	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
-	struct fcc_data *ft;
-	int i = 0, j, count = 0;
-
-	if (last_fcc_update_count < chip->min_fcc_learning_samples)
-		i = last_fcc_update_count;
-	else
-		i = chip->min_fcc_learning_samples;
-
-	for (j = 0; j < i; j++) {
-		ft = &chip->fcc_table[j];
-		count += snprintf(buf + count, PAGE_SIZE - count,
-			"%d %d %d\n", ft->fcc_new, ft->chargecycles,
-			ft->batt_temp);
-	}
-
-	return count;
-}
-
-static DEVICE_ATTR(fcc_data, 0664, fcc_data_get, fcc_data_set);
-static DEVICE_ATTR(fcc_temp, 0664, NULL, fcc_temp_set);
-static DEVICE_ATTR(fcc_chgcyl, 0664, NULL, fcc_chgcyl_set);
-static DEVICE_ATTR(fcc_list, 0664, fcc_list_get, NULL);
-
-static struct attribute *fcc_attrs[] = {
-	&dev_attr_fcc_data.attr,
-	&dev_attr_fcc_temp.attr,
-	&dev_attr_fcc_chgcyl.attr,
-	&dev_attr_fcc_list.attr,
-	NULL
-};
-
-static const struct attribute_group fcc_attr_group = {
-	.attrs = fcc_attrs,
-};
-
 #define OCV_USE_LIMIT_EN		BIT(7)
 static int set_ocv_voltage_thresholds(struct qpnp_bms_chip *chip,
 					int low_voltage_threshold,
@@ -3213,10 +3148,19 @@
 		}
 	}
 
-	pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d\n",
+	/* read the SOC storage to determine if there was a battery removal */
+	rc = qpnp_read_wrapper(chip, &temp, chip->base + SOC_STORAGE_REG, 1);
+	if (!rc) {
+		if (temp == SOC_INVALID)
+			chip->battery_removed = true;
+	}
+
+
+	pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
 			chip->shutdown_soc,
 			chip->shutdown_iavg_ma,
-			chip->shutdown_soc_invalid);
+			chip->shutdown_soc_invalid,
+			chip->battery_removed);
 }
 
 static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *_chip)
@@ -3325,6 +3269,12 @@
 	}								\
 } while (0)
 
+#define SPMI_PROP_READ_BOOL(chip_prop, qpnp_spmi_property)		\
+do {									\
+	chip->chip_prop = of_property_read_bool(chip->spmi->dev.of_node,\
+				"qcom," qpnp_spmi_property);		\
+} while (0)
+
 static inline int bms_read_properties(struct qpnp_bms_chip *chip)
 {
 	int rc;
@@ -3371,8 +3321,7 @@
 	if (chip->adjust_soc_low_threshold >= 45)
 		chip->adjust_soc_low_threshold = 45;
 
-	chip->enable_fcc_learning = of_property_read_bool(
-		chip->spmi->dev.of_node, "qcom,enable-fcc-learning");
+	SPMI_PROP_READ_BOOL(enable_fcc_learning, "enable-fcc-learning");
 	if (chip->enable_fcc_learning) {
 		SPMI_PROP_READ(min_fcc_learning_soc,
 				"min-fcc-learning-soc", rc);
@@ -3380,12 +3329,16 @@
 				"min-fcc-ocv-pc", rc);
 		SPMI_PROP_READ(min_fcc_learning_samples,
 				"min-fcc-learning-samples", rc);
-		chip->fcc_table = kzalloc((sizeof(struct fcc_data) *
-			chip->min_fcc_learning_samples), GFP_KERNEL);
+		SPMI_PROP_READ(fcc_resolution,
+				"fcc-resolution", rc);
+		if (chip->min_fcc_learning_samples > MAX_FCC_CYCLES)
+			chip->min_fcc_learning_samples = MAX_FCC_CYCLES;
+		chip->fcc_learning_samples = devm_kzalloc(&chip->spmi->dev,
+				(sizeof(struct fcc_sample) *
+				chip->min_fcc_learning_samples), GFP_KERNEL);
 		pr_debug("min-fcc-soc=%d, min-fcc-pc=%d, min-fcc-cycles=%d\n",
 			chip->min_fcc_learning_soc, chip->min_fcc_ocv_pc,
 			chip->min_fcc_learning_samples);
-		min_fcc_cycles = chip->min_fcc_learning_samples;
 	}
 
 	pr_debug("dts data: r_sense_uohm:%d, v_cutoff_uv:%d, max_v:%d\n",
@@ -3662,28 +3615,6 @@
 	return 0;
 }
 
-static void check_battery_removal(struct qpnp_bms_chip *chip)
-{
-	int rc;
-	u8 temp = 0;
-
-	/* check if battery was removed at PON */
-	rc = qpnp_read_wrapper(chip, &temp,
-				chip->base + BMS_BATT_REMOVED_REG, 1);
-	if (temp == 0xFF) {
-		pr_debug("New battery inserted at PON\n");
-		temp = battery_removed = 1;
-		rc = qpnp_write_wrapper(chip, &temp,
-				chip->base + BMS_BATT_REMOVED_REG, 1);
-		if (rc)
-			pr_err("Unable to set BMS_BATT_REMOVED_REG\n");
-	} else {
-		if (rc)
-			pr_err("Unable to read BMS_BATT_REMOVED_REG\n");
-		battery_removed = 0;
-	}
-}
-
 static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
 {
 	struct qpnp_bms_chip *chip;
@@ -3711,6 +3642,12 @@
 		goto error_read;
 	}
 
+	mutex_init(&chip->bms_output_lock);
+	mutex_init(&chip->last_ocv_uv_mutex);
+	mutex_init(&chip->vbat_monitor_mutex);
+	mutex_init(&chip->soc_invalidation_mutex);
+	mutex_init(&chip->last_soc_mutex);
+
 	warm_reset = qpnp_pon_is_warm_reset();
 	rc = warm_reset;
 	if (rc < 0)
@@ -3768,12 +3705,6 @@
 
 	bms_initialize_constants(chip);
 
-	mutex_init(&chip->bms_output_lock);
-	mutex_init(&chip->last_ocv_uv_mutex);
-	mutex_init(&chip->vbat_monitor_mutex);
-	mutex_init(&chip->soc_invalidation_mutex);
-	mutex_init(&chip->last_soc_mutex);
-
 	wakeup_source_init(&chip->soc_wake_source.source, "qpnp_soc_wake");
 	wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
 			"qpnp_low_voltage_lock");
@@ -3786,20 +3717,26 @@
 	read_shutdown_soc_and_iavg(chip);
 
 	if (chip->enable_fcc_learning) {
-		restore_fcc_data(chip);
-		rc = sysfs_create_group(&spmi->dev.kobj, &fcc_attr_group);
-		if (rc) {
-			pr_err("Unable to create sysfs entries\n");
-			goto error_setup;
+		if (chip->battery_removed) {
+			rc = discard_backup_fcc_data(chip);
+			if (rc)
+				pr_err("Could not discard backed-up FCC data\n");
+		} else {
+			rc = read_chgcycle_data_from_backup(chip);
+			if (rc)
+				pr_err("Unable to restore charge-cycle data\n");
+
+			rc = read_fcc_data_from_backup(chip);
+			if (rc)
+				pr_err("Unable to restore FCC-learning data\n");
+			else
+				attempt_learning_new_fcc(chip);
 		}
 	}
 
 	dev_set_drvdata(&spmi->dev, chip);
 	device_init_wakeup(&spmi->dev, 1);
 
-	check_battery_removal(chip);
-
-
 	rc = setup_vbat_monitoring(chip);
 	if (rc < 0) {
 		pr_err("failed to set up voltage notifications: %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 2a007ca..3679aa9 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1143,7 +1143,7 @@
 		val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		val->intval = chip->maxinput_dc_ma;
+		val->intval = chip->maxinput_dc_ma * 1000;
 		break;
 	default:
 		return -EINVAL;
@@ -2352,7 +2352,8 @@
 			}
 			rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
 				qpnp_chg_bat_if_batt_pres_irq_handler,
-				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+				| IRQF_SHARED | IRQF_ONESHOT,
 				"batt-pres", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d batt-pres irq: %d\n",
@@ -2766,13 +2767,6 @@
 	chip->duty_cycle_100p = of_property_read_bool(
 					chip->spmi->dev.of_node,
 					"qcom,duty-cycle-100p");
-	if (chip->duty_cycle_100p) {
-		rc = qpnp_buck_set_100_duty_cycle_enable(chip, 1);
-		if (rc) {
-			pr_err("failed to enable duty cycle %d\n", rc);
-			return rc;
-		}
-	}
 
 	/* Get the fake-batt-values property */
 	chip->use_default_batt_values =
@@ -2938,6 +2932,16 @@
 				0xFF,
 				0x80, 1);
 
+			if (chip->duty_cycle_100p) {
+				rc = qpnp_buck_set_100_duty_cycle_enable(chip,
+						1);
+				if (rc) {
+					pr_err("failed to set duty cycle %d\n",
+						rc);
+					goto fail_chg_enable;
+				}
+			}
+
 			break;
 		case SMBB_BAT_IF_SUBTYPE:
 		case SMBBP_BAT_IF_SUBTYPE:
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index 082c9ff..eedb1e5 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -578,11 +578,14 @@
 	unsigned long hwirq, busno;
 	int irq;
 
+	if (!spec || !spmi_ctrl)
+		return -EINVAL;
+
 	pr_debug("spec slave = %u per = %u irq = %u\n",
 					spec->slave, spec->per, spec->irq);
 
 	busno = spmi_ctrl->nr;
-	if (!spec || !spmi_ctrl || busno >= QPNPINT_MAX_BUSSES)
+	if (busno >= QPNPINT_MAX_BUSSES)
 		return -EINVAL;
 
 	hwirq = qpnpint_encode_hwirq(spec);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 52608af..6933163 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -77,6 +77,9 @@
 
 #define TSENS_EEPROM_8X10_1(n)		((n) + 0x1a4)
 #define TSENS_EEPROM_8X10_1_OFFSET	8
+#define TSENS_EEPROM_8X10_2(n)		((n) + 0x1a8)
+#define TSENS_EEPROM_8X10_SPARE_1(n)	((n) + 0xd8)
+#define TSENS_EEPROM_8X10_SPARE_2(n)	((n) + 0xdc)
 
 /* TSENS calibration Mask data */
 #define TSENS_BASE1_MASK		0xff
@@ -207,6 +210,8 @@
 #define TSENS_8X10_TSENS_CAL_SEL	0x70000000
 #define TSENS1_8X10_POINT1_MASK		0x3f
 #define TSENS1_8X10_POINT2_MASK		0xfc0
+#define TSENS_8X10_REDUN_SEL_MASK	0x6000000
+#define TSENS_8X10_REDUN_SEL_SHIFT	25
 
 #define TSENS_BIT_APPEND		0x3
 #define TSENS_CAL_DEGC_POINT1		30
@@ -559,6 +564,9 @@
 	unsigned int reg_cntl;
 	int code, hi_code, lo_code, code_err_chk, sensor_sw_id = 0, rc = 0;
 
+	if (!tm_sensor || trip < 0 || !temp)
+		return -EINVAL;
+
 	rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
 	if (rc < 0) {
 		pr_err("tsens mapping index not found\n");
@@ -721,17 +729,30 @@
 	int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
 	int tsens0_point2 = 0, tsens1_point2 = 0;
 	int tsens_base1_data = 0, tsens_calibration_mode = 0;
-	uint32_t calib_data[2];
+	uint32_t calib_data[2], calib_redun_sel;
 	uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2];
 
 	if (tmdev->calibration_less_mode)
 		goto calibration_less_mode;
 
-	calib_data[0] = readl_relaxed(
+	calib_redun_sel = readl_relaxed(
+			TSENS_EEPROM_8X10_2(tmdev->tsens_calib_addr));
+	calib_redun_sel = calib_redun_sel & TSENS_8X10_REDUN_SEL_MASK;
+	calib_redun_sel >>= TSENS_8X10_REDUN_SEL_SHIFT;
+	pr_debug("calib_redun_sel:%x\n", calib_redun_sel);
+
+	if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) {
+		calib_data[0] = readl_relaxed(
+			TSENS_EEPROM_8X10_SPARE_1(tmdev->tsens_calib_addr));
+		calib_data[1] = readl_relaxed(
+			TSENS_EEPROM_8X10_SPARE_2(tmdev->tsens_calib_addr));
+	} else {
+		calib_data[0] = readl_relaxed(
 			TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr));
-	calib_data[1] = readl_relaxed(
-		(TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
+		calib_data[1] = readl_relaxed(
+			(TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
 					TSENS_EEPROM_8X10_1_OFFSET));
+	}
 
 	tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
 			>> TSENS_8X10_CAL_SEL_SHIFT;
@@ -1325,7 +1346,7 @@
 
 static int get_device_tree_data(struct platform_device *pdev)
 {
-	const struct device_node *of_node = pdev->dev.of_node;
+	struct device_node *of_node = pdev->dev.of_node;
 	struct resource *res_mem = NULL;
 	u32 *tsens_slope_data;
 	u32 *sensor_id;
@@ -1353,8 +1374,13 @@
 		return rc;
 	};
 
-	tsens_calib_mode = of_get_property(of_node,
-			"qcom,calib-mode", NULL);
+	rc = of_property_read_string(of_node,
+				"qcom,calib-mode", &tsens_calib_mode);
+	if (rc) {
+		dev_err(&pdev->dev, "missing calib-mode\n");
+		return -ENODEV;
+	}
+
 	if (!strncmp(tsens_calib_mode, "fuse_map1", 9))
 		calib_type = TSENS_CALIB_FUSE_MAP_8974;
 	else if (!strncmp(tsens_calib_mode, "fuse_map2", 9))
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index cab7c12..9e22afd 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -192,7 +192,7 @@
 	ktime_t clk_off_delay;
 	enum msm_hs_clk_states_e clk_state;
 	enum msm_hs_clk_req_off_state_e clk_req_off_state;
-
+	atomic_t clk_count;
 	struct msm_hs_wakeup wakeup;
 	struct wake_lock dma_wake_lock;  /* held while any DMA active */
 
@@ -241,6 +241,7 @@
 static void msm_hs_start_rx_locked(struct uart_port *uport);
 static void msm_serial_hs_rx_tlet(unsigned long tlet_ptr);
 static void flip_insert_work(struct work_struct *work);
+static void msm_hs_bus_voting(struct msm_hs_port *msm_uport, unsigned int vote);
 
 #define UARTDM_TO_MSM(uart_port) \
 	container_of((uart_port), struct msm_hs_port, uport)
@@ -287,6 +288,61 @@
 	return ret;
 }
 
+static int msm_hs_clock_vote(struct msm_hs_port *msm_uport)
+{
+	int rc = 0;
+
+	if (1 == atomic_inc_return(&msm_uport->clk_count)) {
+		msm_hs_bus_voting(msm_uport, BUS_SCALING);
+		/* Turn on core clk and iface clk */
+		rc = clk_prepare_enable(msm_uport->clk);
+		if (rc) {
+			dev_err(msm_uport->uport.dev,
+				"%s: Could not turn on core clk [%d]\n",
+				__func__, rc);
+			return rc;
+		}
+
+		if (msm_uport->pclk) {
+			rc = clk_prepare_enable(msm_uport->pclk);
+			if (rc) {
+				clk_disable_unprepare(msm_uport->clk);
+				dev_err(msm_uport->uport.dev,
+					"%s: Could not turn on pclk [%d]\n",
+					__func__, rc);
+				return rc;
+			}
+		}
+		msm_uport->clk_state = MSM_HS_CLK_ON;
+	}
+
+
+	return rc;
+}
+
+static void msm_hs_clock_unvote(struct msm_hs_port *msm_uport)
+{
+	int rc = atomic_dec_return(&msm_uport->clk_count);
+
+	if (rc < 0) {
+		msm_hs_bus_voting(msm_uport, BUS_RESET);
+		WARN(rc, "msm_uport->clk_count < 0!");
+		dev_err(msm_uport->uport.dev,
+			"%s: Clocks count invalid  [%d]\n", __func__,
+			atomic_read(&msm_uport->clk_count));
+		return;
+	}
+
+	if (0 == rc) {
+		msm_hs_bus_voting(msm_uport, BUS_RESET);
+		/* Turn off the core clk and iface clk*/
+		clk_disable_unprepare(msm_uport->clk);
+		if (msm_uport->pclk)
+			clk_disable_unprepare(msm_uport->pclk);
+		msm_uport->clk_state = MSM_HS_CLK_OFF;
+	}
+}
+
 static ssize_t show_clock(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
@@ -432,11 +488,7 @@
 	unsigned long flags;
 	int ret = 0;
 
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-	clk_prepare_enable(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_prepare_enable(msm_uport->pclk);
+	msm_hs_clock_vote(msm_uport);
 
 	if (val) {
 		spin_lock_irqsave(&uport->lock, flags);
@@ -461,11 +513,8 @@
 	}
 	/* Calling CLOCK API. Hence mb() requires here. */
 	mb();
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
 
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
+	msm_hs_clock_unvote(msm_uport);
 	return 0;
 }
 
@@ -476,23 +525,16 @@
 	unsigned long flags;
 	int ret = 0;
 
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-	clk_prepare_enable(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_prepare_enable(msm_uport->pclk);
+	msm_hs_clock_vote(msm_uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
 	ret = msm_hs_read(&msm_uport->uport, UARTDM_MR2_ADDR);
 	spin_unlock_irqrestore(&uport->lock, flags);
 
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
+	msm_hs_clock_unvote(msm_uport);
 
 	*val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
 
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
 	return 0;
 }
 DEFINE_SIMPLE_ATTRIBUTE(loopback_enable_fops, msm_serial_loopback_enable_get,
@@ -585,22 +627,12 @@
 		return ret;
 	}
 
-	ret = clk_prepare_enable(msm_uport->clk);
+	ret = msm_hs_clock_vote(msm_uport);
 	if (ret) {
 		printk(KERN_ERR "Error could not turn on UART clk\n");
 		return ret;
 	}
-	if (msm_uport->pclk) {
-		ret = clk_prepare_enable(msm_uport->pclk);
-		if (ret) {
-			clk_disable_unprepare(msm_uport->clk);
-			dev_err(uport->dev,
-				"Error could not turn on UART pclk\n");
-			return ret;
-		}
-	}
 
-	msm_uport->clk_state = MSM_HS_CLK_ON;
 	return 0;
 }
 
@@ -1040,8 +1072,12 @@
 {
 	unsigned int data;
 	unsigned int ret = 0;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
+	msm_hs_clock_vote(msm_uport);
 	data = msm_hs_read(uport, UARTDM_SR_ADDR);
+	msm_hs_clock_unvote(msm_uport);
+
 	if (data & UARTDM_SR_TXEMT_BMSK)
 		ret = TIOCSER_TEMT;
 
@@ -1658,10 +1694,13 @@
 				    unsigned int mctrl)
 {
 	unsigned long flags;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
+	msm_hs_clock_vote(msm_uport);
 	spin_lock_irqsave(&uport->lock, flags);
 	msm_hs_set_mctrl_locked(uport, mctrl);
 	spin_unlock_irqrestore(&uport->lock, flags);
+	msm_hs_clock_unvote(msm_uport);
 }
 EXPORT_SYMBOL(msm_hs_set_mctrl);
 
@@ -1825,11 +1864,7 @@
 	spin_unlock_irqrestore(&uport->lock, flags);
 
 	/* we really want to clock off */
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
-
-	msm_uport->clk_state = MSM_HS_CLK_OFF;
+	msm_hs_clock_unvote(msm_uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
 	if (use_low_power_wakeup(msm_uport)) {
@@ -2020,25 +2055,13 @@
 			disable_irq_nosync(msm_uport->wakeup.irq);
 		spin_unlock_irqrestore(&uport->lock, flags);
 
-		/* Vote for PNOC BUS Scaling */
-		msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-		ret = clk_prepare_enable(msm_uport->clk);
+		ret = msm_hs_clock_vote(msm_uport);
 		if (ret) {
 			dev_err(uport->dev, "Clock ON Failure"
 			"For UART CLK Stalling HSUART\n");
 			break;
 		}
 
-		if (msm_uport->pclk) {
-			ret = clk_prepare_enable(msm_uport->pclk);
-			if (unlikely(ret)) {
-				clk_disable_unprepare(msm_uport->clk);
-				dev_err(uport->dev, "Clock ON Failure"
-				"For UART Pclk Stalling HSUART\n");
-				break;
-			}
-		}
 		spin_lock_irqsave(&uport->lock, flags);
 		/* else fall-through */
 	case MSM_HS_CLK_REQUEST_OFF:
@@ -2375,8 +2398,7 @@
 		disable_irq(msm_uport->wakeup.irq);
 	}
 
-	/* Vote for PNOC BUS Scaling */
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
+	msm_hs_clock_vote(msm_uport);
 
 	spin_lock_irqsave(&uport->lock, flags);
 
@@ -2384,6 +2406,8 @@
 
 	spin_unlock_irqrestore(&uport->lock, flags);
 
+	msm_hs_clock_unvote(msm_uport);
+
 	pm_runtime_enable(uport->dev);
 
 	return 0;
@@ -2403,9 +2427,7 @@
 	if (is_blsp_uart(msm_uport))
 		msm_hs_unconfig_uart_gpios(uport);
 deinit_uart_clk:
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
+	msm_hs_clock_unvote(msm_uport);
 	wake_unlock(&msm_uport->dma_wake_lock);
 
 	return ret;
@@ -3057,6 +3079,8 @@
 	INIT_WORK(&msm_uport->disconnect_rx_endpoint,
 				hsuart_disconnect_rx_endpoint_work);
 	mutex_init(&msm_uport->clk_mutex);
+	atomic_set(&msm_uport->clk_count, 0);
+
 
 	/* Initialize SPS HW connected with UART core */
 	if (is_blsp_uart(msm_uport)) {
@@ -3067,11 +3091,7 @@
 		}
 	}
 
-	msm_hs_bus_voting(msm_uport, BUS_SCALING);
-
-	clk_prepare_enable(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_prepare_enable(msm_uport->pclk);
+	msm_hs_clock_vote(msm_uport);
 
 	ret = uartdm_init_port(uport);
 	if (unlikely(ret)) {
@@ -3106,19 +3126,12 @@
 		uport->line = pdata->userid;
 	ret = uart_add_one_port(&msm_hs_driver, uport);
 	if (!ret) {
-		msm_hs_bus_voting(msm_uport, BUS_RESET);
-		clk_disable_unprepare(msm_uport->clk);
-		if (msm_uport->pclk)
-			clk_disable_unprepare(msm_uport->pclk);
+		msm_hs_clock_unvote(msm_uport);
 		return ret;
 	}
 
 err_clock:
-
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
-	clk_disable_unprepare(msm_uport->clk);
-	if (msm_uport->pclk)
-		clk_disable_unprepare(msm_uport->pclk);
+	msm_hs_clock_unvote(msm_uport);
 
 destroy_mutex:
 	mutex_destroy(&msm_uport->clk_mutex);
@@ -3189,6 +3202,7 @@
 	struct msm_hs_tx *tx = &msm_uport->tx;
 	struct sps_pipe *sps_pipe_handle = tx->cons.pipe_handle;
 
+	msm_hs_clock_vote(msm_uport);
 	if (msm_uport->tx.dma_in_flight) {
 		if (!is_blsp_uart(msm_uport)) {
 			spin_lock_irqsave(&uport->lock, flags);
@@ -3240,16 +3254,12 @@
 	 */
 	mb();
 
-	/* Reset PNOC Bus Scaling */
-	msm_hs_bus_voting(msm_uport, BUS_RESET);
-
 	if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
 		/* to balance clk_state */
-		clk_disable_unprepare(msm_uport->clk);
-		if (msm_uport->pclk)
-			clk_disable_unprepare(msm_uport->pclk);
+		msm_hs_clock_unvote(msm_uport);
 		wake_unlock(&msm_uport->dma_wake_lock);
 	}
+	msm_hs_clock_unvote(msm_uport);
 
 	msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
 	dma_unmap_single(uport->dev, msm_uport->tx.dma_base,
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 2487e3f..0f8a7f0 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -36,6 +36,7 @@
 #include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_ext_chg.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_wakeup.h>
 #include <linux/power_supply.h>
 #include <linux/qpnp/qpnp-adc.h>
 #include <linux/cdev.h>
@@ -196,7 +197,6 @@
 	bool			lpm_irq_seen;
 	struct delayed_work	resume_work;
 	struct work_struct	restart_usb_work;
-	struct wake_lock	wlock;
 	struct dwc3_charger	charger;
 	struct usb_phy		*otg_xceiv;
 	struct delayed_work	chg_work;
@@ -246,8 +246,6 @@
 #define USB_SSPHY_1P8_VOL_MAX		1800000 /* uV */
 #define USB_SSPHY_1P8_HPM_LOAD		23000	/* uA */
 
-static struct dwc3_msm *context;
-
 static struct usb_ext_notification *usb_ext;
 
 /**
@@ -343,8 +341,8 @@
 	tmp &= mask;		/* clear other bits */
 
 	if (tmp != val)
-		dev_err(context->dev, "%s: write: %x to QSCRATCH: %x FAILED\n",
-						__func__, val, offset);
+		pr_err("%s: write: %x to QSCRATCH: %x FAILED\n",
+			__func__, val, offset);
 }
 
 /**
@@ -413,12 +411,12 @@
  * Return DBM EP number according to usb endpoint number.
  *
  */
-static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
+static int dwc3_msm_find_matching_dbm_ep(struct dwc3_msm *mdwc, u8 usb_ep)
 {
 	int i;
 
-	for (i = 0; i < context->dbm_num_eps; i++)
-		if (context->ep_num_mapping[i] == usb_ep)
+	for (i = 0; i < mdwc->dbm_num_eps; i++)
+		if (mdwc->ep_num_mapping[i] == usb_ep)
 			return i;
 
 	return -ENODEV; /* Not found */
@@ -428,13 +426,13 @@
  * Return number of configured DBM endpoints.
  *
  */
-static int dwc3_msm_configured_dbm_ep_num(void)
+static int dwc3_msm_configured_dbm_ep_num(struct dwc3_msm *mdwc)
 {
 	int i;
 	int count = 0;
 
-	for (i = 0; i < context->dbm_num_eps; i++)
-		if (context->ep_num_mapping[i])
+	for (i = 0; i < mdwc->dbm_num_eps; i++)
+		if (mdwc->ep_num_mapping[i])
 			count++;
 
 	return count;
@@ -448,12 +446,13 @@
  * @size - size of the event buffer.
  *
  */
-static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
+static int dwc3_msm_event_buffer_config(struct dwc3_msm *mdwc,
+					u32 addr, u16 size)
 {
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
-	dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
+	dwc3_msm_write_reg(mdwc->base, DBM_GEVNTADR, addr);
+	dwc3_msm_write_reg_field(mdwc->base, DBM_GEVNTSIZ,
 		DBM_GEVNTSIZ_MASK, size);
 
 	return 0;
@@ -463,19 +462,19 @@
  * Reset the DBM registers upon initialization.
  *
  */
-static int dwc3_msm_dbm_soft_reset(int enter_reset)
+static int dwc3_msm_dbm_soft_reset(struct dwc3_msm *mdwc, int enter_reset)
 {
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 	if (enter_reset) {
-		dev_dbg(context->dev, "enter DBM reset\n");
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dev_dbg(mdwc->dev, "enter DBM reset\n");
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_MASK, 1);
 	} else {
-		dev_dbg(context->dev, "exit DBM reset\n");
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dev_dbg(mdwc->dev, "exit DBM reset\n");
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_MASK, 0);
 		/*enable DBM*/
-		dwc3_msm_write_reg_field(context->base, QSCRATCH_GENERAL_CFG,
+		dwc3_msm_write_reg_field(mdwc->base, QSCRATCH_GENERAL_CFG,
 			DBM_EN_MASK, 0x1);
 	}
 
@@ -492,21 +491,21 @@
  * @enter_reset - should we enter a reset state or get out of it.
  *
  */
-static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
+static int dwc3_msm_dbm_ep_soft_reset(struct dwc3_msm *mdwc,
+					u8 dbm_ep, bool enter_reset)
 {
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	if (dbm_ep >= context->dbm_num_eps) {
-		dev_err(context->dev,
-				"%s: Invalid DBM ep index\n", __func__);
+	if (dbm_ep >= mdwc->dbm_num_eps) {
+		dev_err(mdwc->dev, "%s: Invalid DBM ep index\n", __func__);
 		return -ENODEV;
 	}
 
 	if (enter_reset) {
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 1);
 	} else {
-		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		dwc3_msm_write_reg_field(mdwc->base, DBM_SOFT_RESET,
 			DBM_SFT_RST_EPS_MASK & 1 << dbm_ep, 0);
 	}
 
@@ -525,43 +524,43 @@
  *
  * @return int - DBM ep number.
  */
-static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
+static int dwc3_msm_dbm_ep_config(struct dwc3_msm *mdwc, u8 usb_ep, u8 bam_pipe,
 				  bool producer, bool disable_wb,
 				  bool internal_mem, bool ioc)
 {
 	u8 dbm_ep;
 	u32 ep_cfg;
 
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+	dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
 
 	if (dbm_ep < 0) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 				"%s: Invalid usb ep index\n", __func__);
 		return -ENODEV;
 	}
 	/* First, reset the dbm endpoint */
-	dwc3_msm_dbm_ep_soft_reset(dbm_ep, 0);
+	dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, 0);
 
 	/* Set ioc bit for dbm_ep if needed */
-	dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_DBG_CNFG,
 		DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
 
 	ep_cfg = (producer ? DBM_PRODUCER : 0) |
 		(disable_wb ? DBM_DISABLE_WB : 0) |
 		(internal_mem ? DBM_INT_RAM_ACC : 0);
 
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
 		DBM_PRODUCER | DBM_DISABLE_WB | DBM_INT_RAM_ACC, ep_cfg >> 8);
 
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), USB3_EPNUM,
 		usb_ep);
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep),
 		DBM_BAM_PIPE_NUM, bam_pipe);
-	dwc3_msm_write_reg_field(context->base, DBM_PIPE_CFG, 0x000000ff,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_PIPE_CFG, 0x000000ff,
 		0xe4);
-	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
+	dwc3_msm_write_reg_field(mdwc->base, DBM_EP_CFG(dbm_ep), DBM_EN_EP,
 		1);
 
 	return dbm_ep;
@@ -573,35 +572,34 @@
  * @usb_ep - USB ep number.
  *
  */
-static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
+static int dwc3_msm_dbm_ep_unconfig(struct dwc3_msm *mdwc, u8 usb_ep)
 {
 	u8 dbm_ep;
 	u32 data;
 
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
-	dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+	dbm_ep = dwc3_msm_find_matching_dbm_ep(mdwc, usb_ep);
 
 	if (dbm_ep < 0) {
-		dev_err(context->dev,
-				"%s: Invalid usb ep index\n", __func__);
+		dev_err(mdwc->dev, "%s: Invalid usb ep index\n", __func__);
 		return -ENODEV;
 	}
 
-	context->ep_num_mapping[dbm_ep] = 0;
+	mdwc->ep_num_mapping[dbm_ep] = 0;
 
-	data = dwc3_msm_read_reg(context->base, DBM_EP_CFG(dbm_ep));
+	data = dwc3_msm_read_reg(mdwc->base, DBM_EP_CFG(dbm_ep));
 	data &= (~0x1);
-	dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), data);
+	dwc3_msm_write_reg(mdwc->base, DBM_EP_CFG(dbm_ep), data);
 
 	/* Reset the dbm endpoint */
-	dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
+	dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, true);
 	/*
 	 * 10 usec delay is required before deasserting DBM endpoint reset
 	 * according to hardware programming guide.
 	 */
 	udelay(10);
-	dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
+	dwc3_msm_dbm_ep_soft_reset(mdwc, dbm_ep, false);
 
 	return 0;
 }
@@ -620,15 +618,17 @@
 {
 	u8 dbm_ep;
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	u8 bam_pipe = dst_pipe_idx;
 
-	dev_dbg(context->dev, "%s\n", __func__);
+	dev_dbg(mdwc->dev, "%s\n", __func__);
 
 	dbm_ep = bam_pipe;
-	context->ep_num_mapping[dbm_ep] = dep->number;
+	mdwc->ep_num_mapping[dbm_ep] = dep->number;
 
-	dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
-	dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
+	dwc3_msm_write_reg(mdwc->base, DBM_DATA_FIFO(dbm_ep), addr);
+	dwc3_msm_write_reg_field(mdwc->base, DBM_DATA_FIFO_SIZE(dbm_ep),
 		DBM_DATA_FIFO_SIZE_MASK, size);
 
 	return 0;
@@ -648,12 +648,12 @@
 				       struct usb_request *request)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct dwc3_msm_req_complete *req_complete = NULL;
 
 	/* Find original request complete function and remove it from list */
-	list_for_each_entry(req_complete,
-				&context->req_complete_list,
-				list_item) {
+	list_for_each_entry(req_complete, &mdwc->req_complete_list, list_item) {
 		if (req_complete->req == request)
 			break;
 	}
@@ -672,14 +672,14 @@
 	dep->busy_slot++;
 
 	/* Unconfigure dbm ep */
-	dwc3_msm_dbm_ep_unconfig(dep->number);
+	dwc3_msm_dbm_ep_unconfig(mdwc, dep->number);
 
 	/*
 	 * If this is the last endpoint we unconfigured, than reset also
 	 * the event buffers.
 	 */
-	if (0 == dwc3_msm_configured_dbm_ep_num())
-		dwc3_msm_event_buffer_config(0, 0);
+	if (0 == dwc3_msm_configured_dbm_ep_num(mdwc))
+		dwc3_msm_event_buffer_config(mdwc, 0, 0);
 
 	/*
 	 * Call original complete function, notice that dwc->lock is already
@@ -792,6 +792,7 @@
 	struct dwc3_request *req = to_dwc3_request(request);
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
 	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct dwc3_msm_req_complete *req_complete;
 	unsigned long flags;
 	int ret = 0;
@@ -804,23 +805,23 @@
 
 	if (!(request->udc_priv & MSM_SPS_MODE)) {
 		/* Not SPS mode, call original queue */
-		dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
+		dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n",
 					__func__);
 
-		return (context->original_ep_ops[dep->number])->queue(ep,
+		return (mdwc->original_ep_ops[dep->number])->queue(ep,
 								request,
 								gfp_flags);
 	}
 
 	if (!dep->endpoint.desc) {
-		dev_err(dwc->dev,
+		dev_err(mdwc->dev,
 			"%s: trying to queue request %p to disabled ep %s\n",
 			__func__, request, ep->name);
 		return -EPERM;
 	}
 
 	if (dep->number == 0 || dep->number == 1) {
-		dev_err(dwc->dev,
+		dev_err(mdwc->dev,
 			"%s: trying to queue dbm request %p to control ep %s\n",
 			__func__, request, ep->name);
 		return -EPERM;
@@ -829,7 +830,7 @@
 
 	if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list)
 					 || !list_empty(&dep->req_queued)) {
-		dev_err(dwc->dev,
+		dev_err(mdwc->dev,
 			"%s: trying to queue dbm request %p tp ep %s\n",
 			__func__, request, ep->name);
 		return -EPERM;
@@ -844,12 +845,12 @@
 	 */
 	req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
 	if (!req_complete) {
-		dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
+		dev_err(mdwc->dev, "%s: not enough memory\n", __func__);
 		return -ENOMEM;
 	}
 	req_complete->req = request;
 	req_complete->orig_complete = request->complete;
-	list_add_tail(&req_complete->list_item, &context->req_complete_list);
+	list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
 	request->complete = dwc3_msm_req_complete_func;
 
 	/*
@@ -861,11 +862,11 @@
 	internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
 	ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
 
-	ret = dwc3_msm_dbm_ep_config(dep->number,
+	ret = dwc3_msm_dbm_ep_config(mdwc, dep->number,
 					bam_pipe, producer,
 					disable_wb, internal_mem, ioc);
 	if (ret < 0) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 			"error %d after calling dwc3_msm_dbm_ep_config\n",
 			ret);
 		return ret;
@@ -885,13 +886,13 @@
 	ret = __dwc3_msm_ep_queue(dep, req);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	if (ret < 0) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 			"error %d after calling __dwc3_msm_ep_queue\n", ret);
 		return ret;
 	}
 
 	speed = dwc3_readl(dwc->regs, DWC3_DSTS) & DWC3_DSTS_CONNECTSPD;
-	dwc3_msm_write_reg(context->base, DBM_GEN_CFG, speed >> 2);
+	dwc3_msm_write_reg(mdwc->base, DBM_GEN_CFG, speed >> 2);
 
 	return 0;
 }
@@ -913,25 +914,27 @@
 int msm_ep_config(struct usb_ep *ep)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct usb_ep_ops *new_ep_ops;
 
-	dwc3_msm_event_buffer_config(dwc3_msm_read_reg(context->base,
-			DWC3_GEVNTADRLO(0)),
-			dwc3_msm_read_reg(context->base, DWC3_GEVNTSIZ(0)));
+	dwc3_msm_event_buffer_config(mdwc,
+			dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
+			dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0)));
 
 	/* Save original ep ops for future restore*/
-	if (context->original_ep_ops[dep->number]) {
-		dev_err(context->dev,
+	if (mdwc->original_ep_ops[dep->number]) {
+		dev_err(mdwc->dev,
 			"ep [%s,%d] already configured as msm endpoint\n",
 			ep->name, dep->number);
 		return -EPERM;
 	}
-	context->original_ep_ops[dep->number] = ep->ops;
+	mdwc->original_ep_ops[dep->number] = ep->ops;
 
 	/* Set new usb ops as we like */
 	new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
 	if (!new_ep_ops) {
-		dev_err(context->dev,
+		dev_err(mdwc->dev,
 			"%s: unable to allocate mem for new usb ep ops\n",
 			__func__);
 		return -ENOMEM;
@@ -963,18 +966,20 @@
 int msm_ep_unconfig(struct usb_ep *ep)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct usb_ep_ops *old_ep_ops;
 
 	/* Restore original ep ops */
-	if (!context->original_ep_ops[dep->number]) {
-		dev_err(context->dev,
+	if (!mdwc->original_ep_ops[dep->number]) {
+		dev_err(mdwc->dev,
 			"ep [%s,%d] was not configured as msm endpoint\n",
 			ep->name, dep->number);
 		return -EINVAL;
 	}
 	old_ep_ops = (struct usb_ep_ops	*)ep->ops;
-	ep->ops = context->original_ep_ops[dep->number];
-	context->original_ep_ops[dep->number] = NULL;
+	ep->ops = mdwc->original_ep_ops[dep->number];
+	mdwc->original_ep_ops[dep->number] = NULL;
 	kfree(old_ep_ops);
 
 	/*
@@ -1019,14 +1024,16 @@
  * This performs full hardware reset and re-initialization which
  * might be required by some DBM client driver during uninit/cleanup.
  */
-void msm_dwc3_restart_usb_session(void)
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3 *dwc = container_of(gadget, struct dwc3, gadget);
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+	if (mdwc)
+		return;
 
 	dev_dbg(mdwc->dev, "%s\n", __func__);
 	queue_work(system_nrt_wq, &mdwc->restart_usb_work);
-
-	return;
 }
 EXPORT_SYMBOL(msm_dwc3_restart_usb_session);
 
@@ -1058,10 +1065,9 @@
 EXPORT_SYMBOL(msm_register_usb_ext_notification);
 
 /* HSPHY */
-static int dwc3_hsusb_config_vddcx(int high)
+static int dwc3_hsusb_config_vddcx(struct dwc3_msm *dwc, int high)
 {
 	int min_vol, max_vol, ret;
-	struct dwc3_msm *dwc = context;
 
 	max_vol = dwc->vdd_high_vol_level;
 	min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1077,10 +1083,9 @@
 	return ret;
 }
 
-static int dwc3_hsusb_ldo_init(int init)
+static int dwc3_hsusb_ldo_init(struct dwc3_msm *dwc, int init)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
 	if (!init) {
 		regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
@@ -1121,10 +1126,9 @@
 	return rc;
 }
 
-static int dwc3_hsusb_ldo_enable(int on)
+static int dwc3_hsusb_ldo_enable(struct dwc3_msm *dwc, int on)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
 	dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
 
@@ -1182,10 +1186,9 @@
 }
 
 /* SSPHY */
-static int dwc3_ssusb_config_vddcx(int high)
+static int dwc3_ssusb_config_vddcx(struct dwc3_msm *dwc, int high)
 {
 	int min_vol, max_vol, ret;
-	struct dwc3_msm *dwc = context;
 
 	max_vol = dwc->vdd_high_vol_level;
 	min_vol = high ? dwc->vdd_low_vol_level : dwc->vdd_no_vol_level;
@@ -1201,10 +1204,9 @@
 }
 
 /* 3.3v supply not needed for SS PHY */
-static int dwc3_ssusb_ldo_init(int init)
+static int dwc3_ssusb_ldo_init(struct dwc3_msm *dwc, int init)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
 	if (!init) {
 		regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
@@ -1224,12 +1226,11 @@
 	return rc;
 }
 
-static int dwc3_ssusb_ldo_enable(int on)
+static int dwc3_ssusb_ldo_enable(struct dwc3_msm *dwc, int on)
 {
 	int rc = 0;
-	struct dwc3_msm *dwc = context;
 
-	dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+	dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
 
 	if (!on)
 		goto disable_regulators;
@@ -1266,37 +1267,36 @@
  * Config Global Distributed Switch Controller (GDSC)
  * to support controller power collapse
  */
-static int dwc3_msm_config_gdsc(struct dwc3_msm *msm, int on)
+static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on)
 {
 	int ret = 0;
 
-	if (IS_ERR(msm->dwc3_gdsc))
+	if (IS_ERR(mdwc->dwc3_gdsc))
 		return 0;
 
-	if (!msm->dwc3_gdsc) {
-		msm->dwc3_gdsc = devm_regulator_get(msm->dev,
+	if (!mdwc->dwc3_gdsc) {
+		mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev,
 			"USB3_GDSC");
-		if (IS_ERR(msm->dwc3_gdsc))
+		if (IS_ERR(mdwc->dwc3_gdsc))
 			return 0;
 	}
 
 	if (on) {
-		ret = regulator_enable(msm->dwc3_gdsc);
+		ret = regulator_enable(mdwc->dwc3_gdsc);
 		if (ret) {
-			dev_err(msm->dev, "unable to enable usb3 gdsc\n");
+			dev_err(mdwc->dev, "unable to enable usb3 gdsc\n");
 			return ret;
 		}
 	} else {
-		regulator_disable(msm->dwc3_gdsc);
+		regulator_disable(mdwc->dwc3_gdsc);
 	}
 
 	return 0;
 }
 
-static int dwc3_msm_link_clk_reset(bool assert)
+static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert)
 {
 	int ret = 0;
-	struct dwc3_msm *mdwc = context;
 
 	if (assert) {
 		/* Using asynchronous block reset to the hardware */
@@ -1322,7 +1322,7 @@
 }
 
 /* Reinitialize SSPHY parameters by overriding using QSCRATCH CR interface */
-static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *mdwc)
 {
 	u32 data = 0;
 
@@ -1331,14 +1331,14 @@
 	 * in HS mode instead of SS mode. Workaround it by asserting
 	 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
 	 */
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x102D);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x102D);
 	data |= (1 << 7);
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x102D, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x102D, data);
 
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1010);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1010);
 	data &= ~0xFF0;
 	data |= 0x20;
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1010, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1010, data);
 
 	/*
 	 * Fix RX Equalization setting as follows
@@ -1347,13 +1347,13 @@
 	 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
 	 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
 	 */
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1006);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1006);
 	data &= ~(1 << 6);
 	data |= (1 << 7);
 	data &= ~(0x7 << 8);
 	data |= (0x3 << 8);
 	data |= (0x1 << 11);
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1006, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1006, data);
 
 	/*
 	 * Set EQ and TX launch amplitudes as follows
@@ -1361,12 +1361,12 @@
 	 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
 	 * LANE0.TX_OVRD_DRV_LO.EN set to 1.
 	 */
-	data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1002);
+	data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1002);
 	data &= ~0x3F80;
 	data |= (0x16 << 7);
 	data &= ~0x7F;
 	data |= (0x7F | (1 << 14));
-	dwc3_msm_ssusb_write_phycreg(msm->base, 0x1002, data);
+	dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1002, data);
 
 	/*
 	 * Set the QSCRATCH SS_PHY_PARAM_CTRL1 parameters as follows
@@ -1374,73 +1374,73 @@
 	 * TX_DEEMPH_3_5DB [13:8] to 22
 	 * LOS_BIAS [2:0] to 0x5
 	 */
-	dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1,
+	dwc3_msm_write_readback(mdwc->base, SS_PHY_PARAM_CTRL_1,
 				0x07f03f07, 0x07f01605);
 }
 
 /* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc)
 {
 	/* SSPHY Initialization: Use ref_clk from pads and set its parameters */
-	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210002);
 	msleep(30);
 	/* Assert SSPHY reset */
-	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210082);
 	usleep_range(2000, 2200);
 	/* De-assert SSPHY reset - power and ref_clock must be ON */
-	dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+	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(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+	dwc3_msm_write_reg(mdwc->base, SS_PHY_CTRL_REG, 0x10210102);
 	usleep_range(2000, 2200);
 	/*
 	 * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
 	 * and disable RETENTION (power-on default is ENABLED)
 	 */
-	dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+	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(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+	dwc3_msm_write_reg(mdwc->base, QSCRATCH_GENERAL_CFG, 0x78);
 	/*
 	 * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
 	 * VBUS valid threshold, disconnect valid threshold, DC voltage level,
 	 * preempasis and rise/fall time.
 	 */
 	if (override_phy_init)
-		msm->hsphy_init_seq = override_phy_init;
-	if (msm->hsphy_init_seq)
-		dwc3_msm_write_readback(msm->base,
+		mdwc->hsphy_init_seq = override_phy_init;
+	if (mdwc->hsphy_init_seq)
+		dwc3_msm_write_readback(mdwc->base,
 					PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
-					msm->hsphy_init_seq & 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
 	 * are seen where RAM clocks get turned OFF in SS mode
 	 */
-	dwc3_msm_write_reg(msm->base, CGCTL_REG,
-		dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
+	dwc3_msm_write_reg(mdwc->base, CGCTL_REG,
+		dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18);
 
-	dwc3_msm_ss_phy_reg_init(msm);
+	dwc3_msm_ss_phy_reg_init(mdwc);
 	/*
 	 * This is required to restore the POR value after userspace
 	 * is done with charger detection.
 	 */
-	msm->qscratch_ctl_val = dwc3_msm_read_reg(msm->base, QSCRATCH_CTRL_REG);
+	mdwc->qscratch_ctl_val =
+		dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG);
 }
 
-static void dwc3_msm_block_reset(bool core_reset)
+static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset)
 {
-
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = container_of(xceiv, struct dwc3_msm, ext_xceiv);
 	int ret  = 0;
 
 	if (core_reset) {
-		ret = dwc3_msm_link_clk_reset(1);
+		ret = dwc3_msm_link_clk_reset(mdwc, 1);
 		if (ret)
 			return;
 
 		usleep_range(1000, 1200);
-		ret = dwc3_msm_link_clk_reset(0);
+		ret = dwc3_msm_link_clk_reset(mdwc, 0);
 		if (ret)
 			return;
 
@@ -1451,9 +1451,9 @@
 	}
 
 	/* Reset the DBM */
-	dwc3_msm_dbm_soft_reset(1);
+	dwc3_msm_dbm_soft_reset(mdwc, 1);
 	usleep_range(1000, 1200);
-	dwc3_msm_dbm_soft_reset(0);
+	dwc3_msm_dbm_soft_reset(mdwc, 0);
 }
 
 static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -1664,7 +1664,7 @@
 
 static void dwc3_start_chg_det(struct dwc3_charger *charger, bool start)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = container_of(charger, struct dwc3_msm, charger);
 
 	if (start == false) {
 		dev_dbg(mdwc->dev, "canceling charging detection work\n");
@@ -1796,13 +1796,13 @@
 
 	if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
 							!host_bus_suspend)
-		dwc3_hsusb_ldo_enable(0);
+		dwc3_hsusb_ldo_enable(mdwc, 0);
 
-	dwc3_ssusb_ldo_enable(0);
-	dwc3_ssusb_config_vddcx(0);
+	dwc3_ssusb_ldo_enable(mdwc, 0);
+	dwc3_ssusb_config_vddcx(mdwc, 0);
 	if (!host_bus_suspend && !dcp)
-		dwc3_hsusb_config_vddcx(0);
-	wake_unlock(&mdwc->wlock);
+		dwc3_hsusb_config_vddcx(mdwc, 0);
+	pm_relax(mdwc->dev);
 	atomic_set(&mdwc->in_lpm, 1);
 
 	dev_info(mdwc->dev, "DWC3 in low power mode\n");
@@ -1830,7 +1830,7 @@
 		return 0;
 	}
 
-	wake_lock(&mdwc->wlock);
+	pm_stay_awake(mdwc->dev);
 
 	if (mdwc->bus_perf_client) {
 		ret = msm_bus_scale_client_update_request(
@@ -1861,13 +1861,13 @@
 
 	if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
 							!host_bus_suspend)
-		dwc3_hsusb_ldo_enable(1);
+		dwc3_hsusb_ldo_enable(mdwc, 1);
 
-	dwc3_ssusb_ldo_enable(1);
-	dwc3_ssusb_config_vddcx(1);
+	dwc3_ssusb_ldo_enable(mdwc, 1);
+	dwc3_ssusb_config_vddcx(mdwc, 1);
 
 	if (!host_bus_suspend && !dcp)
-		dwc3_hsusb_config_vddcx(1);
+		dwc3_hsusb_config_vddcx(mdwc, 1);
 
 	clk_prepare_enable(mdwc->ref_clk);
 	usleep_range(1000, 1200);
@@ -2221,9 +2221,9 @@
 
 static void dwc3_init_adc_work(struct work_struct *w);
 
-static void dwc3_ext_notify_online(int on)
+static void dwc3_ext_notify_online(void *ctx, int on)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = ctx;
 	bool notify_otg = false;
 
 	if (!mdwc) {
@@ -2271,7 +2271,7 @@
 			disable_irq(mdwc->pmic_id_irq);
 
 		ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
-				      dwc3_ext_notify_online);
+				      dwc3_ext_notify_online, mdwc);
 		dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
 			__func__, ret);
 
@@ -2367,7 +2367,12 @@
 static ssize_t adc_enable_show(struct device *dev,
 			       struct device_attribute *attr, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n", context->id_adc_detect ?
+	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+	if (!mdwc)
+		return -EINVAL;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", mdwc->id_adc_detect ?
 						"enabled" : "disabled");
 }
 
@@ -2375,13 +2380,18 @@
 		struct device_attribute *attr, const char
 		*buf, size_t size)
 {
+	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+	if (!mdwc)
+		return -EINVAL;
+
 	if (!strnicmp(buf, "enable", 6)) {
-		if (!context->id_adc_detect)
-			dwc3_init_adc_work(&context->init_adc_work.work);
+		if (!mdwc->id_adc_detect)
+			dwc3_init_adc_work(&mdwc->init_adc_work.work);
 		return size;
 	} else if (!strnicmp(buf, "disable", 7)) {
 		qpnp_adc_tm_usbid_end();
-		context->id_adc_detect = false;
+		mdwc->id_adc_detect = false;
 		return size;
 	}
 
@@ -2393,25 +2403,27 @@
 
 static int dwc3_msm_ext_chg_open(struct inode *inode, struct file *file)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc =
+		container_of(inode->i_cdev, struct dwc3_msm, ext_chg_cdev);
 
 	pr_debug("dwc3-msm ext chg open\n");
-
+	file->private_data = mdwc;
 	mdwc->ext_chg_opened = true;
+
 	return 0;
 }
 
 static long
 dwc3_msm_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = file->private_data;
 	struct msm_usb_chg_info info = {0};
 	int ret = 0, val;
 
 	switch (cmd) {
 	case MSM_USB_EXT_CHG_INFO:
 		info.chg_block_type = USB_CHG_BLOCK_QSCRATCH;
-		info.page_offset = (context->io_res->start +
+		info.page_offset = (mdwc->io_res->start +
 				QSCRATCH_REG_OFFSET) & ~PAGE_MASK;
 		/*
 		 * The charger block register address space is only
@@ -2454,7 +2466,7 @@
 
 static int dwc3_msm_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = file->private_data;
 	unsigned long vsize = vma->vm_end - vma->vm_start;
 	int ret;
 
@@ -2475,7 +2487,7 @@
 
 static int dwc3_msm_ext_chg_release(struct inode *inode, struct file *file)
 {
-	struct dwc3_msm *mdwc = context;
+	struct dwc3_msm *mdwc = file->private_data;
 
 	pr_debug("dwc3-msm ext chg release\n");
 
@@ -2540,7 +2552,7 @@
 static int __devinit dwc3_msm_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
-	struct dwc3_msm *msm;
+	struct dwc3_msm *mdwc;
 	struct resource *res;
 	void __iomem *tcsr;
 	unsigned long flags;
@@ -2548,39 +2560,38 @@
 	int len = 0;
 	u32 tmp[3];
 
-	msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
-	if (!msm) {
+	mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL);
+	if (!mdwc) {
 		dev_err(&pdev->dev, "not enough memory\n");
 		return -ENOMEM;
 	}
 
-	platform_set_drvdata(pdev, msm);
-	context = msm;
-	msm->dev = &pdev->dev;
+	platform_set_drvdata(pdev, mdwc);
+	mdwc->dev = &pdev->dev;
 
-	INIT_LIST_HEAD(&msm->req_complete_list);
-	INIT_DELAYED_WORK(&msm->chg_work, dwc3_chg_detect_work);
-	INIT_DELAYED_WORK(&msm->resume_work, dwc3_resume_work);
-	INIT_WORK(&msm->restart_usb_work, dwc3_restart_usb_work);
-	INIT_WORK(&msm->id_work, dwc3_id_work);
-	INIT_DELAYED_WORK(&msm->init_adc_work, dwc3_init_adc_work);
-	init_completion(&msm->ext_chg_wait);
+	INIT_LIST_HEAD(&mdwc->req_complete_list);
+	INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work);
+	INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work);
+	INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
+	INIT_WORK(&mdwc->id_work, dwc3_id_work);
+	INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work);
+	init_completion(&mdwc->ext_chg_wait);
 
-	ret = dwc3_msm_config_gdsc(msm, 1);
+	ret = dwc3_msm_config_gdsc(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to configure usb3 gdsc\n");
 		return ret;
 	}
 
-	msm->xo_clk = clk_get(&pdev->dev, "xo");
-	if (IS_ERR(msm->xo_clk)) {
+	mdwc->xo_clk = clk_get(&pdev->dev, "xo");
+	if (IS_ERR(mdwc->xo_clk)) {
 		dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n",
 								__func__);
-		ret = PTR_ERR(msm->xo_clk);
+		ret = PTR_ERR(mdwc->xo_clk);
 		goto disable_dwc3_gdsc;
 	}
 
-	ret = clk_prepare_enable(msm->xo_clk);
+	ret = clk_prepare_enable(mdwc->xo_clk);
 	if (ret) {
 		dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n",
 						__func__, ret);
@@ -2591,62 +2602,62 @@
 	 * DWC3 Core requires its CORE CLK (aka master / bus clk) to
 	 * run at 125Mhz in SSUSB mode and >60MHZ for HSUSB mode.
 	 */
-	msm->core_clk = devm_clk_get(&pdev->dev, "core_clk");
-	if (IS_ERR(msm->core_clk)) {
+	mdwc->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+	if (IS_ERR(mdwc->core_clk)) {
 		dev_err(&pdev->dev, "failed to get core_clk\n");
-		ret = PTR_ERR(msm->core_clk);
+		ret = PTR_ERR(mdwc->core_clk);
 		goto disable_xo;
 	}
-	clk_set_rate(msm->core_clk, 125000000);
-	clk_prepare_enable(msm->core_clk);
+	clk_set_rate(mdwc->core_clk, 125000000);
+	clk_prepare_enable(mdwc->core_clk);
 
-	msm->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
-	if (IS_ERR(msm->iface_clk)) {
+	mdwc->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
+	if (IS_ERR(mdwc->iface_clk)) {
 		dev_err(&pdev->dev, "failed to get iface_clk\n");
-		ret = PTR_ERR(msm->iface_clk);
+		ret = PTR_ERR(mdwc->iface_clk);
 		goto disable_core_clk;
 	}
-	clk_prepare_enable(msm->iface_clk);
+	clk_prepare_enable(mdwc->iface_clk);
 
-	msm->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
-	if (IS_ERR(msm->sleep_clk)) {
+	mdwc->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
+	if (IS_ERR(mdwc->sleep_clk)) {
 		dev_err(&pdev->dev, "failed to get sleep_clk\n");
-		ret = PTR_ERR(msm->sleep_clk);
+		ret = PTR_ERR(mdwc->sleep_clk);
 		goto disable_iface_clk;
 	}
-	clk_prepare_enable(msm->sleep_clk);
+	clk_prepare_enable(mdwc->sleep_clk);
 
-	msm->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
-	if (IS_ERR(msm->hsphy_sleep_clk)) {
+	mdwc->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
+	if (IS_ERR(mdwc->hsphy_sleep_clk)) {
 		dev_err(&pdev->dev, "failed to get sleep_a_clk\n");
-		ret = PTR_ERR(msm->hsphy_sleep_clk);
+		ret = PTR_ERR(mdwc->hsphy_sleep_clk);
 		goto disable_sleep_clk;
 	}
-	clk_prepare_enable(msm->hsphy_sleep_clk);
+	clk_prepare_enable(mdwc->hsphy_sleep_clk);
 
-	msm->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
-	if (IS_ERR(msm->utmi_clk)) {
+	mdwc->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
+	if (IS_ERR(mdwc->utmi_clk)) {
 		dev_err(&pdev->dev, "failed to get utmi_clk\n");
-		ret = PTR_ERR(msm->utmi_clk);
+		ret = PTR_ERR(mdwc->utmi_clk);
 		goto disable_sleep_a_clk;
 	}
-	clk_prepare_enable(msm->utmi_clk);
+	clk_prepare_enable(mdwc->utmi_clk);
 
-	msm->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
-	if (IS_ERR(msm->ref_clk)) {
+	mdwc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+	if (IS_ERR(mdwc->ref_clk)) {
 		dev_err(&pdev->dev, "failed to get ref_clk\n");
-		ret = PTR_ERR(msm->ref_clk);
+		ret = PTR_ERR(mdwc->ref_clk);
 		goto disable_utmi_clk;
 	}
-	clk_prepare_enable(msm->ref_clk);
+	clk_prepare_enable(mdwc->ref_clk);
 
 	of_get_property(node, "qcom,vdd-voltage-level", &len);
 	if (len == sizeof(tmp)) {
 		of_property_read_u32_array(node, "qcom,vdd-voltage-level",
 							tmp, len/sizeof(*tmp));
-		msm->vdd_no_vol_level = tmp[0];
-		msm->vdd_low_vol_level = tmp[1];
-		msm->vdd_high_vol_level = tmp[2];
+		mdwc->vdd_no_vol_level = tmp[0];
+		mdwc->vdd_low_vol_level = tmp[1];
+		mdwc->vdd_high_vol_level = tmp[2];
 	} else {
 		dev_err(&pdev->dev, "no qcom,vdd-voltage-level property\n");
 		ret = -EINVAL;
@@ -2654,99 +2665,100 @@
 	}
 
 	/* SS PHY */
-	msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
-	if (IS_ERR(msm->ssusb_vddcx)) {
+	mdwc->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
+	if (IS_ERR(mdwc->ssusb_vddcx)) {
 		dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
-		ret = PTR_ERR(msm->ssusb_vddcx);
+		ret = PTR_ERR(mdwc->ssusb_vddcx);
 		goto disable_ref_clk;
 	}
 
-	ret = dwc3_ssusb_config_vddcx(1);
+	ret = dwc3_ssusb_config_vddcx(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
 		goto disable_ref_clk;
 	}
 
-	ret = regulator_enable(context->ssusb_vddcx);
+	ret = regulator_enable(mdwc->ssusb_vddcx);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
 		goto unconfig_ss_vddcx;
 	}
 
-	ret = dwc3_ssusb_ldo_init(1);
+	ret = dwc3_ssusb_ldo_init(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
 		goto disable_ss_vddcx;
 	}
 
-	ret = dwc3_ssusb_ldo_enable(1);
+	ret = dwc3_ssusb_ldo_enable(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "ssusb vreg enable failed\n");
 		goto free_ss_ldo_init;
 	}
 
 	/* HS PHY */
-	msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
-	if (IS_ERR(msm->hsusb_vddcx)) {
+	mdwc->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
+	if (IS_ERR(mdwc->hsusb_vddcx)) {
 		dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
-		ret = PTR_ERR(msm->hsusb_vddcx);
+		ret = PTR_ERR(mdwc->hsusb_vddcx);
 		goto disable_ss_ldo;
 	}
 
-	ret = dwc3_hsusb_config_vddcx(1);
+	ret = dwc3_hsusb_config_vddcx(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
 		goto disable_ss_ldo;
 	}
 
-	ret = regulator_enable(context->hsusb_vddcx);
+	ret = regulator_enable(mdwc->hsusb_vddcx);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
 		goto unconfig_hs_vddcx;
 	}
 
-	ret = dwc3_hsusb_ldo_init(1);
+	ret = dwc3_hsusb_ldo_init(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
 		goto disable_hs_vddcx;
 	}
 
-	ret = dwc3_hsusb_ldo_enable(1);
+	ret = dwc3_hsusb_ldo_enable(mdwc, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
 		goto free_hs_ldo_init;
 	}
 
-	msm->id_state = msm->ext_xceiv.id = DWC3_ID_FLOAT;
-	msm->ext_xceiv.otg_capability = of_property_read_bool(node,
+	mdwc->id_state = mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+	mdwc->ext_xceiv.otg_capability = of_property_read_bool(node,
 				"qcom,otg-capability");
-	msm->charger.charging_disabled = of_property_read_bool(node,
+	mdwc->charger.charging_disabled = of_property_read_bool(node,
 				"qcom,charging-disabled");
 
-	msm->charger.skip_chg_detect = of_property_read_bool(node,
+	mdwc->charger.skip_chg_detect = of_property_read_bool(node,
 				"qcom,skip-charger-detection");
 	/*
 	 * DWC3 has separate IRQ line for OTG events (ID/BSV) and for
 	 * DP and DM linestate transitions during low power mode.
 	 */
-	msm->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
-	if (msm->hs_phy_irq < 0) {
+	mdwc->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq");
+	if (mdwc->hs_phy_irq < 0) {
 		dev_dbg(&pdev->dev, "pget_irq for hs_phy_irq failed\n");
-		msm->hs_phy_irq = 0;
+		mdwc->hs_phy_irq = 0;
 	} else {
-		ret = devm_request_irq(&pdev->dev, msm->hs_phy_irq,
+		ret = devm_request_irq(&pdev->dev, mdwc->hs_phy_irq,
 				msm_dwc3_irq, IRQF_TRIGGER_RISING,
-			       "msm_dwc3", msm);
+			       "msm_dwc3", mdwc);
 		if (ret) {
 			dev_err(&pdev->dev, "irqreq HSPHYINT failed\n");
 			goto disable_hs_ldo;
 		}
-		enable_irq_wake(msm->hs_phy_irq);
+		enable_irq_wake(mdwc->hs_phy_irq);
 	}
 
-	if (msm->ext_xceiv.otg_capability) {
-		msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
-		if (msm->pmic_id_irq > 0) {
+	if (mdwc->ext_xceiv.otg_capability) {
+		mdwc->pmic_id_irq =
+			platform_get_irq_byname(pdev, "pmic_id_irq");
+		if (mdwc->pmic_id_irq > 0) {
 			/* check if PMIC ID IRQ is supported */
 			ret = qpnp_misc_irqs_available(&pdev->dev);
 
@@ -2754,14 +2766,15 @@
 				/* qpnp hasn't probed yet; defer dwc probe */
 				goto disable_hs_ldo;
 			} else if (ret == 0) {
-				msm->pmic_id_irq = 0;
+				mdwc->pmic_id_irq = 0;
 			} else {
 				ret = devm_request_irq(&pdev->dev,
-						       msm->pmic_id_irq,
+						       mdwc->pmic_id_irq,
 						       dwc3_pmic_id_irq,
 						       IRQF_TRIGGER_RISING |
 						       IRQF_TRIGGER_FALLING,
-						       "dwc3_msm_pmic_id", msm);
+						       "dwc3_msm_pmic_id",
+						       mdwc);
 				if (ret) {
 					dev_err(&pdev->dev, "irqreq IDINT failed\n");
 					goto disable_hs_ldo;
@@ -2769,21 +2782,21 @@
 
 				local_irq_save(flags);
 				/* Update initial ID state */
-				msm->id_state =
-					!!irq_read_line(msm->pmic_id_irq);
-				if (msm->id_state == DWC3_ID_GROUND)
+				mdwc->id_state =
+					!!irq_read_line(mdwc->pmic_id_irq);
+				if (mdwc->id_state == DWC3_ID_GROUND)
 					queue_work(system_nrt_wq,
-							&msm->id_work);
+							&mdwc->id_work);
 				local_irq_restore(flags);
-				enable_irq_wake(msm->pmic_id_irq);
+				enable_irq_wake(mdwc->pmic_id_irq);
 			}
 		}
 
-		if (msm->pmic_id_irq <= 0) {
+		if (mdwc->pmic_id_irq <= 0) {
 			/* If no PMIC ID IRQ, use ADC for ID pin detection */
-			queue_work(system_nrt_wq, &msm->init_adc_work.work);
+			queue_work(system_nrt_wq, &mdwc->init_adc_work.work);
 			device_create_file(&pdev->dev, &dev_attr_adc_enable);
-			msm->pmic_id_irq = 0;
+			mdwc->pmic_id_irq = 0;
 		}
 	}
 
@@ -2813,59 +2826,60 @@
 		goto disable_hs_ldo;
 	}
 
-	msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
+	mdwc->base = devm_ioremap_nocache(&pdev->dev, res->start,
 		resource_size(res));
-	if (!msm->base) {
+	if (!mdwc->base) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENODEV;
 		goto disable_hs_ldo;
 	}
 
-	msm->io_res = res; /* used to calculate chg block offset */
+	mdwc->io_res = res; /* used to calculate chg block offset */
 
 	if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
-						&msm->hsphy_init_seq))
+						&mdwc->hsphy_init_seq))
 		dev_dbg(&pdev->dev, "unable to read hsphy init seq\n");
-	else if (!msm->hsphy_init_seq)
+	else if (!mdwc->hsphy_init_seq)
 		dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
 
-	dwc3_msm_qscratch_reg_init(msm);
+	dwc3_msm_qscratch_reg_init(mdwc);
 
-	pm_runtime_set_active(msm->dev);
-	pm_runtime_enable(msm->dev);
+	pm_runtime_set_active(mdwc->dev);
+	pm_runtime_enable(mdwc->dev);
 
 	if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
-				 &msm->dbm_num_eps)) {
+				 &mdwc->dbm_num_eps)) {
 		dev_err(&pdev->dev,
 			"unable to read platform data num of dbm eps\n");
-		msm->dbm_num_eps = DBM_MAX_EPS;
+		mdwc->dbm_num_eps = DBM_MAX_EPS;
 	}
 
-	if (msm->dbm_num_eps > DBM_MAX_EPS) {
+	if (mdwc->dbm_num_eps > DBM_MAX_EPS) {
 		dev_err(&pdev->dev,
 			"Driver doesn't support number of DBM EPs. "
 			"max: %d, dbm_num_eps: %d\n",
-			DBM_MAX_EPS, msm->dbm_num_eps);
+			DBM_MAX_EPS, mdwc->dbm_num_eps);
 		ret = -ENODEV;
 		goto disable_hs_ldo;
 	}
 
 	/* usb_psy required only for vbus_notifications or charging support */
-	if (msm->ext_xceiv.otg_capability || !msm->charger.charging_disabled) {
-		msm->usb_psy.name = "usb";
-		msm->usb_psy.type = POWER_SUPPLY_TYPE_USB;
-		msm->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
-		msm->usb_psy.num_supplicants = ARRAY_SIZE(
+	if (mdwc->ext_xceiv.otg_capability ||
+			!mdwc->charger.charging_disabled) {
+		mdwc->usb_psy.name = "usb";
+		mdwc->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+		mdwc->usb_psy.supplied_to = dwc3_msm_pm_power_supplied_to;
+		mdwc->usb_psy.num_supplicants = ARRAY_SIZE(
 						dwc3_msm_pm_power_supplied_to);
-		msm->usb_psy.properties = dwc3_msm_pm_power_props_usb;
-		msm->usb_psy.num_properties =
+		mdwc->usb_psy.properties = dwc3_msm_pm_power_props_usb;
+		mdwc->usb_psy.num_properties =
 					ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
-		msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
-		msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
-		msm->usb_psy.external_power_changed =
+		mdwc->usb_psy.get_property = dwc3_msm_power_get_property_usb;
+		mdwc->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+		mdwc->usb_psy.external_power_changed =
 					dwc3_msm_external_power_changed;
 
-		ret = power_supply_register(&pdev->dev, &msm->usb_psy);
+		ret = power_supply_register(&pdev->dev, &mdwc->usb_psy);
 		if (ret < 0) {
 			dev_err(&pdev->dev,
 					"%s:power_supply_register usb failed\n",
@@ -2883,27 +2897,28 @@
 		}
 	}
 
-	msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
-	if (!msm->bus_scale_table) {
+	mdwc->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+	if (!mdwc->bus_scale_table) {
 		dev_err(&pdev->dev, "bus scaling is disabled\n");
 	} else {
-		msm->bus_perf_client =
-			msm_bus_scale_register_client(msm->bus_scale_table);
+		mdwc->bus_perf_client =
+			msm_bus_scale_register_client(mdwc->bus_scale_table);
 		ret = msm_bus_scale_client_update_request(
-						msm->bus_perf_client, 1);
+						mdwc->bus_perf_client, 1);
 		if (ret)
 			dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
 	}
 
-	msm->otg_xceiv = usb_get_transceiver();
+	mdwc->otg_xceiv = usb_get_transceiver();
 	/* Register with OTG if present, ignore USB2 OTG using other PHY */
-	if (msm->otg_xceiv && !(msm->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
+	if (mdwc->otg_xceiv &&
+			!(mdwc->otg_xceiv->flags & ENABLE_SECONDARY_PHY)) {
 		/* Skip charger detection for simulator targets */
-		if (!msm->charger.skip_chg_detect) {
-			msm->charger.start_detection = dwc3_start_chg_det;
-			ret = dwc3_set_charger(msm->otg_xceiv->otg,
-					&msm->charger);
-			if (ret || !msm->charger.notify_detection_complete) {
+		if (!mdwc->charger.skip_chg_detect) {
+			mdwc->charger.start_detection = dwc3_start_chg_det;
+			ret = dwc3_set_charger(mdwc->otg_xceiv->otg,
+					&mdwc->charger);
+			if (ret || !mdwc->charger.notify_detection_complete) {
 				dev_err(&pdev->dev,
 					"failed to register charger: %d\n",
 					ret);
@@ -2911,129 +2926,130 @@
 			}
 		}
 
-		if (msm->ext_xceiv.otg_capability)
-			msm->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
-		ret = dwc3_set_ext_xceiv(msm->otg_xceiv->otg, &msm->ext_xceiv);
-		if (ret || !msm->ext_xceiv.notify_ext_events) {
+		if (mdwc->ext_xceiv.otg_capability)
+			mdwc->ext_xceiv.ext_block_reset = dwc3_msm_block_reset;
+		ret = dwc3_set_ext_xceiv(mdwc->otg_xceiv->otg,
+						&mdwc->ext_xceiv);
+		if (ret || !mdwc->ext_xceiv.notify_ext_events) {
 			dev_err(&pdev->dev, "failed to register xceiver: %d\n",
 									ret);
 			goto put_xcvr;
 		}
 	} else {
 		dev_dbg(&pdev->dev, "No OTG, DWC3 running in host only mode\n");
-		msm->host_mode = 1;
-		msm->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
-		if (IS_ERR(msm->vbus_otg)) {
+		mdwc->host_mode = 1;
+		mdwc->vbus_otg = devm_regulator_get(&pdev->dev, "vbus_dwc3");
+		if (IS_ERR(mdwc->vbus_otg)) {
 			dev_dbg(&pdev->dev, "Failed to get vbus regulator\n");
-			msm->vbus_otg = 0;
+			mdwc->vbus_otg = 0;
 		} else {
-			ret = regulator_enable(msm->vbus_otg);
+			ret = regulator_enable(mdwc->vbus_otg);
 			if (ret) {
-				msm->vbus_otg = 0;
+				mdwc->vbus_otg = 0;
 				dev_err(&pdev->dev, "Failed to enable vbus_otg\n");
 			}
 		}
-		msm->otg_xceiv = NULL;
+		mdwc->otg_xceiv = NULL;
 	}
-	if (msm->ext_xceiv.otg_capability && msm->charger.start_detection) {
-		ret = dwc3_msm_setup_cdev(msm);
+	if (mdwc->ext_xceiv.otg_capability && mdwc->charger.start_detection) {
+		ret = dwc3_msm_setup_cdev(mdwc);
 		if (ret)
 			dev_err(&pdev->dev, "Fail to setup dwc3 setup cdev\n");
 	}
 
-	wake_lock_init(&msm->wlock, WAKE_LOCK_SUSPEND, "msm_dwc3");
-	wake_lock(&msm->wlock);
-	dwc3_debugfs_init(msm);
+	device_init_wakeup(mdwc->dev, 1);
+	pm_stay_awake(mdwc->dev);
+	dwc3_debugfs_init(mdwc);
 
 	return 0;
 
 put_xcvr:
-	usb_put_transceiver(msm->otg_xceiv);
+	usb_put_transceiver(mdwc->otg_xceiv);
 put_psupply:
-	if (msm->usb_psy.dev)
-		power_supply_unregister(&msm->usb_psy);
+	if (mdwc->usb_psy.dev)
+		power_supply_unregister(&mdwc->usb_psy);
 disable_hs_ldo:
-	dwc3_hsusb_ldo_enable(0);
+	dwc3_hsusb_ldo_enable(mdwc, 0);
 free_hs_ldo_init:
-	dwc3_hsusb_ldo_init(0);
+	dwc3_hsusb_ldo_init(mdwc, 0);
 disable_hs_vddcx:
-	regulator_disable(context->hsusb_vddcx);
+	regulator_disable(mdwc->hsusb_vddcx);
 unconfig_hs_vddcx:
-	dwc3_hsusb_config_vddcx(0);
+	dwc3_hsusb_config_vddcx(mdwc, 0);
 disable_ss_ldo:
-	dwc3_ssusb_ldo_enable(0);
+	dwc3_ssusb_ldo_enable(mdwc, 0);
 free_ss_ldo_init:
-	dwc3_ssusb_ldo_init(0);
+	dwc3_ssusb_ldo_init(mdwc, 0);
 disable_ss_vddcx:
-	regulator_disable(context->ssusb_vddcx);
+	regulator_disable(mdwc->ssusb_vddcx);
 unconfig_ss_vddcx:
-	dwc3_ssusb_config_vddcx(0);
+	dwc3_ssusb_config_vddcx(mdwc, 0);
 disable_ref_clk:
-	clk_disable_unprepare(msm->ref_clk);
+	clk_disable_unprepare(mdwc->ref_clk);
 disable_utmi_clk:
-	clk_disable_unprepare(msm->utmi_clk);
+	clk_disable_unprepare(mdwc->utmi_clk);
 disable_sleep_a_clk:
-	clk_disable_unprepare(msm->hsphy_sleep_clk);
+	clk_disable_unprepare(mdwc->hsphy_sleep_clk);
 disable_sleep_clk:
-	clk_disable_unprepare(msm->sleep_clk);
+	clk_disable_unprepare(mdwc->sleep_clk);
 disable_iface_clk:
-	clk_disable_unprepare(msm->iface_clk);
+	clk_disable_unprepare(mdwc->iface_clk);
 disable_core_clk:
-	clk_disable_unprepare(msm->core_clk);
+	clk_disable_unprepare(mdwc->core_clk);
 disable_xo:
-	clk_disable_unprepare(msm->xo_clk);
+	clk_disable_unprepare(mdwc->xo_clk);
 put_xo:
-	clk_put(msm->xo_clk);
+	clk_put(mdwc->xo_clk);
 disable_dwc3_gdsc:
-	dwc3_msm_config_gdsc(msm, 0);
+	dwc3_msm_config_gdsc(mdwc, 0);
 
 	return ret;
 }
 
 static int __devexit dwc3_msm_remove(struct platform_device *pdev)
 {
-	struct dwc3_msm	*msm = platform_get_drvdata(pdev);
+	struct dwc3_msm	*mdwc = platform_get_drvdata(pdev);
 
-	if (!msm->ext_chg_device) {
-		device_destroy(msm->ext_chg_class, msm->ext_chg_dev);
-		cdev_del(&msm->ext_chg_cdev);
-		class_destroy(msm->ext_chg_class);
-		unregister_chrdev_region(msm->ext_chg_dev, 1);
+	if (!mdwc->ext_chg_device) {
+		device_destroy(mdwc->ext_chg_class, mdwc->ext_chg_dev);
+		cdev_del(&mdwc->ext_chg_cdev);
+		class_destroy(mdwc->ext_chg_class);
+		unregister_chrdev_region(mdwc->ext_chg_dev, 1);
 	}
 
-	if (msm->id_adc_detect)
+	if (mdwc->id_adc_detect)
 		qpnp_adc_tm_usbid_end();
 	if (dwc3_debugfs_root)
 		debugfs_remove_recursive(dwc3_debugfs_root);
-	if (msm->otg_xceiv) {
-		dwc3_start_chg_det(&msm->charger, false);
-		usb_put_transceiver(msm->otg_xceiv);
+	if (mdwc->otg_xceiv) {
+		dwc3_start_chg_det(&mdwc->charger, false);
+		usb_put_transceiver(mdwc->otg_xceiv);
 	}
-	if (msm->usb_psy.dev)
-		power_supply_unregister(&msm->usb_psy);
-	if (msm->vbus_otg)
-		regulator_disable(msm->vbus_otg);
+	if (mdwc->usb_psy.dev)
+		power_supply_unregister(&mdwc->usb_psy);
+	if (mdwc->vbus_otg)
+		regulator_disable(mdwc->vbus_otg);
 
-	pm_runtime_disable(msm->dev);
-	wake_lock_destroy(&msm->wlock);
+	pm_runtime_disable(mdwc->dev);
+	device_init_wakeup(mdwc->dev, 0);
 
-	dwc3_hsusb_ldo_enable(0);
-	dwc3_hsusb_ldo_init(0);
-	regulator_disable(msm->hsusb_vddcx);
-	dwc3_hsusb_config_vddcx(0);
-	dwc3_ssusb_ldo_enable(0);
-	dwc3_ssusb_ldo_init(0);
-	regulator_disable(msm->ssusb_vddcx);
-	dwc3_ssusb_config_vddcx(0);
-	clk_disable_unprepare(msm->core_clk);
-	clk_disable_unprepare(msm->iface_clk);
-	clk_disable_unprepare(msm->sleep_clk);
-	clk_disable_unprepare(msm->hsphy_sleep_clk);
-	clk_disable_unprepare(msm->ref_clk);
-	clk_disable_unprepare(msm->xo_clk);
-	clk_put(msm->xo_clk);
+	dwc3_hsusb_ldo_enable(mdwc, 0);
+	dwc3_hsusb_ldo_init(mdwc, 0);
+	regulator_disable(mdwc->hsusb_vddcx);
+	dwc3_hsusb_config_vddcx(mdwc, 0);
+	dwc3_ssusb_ldo_enable(mdwc, 0);
+	dwc3_ssusb_ldo_init(mdwc, 0);
+	regulator_disable(mdwc->ssusb_vddcx);
+	dwc3_ssusb_config_vddcx(mdwc, 0);
+	clk_disable_unprepare(mdwc->core_clk);
+	clk_disable_unprepare(mdwc->iface_clk);
+	clk_disable_unprepare(mdwc->sleep_clk);
+	clk_disable_unprepare(mdwc->hsphy_sleep_clk);
+	clk_disable_unprepare(mdwc->ref_clk);
+	clk_disable_unprepare(mdwc->xo_clk);
+	clk_put(mdwc->xo_clk);
 
-	dwc3_msm_config_gdsc(msm, 0);
+	dwc3_msm_config_gdsc(mdwc, 0);
 
 	return 0;
 }
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 1bc7757..a7bea63 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -218,7 +218,7 @@
 		 */
 		if (ext_xceiv && ext_xceiv->otg_capability &&
 						ext_xceiv->ext_block_reset)
-			ext_xceiv->ext_block_reset(true);
+			ext_xceiv->ext_block_reset(ext_xceiv, true);
 
 		dwc3_otg_set_peripheral_regs(dotg);
 
@@ -285,7 +285,7 @@
 		 * DBM reset is required, hence perform only DBM reset here */
 		if (ext_xceiv && ext_xceiv->otg_capability &&
 						ext_xceiv->ext_block_reset)
-			ext_xceiv->ext_block_reset(false);
+			ext_xceiv->ext_block_reset(ext_xceiv, false);
 
 		dwc3_otg_set_peripheral_regs(dotg);
 		usb_gadget_vbus_connect(otg->gadget);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 28573a1..7adf874 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -114,7 +114,8 @@
 	void	(*notify_ext_events)(struct usb_otg *otg,
 					enum dwc3_ext_events ext_event);
 	/* for block reset USB core */
-	void	(*ext_block_reset)(bool core_reset);
+	void	(*ext_block_reset)(struct dwc3_ext_xceiv *ext_xceiv,
+					bool core_reset);
 };
 
 /* for external transceiver driver */
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e7074a2..3f8d924 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1853,6 +1853,14 @@
 
 
 	spin_lock_irqsave(mep->lock, flags);
+
+	if (_udc && (!_udc->vbus_active || _udc->suspended)) {
+		pr_debug("ep%d%s prime timer when vbus_active=%d,suspend=%d\n",
+			mep->num, mep->dir ? "IN" : "OUT",
+			_udc->vbus_active, _udc->suspended);
+		goto out;
+	}
+
 	if (!hw_cread(CAP_ENDPTPRIME, BIT(n)))
 		goto out;
 
@@ -2197,6 +2205,9 @@
 	if (mEp == NULL)
 		return -EINVAL;
 
+	del_timer(&mEp->prime_timer);
+	mEp->prime_timer_count = 0;
+
 	hw_ep_flush(mEp->num, mEp->dir);
 
 	while (!list_empty(&mEp->qh.queue)) {
@@ -2926,8 +2937,6 @@
 
 	/* only internal SW should disable ctrl endpts */
 
-	del_timer(&mEp->prime_timer);
-	mEp->prime_timer_count = 0;
 	direction = mEp->dir;
 	do {
 		dbg_event(_usb_addr(mEp), "DISABLE", 0);
@@ -3282,8 +3291,6 @@
 
 	spin_lock_irqsave(mEp->lock, flags);
 
-	del_timer(&mEp->prime_timer);
-	mEp->prime_timer_count = 0;
 	dbg_event(_usb_addr(mEp), "FFLUSH", 0);
 	/*
 	 * _ep_nuke() takes care of flushing the endpoint.
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index cece500..f90967f 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -790,6 +790,7 @@
 void usb_qdss_close(struct usb_qdss_ch *ch)
 {
 	struct f_qdss *qdss = ch->priv_usb;
+	struct usb_gadget *gadget = qdss->cdev->gadget;
 	unsigned long flags;
 
 	pr_debug("usb_qdss_close\n");
@@ -801,7 +802,7 @@
 	ch->app_conn = 0;
 	spin_unlock_irqrestore(&d_lock, flags);
 
-	msm_dwc3_restart_usb_session();
+	msm_dwc3_restart_usb_session(gadget);
 }
 EXPORT_SYMBOL(usb_qdss_close);
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 823229b..8b1f3a8 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -48,7 +48,7 @@
 		return retval;
 
 	/* bursts of unspecified length. */
-	writel(0, USB_AHBBURST);
+	writel_relaxed(0, USB_AHBBURST);
 	/* Use the AHB transactor */
 	writel_relaxed(0x08, USB_AHBMODE);
 	/* Disable streaming mode and select host mode */
@@ -60,6 +60,10 @@
 							USB_PHY_CTRL2);
 	}
 
+	/* Disable ULPI_TX_PKT_EN_CLR_FIX which is valid only for HSIC */
+	writel_relaxed(readl_relaxed(USB_GENCONFIG2) & ~(1<<19),
+					USB_GENCONFIG2);
+
 	ehci_port_power(ehci, 1);
 	return 0;
 }
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index eb65509..fa1932b 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -36,6 +36,7 @@
 #include <linux/usb/quirks.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/msm_ext_chg.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/misc.h>
@@ -888,7 +889,7 @@
 	bool floated_charger;
 	u32 phy_ctrl_val = 0, cmd_val;
 	unsigned ret;
-	u32 portsc;
+	u32 portsc, config2;
 
 	if (atomic_read(&motg->in_lpm))
 		return 0;
@@ -906,6 +907,17 @@
 	prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
 	floated_charger = motg->chg_type == USB_FLOATED_CHARGER;
 
+	/* Enable line state difference wakeup fix for only device and host
+	 * bus suspend scenarios.  Otherwise PHY can not be suspended when
+	 * a charger that pulls DP/DM high is connected.
+	 */
+	config2 = readl_relaxed(USB_GENCONFIG2);
+	if (device_bus_suspend)
+		config2 |= GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+	else
+		config2 &= ~GENCFG2_LINESTATE_DIFF_WAKEUP_EN;
+	writel_relaxed(config2, USB_GENCONFIG2);
+
 	/*
 	 * Abort suspend when,
 	 * 1. charging detection in progress due to cable plug-in
@@ -2207,6 +2219,8 @@
 		/* Clear alt interrupt latch and enable bits */
 		ulpi_write(phy, 0x1F, 0x92);
 		ulpi_write(phy, 0x1F, 0x95);
+		/* re-enable DP and DM pull down resistors */
+		ulpi_write(phy, 0x6, 0xB);
 		break;
 	default:
 		break;
@@ -2448,11 +2462,46 @@
 	}
 }
 
+static void msm_otg_wait_for_ext_chg_done(struct msm_otg *motg)
+{
+	struct usb_phy *phy = &motg->phy;
+	unsigned long t;
+
+	/*
+	 * Defer next cable connect event till external charger
+	 * detection is completed.
+	 */
+
+	if (motg->ext_chg_active) {
+
+		pr_debug("before msm_otg ext chg wait\n");
+
+		t = wait_for_completion_timeout(&motg->ext_chg_wait,
+				msecs_to_jiffies(3000));
+		if (!t)
+			pr_err("msm_otg ext chg wait timeout\n");
+		else
+			pr_debug("msm_otg ext chg wait done\n");
+	}
+
+	if (motg->ext_chg_opened) {
+		if (phy->flags & ENABLE_DP_MANUAL_PULLUP) {
+			ulpi_write(phy, ULPI_MISC_A_VBUSVLDEXT |
+					ULPI_MISC_A_VBUSVLDEXTSEL,
+					ULPI_CLR(ULPI_MISC_A));
+		}
+		/* clear charging register bits */
+		ulpi_write(phy, 0x3F, 0x86);
+		/* re-enable DP and DM pull-down resistors*/
+		ulpi_write(phy, 0x6, 0xB);
+	}
+}
+
 static void msm_otg_sm_work(struct work_struct *w)
 {
 	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
 	struct usb_otg *otg = motg->phy.otg;
-	bool work = 0, srp_reqd;
+	bool work = 0, srp_reqd, dcp;
 
 	pm_runtime_resume(otg->phy->dev);
 	pr_debug("%s work\n", otg_state_string(otg->phy->state));
@@ -2502,12 +2551,16 @@
 				case USB_DCP_CHARGER:
 					/* Enable VDP_SRC */
 					ulpi_write(otg->phy, 0x2, 0x85);
+					if (motg->ext_chg_opened) {
+						init_completion(
+							&motg->ext_chg_wait);
+						motg->ext_chg_active = true;
+					}
 					/* fall through */
 				case USB_PROPRIETARY_CHARGER:
 					msm_otg_notify_charger(motg,
 							IDEV_CHG_MAX);
-					pm_runtime_put_noidle(otg->phy->dev);
-					pm_runtime_suspend(otg->phy->dev);
+					pm_runtime_put_sync(otg->phy->dev);
 					break;
 				case USB_FLOATED_CHARGER:
 					msm_otg_notify_charger(motg,
@@ -2567,9 +2620,12 @@
 			clear_bit(B_FALSE_SDP, &motg->inputs);
 			clear_bit(A_BUS_REQ, &motg->inputs);
 			cancel_delayed_work_sync(&motg->chg_work);
+			dcp = (motg->chg_type == USB_DCP_CHARGER);
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 			motg->chg_type = USB_INVALID_CHARGER;
 			msm_otg_notify_charger(motg, 0);
+			if (dcp)
+				msm_otg_wait_for_ext_chg_done(motg);
 			msm_otg_reset(otg->phy);
 			/*
 			 * There is a small window where ID interrupt
@@ -3552,6 +3608,9 @@
 	case POWER_SUPPLY_PROP_ONLINE:
 		val->intval = motg->online;
 		break;
+	case POWER_SUPPLY_PROP_TYPE:
+		val->intval = psy->type;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3576,6 +3635,9 @@
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		motg->current_max = val->intval;
 		break;
+	case POWER_SUPPLY_PROP_TYPE:
+		psy->type = val->intval;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3608,6 +3670,7 @@
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_SCOPE,
+	POWER_SUPPLY_PROP_TYPE,
 };
 
 const struct file_operations msm_otg_bus_fops = {
@@ -3828,6 +3891,168 @@
 	return 0;
 }
 
+static int msm_otg_ext_chg_open(struct inode *inode, struct file *file)
+{
+	struct msm_otg *motg = the_msm_otg;
+
+	pr_debug("msm_otg ext chg open\n");
+
+	motg->ext_chg_opened = true;
+	file->private_data = (void *)motg;
+	return 0;
+}
+
+static long
+msm_otg_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct msm_otg *motg = file->private_data;
+	struct msm_usb_chg_info info = {0};
+	int ret = 0, val;
+
+	switch (cmd) {
+	case MSM_USB_EXT_CHG_INFO:
+		info.chg_block_type = USB_CHG_BLOCK_ULPI;
+		info.page_offset = motg->io_res->start & ~PAGE_MASK;
+		/* mmap() works on PAGE granularity */
+		info.length = PAGE_SIZE;
+
+		if (copy_to_user((void __user *)arg, &info, sizeof(info))) {
+			pr_err("%s: copy to user failed\n\n", __func__);
+			ret = -EFAULT;
+		}
+		break;
+	case MSM_USB_EXT_CHG_BLOCK_LPM:
+		if (get_user(val, (int __user *)arg)) {
+			pr_err("%s: get_user failed\n\n", __func__);
+			ret = -EFAULT;
+			break;
+		}
+		pr_debug("%s: LPM block request %d\n", __func__, val);
+		if (val) { /* block LPM */
+			if (motg->chg_type == USB_DCP_CHARGER) {
+				/*
+				 * If device is already suspended, resume it.
+				 * The PM usage counter is incremented in
+				 * runtime resume method.  if device is not
+				 * suspended, cancel the scheduled suspend
+				 * and increment the PM usage counter.
+				 */
+				if (pm_runtime_suspended(motg->phy.dev))
+					pm_runtime_resume(motg->phy.dev);
+				else
+					pm_runtime_get_sync(motg->phy.dev);
+			} else {
+				motg->ext_chg_active = false;
+				complete(&motg->ext_chg_wait);
+				ret = -ENODEV;
+			}
+		} else {
+			motg->ext_chg_active = false;
+			complete(&motg->ext_chg_wait);
+			pm_runtime_put(motg->phy.dev);
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int msm_otg_ext_chg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct msm_otg *motg = file->private_data;
+	unsigned long vsize = vma->vm_end - vma->vm_start;
+	int ret;
+
+	if (vma->vm_pgoff || vsize > PAGE_SIZE)
+		return -EINVAL;
+
+	vma->vm_pgoff = __phys_to_pfn(motg->io_res->start);
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+				 vsize, vma->vm_page_prot);
+	if (ret < 0) {
+		pr_err("%s: failed with return val %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int msm_otg_ext_chg_release(struct inode *inode, struct file *file)
+{
+	struct msm_otg *motg = file->private_data;
+
+	pr_debug("msm_otg ext chg release\n");
+
+	motg->ext_chg_opened = false;
+
+	return 0;
+}
+
+static const struct file_operations msm_otg_ext_chg_fops = {
+	.owner = THIS_MODULE,
+	.open = msm_otg_ext_chg_open,
+	.unlocked_ioctl = msm_otg_ext_chg_ioctl,
+	.mmap = msm_otg_ext_chg_mmap,
+	.release = msm_otg_ext_chg_release,
+};
+
+static int msm_otg_setup_ext_chg_cdev(struct msm_otg *motg)
+{
+	int ret;
+
+	if (motg->pdata->enable_sec_phy || motg->pdata->mode == USB_HOST ||
+			motg->pdata->otg_control != OTG_PMIC_CONTROL ||
+			psy != &motg->usb_psy) {
+		pr_debug("usb ext chg is not supported by msm otg\n");
+		return -ENODEV;
+	}
+
+	ret = alloc_chrdev_region(&motg->ext_chg_dev, 0, 1, "usb_ext_chg");
+	if (ret < 0) {
+		pr_err("Fail to allocate usb ext char dev region\n");
+		return ret;
+	}
+	motg->ext_chg_class = class_create(THIS_MODULE, "msm_ext_chg");
+	if (ret < 0) {
+		pr_err("Fail to create usb ext chg class\n");
+		goto unreg_chrdev;
+	}
+	cdev_init(&motg->ext_chg_cdev, &msm_otg_ext_chg_fops);
+	motg->ext_chg_cdev.owner = THIS_MODULE;
+
+	ret = cdev_add(&motg->ext_chg_cdev, motg->ext_chg_dev, 1);
+	if (ret < 0) {
+		pr_err("Fail to add usb ext chg cdev\n");
+		goto destroy_class;
+	}
+	motg->ext_chg_device = device_create(motg->ext_chg_class,
+					NULL, motg->ext_chg_dev, NULL,
+					"usb_ext_chg");
+	if (IS_ERR(motg->ext_chg_device)) {
+		pr_err("Fail to create usb ext chg device\n");
+		ret = PTR_ERR(motg->ext_chg_device);
+		motg->ext_chg_device = NULL;
+		goto del_cdev;
+	}
+
+	init_completion(&motg->ext_chg_wait);
+	pr_debug("msm otg ext chg cdev setup success\n");
+	return 0;
+
+del_cdev:
+	cdev_del(&motg->ext_chg_cdev);
+destroy_class:
+	class_destroy(motg->ext_chg_class);
+unreg_chrdev:
+	unregister_chrdev_region(motg->ext_chg_dev, 1);
+
+	return ret;
+}
+
 struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
@@ -4029,6 +4254,7 @@
 		goto put_pclk;
 	}
 
+	motg->io_res = res;
 	motg->regs = ioremap(res->start, resource_size(res));
 	if (!motg->regs) {
 		dev_err(&pdev->dev, "ioremap failed\n");
@@ -4292,6 +4518,10 @@
 	if (legacy_power_supply && pdata->otg_control == OTG_PMIC_CONTROL)
 		pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
 
+	ret = msm_otg_setup_ext_chg_cdev(motg);
+	if (ret)
+		dev_dbg(&pdev->dev, "fail to setup cdev\n");
+
 	return 0;
 
 remove_phy:
@@ -4353,6 +4583,13 @@
 	if (phy->otg->host || phy->otg->gadget)
 		return -EBUSY;
 
+	if (!motg->ext_chg_device) {
+		device_destroy(motg->ext_chg_class, motg->ext_chg_dev);
+		cdev_del(&motg->ext_chg_cdev);
+		class_destroy(motg->ext_chg_class);
+		unregister_chrdev_region(motg->ext_chg_dev, 1);
+	}
+
 	if (pdev->dev.of_node)
 		msm_otg_setup_devices(pdev, motg->pdata->mode, false);
 	if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
@@ -4444,8 +4681,25 @@
 
 	if (phy->state == OTG_STATE_UNDEFINED)
 		return -EAGAIN;
-	else
-		return 0;
+
+	if (motg->ext_chg_active) {
+		dev_dbg(dev, "Deferring LPM\n");
+		/*
+		 * Charger detection may happen in user space.
+		 * Delay entering LPM by 3 sec.  Otherwise we
+		 * have to exit LPM when user space begins
+		 * charger detection.
+		 *
+		 * This timer will be canceled when user space
+		 * votes against LPM by incrementing PM usage
+		 * counter.  We enter low power mode when
+		 * PM usage counter is decremented.
+		 */
+		pm_schedule_suspend(dev, 3000);
+		return -EAGAIN;
+	}
+
+	return 0;
 }
 
 static int msm_otg_runtime_suspend(struct device *dev)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 04cd78c..7edf3d2 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -871,7 +871,7 @@
 
 	ret = session->dma->get_histo(session->dma);
 	if (ret) {
-		pr_err("mdp3_histogram_collect error = %d\n", ret);
+		pr_debug("mdp3_histogram_collect error = %d\n", ret);
 		return ret;
 	}
 
@@ -920,11 +920,53 @@
 	return ret;
 }
 
+static int mdp3_csc_config(struct mdp3_session_data *session,
+					struct mdp_csc_cfg_data *data)
+{
+	struct mdp3_dma_color_correct_config config;
+	struct mdp3_dma_ccs ccs;
+	int ret = -EINVAL;
+
+	if (!data->csc_data.csc_mv || !data->csc_data.csc_pre_bv ||
+		!data->csc_data.csc_post_bv || !data->csc_data.csc_pre_lv ||
+			!data->csc_data.csc_post_lv) {
+		pr_err("%s : Invalid csc vectors", __func__);
+		return -EINVAL;
+	}
+
+	session->cc_vect_sel = (session->cc_vect_sel + 1) % 2;
+
+	config.ccs_enable = 1;
+	config.ccs_sel = session->cc_vect_sel;
+	config.pre_limit_sel = session->cc_vect_sel;
+	config.post_limit_sel = session->cc_vect_sel;
+	config.pre_bias_sel = session->cc_vect_sel;
+	config.post_bias_sel = session->cc_vect_sel;
+	config.ccs_dirty = true;
+
+	ccs.mv = data->csc_data.csc_mv;
+	ccs.pre_bv = data->csc_data.csc_pre_bv;
+	ccs.post_bv = data->csc_data.csc_post_bv;
+	ccs.pre_lv = data->csc_data.csc_pre_lv;
+	ccs.post_lv = data->csc_data.csc_post_lv;
+
+	mutex_lock(&session->lock);
+	ret = session->dma->config_ccs(session->dma, &config, &ccs);
+	mutex_unlock(&session->lock);
+	return ret;
+}
+
 static int mdp3_pp_ioctl(struct msm_fb_data_type *mfd,
 					void __user *argp)
 {
 	int ret = -EINVAL;
 	struct msmfb_mdp_pp mdp_pp;
+	struct mdp3_session_data *mdp3_session;
+
+	if (!mfd || !mfd->mdp.private1)
+		return -EINVAL;
+
+	mdp3_session = mfd->mdp.private1;
 
 	ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
 	if (ret)
@@ -935,6 +977,11 @@
 		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_csc_config(mdp3_session,
+						&(mdp_pp.data.csc_cfg_data));
+		break;
+
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL.\n");
 		ret = -EINVAL;
@@ -1022,6 +1069,7 @@
 	lut_config.lut_enable = 7;
 	lut_config.lut_sel = mdp3_session->lut_sel;
 	lut_config.lut_position = 0;
+	lut_config.lut_dirty = true;
 	lut.color0_lut = r;
 	lut.color1_lut = g;
 	lut.color2_lut = b;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index 0bbc2ac..9ea1c91 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -50,6 +50,7 @@
 	int histo_status;
 	struct mutex histo_lock;
 	int lut_sel;
+	int cc_vect_sel;
 };
 
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 3b65405..2e9c787 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -219,6 +219,25 @@
 	}
 }
 
+static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
+{
+	u32 cgc;
+	int clock_bit = 10;
+
+	clock_bit += dma->dma_sel;
+
+	if (enable) {
+		cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+		cgc |= BIT(clock_bit);
+		MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+	} else {
+		cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
+		cgc &= ~BIT(clock_bit);
+		MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+	}
+}
+
 static int mdp3_dma_sync_config(struct mdp3_dma *dma,
 			struct mdp3_dma_source *source_config)
 {
@@ -347,11 +366,109 @@
 	return 0;
 }
 
+static void mdp3_ccs_update(struct mdp3_dma *dma)
+{
+	u32 cc_config;
+	int updated = 0;
+
+	cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
+
+	if (dma->ccs_config.ccs_dirty) {
+		cc_config &= DMA_CCS_CONFIG_MASK;
+		if (dma->ccs_config.ccs_enable)
+			cc_config |= BIT(3);
+		else
+			cc_config &= ~BIT(3);
+		cc_config |= dma->ccs_config.ccs_sel << 5;
+		cc_config |= dma->ccs_config.pre_bias_sel << 6;
+		cc_config |= dma->ccs_config.post_bias_sel << 7;
+		cc_config |= dma->ccs_config.pre_limit_sel << 8;
+		cc_config |= dma->ccs_config.post_limit_sel << 9;
+		dma->ccs_config.ccs_dirty = false;
+		updated = 1;
+	}
+
+	if (dma->lut_config.lut_dirty) {
+		cc_config &= DMA_LUT_CONFIG_MASK;
+		cc_config |= dma->lut_config.lut_enable;
+		cc_config |= dma->lut_config.lut_position << 4;
+		cc_config |= dma->lut_config.lut_sel << 10;
+		dma->lut_config.lut_dirty = false;
+		updated = 1;
+	}
+	if (updated) {
+		MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
+
+		/* Make sure ccs configuration update is done before continuing
+		with the DMA transfer */
+		wmb();
+	}
+}
+
+static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
+			struct mdp3_dma_color_correct_config *config,
+			struct mdp3_dma_ccs *ccs)
+{
+	int i;
+	u32 addr;
+
+	if (!ccs)
+		return -EINVAL;
+
+	if (config->ccs_enable) {
+		addr = MDP3_REG_DMA_P_CSC_MV1;
+		if (config->ccs_sel)
+			addr = MDP3_REG_DMA_P_CSC_MV2;
+		for (i = 0; i < 9; i++) {
+			MDP3_REG_WRITE(addr, ccs->mv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
+		if (config->pre_bias_sel)
+			addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
+		for (i = 0; i < 3; i++) {
+			MDP3_REG_WRITE(addr, ccs->pre_bv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_POST_BV1;
+		if (config->post_bias_sel)
+			addr = MDP3_REG_DMA_P_CSC_POST_BV2;
+		for (i = 0; i < 3; i++) {
+			MDP3_REG_WRITE(addr, ccs->post_bv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
+		if (config->pre_limit_sel)
+			addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
+		for (i = 0; i < 6; i++) {
+			MDP3_REG_WRITE(addr, ccs->pre_lv[i]);
+			addr += 4;
+		}
+
+		addr = MDP3_REG_DMA_P_CSC_POST_LV1;
+		if (config->post_limit_sel)
+			addr = MDP3_REG_DMA_P_CSC_POST_LV2;
+		for (i = 0; i < 6; i++) {
+			MDP3_REG_WRITE(addr, ccs->post_lv[i]);
+			addr += 4;
+		}
+	}
+	dma->ccs_config = *config;
+
+	if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+		mdp3_ccs_update(dma);
+
+	return 0;
+}
+
 static int mdp3_dmap_lut_config(struct mdp3_dma *dma,
 			struct mdp3_dma_lut_config *config,
 			struct mdp3_dma_lut *lut)
 {
-	u32 cc_config, addr, color;
+	u32 addr, color;
 	int i;
 
 	if (config->lut_enable && lut) {
@@ -368,119 +485,11 @@
 		}
 	}
 
-	cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
-	cc_config &= DMA_LUT_CONFIG_MASK;
-	cc_config |= config->lut_enable;
-	cc_config |= config->lut_position << 4;
-	cc_config |= config->lut_sel << 10;
-	MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
-	wmb();
-
 	dma->lut_config = *config;
-	return 0;
-}
 
-static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
-			struct mdp3_dma_color_correct_config *config,
-			struct mdp3_dma_ccs *ccs)
-{
-	int i;
-	u32 cc_config, addr;
+	if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+		mdp3_ccs_update(dma);
 
-	cc_config = MDP3_REG_READ(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG);
-	cc_config &= DMA_CCS_CONFIG_MASK;
-	cc_config |= BIT(3);
-	cc_config |= config->ccs_sel << 5;
-	cc_config |= config->pre_bias_sel << 6;
-	cc_config |= config->post_bias_sel << 7;
-	cc_config |= config->pre_limit_sel << 8;
-	cc_config |= config->post_limit_sel << 9;
-
-	MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
-
-	if (config->ccs_enable && ccs) {
-		if (ccs->mv1) {
-			addr = MDP3_REG_DMA_P_CSC_MV1;
-			for (i = 0; i < 9; i++) {
-				MDP3_REG_WRITE(addr, ccs->mv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->mv2) {
-			addr = MDP3_REG_DMA_P_CSC_MV2;
-			for (i = 0; i < 9; i++) {
-				MDP3_REG_WRITE(addr, ccs->mv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_bv1) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_bv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_bv2) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_bv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_bv1) {
-			addr = MDP3_REG_DMA_P_CSC_POST_BV1;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_bv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_bv2) {
-			addr = MDP3_REG_DMA_P_CSC_POST_BV2;
-			for (i = 0; i < 3; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_bv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_lv1) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_lv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->pre_lv2) {
-			addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->pre_lv2[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_lv1) {
-			addr = MDP3_REG_DMA_P_CSC_POST_LV1;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_lv1[i]);
-				addr += 4;
-			}
-		}
-
-		if (ccs->post_lv2) {
-			addr = MDP3_REG_DMA_P_CSC_POST_LV2;
-			for (i = 0; i < 6; i++) {
-				MDP3_REG_WRITE(addr, ccs->post_lv2[i]);
-				addr += 4;
-			}
-		}
-	}
-
-	dma->ccs_config = *config;
 	return 0;
 }
 
@@ -528,8 +537,10 @@
 	spin_lock_irqsave(&dma->dma_lock, flag);
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
 	dma->source_config.buf = buf;
-	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD)
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		mdp3_ccs_update(dma);
 		MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+	}
 
 	if (!intf->active) {
 		pr_debug("mdp3_dmap_update start interface\n");
@@ -610,7 +621,7 @@
 	ret = wait_for_completion_killable_timeout(&dma->histo_comp, timeout);
 
 	if (ret == 0) {
-		pr_err("mdp3_dmap_histo_get time out\n");
+		pr_debug("mdp3_dmap_histo_get time out\n");
 		ret = -ETIMEDOUT;
 	} else if (ret < 0) {
 		pr_err("mdp3_dmap_histo_get interrupted\n");
@@ -682,7 +693,6 @@
 {
 	unsigned long flag;
 	int ret;
-	u32 cgc;
 
 	if (dma->histo_state == MDP3_DMA_HISTO_STATE_START)
 		return -EINVAL;
@@ -690,9 +700,8 @@
 	spin_lock_irqsave(&dma->histo_lock, flag);
 
 	init_completion(&dma->histo_comp);
-	cgc = MDP3_REG_READ(MDP3_REG_CGC_EN);
-	cgc &= ~BIT(10);
-	MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+
+	mdp3_dma_clk_auto_gating(dma, 0);
 
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, BIT(0)|BIT(1));
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
@@ -714,8 +723,7 @@
 		ret = 0;
 	}
 	mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_HIST_RESET_DONE);
-	cgc |= BIT(10);
-	MDP3_REG_WRITE(MDP3_REG_CGC_EN, cgc);
+	mdp3_dma_clk_auto_gating(dma, 1);
 
 	return ret;
 }
@@ -732,6 +740,7 @@
 	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, 0);
 	wmb();
 	dma->histo_state = MDP3_DMA_HISTO_STATE_IDLE;
+	complete(&dma->histo_comp);
 
 	spin_unlock_irqrestore(&dma->histo_lock, flag);
 
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 518bd58..c652818 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -176,16 +176,11 @@
 };
 
 struct mdp3_dma_ccs {
-	u32 *mv1; /*set1 matrix vector, 3x3 */
-	u32 *mv2;
-	u32 *pre_bv1; /*pre-bias vector for set1, 1x3*/
-	u32 *pre_bv2;
-	u32 *post_bv1; /*post-bias vecotr for set1,  */
-	u32 *post_bv2;
-	u32 *pre_lv1; /*pre-limit vector for set 1, 1x6*/
-	u32 *pre_lv2;
-	u32 *post_lv1;
-	u32 *post_lv2;
+	u32 *mv; /*set1 matrix vector, 3x3 */
+	u32 *pre_bv; /*pre-bias vector for set1, 1x3*/
+	u32 *post_bv; /*post-bias vecotr for set1,  */
+	u32 *pre_lv; /*pre-limit vector for set 1, 1x6*/
+	u32 *post_lv;
 };
 
 struct mdp3_dma_lut {
@@ -198,6 +193,7 @@
 	int lut_enable;
 	u32 lut_sel;
 	u32 lut_position;
+	bool lut_dirty;
 };
 
 struct mdp3_dma_color_correct_config {
@@ -207,6 +203,7 @@
 	u32 post_bias_sel;
 	u32 pre_bias_sel;
 	u32 ccs_sel;
+	bool ccs_dirty;
 };
 
 struct mdp3_dma_histogram_config {
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index fb0e8ba..44a5e62 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -360,13 +360,13 @@
 				__func__, rc);
 			goto error;
 		}
-		mp->vreg_config[i].peak_current = val_array[i];
+		mp->vreg_config[i].enable_load = val_array[i];
 
 		pr_debug("%s: %s min=%d, max=%d, pc=%d\n", __func__,
 			mp->vreg_config[i].vreg_name,
 			mp->vreg_config[i].min_voltage,
 			mp->vreg_config[i].max_voltage,
-			mp->vreg_config[i].peak_current);
+			mp->vreg_config[i].enable_load);
 	}
 
 	devm_kfree(dev, val_array);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 91e5660..e4a6b86 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -87,6 +87,9 @@
 static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
 static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
 	enum hdmi_tx_power_module_type module, int enable);
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+				bool wait_audio_tx);
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
 
 struct mdss_hw hdmi_tx_hw = {
 	.hw_ndx = MDSS_HW_HDMI,
@@ -1676,10 +1679,11 @@
 } /* hdmi_tx_powerdown_phy */
 
 static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
-	bool enabled, int num_of_channels)
+	bool enabled)
 {
 	/* Read first before writing */
 	u32 acr_pck_ctrl_reg;
+	u32 sample_rate;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -1687,6 +1691,8 @@
 		return -EINVAL;
 	}
 
+	sample_rate = hdmi_ctrl->audio_data.sample_rate;
+
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
 		DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1721,18 +1727,19 @@
 			return -EPERM;
 		}
 
-		n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
-		cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
-		layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+		n = audio_acr->lut[sample_rate].n;
+		cts = audio_acr->lut[sample_rate].cts;
+		layout = (MSM_HDMI_AUDIO_CHANNEL_2 ==
+			hdmi_ctrl->audio_data.channel_num) ? 0 : 1;
 
 		if (
-		(AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
 			multiplier = 4;
 			n >>= 2; /* divide N by 4 and use multiplier */
 		} else if (
-		(AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
 			multiplier = 2;
 			n >>= 1; /* divide N by 2 and use multiplier */
 		} else {
@@ -1743,12 +1750,16 @@
 
 		/* AUDIO_PRIORITY | SOURCE */
 		acr_pck_ctrl_reg |= 0x80000100;
+
+		/* Reset multiplier bits */
+		acr_pck_ctrl_reg &= ~(7 << 16);
+
 		/* N_MULTIPLE(multiplier) */
 		acr_pck_ctrl_reg |= (multiplier & 7) << 16;
 
-		if ((AUDIO_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+		if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
 			/* SELECT(3) */
 			acr_pck_ctrl_reg |= 3 << 4;
 			/* CTS_48 */
@@ -1759,9 +1770,9 @@
 			/* N */
 			DSS_REG_W(io, HDMI_ACR_48_1, n);
 		} else if (
-		(AUDIO_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
 			/* SELECT(2) */
 			acr_pck_ctrl_reg |= 2 << 4;
 			/* CTS_44 */
@@ -1800,12 +1811,15 @@
 } /* hdmi_tx_audio_acr_setup */
 
 static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
-	bool enabled, u32 num_of_channels, u32 channel_allocation,
-	u32 level_shift, bool down_mix)
+	bool enabled)
 {
 	struct dss_io_data *io = NULL;
 
 	u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+	u32 num_of_channels;
+	u32 channel_allocation;
+	u32 level_shift;
+	u32 down_mix;
 	u32 check_sum, audio_info_0_reg, audio_info_1_reg;
 	u32 audio_info_ctrl_reg;
 	u32 aud_pck_ctrl_2_reg;
@@ -1816,6 +1830,11 @@
 		return -EINVAL;
 	}
 
+	num_of_channels    = hdmi_ctrl->audio_data.channel_num;
+	channel_allocation = hdmi_ctrl->audio_data.spkr_alloc;
+	level_shift        = hdmi_ctrl->audio_data.level_shift;
+	down_mix           = hdmi_ctrl->audio_data.down_mix;
+
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
 		DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1926,8 +1945,8 @@
 } /* hdmi_tx_audio_iframe_setup */
 
 static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
-	u32 num_of_channels, u32 channel_allocation, u32 level_shift,
-	bool down_mix)
+	u32 sample_rate, u32 num_of_channels, u32 channel_allocation,
+	u32 level_shift, bool down_mix)
 {
 	int rc = 0;
 	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
@@ -1937,10 +1956,31 @@
 		return -ENODEV;
 	}
 
-	if (hdmi_ctrl->panel_power_on) {
-		rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true,
-			num_of_channels, channel_allocation, level_shift,
-			down_mix);
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl) && hdmi_ctrl->panel_power_on) {
+
+		/* Map given sample rate to Enum */
+		if (sample_rate == 32000)
+			sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
+		else if (sample_rate == 44100)
+			sample_rate = AUDIO_SAMPLE_RATE_44_1KHZ;
+		else if (sample_rate == 48000)
+			sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+		else if (sample_rate == 88200)
+			sample_rate = AUDIO_SAMPLE_RATE_88_2KHZ;
+		else if (sample_rate == 96000)
+			sample_rate = AUDIO_SAMPLE_RATE_96KHZ;
+		else if (sample_rate == 176400)
+			sample_rate = AUDIO_SAMPLE_RATE_176_4KHZ;
+		else if (sample_rate == 192000)
+			sample_rate = AUDIO_SAMPLE_RATE_192KHZ;
+
+		hdmi_ctrl->audio_data.sample_rate = sample_rate;
+		hdmi_ctrl->audio_data.channel_num = num_of_channels;
+		hdmi_ctrl->audio_data.spkr_alloc  = channel_allocation;
+		hdmi_ctrl->audio_data.level_shift = level_shift;
+		hdmi_ctrl->audio_data.down_mix    = down_mix;
+
+		rc = hdmi_tx_audio_setup(hdmi_ctrl);
 		if (rc)
 			DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.rc=%d\n",
 				__func__, rc);
@@ -2047,7 +2087,6 @@
 static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
-	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -2061,14 +2100,14 @@
 		return -EINVAL;
 	}
 
-	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true);
 	if (rc) {
 		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
 			__func__, rc);
 		return rc;
 	}
 
-	rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true, channels, 0, 0, false);
+	rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true);
 	if (rc) {
 		DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed. rc=%d\n",
 			__func__, rc);
@@ -2080,9 +2119,10 @@
 	return 0;
 } /* hdmi_tx_audio_setup */
 
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+				bool wait_audio_tx)
 {
-	u32 i, status, sleep_us, timeout_us, timeout_sec = 15;
+	u32 i = 0, status, sleep_us, timeout_us, timeout_sec = 15;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -2096,33 +2136,43 @@
 		return;
 	}
 
-	/* Check if audio engine is turned off by QDSP or not */
-	/* send off notification after every 1 sec for 15 seconds */
-	for (i = 0; i < timeout_sec; i++) {
-		sleep_us = 5000; /* Maximum time to sleep between two reads */
-		timeout_us = 1000 * 1000; /* Total time for condition to meet */
+	if (wait_audio_tx) {
+		/* Check if audio engine is turned off by QDSP or not */
+		/* send off notification after every 1 sec for 15 seconds */
+		for (i = 0; i < timeout_sec; i++) {
+			/* Maximum time to sleep between two reads */
+			sleep_us = 5000;
+			/* Total time for condition to meet */
+			timeout_us = 1000 * 1000;
 
-		if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
-			status, ((status & BIT(0)) == 0),
-			sleep_us, timeout_us)) {
+			if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
+				status, ((status & BIT(0)) == 0),
+				sleep_us, timeout_us)) {
 
-			DEV_ERR("%s: audio still on after %d sec. try again\n",
+				DEV_ERR(
+				"%s: audio still on after %d sec. try again\n",
 				__func__, i+1);
 
-			hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, true);
-			continue;
+				hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0,
+					true);
+				continue;
+			}
+			break;
 		}
-		break;
 	}
+
 	if (i == timeout_sec)
 		DEV_ERR("%s: Error: cannot turn off audio engine\n", __func__);
 
-	if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false, 0, 0, 0, false))
+	if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false))
 		DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.\n", __func__);
 
-	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false))
 		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
 
+	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
+
 	DEV_INFO("HDMI Audio: Disabled\n");
 } /* hdmi_tx_audio_off */
 
@@ -2239,7 +2289,7 @@
 
 	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
 		hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
-		hdmi_tx_audio_off(hdmi_ctrl);
+		hdmi_tx_audio_off(hdmi_ctrl, true);
 	}
 
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
@@ -2656,7 +2706,8 @@
 
 	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
 
-	hdmi_ctrl->audio_sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
 
 	hdmi_ctrl->sdev.name = "hdmi";
 	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
@@ -3216,13 +3267,13 @@
 				__func__, hdmi_tx_pm_name(module_type), rc);
 			goto error;
 		}
-		mp->vreg_config[j].peak_current = val_array[i];
+		mp->vreg_config[j].enable_load = val_array[i];
 
 		DEV_DBG("%s: %s min=%d, max=%d, pc=%d\n", __func__,
 			mp->vreg_config[j].vreg_name,
 			mp->vreg_config[j].min_voltage,
 			mp->vreg_config[j].max_voltage,
-			mp->vreg_config[j].peak_current);
+			mp->vreg_config[j].enable_load);
 
 		ndx_mask >>= 1;
 		j++;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index d4f8e67..18ee782 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -38,12 +38,20 @@
 	struct dss_module_power power_data[HDMI_TX_MAX_PM];
 };
 
+struct hdmi_audio {
+	int sample_rate;
+	int channel_num;
+	int spkr_alloc;
+	int level_shift;
+	int down_mix;
+};
+
 struct hdmi_tx_ctrl {
 	struct platform_device *pdev;
 	struct hdmi_tx_platform_data pdata;
 	struct mdss_panel_data panel_data;
 
-	int audio_sample_rate;
+	struct hdmi_audio audio_data;
 
 	struct mutex mutex;
 	struct kobject *kobj;
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 31058f8..c862e78 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -213,7 +213,7 @@
 			}
 			msleep(in_vreg[i].pre_on_sleep);
 			rc = regulator_set_optimum_mode(in_vreg[i].vreg,
-				in_vreg[i].peak_current);
+				in_vreg[i].enable_load);
 			if (rc < 0) {
 				DEV_ERR("%pS->%s: %s set opt m fail\n",
 					__builtin_return_address(0), __func__,
@@ -233,7 +233,8 @@
 		for (i = num_vreg-1; i >= 0; i--)
 			if (regulator_is_enabled(in_vreg[i].vreg)) {
 				msleep(in_vreg[i].pre_off_sleep);
-				regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+				regulator_set_optimum_mode(in_vreg[i].vreg,
+					in_vreg[i].disable_load);
 				regulator_disable(in_vreg[i].vreg);
 				msleep(in_vreg[i].post_off_sleep);
 			}
@@ -241,12 +242,13 @@
 	return rc;
 
 disable_vreg:
-	regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+	regulator_set_optimum_mode(in_vreg[i].vreg, in_vreg[i].disable_load);
 
 vreg_set_opt_mode_fail:
 	for (i--; i >= 0; i--) {
 		msleep(in_vreg[i].pre_off_sleep);
-		regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+		regulator_set_optimum_mode(in_vreg[i].vreg,
+			in_vreg[i].disable_load);
 		regulator_disable(in_vreg[i].vreg);
 		msleep(in_vreg[i].post_off_sleep);
 	}
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index cb0fb70..6ad21e8 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -52,7 +52,8 @@
 	char vreg_name[32];
 	int min_voltage;
 	int max_voltage;
-	int peak_current;
+	int enable_load;
+	int disable_load;
 	int pre_on_sleep;
 	int post_on_sleep;
 	int pre_off_sleep;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index d1e5e64..eaef12b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -30,6 +30,7 @@
 static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
 
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp);
 
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
 				       u32 reg, u32 val)
@@ -94,6 +95,11 @@
 	}
 }
 
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp)
+{
+	return bitmap_weight(smp, SMP_MB_CNT) == 0;
+}
+
 static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
 {
 	u32 fetch_size, val, wm[3];
@@ -227,6 +233,8 @@
 
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < MAX_PLANES; i++) {
+		if (__mdss_mdp_pipe_smp_mmb_is_empty(pipe->smp_map[i].reserved))
+			continue;
 		mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
 			pipe->smp_map[i].reserved);
 		cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
@@ -708,10 +716,9 @@
 		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
 			mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
 			opmode);
-
-		mdss_mdp_smp_alloc(pipe);
 	}
 
+	mdss_mdp_smp_alloc(pipe);
 	ret = mdss_mdp_src_addr_setup(pipe, src_data);
 	if (ret) {
 		pr_err("addr setup error for pnum=%d\n", pipe->num);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 3f03725..82b56e3 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -373,7 +373,7 @@
 
 /*  USB_HANDSHAKING FUNCTIONS */
 static int mhl_sii_device_discovery(void *data, int id,
-			     void (*usb_notify_cb)(int online))
+			     void (*usb_notify_cb)(void *, int), void *ctx)
 {
 	int rc;
 	struct mhl_tx_ctrl *mhl_ctrl = data;
@@ -398,8 +398,10 @@
 		return -EINVAL;
 	}
 
-	if (!mhl_ctrl->notify_usb_online)
+	if (!mhl_ctrl->notify_usb_online) {
 		mhl_ctrl->notify_usb_online = usb_notify_cb;
+		mhl_ctrl->notify_ctx = ctx;
+	}
 
 	if (!mhl_ctrl->disc_enabled) {
 		spin_lock_irqsave(&mhl_ctrl->lock, flags);
@@ -904,7 +906,7 @@
 		mhl_ctrl->mhl_mode = 1;
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
-			mhl_ctrl->notify_usb_online(1);
+			mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 1);
 	} else {
 		pr_debug("%s: non-mhl sink\n", __func__);
 		mhl_ctrl->mhl_mode = 0;
@@ -1004,7 +1006,7 @@
 		mhl_msm_disconnection(mhl_ctrl);
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
-			mhl_ctrl->notify_usb_online(0);
+			mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
 		return 0;
 	}
 
@@ -1019,7 +1021,7 @@
 		mhl_msm_disconnection(mhl_ctrl);
 		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
-			mhl_ctrl->notify_usb_online(0);
+			mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
 		return 0;
 	}
 
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index cfc690e..5b69884 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -39,8 +39,8 @@
 
 enum coresight_clk_rate {
 	CORESIGHT_CLK_RATE_OFF,
-	CORESIGHT_CLK_RATE_TRACE,
-	CORESIGHT_CLK_RATE_HSTRACE,
+	CORESIGHT_CLK_RATE_TRACE = 1000,
+	CORESIGHT_CLK_RATE_HSTRACE = 2000,
 };
 
 enum coresight_dev_type {
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 4fa41b5..6f00df7 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -97,6 +97,23 @@
 	uint32_t gain;
 };
 
+struct epm_marker_level {
+	uint8_t		level;
+};
+
+struct epm_gpio_buffer_request {
+	uint8_t		cmd;
+	uint8_t		bitmask_monitor_pin;
+	uint8_t		status;
+};
+
+struct epm_get_gpio_buffer_resp {
+	uint8_t		cmd;
+	uint8_t		status;
+	uint8_t		bitmask_monitor_pin;
+	uint32_t	timestamp;
+};
+
 #ifdef __KERNEL__
 struct epm_adc_platform_data {
 	struct epm_chan_properties *channel;
@@ -121,7 +138,19 @@
 #define EPM_ADC_DEINIT		_IOR(EPM_ADC_IOCTL_CODE, 3,	\
 					     uint32_t)
 
-#define EPM_PSOC_ADC_INIT		_IOR(EPM_ADC_IOCTL_CODE, 4, \
+#define EPM_MARKER1_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 90,	\
+						uint32_t)
+
+#define EPM_MARKER1_RELEASE	_IOWR(EPM_ADC_IOCTL_CODE, 91,	\
+						uint32_t)
+
+#define EPM_MARKER2_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 95,	\
+						uint32_t)
+
+#define EPM_MARKER2_RELEASE	_IOWR(EPM_ADC_IOCTL_CODE, 92,	\
+						uint32_t)
+
+#define EPM_PSOC_ADC_INIT		_IOWR(EPM_ADC_IOCTL_CODE, 4, \
 					struct epm_psoc_init_resp)
 
 #define EPM_PSOC_ADC_CHANNEL_ENABLE	_IOWR(EPM_ADC_IOCTL_CODE, 5, \
@@ -157,4 +186,13 @@
 #define EPM_PSOC_ADC_SET_VADC_REFERENCE		_IOWR(EPM_ADC_IOCTL_CODE, 15, \
 						struct epm_psoc_set_vadc)
 
+#define EPM_PSOC_ADC_DEINIT		_IOWR(EPM_ADC_IOCTL_CODE, 16,	\
+							     uint32_t)
+
+#define EPM_PSOC_GPIO_BUFFER_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 17,	\
+								uint32_t)
+
+#define EPM_PSOC_GET_GPIO_BUFFER_DATA	_IOWR(EPM_ADC_IOCTL_CODE, 18,	\
+								uint32_t)
+
 #endif /* __EPM_ADC_H */
diff --git a/include/linux/input/kxtj9.h b/include/linux/input/kxtj9.h
index d415579..65378c0 100644
--- a/include/linux/input/kxtj9.h
+++ b/include/linux/input/kxtj9.h
@@ -46,7 +46,7 @@
 	/* Output resolution: 8-bit valid or 12-bit valid */
 	#define RES_8BIT		0
 	#define RES_12BIT		(1 << 6)
-	u8 res_12bit;
+	u8 res_ctl;
 	/* Output g-range: +/-2g, 4g, or 8g */
 	#define KXTJ9_G_2G		0
 	#define KXTJ9_G_4G		(1 << 3)
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index 7297ff3..560f75b 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -137,7 +137,8 @@
 	uint8_t chip_rev_id;
 	int mhl_mode;
 	struct completion rgnd_done;
-	void (*notify_usb_online)(int online);
+	void (*notify_usb_online)(void *ctx, int online);
+	void *notify_ctx;
 	struct usb_ext_notification *mhl_info;
 	bool disc_enabled;
 	struct power_supply mhl_psy;
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index a741107..e8ca1cd 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -54,12 +54,16 @@
 #define AUDIO_SET_ASM_CUSTOM_TOPOLOGY	_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
 #define AUDIO_SET_SPEAKER_PROT _IOW(AUDIO_IOCTL_MAGIC, 25, \
-		struct msm_spk_prot_cfg)
+			struct msm_spk_prot_cfg)
 #define AUDIO_GET_SPEAKER_PROT _IOR(AUDIO_IOCTL_MAGIC, 26, \
-		struct msm_spk_prot_status)
+			struct msm_spk_prot_status)
 #define AUDIO_SET_AANC_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+27), unsigned)
-#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+30)
+#define AUDIO_REGISTER_VOCPROC_VOL_TABLE	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+28), unsigned)
+#define AUDIO_DEREGISTER_VOCPROC_VOL_TABLE	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+29), unsigned)
+#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+40)
 
 /* ACDB structures */
 struct cal_block {
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 1c9884c..f04d2bf 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -26,6 +26,7 @@
 #include <linux/pm_qos.h>
 #include <linux/hrtimer.h>
 #include <linux/power_supply.h>
+#include <linux/cdev.h>
 /*
  * The following are bit fields describing the usb_request.udc_priv word.
  * These bit fields are set by function drivers that wish to queue
@@ -347,6 +348,7 @@
 	struct clk *phy_reset_clk;
 	struct clk *core_clk;
 	long core_clk_rate;
+	struct resource *io_res;
 	void __iomem *regs;
 #define ID		0
 #define B_SESS_VLD	1
@@ -434,6 +436,14 @@
 	unsigned int online;
 	unsigned int host_mode;
 	unsigned int current_max;
+
+	dev_t ext_chg_dev;
+	struct cdev ext_chg_cdev;
+	struct class *ext_chg_class;
+	struct device *ext_chg_device;
+	bool ext_chg_opened;
+	bool ext_chg_active;
+	struct completion ext_chg_wait;
 };
 
 struct ci13xxx_platform_data {
@@ -496,7 +506,7 @@
 /**
  * struct usb_ext_notification: event notification structure
  * @notify: pointer to client function to call when ID event is detected.
- *          The last parameter is provided by driver to be called back when
+ *          The function parameter is provided by driver to be called back when
  *          external client indicates it is done using the USB. This function
  *          should return 0 if handled successfully, otherise an error code.
  * @ctxt: client-specific context pointer
@@ -510,7 +520,7 @@
  * called with the online parameter set to false.
  */
 struct usb_ext_notification {
-	int (*notify)(void *, int, void (*)(int online));
+	int (*notify)(void *, int, void (*)(void *, int online), void *);
 	void *ctxt;
 };
 #ifdef CONFIG_USB_BAM
@@ -540,7 +550,7 @@
 int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
 	u8 dst_pipe_idx);
 
-void msm_dwc3_restart_usb_session(void);
+void msm_dwc3_restart_usb_session(struct usb_gadget *gadget);
 
 int msm_register_usb_ext_notification(struct usb_ext_notification *info);
 #else
@@ -560,7 +570,7 @@
 	return -ENODEV;
 }
 
-static inline void msm_dwc3_restart_usb_session(void)
+static inline void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
 {
 	return;
 }
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index ba75cb9..064d210 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
 #define USB_HS_GPTIMER_BASE  (MSM_USB_BASE + 0x80)
 
 #define GENCFG2_SESS_VLD_CTRL_EN	BIT(7)
+#define GENCFG2_LINESTATE_DIFF_WAKEUP_EN BIT(12)
 
 #define USB_USBCMD           (MSM_USB_BASE + 0x0140)
 #define USB_USBSTS           (MSM_USB_BASE + 0x0144)
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 6358f8a..2805401 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -46,6 +46,8 @@
 
 #define MAX_EEPROM_NAME 32
 
+#define MAX_AF_ITERATIONS 3
+
 enum msm_camera_i2c_reg_addr_type {
 	MSM_CAMERA_I2C_BYTE_ADDR = 1,
 	MSM_CAMERA_I2C_WORD_ADDR,
@@ -78,6 +80,11 @@
 enum msm_sensor_power_seq_gpio_t {
 	SENSOR_GPIO_RESET,
 	SENSOR_GPIO_STANDBY,
+	SENSOR_GPIO_AF_PWDM,
+	SENSOR_GPIO_VIO,
+	SENSOR_GPIO_VANA,
+	SENSOR_GPIO_VDIG,
+	SENSOR_GPIO_VAF,
 	SENSOR_GPIO_MAX,
 };
 
@@ -133,6 +140,11 @@
 	REG_GPIO,
 };
 
+enum sensor_af_t {
+	SENSOR_AF_FOCUSSED,
+	SENSOR_AF_NOT_FOCUSSED,
+};
+
 struct msm_sensor_power_setting {
 	enum msm_sensor_power_seq_type_t seq_type;
 	uint16_t seq_val;
@@ -346,6 +358,11 @@
 	CFG_SET_RESOLUTION,
 	CFG_SET_STOP_STREAM,
 	CFG_SET_START_STREAM,
+	CFG_SET_SATURATION,
+	CFG_SET_CONTRAST,
+	CFG_SET_SHARPNESS,
+	CFG_SET_AUTOFOCUS,
+	CFG_CANCEL_AUTOFOCUS,
 };
 
 enum msm_actuator_cfg_type_t {
@@ -509,6 +526,9 @@
 #define VIDIOC_MSM_EEPROM_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_eeprom_cfg_data)
 
+#define VIDIOC_MSM_SENSOR_GET_AF_STATUS \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, uint32_t)
+
 #define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
 
 #endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 46bce9e..e5d5c32 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -113,7 +113,7 @@
 		channel_allocation);
 
 	codec_data->hdmi_ops.audio_info_setup(codec_data->hdmi_core_pdev,
-			num_channels, channel_allocation,
+			params_rate(params), num_channels, channel_allocation,
 			level_shift, down_mix);
 
 	return 0;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 03de4e0..59354a3 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -3096,6 +3096,8 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+	uint32_t impedl, impedr;
+	int ret = 0;
 
 	pr_debug("%s %s %d\n", __func__, w->name, event);
 
@@ -3107,6 +3109,13 @@
 						 WCD9XXX_CLSH_STATE_HPHL,
 						 WCD9XXX_CLSH_REQ_ENABLE,
 						 WCD9XXX_CLSH_EVENT_PRE_DAC);
+		ret = wcd9xxx_mbhc_get_impedance(&taiko_p->mbhc,
+					&impedl, &impedr);
+		if (!ret)
+			wcd9xxx_clsh_imped_config(codec, impedl);
+		else
+			dev_err(codec->dev, "Failed to get mbhc impedance %d\n",
+						ret);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index bfd66ea..d00b843 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -30,6 +30,387 @@
 #define BUCK_SETTLE_TIME_US 50
 #define NCP_SETTLE_TIME_US 50
 
+#define MAX_IMPED_PARAMS 13
+
+struct wcd9xxx_imped_val {
+	u32 imped_val;
+	u8 index;
+};
+
+static const struct wcd9xxx_reg_mask_val imped_table[][MAX_IMPED_PARAMS] = {
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x46},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x47},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0C},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0E},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x49},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x17},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x5F},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCF},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x0F},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x59},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xCE},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x10},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x66},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x9A},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x02},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xBD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x11},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x37},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA6},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x08},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x76},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x04},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x11},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x4E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAD},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x09},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x12},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x12},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0A},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x13},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x7A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0B},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x60},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x09},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0C},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x14},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x79},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1F},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0D},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x15},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x78},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x16},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x0E},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x89},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x40},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x10},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x97},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xD0},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x12},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xB7},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x17},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xA4},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x15},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x08},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x18},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x8B},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x18},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAC},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x20},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1A},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x9A},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x17},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x13},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1B},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2E},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x1A},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x14},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x1F},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x19},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xB9},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x06},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x10},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x23},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x18},
+	},
+	{
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0xA9},
+		{WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x07},
+		{WCD9XXX_A_CDC_CLSH_K_ADDR, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1D},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x27},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x35},
+		{WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+		{WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0xff, 0x26},
+		{WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0xff, 0x16},
+	},
+};
+
+static const struct wcd9xxx_imped_val imped_index[] = {
+	{4000, 0},
+	{4500, 1},
+	{5000, 2},
+	{5500, 3},
+	{6000, 4},
+	{6500, 5},
+	{7000, 6},
+	{7700, 7},
+	{8470, 8},
+	{9317, 9},
+	{10248, 10},
+	{11273, 11},
+	{12400, 12},
+	{13641, 13},
+	{15005, 14},
+	{16505, 15},
+	{18156, 16},
+	{19971, 17},
+	{21969, 18},
+	{24165, 19},
+	{26582, 20},
+	{29240, 21},
+	{32164, 22},
+};
+
 static inline void wcd9xxx_enable_clsh_block(
 	struct snd_soc_codec *codec,
 	bool on)
@@ -165,6 +546,40 @@
 	}
 }
 
+static int get_impedance_index(u32 imped)
+{
+	int i = 0;
+	if (imped < imped_index[i].imped_val) {
+		pr_debug("%s, detected impedance is less than 4 Ohm\n",
+				__func__);
+		goto ret;
+	}
+	for (i = 0; i < ARRAY_SIZE(imped_index); i++) {
+		if (imped >= imped_index[i].imped_val &&
+			imped < imped_index[i + 1].imped_val)
+			break;
+	}
+ret:
+	pr_debug("%s: selected impedance index = %d\n",
+			__func__, imped_index[i].index);
+	return imped_index[i].index;
+}
+
+void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
+				  int imped)
+{
+	int i  = 0;
+	int index = 0;
+	index = get_impedance_index(imped);
+	if (index > ARRAY_SIZE(imped_index)) {
+		pr_err("%s, invalid imped = %d\n", __func__, imped);
+		return;
+	}
+	for (i = 0; i < MAX_IMPED_PARAMS; i++)
+		snd_soc_write(codec, imped_table[index][i].reg,
+					imped_table[index][i].val);
+}
+
 static void wcd9xxx_clsh_comp_req(struct snd_soc_codec *codec,
 				  struct wcd9xxx_clsh_cdc_data *clsh_d,
 				  int compute_pa, bool on)
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 50381c9..654964e 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -74,6 +74,9 @@
 extern void wcd9xxx_clsh_init(struct wcd9xxx_clsh_cdc_data *clsh,
 			      struct wcd9xxx_resmgr *resmgr);
 
+extern void wcd9xxx_clsh_imped_config(struct snd_soc_codec *codec,
+				  int imped);
+
 enum wcd9xxx_codec_event {
 	WCD9XXX_CODEC_EVENT_CODEC_UP = 0,
 };
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index e34dec1..d0c00a7 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -220,11 +220,15 @@
 	pr_debug("%s: leave\n", __func__);
 }
 
-/* called under codec_resource_lock acquisition */
-static void __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
+/*
+ * called under codec_resource_lock acquisition
+ * return old status
+ */
+static bool __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
 				     int vddio_switch, bool restartpolling,
 				     bool checkpolling)
 {
+	bool ret;
 	int cfilt_k_val;
 	bool override;
 	struct snd_soc_codec *codec;
@@ -234,9 +238,11 @@
 
 	if (mbhc->micbias_enable) {
 		pr_debug("%s: micbias is already on\n", __func__);
-		return;
+		ret = mbhc->mbhc_micbias_switched;
+		return ret;
 	}
 
+	ret = mbhc->mbhc_micbias_switched;
 	if (vddio_switch && !mbhc->mbhc_micbias_switched &&
 	    (!checkpolling || mbhc->polling_active)) {
 		if (restartpolling)
@@ -343,11 +349,13 @@
 		mbhc->mbhc_micbias_switched = false;
 		pr_debug("%s: VDDIO switch disabled\n", __func__);
 	}
+
+	return ret;
 }
 
 static void wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, int vddio_switch)
 {
-	return __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
+	__wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
 }
 
 static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
@@ -1124,10 +1132,15 @@
 /*
  * wcd9xxx_find_plug_type : Find out and return the best plug type with given
  *			    list of wcd9xxx_mbhc_detect structure.
+ * param mbhc wcd9xxx_mbhc structure
+ * param dt collected measurements
+ * param size array size of dt
+ * param event_state mbhc->event_state when dt is collected
  */
 static enum wcd9xxx_mbhc_plug_type
 wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
-		       struct wcd9xxx_mbhc_detect *dt, const int size)
+		       struct wcd9xxx_mbhc_detect *dt, const int size,
+		       unsigned long event_state)
 {
 	int i;
 	int ch;
@@ -1140,6 +1153,8 @@
 	const s16 hs_max = plug_type->v_hs_max;
 	const s16 no_mic = plug_type->v_no_mic;
 
+	pr_debug("%s: event_state 0x%lx\n", __func__, event_state);
+
 	for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
 		vdce = wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce);
 		if (d->vddio)
@@ -1181,7 +1196,10 @@
 			goto exit;
 		}
 	}
-	if (ch != size && ch > 0) {
+
+	if (event_state & (1 << MBHC_EVENT_PA_HPHL)) {
+		pr_debug("%s: HPHL PA was ON\n", __func__);
+	} else if (ch != size && ch > 0) {
 		pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
 		type = PLUG_TYPE_INVALID;
 		goto exit;
@@ -1221,12 +1239,18 @@
 		     maxv))
 			type = PLUG_TYPE_GND_MIC_SWAP;
 	}
-	if (((type == PLUG_TYPE_HEADSET || type == PLUG_TYPE_HEADPHONE) &&
-	    ch != size) || (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
-		pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
-		    __func__, type);
-		type = PLUG_TYPE_INVALID;
+
+	/* if HPHL PA was on, we cannot use hphl status */
+	if (!(event_state & (1UL << MBHC_EVENT_PA_HPHL))) {
+		if (((type == PLUG_TYPE_HEADSET ||
+		      type == PLUG_TYPE_HEADPHONE) && ch != size) ||
+		    (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
+			pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
+				 __func__, type);
+			type = PLUG_TYPE_INVALID;
+		}
 	}
+
 	if (type == PLUG_TYPE_HEADSET && dvddio) {
 		if ((dvddio->_vdces > hs_max) ||
 		    (dvddio->_vdces > minv + WCD9XXX_THRESHOLD_MIC_THRESHOLD)) {
@@ -1294,6 +1318,7 @@
 wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
 {
 	int i;
+	bool vddioon;
 	struct wcd9xxx_mbhc_plug_type_cfg *plug_type_ptr;
 	struct wcd9xxx_mbhc_detect rt[NUM_DCE_PLUG_INS_DETECT];
 	enum wcd9xxx_mbhc_plug_type type = PLUG_TYPE_INVALID;
@@ -1308,6 +1333,13 @@
 	/* GND and MIC swap detection requires at least 2 rounds of DCE */
 	BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
 
+	/*
+	 * There are chances vddio switch is on and cfilt voltage is adjusted
+	 * to vddio voltage even after plug type removal reported.
+	 */
+	vddioon = __wcd9xxx_switch_micbias(mbhc, 0, false, false);
+	pr_debug("%s: vddio switch was %s\n", __func__, vddioon ? "on" : "off");
+
 	plug_type_ptr =
 	    WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
 
@@ -1350,7 +1382,11 @@
 			wcd9xxx_codec_hphr_gnd_switch(codec, false);
 	}
 
-	type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt));
+	if (vddioon)
+		__wcd9xxx_switch_micbias(mbhc, 1, false, false);
+
+	type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt),
+				      mbhc->event_state);
 
 	pr_debug("%s: leave\n", __func__);
 	return type;
@@ -2134,6 +2170,7 @@
 	unsigned long timeout;
 	int retry = 0, pt_gnd_mic_swap_cnt = 0;
 	bool correction = false;
+	bool wrk_complete = true;
 
 	pr_debug("%s: enter\n", __func__);
 
@@ -2159,12 +2196,14 @@
 		++retry;
 		rmb();
 		if (mbhc->hs_detect_work_stop) {
+			wrk_complete = false;
 			pr_debug("%s: stop requested\n", __func__);
 			break;
 		}
 
 		msleep(HS_DETECT_PLUG_INERVAL_MS);
 		if (wcd9xxx_swch_level_remove(mbhc)) {
+			wrk_complete = false;
 			pr_debug("%s: Switch level is low\n", __func__);
 			break;
 		}
@@ -2238,7 +2277,9 @@
 	if (plug_type == PLUG_TYPE_HIGH_HPH) {
 		pr_debug("%s: polling is done, still HPH, so enabling MIC trigger\n",
 			 __func__);
+		WCD9XXX_BCL_LOCK(mbhc->resmgr);
 		wcd9xxx_find_plug_and_report(mbhc, plug_type);
+		WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
 	}
 	/* Turn off override */
 	if (!correction)
@@ -2248,10 +2289,11 @@
 
 	if (mbhc->mbhc_cfg->detect_extn_cable) {
 		WCD9XXX_BCL_LOCK(mbhc->resmgr);
-		if (mbhc->current_plug == PLUG_TYPE_HEADPHONE ||
+		if ((mbhc->current_plug == PLUG_TYPE_HEADPHONE &&
+		    wrk_complete) ||
 		    mbhc->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
 		    mbhc->current_plug == PLUG_TYPE_INVALID ||
-		    plug_type == PLUG_TYPE_INVALID) {
+		    (plug_type == PLUG_TYPE_INVALID && wrk_complete)) {
 			/* Enable removal detection */
 			wcd9xxx_cleanup_hs_polling(mbhc);
 			wcd9xxx_enable_hs_detect(mbhc, 0, 0, false);
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index d6090cf..2836b87 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/msm_audio_ion.h>
 #include "audio_acdb.h"
+#include "q6voice.h"
 
 
 #define MAX_NETWORKS			15
@@ -949,6 +950,36 @@
 	return result;
 }
 
+static int register_vocvol_table(void)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	result = voc_register_vocproc_vol_table();
+	if (result < 0) {
+		pr_err("%s: Register vocproc vol failed!\n", __func__);
+		goto done;
+	}
+
+done:
+	return result;
+}
+
+static int deregister_vocvol_table(void)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	result = voc_deregister_vocproc_vol_table();
+	if (result < 0) {
+		pr_err("%s: Deregister vocproc vol failed!\n", __func__);
+		goto done;
+	}
+
+done:
+	return result;
+}
+
 static int acdb_open(struct inode *inode, struct file *f)
 {
 	s32 result = 0;
@@ -1139,10 +1170,16 @@
 		}
 		if (copy_to_user((void *)arg, &prot_status,
 			sizeof(prot_status))) {
-			pr_err("%s Failed to update prot_status\n", __func__);
+			pr_err("%s: Failed to update prot_status\n", __func__);
 		}
 		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
+	case AUDIO_REGISTER_VOCPROC_VOL_TABLE:
+		result = register_vocvol_table();
+		goto done;
+	case AUDIO_DEREGISTER_VOCPROC_VOL_TABLE:
+		result = deregister_vocvol_table();
+		goto done;
 	}
 
 	if (copy_from_user(&size, (void *) arg, sizeof(size))) {
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index f268171..be62727 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -95,7 +95,6 @@
 static int voice_alloc_and_map_oob_mem(struct voice_data *v);
 
 static struct voice_data *voice_get_session_by_idx(int idx);
-static int voice_get_idx_for_session(u32 session_id);
 
 static u16 voice_get_mvm_handle(struct voice_data *v)
 {
@@ -240,7 +239,7 @@
 	return v;
 }
 
-static int voice_get_idx_for_session(u32 session_id)
+int voice_get_idx_for_session(u32 session_id)
 {
 	int idx = 0;
 
@@ -300,6 +299,16 @@
 	return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
 }
 
+static bool is_voc_state_active(int voc_state)
+{
+	if ((voc_state == VOC_RUN) ||
+		(voc_state == VOC_CHANGE) ||
+		(voc_state == VOC_STANDBY))
+		return true;
+
+	return false;
+}
+
 static bool is_other_session_active(u32 session_id)
 {
 	int i;
@@ -310,9 +319,7 @@
 		if (common.voice[i].session_id == session_id)
 			continue;
 
-		if ((common.voice[i].voc_state == VOC_RUN) ||
-		    (common.voice[i].voc_state == VOC_CHANGE) ||
-		    (common.voice[i].voc_state == VOC_STANDBY)) {
+		if (is_voc_state_active(common.voice[i].voc_state)) {
 			ret = true;
 			break;
 		}
@@ -1213,9 +1220,8 @@
 	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
 		v = &common.voice[i];
 		if ((v->dtmf_rx_detect_en) &&
-			((v->voc_state == VOC_RUN) ||
-			 (v->voc_state == VOC_CHANGE) ||
-			 (v->voc_state == VOC_STANDBY))) {
+			is_voc_state_active(v->voc_state)) {
+
 			pr_debug("disable dtmf det on ses_id=%d\n",
 				 v->session_id);
 			voice_send_dtmf_rx_detection_cmd(v, 0);
@@ -1236,9 +1242,7 @@
 	mutex_lock(&v->lock);
 	v->dtmf_rx_detect_en = enable;
 
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
+	if (is_voc_state_active(v->voc_state))
 		ret = voice_send_dtmf_rx_detection_cmd(v,
 						       v->dtmf_rx_detect_en);
 
@@ -2327,6 +2331,62 @@
 	return ret;
 }
 
+int voc_register_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result = voice_send_cvp_register_vol_cal_cmd(v);
+			if (result) {
+				pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+				mutex_unlock(&v->lock);
+				goto done;
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+done:
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
+int voc_deregister_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result = voice_send_cvp_deregister_vol_cal_cmd(v);
+			if (result) {
+				pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+				mutex_unlock(&v->lock);
+				goto done;
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+done:
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
 static int voice_map_memory_physical_cmd(struct voice_data *v,
 					 struct mem_map_table *table_info,
 					 dma_addr_t phys,
@@ -3870,9 +3930,7 @@
 
 	v->stream_tx.stream_mute = mute;
 
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
+	if (is_voc_state_active(v->voc_state))
 		ret = voice_send_stream_mute_cmd(v);
 
 	mutex_unlock(&v->lock);
@@ -4026,9 +4084,7 @@
 
 	v->dev_rx.volume = vol_idx;
 
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
+	if (is_voc_state_active(v->voc_state))
 		ret = voice_send_vol_index_cmd(v);
 
 	mutex_unlock(&v->lock);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index b8f7008..42b1800 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1377,9 +1377,13 @@
 int voc_alloc_cal_shared_memory(void);
 int voc_alloc_voip_shared_memory(void);
 int is_voc_initialized(void);
+int voc_register_vocproc_vol_table(void);
+int voc_deregister_vocproc_vol_table(void);
 
 uint32_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set, uint16_t port_id);
 int voc_start_record(uint32_t port_id, uint32_t set);
+int voice_get_idx_for_session(u32 session_id);
+
 #endif
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index 1f2a487..a4983d3 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -24,7 +24,7 @@
 #include <sound/q6asm-v2.h>
 #include <sound/q6afe-v2.h>
 #include <sound/apr_audio-v2.h>
-
+#include <q6voice.h>
 #include "audio_acdb.h"
 
 
@@ -352,13 +352,13 @@
 	return;
 }
 
-static int get_voice_index_cvs(u32 cvs_handle)
+static u32 get_voice_session_id_cvs(u32 cvs_handle)
 {
 	u32 i;
 
 	for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
 		if (rtac_voice_data.voice[i].cvs_handle == cvs_handle)
-			return i;
+			return voice_session_id[i];
 	}
 
 	pr_err("%s: No voice index for CVS handle %d found returning 0\n",
@@ -366,13 +366,13 @@
 	return 0;
 }
 
-static int get_voice_index_cvp(u32 cvp_handle)
+static u32 get_voice_session_id_cvp(u32 cvp_handle)
 {
 	u32 i;
 
 	for (i = 0; i < rtac_voice_data.num_of_voice_combos; i++) {
 		if (rtac_voice_data.voice[i].cvp_handle == cvp_handle)
-			return i;
+			return voice_session_id[i];
 	}
 
 	pr_err("%s: No voice index for CVP handle %d found returning 0\n",
@@ -383,9 +383,11 @@
 static int get_voice_index(u32 mode, u32 handle)
 {
 	if (mode == RTAC_CVP)
-		return get_voice_index_cvp(handle);
+		return voice_get_idx_for_session(
+			get_voice_session_id_cvp(handle));
 	if (mode == RTAC_CVS)
-		return get_voice_index_cvs(handle);
+		return voice_get_idx_for_session(
+			get_voice_session_id_cvs(handle));
 
 	pr_err("%s: Invalid mode %d, returning 0\n",
 	       __func__, mode);
@@ -847,8 +849,7 @@
 		payload_size);
 	voice_params.src_svc = 0;
 	voice_params.src_domain = APR_DOMAIN_APPS;
-	voice_params.src_port = voice_session_id[
-					get_voice_index(mode, dest_port)];
+	voice_params.src_port = get_voice_index(mode, dest_port);
 	voice_params.dest_svc = 0;
 	voice_params.dest_domain = APR_DOMAIN_MODEM;
 	voice_params.dest_port = (u16)dest_port;