Merge "defconfig: msm8610: enable options for QView"
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/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 6fe88a9..4c6ae93 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -35,6 +35,8 @@
 					needed during wakeup.
  - atmel,no-force-update	: flag that signifies whether force configuration
 					update is applicable or not
+ - atmel,no-lpm-support		: flag that signifies whether low power mode is
+					supported or not on this platform
 
 Example:
 	i2c@f9966000 {
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/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-rumi.dtsi b/arch/arm/boot/dts/mpq8092-rumi.dtsi
index 2016998..cc345d8 100644
--- a/arch/arm/boot/dts/mpq8092-rumi.dtsi
+++ b/arch/arm/boot/dts/mpq8092-rumi.dtsi
@@ -24,13 +24,13 @@
 	};
 
 	qcom,sdcc@f9824000 {
-		status = "disabled";
                 qcom,clk-rates = <400000 19200000>;
+		status = "ok";
         };
 
         qcom,sdcc@f98a4000 {
-		status = "disabled";
                 qcom,clk-rates = <400000 19200000>;
+		status = "ok";
         };
 
 	qcom,sps@f998000 {
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 7dd3ea8..04f0945 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -291,6 +291,10 @@
 	status = "ok";
 };
 
+&gdsc_vpu {
+	status = "ok";
+};
+
 &gdsc_oxili_gx {
 	status = "ok";
 };
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 2008e1e..0f93c8e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -32,10 +32,13 @@
 			reg = <0x800 0x100>;
 			interrupts = <0x0 0x8 0x0>,
 				     <0x0 0x8 0x1>,
-				     <0x0 0x8 0x4>;
-			interrupt-names = "kpdpwr", "resin", "resin-bark";
+				     <0x0 0x8 0x4>,
+				     <0x0 0x8 0x5>;
+			interrupt-names = "kpdpwr", "resin",
+					"resin-bark", "kpdpwr-resin-bark";
 			qcom,pon-dbc-delay = <15625>;
 			qcom,system-reset;
+			qcom,s3-debounce = <32>;
 
 			qcom,pon_1 {
 				qcom,pon-type = <0>;
@@ -52,6 +55,15 @@
 				qcom,s2-type = <1>;
 				linux,code = <114>;
 			};
+
+			qcom,pon_3 {
+				qcom,pon-type = <3>;
+				qcom,support-reset = <1>;
+				qcom,pull-up = <1>;
+				qcom,s1-timer = <6720>;
+				qcom,s2-timer = <2000>;
+				qcom,s2-type = <7>;
+			};
 		};
 
 		pm8226_chg: qcom,charger {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 259dfdb..7acb1fe 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -114,8 +114,6 @@
 
 &sdcc1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -140,8 +138,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 4b2a4ad..ddb61bc 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -131,8 +131,6 @@
 
 &sdcc1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -157,8 +155,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 8af5ef5..669f54a 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -129,8 +129,6 @@
 
 &sdcc1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
@@ -155,8 +153,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8226_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2950000 2950000>;
 	qcom,vdd-current-level = <800 500000>;
 
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 cd0063b..b836100 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -1025,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>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 6b61317..ce4ada5 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>;
 			};
 		};
 	};
@@ -242,8 +246,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2900000 2900000>;
 	qcom,vdd-current-level = <200 400000>;
 
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 16fc2e7..221ace4 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -42,6 +42,7 @@
 		atmel,display-coords = <0 0 480 800>;
 		atmel,i2c-pull-up;
 		atmel,no-force-update;
+		atmel,no-lpm-support;
 		atmel,cfg_1 {
 			atmel,family-id = <0x81>;
 			atmel,variant-id = <0x15>;
@@ -105,6 +106,27 @@
 			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>;
+		};
+
+		mma8x5x@1d {
+			reg = <0x1d>;
+			compatible = "fsl,mma8x5x";
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			fsl,irq-gpio = <&msmgpio 81 0x00>;
+			fsl,sensors-position = <5>;
+		};
 	};
 
 	gen-vkeys {
@@ -239,9 +261,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>;
 			};
 		};
 	};
@@ -259,8 +285,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2900000 2900000>;
 	qcom,vdd-current-level = <200 400000>;
 
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index 62ef933..24c2490 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -38,6 +38,34 @@
 
         qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
     };
+    i2c@f9923000{
+		focaltech@38{
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <1 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vcc_i2c-supply = <&pm8110_l14>;
+			focaltech,family-id = <0x06>;
+			focaltech,reset-gpio = <&msmgpio 0 0x00>;
+			focaltech,irq-gpio = <&msmgpio 1 0x00>;
+			focaltech,display-coords = <0 0 480 854>;
+			focaltech,panel-coords = <0 0 480 946>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+		};
+	};
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "ft5x06_ts";
+		qcom,disp-maxx = <480>;
+		qcom,disp-maxy = <854>;
+		qcom,panel-maxx = <481>;
+		qcom,panel-maxy = <946>;
+		qcom,key-codes = <139 102 158>;
+		qcom,y-offset = <0>;
+	};
     i2c@f9925000 {
 		fsl@1c {
 			compatible = "fsl,mma8x5x";
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 5a30d40..ea47d45 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -213,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>;
 			};
 		};
 	};
@@ -233,8 +237,6 @@
 
 &sdhc_1 {
 	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
 	qcom,vdd-voltage-level = <2900000 2900000>;
 	qcom,vdd-current-level = <200 400000>;
 
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 9a796e2..ee444e3 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -253,8 +253,6 @@
 		interrupt-names = "core_irq", "bam_irq";
 
 		vdd-supply = <&pm8110_l17>;
-		qcom,vdd-always-on;
-		qcom,vdd-lpm-sup;
 		qcom,vdd-voltage-level = <2900000 2900000>;
 		qcom,vdd-current-level = <9000 400000>;
 
@@ -755,7 +753,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>;
@@ -915,6 +913,11 @@
 				<55 512 393600 3936000>;
 	};
 
+	cpu-pmu {
+		compatible = "arm,cortex-a7-pmu";
+		qcom,irq-is-percpu;
+		interrupts = <1 7 0xf00>;
+	};
 };
 
 &gdsc_vfe {
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.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 791f048..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>;
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/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 bf92d6c..f2d1e29 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -244,6 +244,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 9231ca7..9ce4f5d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_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/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/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index c54c3db..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),
@@ -337,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-dsi-8610.c b/arch/arm/mach-msm/clock-dsi-8610.c
index 44b332e..73196fe 100644
--- a/arch/arm/mach-msm/clock-dsi-8610.c
+++ b/arch/arm/mach-msm/clock-dsi-8610.c
@@ -192,7 +192,7 @@
 	status = readl_relaxed(dsi_base + DSI_DSIPHY_PLL_CTRL_0);
 	if (!status & DSI_PLL_RDY_BIT) {
 		pr_err("DSI PLL not ready\n");
-		clk_disable(dsi_ahb_clk);
+		clk_disable_unprepare(dsi_ahb_clk);
 		return HANDOFF_DISABLED_CLK;
 	}
 
@@ -370,35 +370,19 @@
 	return HANDOFF_ENABLED_CLK;
 }
 
-int dsi_prepare(struct clk *clk)
-{
-	return clk_prepare(dsi_ahb_clk);
-}
-
-void dsi_unprepare(struct clk *clk)
-{
-	clk_unprepare(dsi_ahb_clk);
-}
-
 struct clk_ops clk_ops_dsi_dsiclk = {
-	.prepare = dsi_prepare,
-	.unprepare = dsi_unprepare,
 	.set_rate = dsi_dsiclk_set_rate,
 	.round_rate = dsi_dsiclk_round_rate,
 	.handoff = dsi_dsiclk_handoff,
 };
 
 struct clk_ops clk_ops_dsi_byteclk = {
-	.prepare = dsi_prepare,
-	.unprepare = dsi_unprepare,
 	.set_rate = dsi_byteclk_set_rate,
 	.round_rate = dsi_byteclk_round_rate,
 	.handoff = dsi_byteclk_handoff,
 };
 
 struct clk_ops clk_ops_dsi_vco = {
-	.prepare = dsi_prepare,
-	.unprepare = dsi_unprepare,
 	.enable = dsi_pll_vco_enable,
 	.disable = dsi_pll_vco_disable,
 	.set_rate = dsi_pll_vco_set_rate,
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/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/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index c979e0c..7cfbd93 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -327,30 +327,43 @@
 
 static inline int msm_soc_version_supports_iommu_v0(void)
 {
+	static int soc_supports_v0 = -1;
 #ifdef CONFIG_OF
 	struct device_node *node;
+#endif
 
+	if (soc_supports_v0 != -1)
+		return soc_supports_v0;
+
+#ifdef CONFIG_OF
 	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v1");
 	if (node) {
+		soc_supports_v0 = 0;
 		of_node_put(node);
 		return 0;
 	}
 
 	node = of_find_compatible_node(NULL, NULL, "qcom,msm-smmu-v0");
 	if (node) {
+		soc_supports_v0 = 1;
 		of_node_put(node);
 		return 1;
 	}
 #endif
 	if (cpu_is_msm8960() &&
-	    SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2)
+	    SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2) {
+		soc_supports_v0 = 0;
 		return 0;
+	}
 
 	if (cpu_is_msm8x60() &&
 	    (SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 2 ||
 	    SOCINFO_VERSION_MINOR(socinfo_get_version()) < 1))	{
+		soc_supports_v0 = 0;
 		return 0;
 	}
+
+	soc_supports_v0 = 1;
 	return 1;
 }
 #endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 6f83c53..32d58d4 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -174,8 +174,8 @@
 	/* Request Power State */
 	unsigned power_state;
 	struct ocmem_eviction_data *edata;
-	/* Request that triggered eviction */
-	struct ocmem_req *e_handle;
+	/* Eviction data of the request being evicted */
+	struct ocmem_eviction_data *eviction_info;
 };
 
 struct ocmem_handle {
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index a3fd6b2..cbf7933 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1192,19 +1192,23 @@
 }
 
 /* Remove the request from eviction lists */
-static void cancel_restore(struct ocmem_req *e_handle,
-				struct ocmem_req *req)
+static void cancel_restore(struct ocmem_req *req)
 {
-	struct ocmem_eviction_data *edata = e_handle->edata;
+	struct ocmem_eviction_data *edata;
 
-	if (!edata || !req)
+	if (!req)
+		return;
+
+	edata = req->eviction_info;
+
+	if (!edata)
 		return;
 
 	if (list_empty(&edata->req_list))
 		return;
 
 	list_del_init(&req->eviction_list);
-	req->e_handle = NULL;
+	req->eviction_info = NULL;
 
 	return;
 }
@@ -1499,8 +1503,8 @@
 	}
 
 	/* Remove the request from any restore lists */
-	if (req->e_handle)
-		cancel_restore(req->e_handle, req);
+	if (req->eviction_info)
+		cancel_restore(req);
 
 	/* Remove the request from any pending opreations */
 	if (TEST_STATE(req, R_ENQUEUED)) {
@@ -1747,12 +1751,7 @@
 		goto shrink_fail;
 	}
 
-	if (!req->e_handle) {
-		pr_err("Unable to find evicting request\n");
-		goto shrink_fail;
-	}
-
-	edata = req->e_handle->edata;
+	edata = req->eviction_info;
 
 	if (!edata) {
 		pr_err("Unable to find eviction data\n");
@@ -1905,7 +1904,7 @@
 						&e_req->eviction_list,
 						&edata->req_list);
 					atomic_inc(&edata->pending);
-					e_req->e_handle = req;
+					e_req->eviction_info = edata;
 				}
 			}
 		} else {
@@ -2037,7 +2036,7 @@
 		pr_debug("ocmem: restoring evicted request %p\n",
 							req);
 		req->edata = NULL;
-		req->e_handle = NULL;
+		req->eviction_info = NULL;
 		req->op = SCHED_ALLOCATE;
 		inc_ocmem_stat(zone_of(req), NR_RESTORES);
 		sched_enqueue(req);
@@ -2076,8 +2075,11 @@
 	struct ocmem_eviction_data *edata = evictions[id];
 	int rc = 0;
 
-	if (!edata)
+	if (!edata) {
+		pr_err("Client %s invoked restore without any eviction\n",
+					get_name(id));
 		return -EINVAL;
+	}
 
 	mutex_lock(&free_mutex);
 	rc = __restore_common(edata);
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 643d945..0a799aa 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -33,6 +33,7 @@
 	"8  Perf: Add cortex A7 perf support\n"
 	"9  ARM: dts: msm: add perf-events support for msm8226\n"
 	"10 Perf: Fix counts across power collapse\n"
+	"11 ARM: dts: msm: add perf-events support for msm8x10, msm8x12\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
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/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e65b5ba..c2efc34 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -360,9 +360,13 @@
 PTE_SET_FN(nx, pte_mknexec)
 
 SET_MEMORY_FN(ro, pte_set_ro)
+EXPORT_SYMBOL(set_memory_ro);
 SET_MEMORY_FN(rw, pte_set_rw)
+EXPORT_SYMBOL(set_memory_rw);
 SET_MEMORY_FN(x, pte_set_x)
+EXPORT_SYMBOL(set_memory_x);
 SET_MEMORY_FN(nx, pte_set_nx)
+EXPORT_SYMBOL(set_memory_nx);
 
 /*
  * Adjust the PMD section entries according to the CPU in use.
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 83d94f1..7f7b4d7 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -395,21 +395,26 @@
 static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
 			remote_arg_t *rpra, remote_arg_t *upra,
 			struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs,
-			int *nbufs)
+			int *nbufs, int *fds)
 {
+	struct fastrpc_apps *me = &gfa;
 	struct smq_invoke_buf *list;
 	struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
 	struct smq_phy_page *pages;
+	struct ion_handle **handles;
 	void *args;
 	int i, rlen, size, used, inh, bufs = 0, err = 0;
 	int inbufs = REMOTE_SCALARS_INBUFS(sc);
 	int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+	unsigned long iova, len;
 
 	list = smq_invoke_buf_start(rpra, sc);
 	pages = smq_phy_page_start(sc, list);
 	used = ALIGN(pbuf->used, BALIGN);
 	args = (void *)((char *)pbuf->virt + used);
 	rlen = pbuf->size - used;
+	if (fds)
+		handles = (struct ion_handle **)(fds + inbufs + outbufs);
 	for (i = 0; i < inbufs + outbufs; ++i) {
 
 		rpra[i].buf.len = pra[i].buf.len;
@@ -418,6 +423,22 @@
 		if (list[i].num) {
 			rpra[i].buf.pv = pra[i].buf.pv;
 			continue;
+		} else if (me->smmu.enabled && fds && (fds[i] >= 0)) {
+			len = buf_page_size(pra[i].buf.len);
+			handles[i] = ion_import_dma_buf(me->iclient, fds[i]);
+			VERIFY(err, 0 == IS_ERR_OR_NULL(handles[i]));
+			if (err)
+				goto bail;
+			VERIFY(err, 0 == ion_map_iommu(me->iclient, handles[i],
+						me->smmu.domain_id, 0, SZ_4K, 0,
+						&iova, &len, 0, 0));
+			if (err)
+				goto bail;
+			rpra[i].buf.pv = pra[i].buf.pv;
+			list[i].num = 1;
+			pages[list[i].pgidx].addr = iova;
+			pages[list[i].pgidx].size = len;
+			continue;
 		}
 		if (rlen < pra[i].buf.len) {
 			struct fastrpc_buf *b;
@@ -770,15 +791,17 @@
 static int fastrpc_release_current_dsp_process(void);
 
 static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t kernel,
-			struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra)
+			struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra,
+			int *fds)
 {
 	remote_arg_t *rpra = 0;
 	struct fastrpc_device *dev = 0;
 	struct smq_invoke_ctx *ctx = 0;
 	struct fastrpc_buf obuf, *abufs = 0, *b;
+	struct ion_handle **handles;
 	int interrupted = 0;
 	uint32_t sc;
-	int i, nbufs = 0, err = 0;
+	int i, bufs, nbufs = 0, err = 0;
 
 	sc = invoke->sc;
 	obuf.handle = 0;
@@ -798,7 +821,7 @@
 			goto bail;
 		rpra = (remote_arg_t *)obuf.virt;
 		VERIFY(err, 0 == get_args(kernel, sc, pra, rpra, invoke->pra,
-					&obuf, &abufs, &nbufs));
+					&obuf, &abufs, &nbufs, fds));
 		if (err)
 			goto bail;
 	}
@@ -828,8 +851,19 @@
 	}
 	context_free(ctx);
 
-	if (me->smmu.enabled)
+	if (me->smmu.enabled) {
+		bufs = REMOTE_SCALARS_LENGTH(sc);
+		if (fds) {
+			handles = (struct ion_handle **)(fds + bufs);
+			for (i = 0; i < bufs; i++)
+				if (!IS_ERR_OR_NULL(handles[i])) {
+					ion_unmap_iommu(me->iclient, handles[i],
+							me->smmu.domain_id, 0);
+					ion_free(me->iclient, handles[i]);
+				}
+		}
 		iommu_detach_group(me->smmu.domain, me->smmu.group);
+	}
 	for (i = 0, b = abufs; i < nbufs; ++i, ++b)
 		free_mem(b);
 
@@ -856,7 +890,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	return err;
 }
 
@@ -874,7 +908,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	return err;
 }
 
@@ -912,7 +946,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(2, 2, 1);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	mmap->vaddrout = routargs.vaddrout;
 	if (err)
 		goto bail;
@@ -941,7 +975,7 @@
 	ioctl.handle = 1;
 	ioctl.sc = REMOTE_SCALARS_MAKE(3, 1, 0);
 	ioctl.pra = ra;
-	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+	VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra, 0)));
 	return err;
 }
 
@@ -1107,33 +1141,49 @@
 				 unsigned long ioctl_param)
 {
 	struct fastrpc_apps *me = &gfa;
-	struct fastrpc_ioctl_invoke invoke;
+	struct fastrpc_ioctl_invoke_fd invokefd;
+	struct fastrpc_ioctl_invoke *invoke = &invokefd.inv;
 	struct fastrpc_ioctl_mmap mmap;
 	struct fastrpc_ioctl_munmap munmap;
 	remote_arg_t *pra = 0;
 	void *param = (char *)ioctl_param;
 	struct file_data *fdata = (struct file_data *)file->private_data;
-	int bufs, err = 0;
+	int *fds = 0;
+	int bufs, size = 0, err = 0;
 
 	switch (ioctl_num) {
+	case FASTRPC_IOCTL_INVOKE_FD:
 	case FASTRPC_IOCTL_INVOKE:
-		VERIFY(err, 0 == copy_from_user(&invoke, param,
-						sizeof(invoke)));
+		invokefd.fds = 0;
+		size = (ioctl_num == FASTRPC_IOCTL_INVOKE) ?
+				sizeof(*invoke) : sizeof(invokefd);
+		VERIFY(err, 0 == copy_from_user(&invokefd, param, size));
 		if (err)
 			goto bail;
-		bufs = REMOTE_SCALARS_INBUFS(invoke.sc) +
-			REMOTE_SCALARS_OUTBUFS(invoke.sc);
+		bufs = REMOTE_SCALARS_INBUFS(invoke->sc) +
+			REMOTE_SCALARS_OUTBUFS(invoke->sc);
 		if (bufs) {
-			bufs = bufs * sizeof(*pra);
-			VERIFY(err, 0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+			size = bufs * sizeof(*pra);
+			if (invokefd.fds)
+				size = size + bufs * sizeof(*fds) +
+					bufs * sizeof(struct ion_handle *);
+			VERIFY(err, 0 != (pra = kzalloc(size, GFP_KERNEL)));
 			if (err)
 				goto bail;
 		}
-		VERIFY(err, 0 == copy_from_user(pra, invoke.pra, bufs));
+		VERIFY(err, 0 == copy_from_user(pra, invoke->pra,
+						bufs * sizeof(*pra)));
 		if (err)
 			goto bail;
-		VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
-								pra)));
+		if (invokefd.fds) {
+			fds = (int *)(pra + bufs);
+			VERIFY(err, 0 == copy_from_user(fds, invokefd.fds,
+							bufs * sizeof(*fds)));
+		if (err)
+			goto bail;
+		}
+		VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 0, invoke,
+								pra, fds)));
 		if (err)
 			goto bail;
 		break;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index f2804ad..da70eb5 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -19,6 +19,7 @@
 #define FASTRPC_IOCTL_INVOKE  _IOWR('R', 1, struct fastrpc_ioctl_invoke)
 #define FASTRPC_IOCTL_MMAP    _IOWR('R', 2, struct fastrpc_ioctl_mmap)
 #define FASTRPC_IOCTL_MUNMAP  _IOWR('R', 3, struct fastrpc_ioctl_munmap)
+#define FASTRPC_IOCTL_INVOKE_FD  _IOWR('R', 4, struct fastrpc_ioctl_invoke_fd)
 #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
 #define DEVICE_NAME      "adsprpc-smd"
 
@@ -94,6 +95,11 @@
 	remote_arg_t *pra;	/* remote arguments list */
 };
 
+struct fastrpc_ioctl_invoke_fd {
+	struct fastrpc_ioctl_invoke inv;
+	int *fds;		/* fd list */
+};
+
 struct fastrpc_ioctl_munmap {
 	uint32_t vaddrout;	/* address to unmap */
 	int  size;		/* size */
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/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index f990ada..118c39a 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -264,6 +264,9 @@
 		}
 	}
 
+	if (!outer_cache_op)
+		return -EINVAL;
+
 	outer_cache_op(buff_phys_start + offset,
 		       buff_phys_start + offset + length);
 
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-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/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/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/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 479b788..5415f4e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -393,6 +393,9 @@
 	bool update_cfg;
 	const char *fw_name;
 	bool no_force_update;
+	bool lpm_support;
+	bool regs_enabled;
+
 #if defined(CONFIG_SECURE_TOUCH)
 	atomic_t st_enabled;
 	atomic_t st_pending_irqs;
@@ -2158,6 +2161,11 @@
 	if (on == false)
 		goto power_off;
 
+	if (data->regs_enabled) {
+		dev_dbg(&data->client->dev, "regs are already enabled\n");
+		return 0;
+	}
+
 	rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
 	if (rc < 0) {
 		dev_err(&data->client->dev,
@@ -2206,6 +2214,8 @@
 		}
 	}
 
+	data->regs_enabled = true;
+
 	msleep(130);
 
 	return 0;
@@ -2226,6 +2236,12 @@
 	return rc;
 
 power_off:
+
+	if (!data->regs_enabled) {
+		dev_dbg(&data->client->dev, "regs are already disabled\n");
+		return 0;
+	}
+
 	reg_set_optimum_mode_check(data->vcc_ana, 0);
 	regulator_disable(data->vcc_ana);
 	if (data->pdata->digital_pwr_regulator) {
@@ -2236,6 +2252,9 @@
 		reg_set_optimum_mode_check(data->vcc_i2c, 0);
 		regulator_disable(data->vcc_i2c);
 	}
+
+	data->regs_enabled = false;
+
 	msleep(50);
 	return 0;
 }
@@ -2435,8 +2454,9 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
-	mutex_lock(&input_dev->mutex);
+	disable_irq(data->irq);
 
+	mutex_lock(&input_dev->mutex);
 	if (input_dev->users) {
 		error = mxt_stop(data);
 		if (error < 0) {
@@ -2444,16 +2464,24 @@
 			mutex_unlock(&input_dev->mutex);
 			return error;
 		}
-
 	}
 
 	mutex_unlock(&input_dev->mutex);
+	mxt_release_all(data);
 
 	/* put regulators in low power mode */
-	error = mxt_regulator_lpm(data, true);
-	if (error < 0) {
-		dev_err(dev, "failed to enter low power mode\n");
-		return error;
+	if (data->lpm_support) {
+		error = mxt_regulator_lpm(data, true);
+		if (error < 0) {
+			dev_err(dev, "failed to enter low power mode\n");
+			return error;
+		}
+	} else {
+		error = mxt_power_on(data, false);
+		if (error < 0) {
+			dev_err(dev, "failed to disable regulators\n");
+			return error;
+		}
 	}
 
 	return 0;
@@ -2466,13 +2494,25 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
-	/* put regulators in high power mode */
-	error = mxt_regulator_lpm(data, false);
-	if (error < 0) {
-		dev_err(dev, "failed to enter high power mode\n");
-		return error;
+	/* put regulators back in active power mode */
+	if (data->lpm_support) {
+		error = mxt_regulator_lpm(data, false);
+		if (error < 0) {
+			dev_err(dev, "failed to enter high power mode\n");
+			return error;
+		}
+	} else {
+		error = mxt_power_on(data, true);
+		if (error < 0) {
+			dev_err(dev, "failed to enable regulators\n");
+			return error;
+		}
+		mxt_power_on_delay(data);
 	}
 
+	mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+	mxt_reset_delay(data);
+
 	mutex_lock(&input_dev->mutex);
 
 	if (input_dev->users) {
@@ -2495,6 +2535,8 @@
 
 	mutex_unlock(&input_dev->mutex);
 
+	enable_irq(data->irq);
+
 	return 0;
 }
 
@@ -2672,6 +2714,9 @@
 	pdata->no_force_update = of_property_read_bool(np,
 						"atmel,no-force-update");
 
+	pdata->no_lpm_support = of_property_read_bool(np,
+					"atmel,no-lpm-support");
+
 	/* reset, irq gpio info */
 	pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
 				0, &pdata->reset_gpio_flags);
@@ -2877,6 +2922,7 @@
 	data->input_dev = input_dev;
 	data->pdata = pdata;
 	data->no_force_update = pdata->no_force_update;
+	data->lpm_support = !pdata->no_lpm_support;
 
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(EV_KEY, input_dev->evbit);
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/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 982e4d4..d92a9c1 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -360,6 +360,25 @@
 	return ret;
 }
 
+static u32 get_hfi_buf_mode(enum buffer_mode_type hal_buf_mode)
+{
+	u32 buf_mode;
+	switch (hal_buf_mode) {
+	case HAL_BUFFER_MODE_STATIC:
+		buf_mode = HFI_BUFFER_MODE_STATIC;
+		break;
+	case HAL_BUFFER_MODE_RING:
+		buf_mode = HFI_BUFFER_MODE_RING;
+		break;
+	default:
+		dprintk(VIDC_ERR, "Invalid buffer mode :0x%x\n",
+				hal_buf_mode);
+		buf_mode = 0;
+		break;
+	}
+	return buf_mode;
+}
+
 int create_pkt_cmd_session_set_buffers(
 		struct hfi_cmd_session_set_buffers_packet *pkt,
 		u32 session_id,
@@ -1277,6 +1296,39 @@
 		pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
 		break;
 	}
+	case HAL_PARAM_BUFFER_ALLOC_MODE:
+	{
+		u32 buffer_type;
+		u32 buffer_mode;
+		struct hfi_buffer_alloc_mode *hfi;
+		struct hal_buffer_alloc_mode *alloc_info = pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
+		hfi = (struct hfi_buffer_alloc_mode *)
+			&pkt->rg_property_data[1];
+		buffer_type = get_hfi_buffer(alloc_info->buffer_type);
+		if (buffer_type)
+			hfi->buffer_type = buffer_type;
+		else
+			return -EINVAL;
+		buffer_mode = get_hfi_buf_mode(alloc_info->buffer_mode);
+		if (buffer_mode)
+			hfi->buffer_mode = buffer_mode;
+		else
+			return -EINVAL;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_buffer_alloc_mode);
+		break;
+	}
+	case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
+		break;
+	}
 	/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
 	case HAL_CONFIG_BUFFER_REQUIREMENTS:
 	case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 7039929..96bf9f4 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -68,6 +68,10 @@
 	"Extradata aspect ratio",
 	"Extradata mpeg2 seqdisp",
 };
+static const char *const mpeg_vidc_video_alloc_mode_type[] = {
+	"Buffer Allocation Static",
+	"Buffer Allocation Ring Buffer",
+};
 
 static const char *const perf_level[] = {
 	"Nominal",
@@ -249,6 +253,33 @@
 		.qmenu = perf_level,
 		.step = 0,
 	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE,
+		.name = "Buffer allocation mode",
+		.type = V4L2_CTRL_TYPE_MENU,
+		.minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
+		.maximum = V4L2_MPEG_VIDC_VIDEO_RING,
+		.default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
+		.menu_skip_mask = ~(
+			(1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
+			(1 << V4L2_MPEG_VIDC_VIDEO_RING)
+			),
+		.qmenu = mpeg_vidc_video_alloc_mode_type,
+		.step = 0,
+		.cluster = 0,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY,
+		.name = "Video frame assembly",
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.minimum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+		.maximum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE,
+		.default_value =  V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+		.step = 1,
+		.menu_skip_mask = 0,
+		.qmenu = NULL,
+		.cluster = 0,
+	},
 };
 
 #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
@@ -1357,13 +1388,29 @@
 		}
 
 		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE:
+	{
+		struct hal_buffer_alloc_mode mode;
+		property_id = HAL_PARAM_BUFFER_ALLOC_MODE;
+		mode.buffer_mode = ctrl->val;
+		mode.buffer_type = HAL_BUFFER_INPUT;
+		pdata = &mode;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY:
+	{
+		property_id = HAL_PARAM_VDEC_FRAME_ASSEMBLY;
+		hal_property.enable = ctrl->val;
+		pdata = &hal_property;
+		break;
+	}
 	default:
 		break;
 	}
 
 	if (!rc && property_id) {
 		dprintk(VIDC_DBG,
-			"Control: HAL property = %d, ctrl_id = 0x%x, ctrl_value = %d\n",
+			"Control: HAL property=0x%x,ctrl: id=0x%x,value=0x%x\n",
 			property_id, ctrl->id, ctrl->val);
 			rc = call_hfi_op(hdev, session_set_property, (void *)
 				inst->session, property_id, pdata);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 77f838c..5f0ec4e 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);
@@ -728,6 +744,15 @@
 	vb = response->clnt_data;
 	inst = (struct msm_vidc_inst *)response->session_id;
 	if (vb) {
+		vb->v4l2_planes[0].bytesused = response->input_done.filled_len;
+		vb->v4l2_planes[0].data_offset = response->input_done.offset;
+		if (vb->v4l2_planes[0].data_offset > vb->v4l2_planes[0].length)
+			dprintk(VIDC_ERR, "Error: data_offset overflow\n");
+		if (vb->v4l2_planes[0].bytesused > vb->v4l2_planes[0].length)
+			dprintk(VIDC_ERR, "Error: buffer overflow\n");
+		if ((u8 *)vb->v4l2_planes[0].m.userptr !=
+			response->input_done.packet_buffer)
+			dprintk(VIDC_ERR, "Error: unexpected buffer address\n");
 		mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 		mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
@@ -1889,10 +1914,19 @@
 		memset(&frame_data, 0 , sizeof(struct vidc_frame_data));
 		frame_data.alloc_len = vb->v4l2_planes[0].length;
 		frame_data.filled_len = vb->v4l2_planes[0].bytesused;
+		frame_data.offset = vb->v4l2_planes[0].data_offset;
 		frame_data.device_addr = vb->v4l2_planes[0].m.userptr;
 		frame_data.timestamp = time_usec;
 		frame_data.flags = 0;
 		frame_data.clnt_data = (u32)vb;
+		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+			(frame_data.filled_len > frame_data.alloc_len ||
+			frame_data.offset > frame_data.alloc_len)) {
+			dprintk(VIDC_ERR,
+				"Buffer will overflow, not queueing it\n");
+			rc = -EINVAL;
+			goto err_bad_input;
+		}
 		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 			frame_data.buffer_type = HAL_BUFFER_INPUT;
 			if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_EOS) {
@@ -1911,8 +1945,11 @@
 				V4L2_QCOM_BUF_TIMESTAMP_INVALID)
 				frame_data.timestamp = LLONG_MAX;
 			dprintk(VIDC_DBG,
-				"Sending etb to hal: Alloc: %d :filled: %d\n",
-				frame_data.alloc_len, frame_data.filled_len);
+				"Sending etb to hal: device_addr: 0x%x"
+				"Alloc: %d, filled: %d, offset: %d\n",
+				frame_data.device_addr,
+				frame_data.alloc_len, frame_data.filled_len,
+				frame_data.offset);
 			rc = call_hfi_op(hdev, session_etb, (void *)
 					inst->session, &frame_data);
 			if (!rc)
@@ -1965,6 +2002,7 @@
 			rc = -EINVAL;
 		}
 	}
+err_bad_input:
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to queue buffer\n");
 err_no_mem:
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8ee9c32..47b88db 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1423,6 +1423,10 @@
 		break;
 	case HAL_SYS_DEBUG_CONFIG:
 		break;
+	case HAL_PARAM_BUFFER_ALLOC_MODE:
+		break;
+	case HAL_PARAM_VDEC_FRAME_ASSEMBLY:
+		break;
 	/*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
 	case HAL_CONFIG_BUFFER_REQUIREMENTS:
 	case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 389c13f..288b386 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -172,6 +172,8 @@
 	HAL_PARAM_VENC_H264_VUI_TIMING_INFO,
 	HAL_PARAM_VENC_H264_GENERATE_AUDNAL,
 	HAL_PARAM_VENC_MAX_NUM_B_FRAMES,
+	HAL_PARAM_BUFFER_ALLOC_MODE,
+	HAL_PARAM_VDEC_FRAME_ASSEMBLY,
 };
 
 enum hal_domain {
@@ -860,6 +862,16 @@
 	HAL_UNUSED_SEQCHG = 0x10000000,
 };
 
+enum buffer_mode_type {
+	HAL_BUFFER_MODE_STATIC = 0x00000000,
+	HAL_BUFFER_MODE_RING,
+};
+
+struct hal_buffer_alloc_mode {
+	enum hal_buffer buffer_type;
+	enum buffer_mode_type buffer_mode;
+};
+
 /* HAL Response */
 
 enum command_response {
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 2e9db1f..90d9826 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1579,9 +1579,7 @@
 	if (err)
 		goto out;
 
-	if (mmc_can_poweroff_notify(host->card))
-		err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
-	else if (mmc_card_can_sleep(host))
+	if (mmc_card_can_sleep(host))
 		err = mmc_card_sleep(host);
 	else if (!mmc_host_is_spi(host))
 		mmc_deselect_cards(host);
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_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/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 23941a9..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;
@@ -2767,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 =
@@ -2939,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/n_smux.c b/drivers/tty/n_smux.c
index 3794aa9..c8e5163 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -297,6 +297,8 @@
 	[SMUX_HIGH_WM_HIT] = "HIGH_WM_HIT",
 	[SMUX_RX_RETRY_HIGH_WM_HIT] = "RX_RETRY_HIGH_WM_HIT",
 	[SMUX_RX_RETRY_LOW_WM_HIT] = "RX_RETRY_LOW_WM_HIT",
+	[SMUX_LOCAL_CLOSED] = "LOCAL_CLOSED",
+	[SMUX_REMOTE_CLOSED] = "REMOTE_CLOSED",
 };
 
 static const char * const smux_local_state[] = {
@@ -553,6 +555,8 @@
 
 	/* Close all ports */
 	for (i = 0 ; i < SMUX_NUM_LOGICAL_CHANNELS; i++) {
+		union notifier_metadata meta;
+		int send_disconnect = 0;
 		ch = &smux_lch[i];
 		SMUX_DBG("smux: %s: cleaning up lcid %d\n", __func__, i);
 
@@ -563,14 +567,19 @@
 		smux_purge_ch_tx_queue(ch, 1);
 		spin_unlock(&ch->tx_lock_lhb2);
 
+		meta.disconnected.is_ssr = smux.in_reset;
 		/* Notify user of disconnect and reset channel state */
 		if (ch->local_state == SMUX_LCH_LOCAL_OPENED ||
 			ch->local_state == SMUX_LCH_LOCAL_CLOSING) {
-			union notifier_metadata meta;
-
-			meta.disconnected.is_ssr = smux.in_reset;
-			schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
+			schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED, &meta);
+			send_disconnect = 1;
 		}
+		if (ch->remote_state != SMUX_LCH_REMOTE_CLOSED) {
+			schedule_notify(ch->lcid, SMUX_REMOTE_CLOSED, &meta);
+			send_disconnect = 1;
+		}
+		if (send_disconnect)
+			schedule_notify(ch->lcid, SMUX_DISCONNECTED, &meta);
 
 		ch->local_state = SMUX_LCH_LOCAL_CLOSED;
 		ch->remote_state = SMUX_LCH_REMOTE_CLOSED;
@@ -857,6 +866,10 @@
 
 	IPC_LOG_STR("smux: %s ch:%d\n", event_to_str(event), lcid);
 	ch = &smux_lch[lcid];
+	if (!ch->notify) {
+		SMUX_DBG("%s: [%d]lcid notify fn is NULL\n", __func__, lcid);
+		return ret;
+	}
 	notify_handle = kzalloc(sizeof(struct smux_notify_handle),
 						GFP_ATOMIC);
 	if (!notify_handle) {
@@ -1235,6 +1248,7 @@
 				SMUX_LCH_LOCAL_CLOSING,
 				SMUX_LCH_LOCAL_CLOSED);
 		ch->local_state = SMUX_LCH_LOCAL_CLOSED;
+		schedule_notify(lcid, SMUX_LOCAL_CLOSED, &meta_disconnected);
 		if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
 			schedule_notify(lcid, SMUX_DISCONNECTED,
 				&meta_disconnected);
@@ -1422,6 +1436,7 @@
 			}
 		}
 
+		schedule_notify(lcid, SMUX_REMOTE_CLOSED, &meta_disconnected);
 		if (ch->local_state == SMUX_LCH_LOCAL_CLOSED)
 			schedule_notify(lcid, SMUX_DISCONNECTED,
 				&meta_disconnected);
@@ -2360,8 +2375,11 @@
 		union notifier_metadata meta_disconnected;
 
 		meta_disconnected.disconnected.is_ssr = smux.in_reset;
-		schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+		schedule_notify(ch->lcid, SMUX_LOCAL_CLOSED,
 			&meta_disconnected);
+		if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED)
+			schedule_notify(ch->lcid, SMUX_DISCONNECTED,
+				&meta_disconnected);
 	}
 }
 
@@ -3089,11 +3107,15 @@
  *
  * @returns 0 for success, <0 otherwise
  *
- * A channel must be fully closed (either not previously opened or
- * msm_smux_close() has been called and the SMUX_DISCONNECTED has been
- * received.
+ * The local channel state must be closed (either not previously
+ * opened or msm_smux_close() has been called and the SMUX_LOCAL_CLOSED
+ * notification has been received).
  *
- * One the remote side is opened, the client will receive a SMUX_CONNECTED
+ * If open is called before the SMUX_LOCAL_CLOSED has been received,
+ * then the function will return -EAGAIN and the client will need to
+ * retry the open later.
+ *
+ * Once the remote side is opened, the client will receive a SMUX_CONNECTED
  * event.
  */
 int msm_smux_open(uint8_t lcid, void *priv,
@@ -3170,7 +3192,8 @@
  * @returns 0 for success, <0 otherwise
  *
  * Once the close event has been acknowledge by the remote side, the client
- * will receive a SMUX_DISCONNECTED notification.
+ * will receive an SMUX_LOCAL_CLOSED notification.  If the remote side is also
+ * closed, then an SMUX_DISCONNECTED notification will also be sent.
  */
 int msm_smux_close(uint8_t lcid)
 {
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index 8d17674..130b65e 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -194,6 +194,8 @@
 	int event_high_wm;
 	int event_rx_retry_high_wm;
 	int event_rx_retry_low_wm;
+	int event_local_closed;
+	int event_remote_closed;
 
 	/* TIOCM changes */
 	int event_tiocm;
@@ -249,6 +251,8 @@
 	cb->event_high_wm = 0;
 	cb->event_rx_retry_high_wm = 0;
 	cb->event_rx_retry_low_wm = 0;
+	cb->event_local_closed = 0;
+	cb->event_remote_closed = 0;
 	cb->event_tiocm = 0;
 	cb->tiocm_meta.tiocm_old = 0;
 	cb->tiocm_meta.tiocm_new = 0;
@@ -311,6 +315,8 @@
 		"\tevent_high_wm=%d\n"
 		"\tevent_rx_retry_high_wm=%d\n"
 		"\tevent_rx_retry_low_wm=%d\n"
+		"\tevent_local_closed=%d\n"
+		"\tevent_remote_closed=%d\n"
 		"\tevent_tiocm=%d\n"
 		"\tevent_read_done=%d\n"
 		"\tevent_read_failed=%d\n"
@@ -329,6 +335,8 @@
 		cb->event_high_wm,
 		cb->event_rx_retry_high_wm,
 		cb->event_rx_retry_low_wm,
+		cb->event_local_closed,
+		cb->event_remote_closed,
 		cb->event_tiocm,
 		cb->event_read_done,
 		cb->event_read_failed,
@@ -467,6 +475,22 @@
 		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
 		break;
 
+	case SMUX_LOCAL_CLOSED:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_local_closed;
+		cb_data_ptr->event_disconnected_ssr =
+			((struct smux_meta_disconnected *)metadata)->is_ssr;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+		break;
+
+	case SMUX_REMOTE_CLOSED:
+		spin_lock_irqsave(&cb_data_ptr->lock, flags);
+		++cb_data_ptr->event_remote_closed;
+		cb_data_ptr->event_disconnected_ssr =
+			((struct smux_meta_disconnected *)metadata)->is_ssr;
+		spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
+		break;
+
 	default:
 		pr_err("%s: unknown event %d\n", __func__, event);
 	};
@@ -609,13 +633,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -783,13 +812,18 @@
 
 		/* verify SSR events */
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, 5*HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, 10*HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		mock_cb_data_reset(&cb_data);
 
 		/* close port */
@@ -894,6 +928,8 @@
 			break;
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		mock_cb_data_reset(&cb_data);
 
 		/* close port */
@@ -1272,13 +1308,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -1442,13 +1483,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -1552,13 +1598,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -1884,13 +1935,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -2010,13 +2066,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
@@ -2139,13 +2200,18 @@
 		/* close port */
 		ret = msm_smux_close(SMUX_TEST_LCID);
 		UT_ASSERT_INT(ret, ==, 0);
-		UT_ASSERT_INT(
-			(int)wait_for_completion_timeout(
-				&cb_data.cb_completion, HZ),
-			>, 0);
-		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+		while (cb_data.cb_count < 3) {
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion, HZ),
+				>, 0);
+			INIT_COMPLETION(cb_data.cb_completion);
+		}
+		UT_ASSERT_INT(cb_data.cb_count, ==, 3);
 		UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
 		UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+		UT_ASSERT_INT(cb_data.event_local_closed, ==, 1);
+		UT_ASSERT_INT(cb_data.event_remote_closed, ==, 1);
 		break;
 	}
 
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/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/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2a98e49..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
@@ -2450,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));
@@ -2504,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,
@@ -2569,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
@@ -3554,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;
 	}
@@ -3578,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;
 	}
@@ -3610,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 = {
@@ -3830,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;
@@ -4031,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");
@@ -4294,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:
@@ -4355,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)
@@ -4446,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/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index 309effc..8dd3d55 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -57,6 +57,8 @@
 	int64_t Od;
 	int64_t Odprime;
 	int64_t Oreq;
+	int64_t init_phase_temp;
+	int64_t delta;
 	uint32_t mult;
 
 	/*
@@ -149,7 +151,24 @@
 				Oreq = (Osprime & int_mask) - one;
 
 				/* calculate initial phase */
-				init_phase = (int)((Osprime - Oreq) >> 4);
+				init_phase_temp = Osprime - Oreq;
+				delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+				init_phase_temp -= delta;
+
+				/* limit to valid range before the left shift */
+				delta = (init_phase_temp & (1LL << 63)) ?
+						4 : -4;
+				delta <<= PQF_PLUS_4;
+				while (abs((int)(init_phase_temp >>
+							PQF_PLUS_4)) > 4)
+					init_phase_temp += delta;
+
+				/*
+				 * right shift to account for extra bits of
+				 * precision
+				 */
+				init_phase = (int)(init_phase_temp >> 4);
+
 			}
 		} else {
 			/*
@@ -181,7 +200,18 @@
 			Oreq = (Osprime & int_mask) - one;
 
 			/* calculate initial phase */
-			init_phase = (int)((Osprime - Oreq) >> 4);
+			init_phase_temp = Osprime - Oreq;
+			delta = ((int64_t) (org) << PQF_PLUS_4) - Oreq;
+			init_phase_temp -= delta;
+
+			/* limit to valid range before the left shift */
+			delta = (init_phase_temp & (1LL << 63)) ? 4 : -4;
+			delta <<= PQF_PLUS_4;
+			while (abs((int)(init_phase_temp >> PQF_PLUS_4)) > 4)
+				init_phase_temp += delta;
+
+			/* right shift to account for extra bits of precision */
+			init_phase = (int)(init_phase_temp >> 4);
 		}
 	}
 
@@ -331,13 +361,43 @@
 	return rgb;
 }
 
-static uint8_t *mdp_adjust_rot_addr(struct ppp_blit_op *iBuf,
+uint8_t *mdp_bg_adjust_rot_addr(struct ppp_blit_op *iBuf,
+	uint8_t *addr, uint32_t bpp, uint32_t uv)
+{
+	uint32_t dest_ystride = iBuf->bg.prop.width * bpp;
+	uint32_t h_slice = 1, min_val;
+
+	if (uv && ((iBuf->bg.color_fmt == MDP_Y_CBCR_H2V2) ||
+		(iBuf->bg.color_fmt == MDP_Y_CRCB_H2V2)))
+		h_slice = 2;
+
+	if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^
+		((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) {
+		min_val = (iBuf->bg.roi.width + iBuf->bg.roi.x) % 16;
+		if (!min_val)
+			min_val = 16;
+		addr +=
+		    (iBuf->bg.roi.width -
+			    MIN(min_val, iBuf->bg.roi.width)) * bpp;
+	}
+	if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
+		min_val = (iBuf->bg.roi.height + iBuf->bg.roi.y) % 16;
+		if (!min_val)
+			min_val = 16;
+		addr +=
+			((iBuf->bg.roi.height -
+			MIN(min_val, iBuf->bg.roi.height))/h_slice) *
+			dest_ystride;
+	}
+
+	return addr;
+}
+
+uint8_t *mdp_dst_adjust_rot_addr(struct ppp_blit_op *iBuf,
 	uint8_t *addr, uint32_t bpp, uint32_t uv)
 {
 	uint32_t dest_ystride = iBuf->dst.prop.width * bpp;
 	uint32_t h_slice = 1;
-	if (0)
-		return 0;
 
 	if (uv && ((iBuf->dst.color_fmt == MDP_Y_CBCR_H2V2) ||
 		(iBuf->dst.color_fmt == MDP_Y_CRCB_H2V2)))
@@ -350,16 +410,10 @@
 			    MIN(16, iBuf->dst.roi.width)) * bpp;
 	}
 	if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
-		if (1) {
-			addr +=
-				((iBuf->dst.roi.height -
-				MIN(16, iBuf->dst.roi.height))/h_slice) *
-				dest_ystride;
-		} else {
-			addr +=
-			(iBuf->dst.roi.width -
-				MIN(16, iBuf->dst.roi.width)) * bpp;
-		}
+		addr +=
+			((iBuf->dst.roi.height -
+			MIN(16, iBuf->dst.roi.height))/h_slice) *
+			dest_ystride;
 	}
 
 	return addr;
@@ -378,8 +432,10 @@
 		img->p0 += (x + y * ALIGN(width, 32)) * bpp;
 	else
 		img->p0 += (x + y * width) * bpp;
-	if (layer != 0)
-		img->p0 = mdp_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+	if (layer == 1)
+		img->p0 = mdp_bg_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+	else if (layer == 2)
+		img->p0 = mdp_dst_adjust_rot_addr(blit_op, img->p0, bpp, 0);
 
 	if (img->p1) {
 		/*
@@ -394,8 +450,14 @@
 		else
 			img->p1 += ((x / h_slice) * h_slice +
 			((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
-		if (layer != 0)
-			img->p1 = mdp_adjust_rot_addr(blit_op, img->p1, bpp, 1);
+
+		if (layer == 1) {
+			img->p0 = mdp_bg_adjust_rot_addr(blit_op,
+					img->p0, bpp, 0);
+		} else if (layer == 2) {
+			img->p0 = mdp_dst_adjust_rot_addr(blit_op,
+					img->p0, bpp, 0);
+		}
 	}
 }
 
@@ -1044,7 +1106,6 @@
 	}
 
 	if (*pppop_reg_ptr & PPP_OP_BLEND_ON) {
-		blit_op->bg = blit_op->dst;
 		config_ppp_background(&blit_op->bg);
 
 		if (blit_op->dst.color_fmt == MDP_YCRYCB_H2V1) {
@@ -1152,9 +1213,11 @@
 		blit_op->dst.p1 = NULL;
 	}
 
+	blit_op->bg = blit_op->dst;
 	/* Jumping from Y-Plane to Chroma Plane */
 	/* first pixel addr calculation */
 	mdp_adjust_start_addr(blit_op, &blit_op->src, sv_slice, sh_slice, 0);
+	mdp_adjust_start_addr(blit_op, &blit_op->bg, dv_slice, dh_slice, 1);
 	mdp_adjust_start_addr(blit_op, &blit_op->dst, dv_slice, dh_slice, 2);
 
 	config_ppp_scale(blit_op, &ppp_operation_reg);
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/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index b903dfb..e9fbf90 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -77,6 +77,7 @@
 	int *key_codes;
 	bool need_calibration;
 	bool no_force_update;
+	bool no_lpm_support;
 	u8 bl_addr;
 
 	u8(*read_chg) (void);
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/smux.h b/include/linux/smux.h
index 56b18fa..1157cef 100644
--- a/include/linux/smux.h
+++ b/include/linux/smux.h
@@ -1,6 +1,6 @@
 /* include/linux/smux.h
  *
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -79,6 +79,8 @@
 	SMUX_HIGH_WM_HIT,     /* @metadata is NULL */
 	SMUX_RX_RETRY_HIGH_WM_HIT,  /* @metadata is NULL */
 	SMUX_RX_RETRY_LOW_WM_HIT,   /* @metadata is NULL */
+	SMUX_LOCAL_CLOSED,
+	SMUX_REMOTE_CLOSED,
 };
 
 /**
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/linux/videodev2.h b/include/linux/videodev2.h
index 81187aa..7ad0c16 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1856,6 +1856,21 @@
 	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED = 0,
 	V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
 };
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE		\
+		(V4L2_CID_MPEG_MSM_VIDC_BASE+30)
+enum v4l2_mpeg_vidc_video_alloc_mode_type {
+	V4L2_MPEG_VIDC_VIDEO_STATIC	= 0,
+	V4L2_MPEG_VIDC_VIDEO_RING	= 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY	\
+		(V4L2_CID_MPEG_MSM_VIDC_BASE+31)
+enum v4l2_mpeg_vidc_video_assembly {
+	V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE	= 0,
+	V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE	= 1,
+};
+
 /*  Camera class control IDs */
 #define V4L2_CID_CAMERA_CLASS_BASE 	(V4L2_CTRL_CLASS_CAMERA | 0x900)
 #define V4L2_CID_CAMERA_CLASS 		(V4L2_CTRL_CLASS_CAMERA | 1)
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/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 69e4cca..212924f 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -2639,17 +2639,31 @@
 	case SND_SOC_DAPM_PRE_PMU:
 
 		(*dmic_clk_cnt)++;
-		if (*dmic_clk_cnt == 1)
+		if (*dmic_clk_cnt == 1) {
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x0);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x0);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x0);
 			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
 					dmic_clk_en, dmic_clk_en);
+		}
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 
 		(*dmic_clk_cnt)--;
-		if (*dmic_clk_cnt  == 0)
+		if (*dmic_clk_cnt  == 0) {
 			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
 					dmic_clk_en, 0);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+			snd_soc_update_bits(codec,
+					TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+		}
 		break;
 	}
 	return 0;
@@ -8772,6 +8786,13 @@
 				      tabla_2_higher_codec_reg_init_val[i].mask,
 				      tabla_2_higher_codec_reg_init_val[i].val);
 	}
+	snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK0_MODE, 0x7, 0x4);
+	snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK1_MODE, 0x7, 0x4);
+	snd_soc_update_bits(codec, TABLA_A_CDC_DMIC_CLK2_MODE, 0x7, 0x4);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x90, 0x90);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x8, 0x8);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA0, 0x90, 0x0);
+	snd_soc_update_bits(codec, TABLA_A_PIN_CTL_DATA1, 0x8, 0x0);
 }
 
 static void tabla_update_reg_address(struct tabla_priv *priv)
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/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9f4e189..aa6ef6b 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -127,6 +127,7 @@
 	int i = 0;
 	int time_stamp_flag = 0;
 	int buffer_length = 0;
+	int stop_playback = 0;
 
 	pr_debug("%s opcode =%08x\n", __func__, opcode);
 	switch (opcode) {
@@ -151,9 +152,15 @@
 		/*
 		 * check for underrun
 		 */
+		snd_pcm_stream_lock_irq(substream);
 		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
-			pr_info("render stopped");
 			runtime->render_flag |= SNDRV_RENDER_STOPPED;
+			stop_playback = 1;
+		}
+		snd_pcm_stream_unlock_irq(substream);
+
+		if (stop_playback) {
+			pr_err("underrun! render stopped\n");
 			break;
 		}
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 2e5ff35..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;
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 4a3ff2a..42b1800 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1384,4 +1384,6 @@
 
 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;