Merge "ASoC: wcd9xxx: Change Supply Switch Control to automatic"
diff --git a/Documentation/devicetree/bindings/i2c/i2c-qup.txt b/Documentation/devicetree/bindings/i2c/i2c-qup.txt
index a7976e8..fd7b635 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-qup.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-qup.txt
@@ -28,10 +28,18 @@
 		      recovery procedure.
  - qcom,sda-gpio     : I2C data  GPIO number. Required for execution of bus
 		      recovery procedure.
+ - qcom,active-only  : Vote for core clock when the application processor goes
+		      to active state and remove that vote when it goes to idle
+		      state. This flag may improve service time of first i2c
+		      request at the expense of power consumption. When this
+		      entry is not present, voting is done by the runtime-pm
+		      callbacks.
+ - qcom,master-id    : Master endpoint number used for voting on clocks using
+		      bus-scaling driver.
 
 Example:
-	i2c@f9966000 {
-		cell-index = <0>;
+	i2c_3: i2c@f9966000 {
+		cell-index = <3>;
 		compatible = "qcom,i2c-qup";
 		reg = <0xf9966000 0x1000>;
 		reg-names = "qup_phys_addr";
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index c409ea6..ae1f648 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -50,7 +50,7 @@
 RGB Led is a tri-colored led, Red, Blue & Green.
 
 Required properties for RGB led:
-- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
+- qcom,mode: mode the led should operate in, options "pwm" and "lpg"
 - qcom,pwm-channel: pwm channel the led will operate on
 
 Required properties for PWM mode only:
@@ -59,6 +59,8 @@
 Required properties for LPG mode only:
 - qcom,duty-pcts: array of values for duty cycle to go through
 - qcom,start-idx: starting point duty-pcts array
+
+Optional properties for LPG mode only:
 - qcom,pause-lo: pause at low end of cycle
 - qcom,pause-hi: pause at high end of cycle
 - qcom,ramp-step-ms: step between each cycle (ms)
@@ -76,12 +78,28 @@
 - qcom,default-state: default state of the led, should be "on" or "off"
 - 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"
+
+Required properties for PWM mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,pwm-us: time the pwm device will modulate at (us)
+
+Required properties for LPG mode only:
+- qcom,pwm-channel: pwm channel the led will operate on
+- qcom,duty-pcts: array of values for duty cycle to go through
+- qcom,start-idx: starting point duty-pcts array
+
+Optional properties for LPG mode only:
+- qcom,pause-lo: pause at low end of cycle
+- qcom,pause-hi: pause at high end of cycle
+- qcom,ramp-step-ms: step between each cycle (ms)
+- qcom,lut-flags: flags to be used in lut configuration
 
 Keypad backlight is a backlight source for buttons. It supports four rows
 and the required rows are enabled by specifying values in the properties.
 
 Required properties for keypad backlight:
-- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
+- qcom,mode: mode the led should operate in, options "pwm" and "lpg"
 - qcom,pwm-channel: pwm channel the led will operate on
 - qcom,pwm-us: time the pwm device will modulate at (us)
 - qcom,row-src-sel-val: select source for rows. One bit is used for each row.
@@ -89,6 +107,19 @@
 - qcom,row-scan-val: select rows for scanning
 - qcom,row-scan-en: row scan enable
 
+Required properties for PWM mode only:
+- qcom,pwm-us: time the pwm device will modulate at (us)
+
+Required properties for LPG mode only:
+- qcom,duty-pcts: array of values for duty cycle to go through
+- qcom,start-idx: starting point duty-pcts array
+
+Optional properties for LPG mode only:
+- qcom,pause-lo: pause at low end of cycle
+- qcom,pause-hi: pause at high end of cycle
+- qcom,ramp-step-ms: step between each cycle (ms)
+- qcom,lut-flags: flags to be used in lut configuration
+
 Example:
 
 	qcom,leds@a200 {
@@ -105,12 +136,30 @@
 		};
 	};
 
+	qcom,leds@a300 {
+		status = "okay";
+		qcom,led_mpp_pwm {
+			label = "mpp";
+			linux,name = "green";
+			linux,default-trigger = "none";
+			qcom,default-state = "off";
+			qcom,max-current = <40>;
+			qcom,current-setting = <5>;
+			qcom,id = <6>;
+			qcom,mode = "pwm";
+			qcom,source-sel = <8>;
+			qcom,mode-ctrl = <0x60>;
+			qcom,pwm-channel = <0>;
+			qcom,pwm-us = <1000>;
+		};
+	};
+
 	qcom,leds@d000 {
 		status = "okay";
 		qcom,rgb_pwm {
 			label = "rgb";
 			linux,name = "led:rgb_red";
-			qcom,mode = <0>;
+			qcom,mode = "pwm";
 			qcom,pwm-channel = <6>;
 			qcom,pwm-us = <1000>;
 			qcom,duty-ms = <20>;
@@ -128,7 +177,7 @@
 		qcom,rgb_lpg {
 			label = "rgb";
 			linux,name = "led:rgb_blue";
-			qcom,mode = <1>;
+			qcom,mode = "lpg";
 			qcom,pwm-channel = <4>;
 			qcom,start-idx = <1>;
 			qcom,idx-len = <10>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 359ee6c..43df9cc 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -41,6 +41,8 @@
 					by default. This can then be overriden
 					writing the the module parameter
 					"charging_disabled".
+- qcom,duty-cycle-100p:			Set this property to enable the 100% duty
+					cycle feature.
 - qcom,use-default-batt-values:		Set this flag to force reporting of
 					battery temperature of 250 decidegree
 					Celsius, state of charge to be 50%
@@ -63,6 +65,10 @@
 					detection, "bpd_thm_id" selects both.
 					If the property is not set the hw default will
 					be used.
+- otg-parent-supply			Specify a phandle to a parent supply regulator
+					for the OTG regulator.
+- boost-parent-supply			Specify a phandle to a parent supply regulator
+					for the boost regulator.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
@@ -85,6 +91,7 @@
 
 			qcom,usb-chgpth:
 			 - usbin-valid
+
 			qcom,chgr:
 			 - chg-done
 			 - chg-failed
@@ -141,6 +148,16 @@
 			 - limit-error:		Limiting error on SMBB boost.
 			 - boost-pwr-ok:	Status of boost power.
 
+Sub node optional properties:
+			qcom,usb-chgpth:
+			 - regulator-name:	A string used as a descriptive name
+						for the OTG regulator.
+			qcom,boost:
+			 - regulator-min-microvolt:	Minimum boost voltage setting.
+			 - regulator-max-microvolt:	Maximum boost voltage setting.
+			 - regulator-name:	A string used as a descriptive name
+						for the boost regulator.
+
 Example:
 	pm8941-chg {
 		spmi-dev-container;
@@ -148,6 +165,9 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		otg-parent-supply = <&pm8941_boost>;
+		boost-parent-supply = <&foo_parent_reg>;
+
 		qcom,vddmax-mv = <4200>;
 		qcom,vddsafe-mv = <4200>;
 		qcom,vinmin-mv = <4200>;
@@ -218,7 +238,7 @@
 						"batt-pres";
 		};
 
-		qcom,usb-chgpth@1300 {
+		pm8941_chg_otg: qcom,usb-chgpth@1300 {
 			reg = <0x1300 0x100>;
 			interrupts =	<0 0x13 0x0>,
 					<0 0x13 0x1>,
@@ -238,7 +258,7 @@
 						"coarse-det-dc";
 		};
 
-		qcom,boost@1500 {
+		pm8941_chg_boost: qcom,boost@1500 {
 			reg = <0x1500 0x100>;
 			interrupts =	<0x0 0x15 0x0>,
 					<0x0 0x15 0x1>;
@@ -251,3 +271,15 @@
 			reg = <0x1600 0x100>;
 		};
 	};
+
+In regulator specific device tree file:
+
+	&pm8941_chg_boost {
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-name = "8941_smbb_boost";
+	};
+
+	&pm8941_chg_otg {
+		regulator-name = "8941_smbb_otg";
+	};
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index daa68b3..d58fa90 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -15,8 +15,8 @@
  - qcom,retain-mems: Presence denotes a hardware requirement to leave the
 		     forced memory retention signals in the core's clock
 		     branch control register asserted.
- - qcom,retain-logic: Presence denotes a requirement to leave power to the
-		      core's logic enabled.
+ - qcom,skip-logic-collapse: Presence denotes a requirement to leave power to
+                             the core's logic enabled.
 
 Example:
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
new file mode 100644
index 0000000..20468b2
--- /dev/null
+++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
@@ -0,0 +1,16 @@
+* Universal Flash Storage (UFS) Host Controller
+
+UFSHC nodes are defined to describe on-chip UFS host controllers.
+Each UFS controller instance should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains "jedec,ufs-1.1"
+- interrupts        : <interrupt mapping for UFS host controller IRQ>
+- reg               : <registers mapping>
+
+Example:
+	ufshc@0xfc598000 {
+		compatible = "jedec,ufs-1.1";
+		reg = <0xfc598000 0x800>;
+		interrupts = <0 28 0>;
+	};
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index b0d6b4d..a3a9935 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -40,8 +40,15 @@
   DATA GPIO PAD.
 - qcom,phy-sof-workaround : If present then HSIC PHY has h/w BUGs related to
   SOFs. Software workarounds are required for the same.
+- qcom,pool-64-bit-align: If present then the pool's memory will be aligned
+  to 64 bits
+- qcom,enable_hbm: if present host bus manager is enabled.
+- qcom,disable-park-mode: if present park mode is enabled. Park mode enables executing
+  up to 3 usb packets from each QH.
 - hsic,consider-ipa-handshake: If present then hsic low power mode is
   depend on suitable handshake with the IPA peer.
+- qcom,ahb-async-bridge-bypass: if present AHB ASYNC bridge will be bypassed such that
+  the bridge on the slave AHB is always used.
 
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index de1577d..fbe2d25 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -121,11 +121,6 @@
 
 Optional properties :
 - qcom,usb2-enable-hsphy2: If present, select second PHY for USB operation.
-- qcom,pool-64-bit-align: If present then the pool's memory will be aligned
-  to 64 bits
-- qcom,enable_hbm: if present host bus manager is enabled.
-- qcom,disable-park-mode: if present park mode is enabled. Park mode enables executing
-  up to 3 usb packets from each QH.
 
 Example MSM HSUSB EHCI controller device node :
 	ehci: qcom,ehci-host@f9a55000 {
diff --git a/arch/arm/boot/dts/fsm9900-rumi.dts b/arch/arm/boot/dts/fsm9900-rumi.dts
new file mode 100644
index 0000000..2b380c7
--- /dev/null
+++ b/arch/arm/boot/dts/fsm9900-rumi.dts
@@ -0,0 +1,31 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "fsm9900.dtsi"
+
+/ {
+	model = "Qualcomm FSM9900 Rumi";
+	compatible = "qcom,fsm9900-rumi", "qcom,fsm9900", "qcom-sim";
+	qcom,msm-id = <188 0 0>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+};
+
+&soc {
+	uart0: serial@f9960000 {
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/fsm9900-sim.dts b/arch/arm/boot/dts/fsm9900-sim.dts
new file mode 100644
index 0000000..050929e
--- /dev/null
+++ b/arch/arm/boot/dts/fsm9900-sim.dts
@@ -0,0 +1,32 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "fsm9900.dtsi"
+
+/ {
+	model = "Qualcomm FSM9900 Simulator";
+	compatible = "qcom,fsm9900-sim", "qcom,fsm9900", "qcom-sim";
+	qcom,msm-id = <188 0 0>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+};
+
+&soc {
+	uart0: serial@f9960000 {
+		interrupts = <0 116 0>;
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/fsm9900.dtsi b/arch/arm/boot/dts/fsm9900.dtsi
new file mode 100644
index 0000000..766db36
--- /dev/null
+++ b/arch/arm/boot/dts/fsm9900.dtsi
@@ -0,0 +1,94 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "skeleton64.dtsi"
+
+/ {
+	model = "Qualcomm FSM9900";
+	compatible = "qcom,fsm9900";
+	interrupt-parent = <&intc>;
+	soc: soc { };
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0 0 0xffffffff>;
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xF9000000 0x1000>,
+		      <0xF9002000 0x1000>;
+	};
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+		ngpio = <142>;
+		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <5>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 2 0 1 3 0>;
+		clock-frequency = <19200000>;
+	};
+
+	serial@f9960000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf9960000 0x1000>;
+		interrupts = <0 104 0>;
+		status = "disabled";
+	};
+
+	cpu-pmu {
+		compatible = "qcom,krait-pmu";
+		qcom,irq-is-percpu;
+		interrupts = <1 7 0xf00>;
+	};
+
+	qcom,msm-imem@fe805000 {
+		compatible = "qcom,msm-imem";
+		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
+	};
+
+	qcom,cache_erp {
+		compatible = "qcom,cache_erp";
+		interrupts = <1 9 0>, <0 2 0>;
+		interrupt-names = "l1_irq", "l2_irq";
+	};
+
+	qcom,cache_dump {
+		compatible = "qcom,cache_dump";
+		qcom,l1-dump-size = <0x100000>;
+		qcom,l2-dump-size = <0x500000>;
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
+	};
+
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ion-heap@30 { /* SYSTEM HEAP */
+			reg = <30>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/mpq8092-regulator.dtsi b/arch/arm/boot/dts/mpq8092-regulator.dtsi
index e6866e5..63896e9 100644
--- a/arch/arm/boot/dts/mpq8092-regulator.dtsi
+++ b/arch/arm/boot/dts/mpq8092-regulator.dtsi
@@ -16,6 +16,14 @@
 &spmi_bus {
 
 	qcom,pma8084@1 {
+		pma8084_s1: regulator@1400 {
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <900000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
 
 		pma8084_s3: regulator@1a00 {
 			regulator-min-microvolt = <1350000>;
@@ -53,19 +61,21 @@
 			status = "okay";
 		};
 
-		pma8084_s7: regulator@2600 {
-			regulator-min-microvolt = <900000>;
-			regulator-max-microvolt = <900000>;
+		pma8084_s8: regulator@2900 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
 			qcom,enable-time = <500>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
 		};
 
-		pma8084_s8: regulator@2900 {
+		pma8084_s12: regulator@3500 {
 			regulator-min-microvolt = <900000>;
 			regulator-max-microvolt = <900000>;
 			qcom,enable-time = <500>;
 			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
 			status = "okay";
 		};
 
@@ -82,8 +92,8 @@
 
 		pma8084_l2: regulator@4100 {
 			parent-supply = <&pma8084_s3>;
-			regulator-min-microvolt = <900000>;
-			regulator-max-microvolt = <900000>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
@@ -100,23 +110,14 @@
 
 		pma8084_l4: regulator@4300 {
 			parent-supply = <&pma8084_s3>;
-			regulator-min-microvolt = <1000000>;
-			regulator-max-microvolt = <1000000>;
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
 		};
 
 		pma8084_l6: regulator@4500 {
-			parent-supply = <&pma8084_s5>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pma8084_l8: regulator@4700 {
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
@@ -133,24 +134,6 @@
 		};
 
 		pma8084_l10: regulator@4900 {
-			regulator-min-microvolt = <2000000>;
-			regulator-max-microvolt = <2000000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pma8084_l11: regulator@4a00 {
-			parent-supply = <&pma8084_s3>;
-			regulator-min-microvolt = <1300000>;
-			regulator-max-microvolt = <1300000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pma8084_l12: regulator@4b00 {
-			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
@@ -158,25 +141,41 @@
 			status = "okay";
 		};
 
-		pma8084_l13: regulator@4c00 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
+		pma8084_l11: regulator@4a00 {
+			parent-supply = <&pma8084_s3>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
 		};
 
+		pma8084_l12: regulator@4b00 {
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_l13: regulator@4c00 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			status = "okay";
+		};
+
 		pma8084_l14: regulator@4d00 {
-			parent-supply = <&pma8084_s5>;
-			regulator-min-microvolt = <1000000>;
-			regulator-max-microvolt = <1000000>;
+			regulator-min-microvolt = <950000>;
+			regulator-max-microvolt = <950000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
 		};
 
 		pma8084_l15: regulator@4e00 {
-			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
@@ -185,7 +184,7 @@
 		};
 
 		pma8084_l16: regulator@4f00 {
-			parent-supply = <&pma8084_s4>;
+			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <750000>;
 			regulator-max-microvolt = <750000>;
 			qcom,enable-time = <200>;
@@ -198,7 +197,6 @@
 			regulator-max-microvolt = <3150000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
-			regulator-always-on;
 			qcom,system-load = <100000>;
 			status = "okay";
 		};
@@ -212,7 +210,7 @@
 		};
 
 		pma8084_l19: regulator@5200 {
-			parent-supply = <&pma8084_s4>;
+			parent-supply = <&pma8084_s5>;
 			regulator-min-microvolt = <1500000>;
 			regulator-max-microvolt = <1500000>;
 			qcom,enable-time = <200>;
@@ -225,6 +223,7 @@
 			regulator-max-microvolt = <2950000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
+			regulator-always-on;
 			status = "okay";
 		};
 
@@ -233,14 +232,16 @@
 			regulator-max-microvolt = <2950000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
+			regulator-always-on;
 			status = "okay";
 		};
 
 		pma8084_l22: regulator@5500 {
-			regulator-min-microvolt = <2500000>;
-			regulator-max-microvolt = <2500000>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
+			regulator-always-on;
 			status = "okay";
 		};
 
@@ -257,6 +258,31 @@
 			regulator-max-microvolt = <3075000>;
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			status = "okay";
+		};
+
+		pma8084_l25: regulator@5800 {
+			parent-supply = <&pma8084_s5>;
+			regulator-min-microvolt = <2000000>;
+			regulator-max-microvolt = <2000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+		pma8084_l26: regulator@5900 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+		pma8084_l27: regulator@5A00 {
+			parent-supply = <&pma8084_s3>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
 			status = "okay";
 		};
 
@@ -274,6 +300,20 @@
 			status = "okay";
 		};
 
+		pma8084_lvs3: regulator@8200 {
+			parent-supply = <&pma8084_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pma8084_lvs4: regulator@8300 {
+			parent-supply = <&pma8084_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
 		pma8084_mvs1: regulator@8400 {
 			qcom,enable-time = <200>;
 			qcom,pull-down-enable = <1>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index d6d919b..128d90c 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -211,6 +211,18 @@
 			label = "mpp";
 		};
 
+		qcom,leds@a300 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa300 0x100>;
+			label = "mpp";
+		};
+
+		qcom,leds@a500 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa500 0x100>;
+			label = "mpp";
+		};
+
 		pm8226_gpios: gpios {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 34ea33d..85a5608 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -247,7 +247,7 @@
 
 			};
 
-			qcom,usb-chgpth@1300 {
+			pm8941_chg_otg: qcom,usb-chgpth@1300 {
 				status = "disabled";
 				reg = <0x1300 0x100>;
 				interrupts =	<0 0x13 0x0>,
@@ -269,7 +269,7 @@
 							"dcin-valid";
 			};
 
-			qcom,boost@1500 {
+			pm8941_chg_boost: qcom,boost@1500 {
 				status = "disabled";
 				reg = <0x1500 0x100>;
 				interrupts =	<0x0 0x15 0x0>,
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index b96a9e1..6bbdf9f 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -254,11 +254,51 @@
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
 				qcom,id = <6>;
-				qcom,mode = <2>;
+				qcom,mode = "manual";
 				qcom,source-sel = <1>;
 				qcom,mode-ctrl = <0x60>;
 			};
 		};
+
+		qcom,leds@a300 {
+			status = "okay";
+			qcom,led_mpp_4 {
+				label = "mpp";
+				linux,name = "green";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = "lpg";
+				qcom,source-sel = <8>;
+				qcom,mode-ctrl = <0x60>;
+				qcom,pwm-channel = <0>;
+				qcom,start-idx = <1>;
+				qcom,duty-pcts = [00 00 00 00 64
+						 64 00 00 00 00];
+			};
+		};
+
+		qcom,leds@a500 {
+			status = "okay";
+			qcom,led_mpp_6 {
+				label = "mpp";
+				linux,name = "red";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode-ctrl = <0x60>;
+				qcom,source-sel = <10>;
+				qcom,mode = "lpg";
+				qcom,pwm-channel = <5>;
+				qcom,start-idx = <1>;
+				qcom,duty-pcts = [00 00 00 00 64
+						 64 00 00 00 00];
+			};
+		};
 	};
 
 	qcom,pm8226@1 {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 65b71e9..967eb82 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -242,11 +242,51 @@
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
 				qcom,id = <6>;
-				qcom,mode = <2>;
+				qcom,mode = "manual";
 				qcom,source-sel = <1>;
 				qcom,mode-ctrl = <0x60>;
 			};
 		};
+
+		qcom,leds@a300 {
+			status = "okay";
+			qcom,led_mpp_4 {
+				label = "mpp";
+				linux,name = "green";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = "lpg";
+				qcom,source-sel = <8>;
+				qcom,mode-ctrl = <0x60>;
+				qcom,pwm-channel = <0>;
+				qcom,start-idx = <1>;
+				qcom,duty-pcts = [00 00 00 00 64
+						 64 00 00 00 00];
+			};
+		};
+
+		qcom,leds@a500 {
+			status = "okay";
+			qcom,led_mpp_6 {
+				label = "mpp";
+				linux,name = "red";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode-ctrl = <0x60>;
+				qcom,source-sel = <10>;
+				qcom,mode = "lpg";
+				qcom,pwm-channel = <5>;
+				qcom,start-idx = <1>;
+				qcom,duty-pcts = [00 00 00 00 64
+						 64 00 00 00 00];
+			};
+		};
 	};
 
 	qcom,pm8226@1 {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index aba5c4a..f6e8f8b 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -245,11 +245,51 @@
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
 				qcom,id = <6>;
-				qcom,mode = <2>;
+				qcom,mode = "manual";
 				qcom,source-sel = <1>;
 				qcom,mode-ctrl = <0x60>;
 			};
 		};
+
+		qcom,leds@a300 {
+			status = "okay";
+			qcom,led_mpp_4 {
+				label = "mpp";
+				linux,name = "green";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = "lpg";
+				qcom,source-sel = <8>;
+				qcom,mode-ctrl = <0x60>;
+				qcom,pwm-channel = <0>;
+				qcom,start-idx = <1>;
+				qcom,duty-pcts = [00 00 00 00 64
+						 64 00 00 00 00];
+			};
+		};
+
+		qcom,leds@a500 {
+			status = "okay";
+			qcom,led_mpp_6 {
+				label = "mpp";
+				linux,name = "red";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode-ctrl = <0x60>;
+				qcom,source-sel = <10>;
+				qcom,mode = "lpg";
+				qcom,pwm-channel = <5>;
+				qcom,start-idx = <1>;
+				qcom,duty-pcts = [00 00 00 00 64
+						 64 00 00 00 00];
+			};
+		};
 	};
 
 	qcom,pm8226@1 {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 0d3b444..dfb9c43 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -271,6 +271,7 @@
 		compatible = "qcom,android-usb";
 		reg = <0xfe8050c8 0xc8>;
 		qcom,android-usb-cdrom;
+		qcom,android-usb-swfi-latency = <1>;
 	};
 
 	wcd9xxx_intc: wcd9xxx-irq {
@@ -985,8 +986,8 @@
 		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
-				<56 512 0 0>,
-				<56 512 3936000 393600>;
+				<55 512 0 0>,
+				<55 512 3936000 393600>;
 	};
 
         qcom,qcedev@fd400000 {
@@ -1003,8 +1004,8 @@
 		qcom,msm-bus,active-only = <0>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
-				<56 512 0 0>,
-				<56 512 3936000 393600>;
+				<55 512 0 0>,
+				<55 512 3936000 393600>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
new file mode 100644
index 0000000..d057260
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&i2c {
+
+	led_flash0: qcom,led-flash@60 {
+		cell-index = <0>;
+		reg = <0x60>;
+		qcom,slave-id = <0x60 0x00 0x0011>;
+		compatible = "qcom,led-flash";
+		qcom,flash-name = "adp1600";
+		qcom,flash-type = <1>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 18 0>,
+			<&msmgpio 19 0>;
+		qcom,gpio-flash-en = <0>;
+		qcom,gpio-flash-now = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <0 0>;
+		qcom,gpio-req-tbl-label = "FLASH_EN",
+			"FLASH_NOW";
+	};
+
+	actuator0: qcom,actuator@6e {
+		cell-index = <3>;
+		reg = <0x6c>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
+	qcom,camera@6f {
+		compatible = "qcom,ov8825";
+		reg = <0x6f>;
+		qcom,slave-id = <0x6c 0x300a 0x8825>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,actuator-src = <&actuator0>;
+		qcom,led-flash-src = <&led_flash0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "ov8825";
+		cam_vdig-supply = <&pm8110_l2>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		cam_vaf-supply = <&pm8110_l16>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+							 "cam_vaf";
+		qcom,cam-vreg-type = <0 0 0 0>;
+		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000 3000000>;
+		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000 3000000>;
+		qcom,cam-vreg-op-mode = <200000 8000 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 13 0>,
+			<&msmgpio 21 0>,
+			<&msmgpio 20 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY";
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+	};
+
+	qcom,camera@6d {
+		compatible = "qcom,ov9724";
+		reg = <0x6d>;
+		qcom,slave-id = <0x20 0x0 0x9724>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "ov9724";
+		cam_vdig-supply = <&pm8110_l4>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 1 0>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 14 0>,
+				<&msmgpio 15 0>,
+				<&msmgpio 8 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+				"CAM_RESET",
+				"CAM_STANDBY";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x1>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610-camera.dtsi b/arch/arm/boot/dts/msm8610-camera.dtsi
new file mode 100644
index 0000000..b1c94dd
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-camera.dtsi
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc{
+	qcom,msm-cam@fd8c0000 {
+		compatible = "qcom,msm-cam";
+		reg = <0xfd8C0000 0x10000>;
+		reg-names = "msm-cam";
+	};
+
+	qcom,csiphy@fda00c00 {
+		cell-index = <0>;
+		compatible = "qcom,csiphy";
+		reg = <0xfda00c00 0x1f4>;
+		reg-names = "csiphy";
+		interrupts = <0 78 0>;
+		interrupt-names = "csiphy";
+	};
+
+	qcom,csiphy@fda01000 {
+		cell-index = <1>;
+		compatible = "qcom,csiphy";
+		reg = <0xfda01000 0x1f4>;
+		reg-names = "csiphy";
+		interrupts = <0 79 0>;
+		interrupt-names = "csiphy";
+	};
+
+	qcom,csid@fda00000 {
+		cell-index = <0>;
+		compatible = "qcom,csid";
+		reg = <0xfda00000 0x100>;
+		reg-names = "csid";
+		interrupts = <0 50 0>;
+		interrupt-names = "csid";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8110_l4>;
+	};
+
+	qcom,csid@fda00400 {
+		cell-index = <1>;
+		compatible = "qcom,csid";
+		reg = <0xfda00400 0x100>;
+		reg-names = "csid";
+		interrupts = <0 51 0>;
+		interrupt-names = "csid";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8110_l4>;
+	};
+
+	qcom,ispif@fda00800 {
+		cell-index = <0>;
+		compatible = "qcom,ispif";
+		reg = <0xfda00800 0x200>;
+		reg-names = "ispif";
+		interrupts = <0 52 0>;
+		interrupt-names = "ispif";
+	};
+
+	qcom,vfe@fde00000 {
+		cell-index = <0>;
+		compatible = "qcom,vfe32";
+		reg = <0xfde00000 0x800>;
+		reg-names = "vfe", "vfe_vbif";
+		interrupts = <0 49 0>;
+		interrupt-names = "vfe";
+		vdd-supply = <&gdsc_vfe>;
+	};
+
+};
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index d7fe3cf..257a41c 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -14,6 +14,7 @@
 
 /include/ "msm8610.dtsi"
 /include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 CDP";
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index 1766422..af0e3e4 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -21,7 +21,7 @@
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
 			qcom,memory-reservation-type = "EBI1";
-			qcom,memory-reservation-size = <0x800000>;
+			qcom,memory-reservation-size = <0x300000>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index e7fe9ca..abd4228 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -14,6 +14,7 @@
 
 /include/ "msm8610.dtsi"
 /include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 MTP";
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index ca3e7ca..689392c 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -33,6 +33,7 @@
 	soc: soc { };
 };
 
+/include/ "msm8610-camera.dtsi"
 /include/ "msm-iommu-v0.dtsi"
 /include/ "msm8610-ion.dtsi"
 /include/ "msm8610-gpu.dtsi"
@@ -472,7 +473,7 @@
                 qcom,i2c-bus-freq = <100000>;
         };
 
-	i2c@f9928000 { /* BLSP1 QUP6 */
+	i2c: i2c@f9928000 { /* BLSP1 QUP6 */
 		cell-index = <6>;
 		compatible = "qcom,i2c-qup";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index ad5f175..a822af5 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -608,12 +608,6 @@
 	};
 
 	mpp@a400 { /* MPP 5 */
-		/* SPI_ETH config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-sel = <0>; /* CONSTANT */
-		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
 	mpp@a500 { /* MPP 6 */
diff --git a/arch/arm/boot/dts/msm8974-leds.dtsi b/arch/arm/boot/dts/msm8974-leds.dtsi
index c4780b0..5e91f45 100644
--- a/arch/arm/boot/dts/msm8974-leds.dtsi
+++ b/arch/arm/boot/dts/msm8974-leds.dtsi
@@ -18,7 +18,7 @@
 			qcom,rgb_0 {
 				label = "rgb";
 				linux,name = "led:rgb_red";
-				qcom,mode = <0>;
+				qcom,mode = "pwm";
 				qcom,pwm-channel = <6>;
 				qcom,pwm-us = <1000>;
 				qcom,max-current = <12>;
@@ -31,7 +31,7 @@
 			qcom,rgb_1 {
 				label = "rgb";
 				linux,name = "led:rgb_green";
-				qcom,mode = <0>;
+				qcom,mode = "pwm";
 				qcom,pwm-channel = <5>;
 				qcom,pwm-us = <1000>;
 				qcom,max-current = <12>;
@@ -43,7 +43,7 @@
 			qcom,rgb_2 {
 				label = "rgb";
 				linux,name = "led:rgb_blue";
-				qcom,mode = <0>;
+				qcom,mode = "pwm";
 				qcom,pwm-channel = <4>;
 				qcom,pwm-us = <1000>;
 				qcom,max-current = <12>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index c2dae28..b30d65c 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -424,10 +424,6 @@
 	qcom,otg-capability;
 };
 
-&pm8941_mvs1 {
-	parent-supply = <&ext_5v>;
-};
-
 &pm8941_mvs2 {
 	parent-supply = <&ext_5v>;
 };
@@ -777,6 +773,7 @@
 
 &pm8941_chg {
 	status = "ok";
+	otg-parent-supply = <&ext_5v>;
 
 	qcom,charging-disabled;
 
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 4d28a1d..e798fc0 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -637,13 +637,6 @@
 	};
 
 	mpp@a400 { /* MPP 5 */
-		/* SPI_ETH config */
-		qcom,mode = <1>; /* DIG_OUT */
-		qcom,output-type = <0>; /* CMOS */
-		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-sel = <0>; /* CONSTANT */
-		qcom,out-strength = <1>;  /* QPNP_PIN_OUT_STRENGTH_LOW */
-		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
 	mpp@a500 { /* MPP 6 */
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 35f3993..2114686 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -25,7 +25,7 @@
 		};
 
 		pm8941_mvs1: regulator@8300 {
-			parent-supply = <&pm8941_boost>;
+			parent-supply = <&pm8941_chg_otg>;
 			qcom,enable-time = <1000>;
 			qcom,pull-down-enable = <1>;
 			interrupts = <0x1 0x83 0x2>;
@@ -552,3 +552,17 @@
 		regulator-always-on;
 	};
 };
+
+&pm8941_chg {
+	otg-parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg_boost {
+	regulator-min-microvolt = <5000000>;
+	regulator-max-microvolt = <5000000>;
+	regulator-name = "8941_smbb_boost";
+};
+
+&pm8941_chg_otg {
+	regulator-name = "8941_smbb_otg";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index 1735515..792a78c 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -36,5 +36,5 @@
 };
 
 &pm8941_chg {
-	qcom,bpd-detection = "bpd_id";
+	qcom,bpd-detection = "bpd_thm";
 };
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 44ebe67..4367807 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -767,6 +767,7 @@
 		interrupt-names = "qup_err_intr";
 		qcom,i2c-bus-freq = <100000>;
 		qcom,i2c-src-freq = <50000000>;
+		qcom,master-id = <84>;
 	};
 
 	i2c_1: i2c@f9923000 {
@@ -782,6 +783,7 @@
 		qcom,i2c-src-freq = <19200000>;
 		qcom,scl-gpio = <&msmgpio 3 0>;
 		qcom,sda-gpio = <&msmgpio 2 0>;
+		qcom,master-id = <86>;
 		status = "disabled";
 	};
 
@@ -796,6 +798,7 @@
 		interrupt-names = "qup_err_intr";
 		qcom,i2c-bus-freq = <100000>;
 		qcom,i2c-src-freq = <50000000>;
+		qcom,master-id = <86>;
 	};
 
 	spi_0: spi@f9923000 {
@@ -1613,6 +1616,7 @@
 
 &gdsc_venus {
 	qcom,clock-names = "core_clk";
+	qcom,skip-logic-collapse;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 9b18b72..bde734e 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -34,6 +34,8 @@
 		coresight-id = <1>;
 		coresight-name = "coresight-tpiu";
 		coresight-nr-inports = <1>;
+
+		vdd-supply = <&ext_2p95v>;
 	};
 
 	replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index ca09370..c865c58 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -191,6 +191,7 @@
 		qcom,pool-64-bit-align;
 		qcom,enable-hbm;
 		hsic,consider-ipa-handshake;
+		qcom,ahb-async-bridge-bypass;
 	};
 
 	qcom,usbbam@f9a44000 {
@@ -256,7 +257,7 @@
 			qcom,dst-bam-physical-address = <0xf9a04000>;
 			qcom,dst-bam-pipe-index = <3>;
 			qcom,data-fifo-size = <0xD480>;
-			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,descriptor-fifo-size = <0x3200>;
 			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe4 {
@@ -269,7 +270,7 @@
 			qcom,dst-bam-physical-address = <0xf9a04000>;
 			qcom,dst-bam-pipe-index = <4>;
 			qcom,data-fifo-size = <0xD480>;
-			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,descriptor-fifo-size = <0x3200>;
 			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe5 {
@@ -282,7 +283,7 @@
 			qcom,dst-bam-physical-address = <0xf9a04000>;
 			qcom,dst-bam-pipe-index = <5>;
 			qcom,data-fifo-size = <0xD480>;
-			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,descriptor-fifo-size = <0x3200>;
 			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe6 {
@@ -295,7 +296,7 @@
 			qcom,dst-bam-physical-address = <0xf9a04000>;
 			qcom,dst-bam-pipe-index = <6>;
 			qcom,data-fifo-size = <0xD480>;
-			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,descriptor-fifo-size = <0x3200>;
 			qcom,reset-bam-on-connect;
 		};
 		qcom,pipe7 {
@@ -307,8 +308,8 @@
 			qcom,peer-bam = <2>;
 			qcom,src-bam-physical-address = <0xf9a04000>;
 			qcom,src-bam-pipe-index = <7>;
-			qcom,data-fifo-size = <0xD480>;
-			qcom,descriptor-fifo-size = <0x1A80>;
+			qcom,data-fifo-size = <0xDFE>;
+			qcom,descriptor-fifo-size = <0xB30>;
 			qcom,reset-bam-on-connect;
 		};
 	};
diff --git a/arch/arm/boot/dts/msmsamarium-sim.dts b/arch/arm/boot/dts/msmsamarium-sim.dts
index 2774f7f..4acffae 100644
--- a/arch/arm/boot/dts/msmsamarium-sim.dts
+++ b/arch/arm/boot/dts/msmsamarium-sim.dts
@@ -23,3 +23,33 @@
 &uartblsp0dm2{
 	status = "ok";
 };
+
+&sdcc1 {
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,sup-voltages = <2950 2950>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	qcom,nonremovable;
+	status = "ok";
+};
+
+&sdcc2 {
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,sup-voltages = <2950 2950>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,xpc;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+	qcom,current-limit = <800>;
+
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index 9d9ff87..81699b6 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -63,4 +63,28 @@
 		compatible = "qcom,msm-imem";
 		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
 	};
+
+	sdcc1: qcom,sdcc@f9824000 {
+		cell-index = <1>; /* SDC1 eMMC slot */
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf9824000 0x800>;
+		reg-names = "core_mem";
+		interrupts = <0 123 0>;
+		interrupt-names = "core_irq";
+
+		qcom,bus-width = <8>;
+		status = "disabled";
+	};
+
+	sdcc2: qcom,sdcc@f98a4000 {
+		cell-index = <2>; /* SDC2 SD card slot */
+		compatible = "qcom,msm-sdcc";
+		reg = <0xf98a4000 0x800>;
+		reg-names = "core_mem";
+		interrupts = <0 125 0>;
+		interrupt-names = "core_irq";
+
+		qcom,bus-width = <4>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index c0084bf..549bc73 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -49,6 +49,7 @@
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_IPC_ROUTER_SECURITY=y
+CONFIG_MSM_QMI_INTERFACE=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_RPM_REGULATOR_SMD=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
diff --git a/arch/arm/configs/fsm9900_defconfig b/arch/arm/configs/fsm9900_defconfig
new file mode 100644
index 0000000..94e18ae
--- /dev/null
+++ b/arch/arm/configs/fsm9900_defconfig
@@ -0,0 +1,261 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_XZ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_IOSCHED_TEST=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_FSM9900=y
+CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
+CONFIG_MSM_MPM_OF=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_CPU_HAS_L2_PMU=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_IPC_ROUTER_SECURITY=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_SPM_V2=y
+CONFIG_MSM_L2_SPM=y
+CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_NONSECURE=y
+CONFIG_SENSORS_ADSP=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
+CONFIG_MSM_CACHE_ERP=y
+CONFIG_MSM_L1_ERR_PANIC=y
+CONFIG_MSM_L1_RECOV_ERR_PANIC=y
+CONFIG_MSM_L1_ERR_LOG=y
+CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
+CONFIG_MSM_L2_ERP_PORT_PANIC=y
+CONFIG_MSM_L2_ERP_1BIT_PANIC=y
+CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_CACHE_DUMP=y
+CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
+CONFIG_SCHED_MC=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CP_ACCESS=y
+CONFIG_USE_OF=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_NET_IPIP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_NET_ACTIVITY_STATS is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_MII=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_MSM_RMNET is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
+CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
+CONFIG_SPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
+CONFIG_MSM_QPNP_INT=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_GPIO_QPNP_PIN_DEBUG=y
+CONFIG_SENSORS_EPM_ADC=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_USB=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_MSM_SSBI=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_PWM=y
+CONFIG_QPNP_POWER_ON=y
+CONFIG_QPNP_CLKDIV=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_PSTORE=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=m
+CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_CRC_CCITT=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 108a68f..6b62269 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -306,6 +306,7 @@
 	select ARCH_WANT_KMAP_ATOMIC_FLUSH
 	select MEMORY_HOLE_CARVEOUT
 	select DONT_MAP_HOLE_AFTER_MEMBANK0
+	select QMI_ENCDEC
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
@@ -2721,14 +2722,25 @@
 	  related operations of OCMEM. Both local power management
 	  and RPM assisted power management operations are supported.
 
-config MSM_OCMEM_POWER_DISABLE
-	bool "OCMEM Disable Power Control"
+config MSM_OCMEM_DEBUG_ALWAYS_ON
+	bool "Keep OCMEM always turned ON"
 	depends on MSM_OCMEM_DEBUG
 	help
+	  Always vote for all OCMEM clocks and keep all OCMEM
+	  macros turned ON and never allow them to be turned OFF.
+	  Both local power management and RPM assisted power modes
+	  are supported for individual macro power control operations.
+
+config MSM_OCMEM_POWER_DISABLE
+	bool "OCMEM Disable Power Control"
+	depends on MSM_OCMEM
+	help
 	  Disable all OCMEM power management.
-	  This keeps all OCMEM macros turned ON at all times thus
-	  never allowing them to be turned OFF. Both local power
-	  management and RPM assisted power modes are supported.
+	  Skip all OCMEM power operations that turn ON or
+	  turn OFF the macros. Both local power management and
+	  RPM assisted power management operations are skipped.
+	  Enable this configuration if OCMEM is being exclusively
+	  used as GMEM or OCIMEM.
 
 config SENSORS_ADSP
 	bool "Enable Sensors Driver Support for ADSP"
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f969e31..372f8ba 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -85,7 +85,6 @@
 #include "pm.h"
 #include "pm-boot.h"
 #include "devices-msm8x60.h"
-#include "smd_private.h"
 #include "platsmp.h"
 
 #define MHL_GPIO_INT           30
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index ab5cc3a..7b81c11 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -75,8 +75,6 @@
 static struct of_dev_auxdata mpq8092_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
 			"msm_serial_hsl.0", NULL),
-	OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
-			"spmi-pmic-arb.0", NULL),
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9824000, \
 			"msm_sdcc.1", NULL),
 	OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 593e2b1..8303992 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -75,7 +75,7 @@
 static struct gpiomux_setting lcd_en_sus_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_DOWN,
+	.pull = GPIOMUX_PULL_UP,
 };
 
 static struct gpiomux_setting gpio_keys_active = {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index ccea956..e097faf 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -96,7 +96,6 @@
 #include "rpm_resources.h"
 #include <mach/mpm.h>
 #include "clock.h"
-#include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
 #include "board-8930.h"
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index cb88cdc..b45e690 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -98,7 +98,6 @@
 #include "rpm_resources.h"
 #include <mach/mpm.h>
 #include "clock.h"
-#include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
 #include "platsmp.h"
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 76dbaef..c8a88d7 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -1001,7 +1001,6 @@
 	},
 };
 
-#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
 static struct gpiomux_setting sdc3_clk_actv_cfg = {
 	.func = GPIOMUX_FUNC_2,
 	.drv = GPIOMUX_DRV_8MA,
@@ -1082,9 +1081,6 @@
 	msm_gpiomux_install(msm8974_sdc3_configs,
 			    ARRAY_SIZE(msm8974_sdc3_configs));
 }
-#else
-static void msm_gpiomux_sdc3_install(void) {}
-#endif /* CONFIG_MMC_MSM_SDC3_SUPPORT */
 
 #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
 static struct gpiomux_setting sdc4_clk_actv_cfg = {
@@ -1219,7 +1215,11 @@
 	msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
 
 	msm_gpiomux_install(&sd_card_det, 1);
-	msm_gpiomux_sdc3_install();
+
+	if (machine_is_apq8074() && (of_board_is_liquid() || \
+	    of_board_is_dragonboard()))
+		msm_gpiomux_sdc3_install();
+
 	msm_gpiomux_sdc4_install();
 
 	msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 1034516..5df3f3e 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3039,6 +3039,18 @@
 	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,  "scm"),
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,  "scm"),
 	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,      "scm"),
+
+	/* Add QCEDEV clocks */
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,      "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,  "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,  "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,      "fd400000.qcom,qcedev"),
+
+	/* Add QCRYPTO clocks */
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,     "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c, "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c, "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,     "fd404000.qcom,qcrypto"),
 };
 
 static struct clk_lookup msm_clocks_8610_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index dabab9f..53e35ef 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5395,12 +5395,6 @@
 		writel_relaxed(regval | BIT(26) | BIT(25),
 				GCC_REG_BASE(APCS_CLOCK_BRANCH_ENA_VOTE));
 	}
-
-	/*
-	 * TODO: Confirm that no clocks need to be voted on in this sleep vote
-	 * register.
-	 */
-	writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
 }
 
 static void __init msm8974_clock_post_init(void)
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index fff517a..24af44e 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -175,39 +175,19 @@
 
 	cf = rcg->current_freq;
 
-	/* Enable source clock dependency for the new freq. */
-	if (c->prepare_count) {
-		rc = clk_prepare(nf->src_clk);
-		if (rc)
-			return rc;
-	}
-
-	spin_lock_irqsave(&c->lock, flags);
-	if (c->count) {
-		rc = clk_enable(nf->src_clk);
-		if (rc) {
-			spin_unlock_irqrestore(&c->lock, flags);
-			clk_unprepare(nf->src_clk);
-			return rc;
-		}
-	}
+	rc = __clk_pre_reparent(c, nf->src_clk, &flags);
+	if (rc)
+		return rc;
 
 	BUG_ON(!rcg->set_rate);
 
 	/* Perform clock-specific frequency switch operations. */
 	rcg->set_rate(rcg, nf);
-
-	/* Release source requirements of the old freq. */
-	if (c->count)
-		clk_disable(cf->src_clk);
-	spin_unlock_irqrestore(&c->lock, flags);
-
-	if (c->prepare_count)
-		clk_unprepare(cf->src_clk);
-
 	rcg->current_freq = nf;
 	c->parent = nf->src_clk;
 
+	__clk_post_reparent(c, cf->src_clk, &flags);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 608018c..582bccf 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -475,7 +475,7 @@
 	mutex_lock(&clk->prepare_lock);
 
 	/* Return early if the rate isn't going to change */
-	if (clk->rate == rate)
+	if (clk->rate == rate && !(clk->flags & CLKFLAG_NO_RATE_CACHE))
 		goto out;
 
 	trace_clock_set_rate(name, rate, raw_smp_processor_id());
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 1701262..0963e27 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -48,13 +48,17 @@
 	struct clk		**clocks;
 	int			clock_count;
 	bool			toggle_mems;
-	bool			retain_logic;
+	bool			toggle_logic;
+	bool			resets_asserted;
 };
 
 static int gdsc_is_enabled(struct regulator_dev *rdev)
 {
 	struct gdsc *sc = rdev_get_drvdata(rdev);
 
+	if (!sc->toggle_logic)
+		return !sc->resets_asserted;
+
 	return !!(readl_relaxed(sc->gdscr) & PWR_ON_MASK);
 }
 
@@ -64,15 +68,22 @@
 	uint32_t regval;
 	int i, ret;
 
-	regval = readl_relaxed(sc->gdscr);
-	regval &= ~SW_COLLAPSE_MASK;
-	writel_relaxed(regval, sc->gdscr);
+	if (sc->toggle_logic) {
+		regval = readl_relaxed(sc->gdscr);
+		regval &= ~SW_COLLAPSE_MASK;
+		writel_relaxed(regval, sc->gdscr);
 
-	ret = readl_tight_poll_timeout(sc->gdscr, regval, regval & PWR_ON_MASK,
-				       TIMEOUT_US);
-	if (ret) {
-		dev_err(&rdev->dev, "%s enable timed out\n", sc->rdesc.name);
-		return ret;
+		ret = readl_tight_poll_timeout(sc->gdscr, regval,
+					regval & PWR_ON_MASK, TIMEOUT_US);
+		if (ret) {
+			dev_err(&rdev->dev, "%s enable timed out\n",
+				sc->rdesc.name);
+			return ret;
+		}
+	} else {
+		for (i = 0; i < sc->clock_count; i++)
+			clk_reset(sc->clocks[i], CLK_RESET_DEASSERT);
+		sc->resets_asserted = false;
 	}
 
 	if (sc->toggle_mems) {
@@ -99,7 +110,7 @@
 	uint32_t regval;
 	int i, ret = 0;
 
-	if (!sc->retain_logic) {
+	if (sc->toggle_logic) {
 		regval = readl_relaxed(sc->gdscr);
 		regval |= SW_COLLAPSE_MASK;
 		writel_relaxed(regval, sc->gdscr);
@@ -110,6 +121,10 @@
 		if (ret)
 			dev_err(&rdev->dev, "%s disable timed out\n",
 				sc->rdesc.name);
+	} else {
+		for (i = 0; i < sc->clock_count; i++)
+			clk_reset(sc->clocks[i], CLK_RESET_ASSERT);
+		sc->resets_asserted = true;
 	}
 
 	if (sc->toggle_mems) {
@@ -219,8 +234,20 @@
 		}
 	}
 	sc->toggle_mems = !retain_mems;
-	sc->retain_logic = of_property_read_bool(pdev->dev.of_node,
-					    "qcom,retain-logic");
+	sc->toggle_logic = !of_property_read_bool(pdev->dev.of_node,
+						"qcom,skip-logic-collapse");
+	if (!sc->toggle_logic) {
+		regval &= ~SW_COLLAPSE_MASK;
+		writel_relaxed(regval, sc->gdscr);
+
+		ret = readl_tight_poll_timeout(sc->gdscr, regval,
+					regval & PWR_ON_MASK, TIMEOUT_US);
+		if (ret) {
+			dev_err(&pdev->dev, "%s enable timed out\n",
+				sc->rdesc.name);
+			return ret;
+		}
+	}
 
 	sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
 				      pdev->dev.of_node);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index d3ef0be..7b26bd6 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -510,6 +510,15 @@
 	bool mhl_enabled;
 };
 
+/**
+ * msm_i2c_platform_data: i2c-qup driver configuration data
+ *
+ * @active_only when set, votes when system active and removes the vote when
+ *       system goes idle (optimises for performance). When unset, voting using
+ *       runtime pm (optimizes for power).
+ * @master_id master id number of the i2c core or its wrapper (BLSP/GSBI).
+ *       When zero, clock path voting is disabled.
+ */
 struct msm_i2c_platform_data {
 	int clk_freq;
 	uint32_t rmutex;
@@ -523,6 +532,8 @@
 	int use_gsbi_shared_mode;
 	int keep_ahb_clk_on;
 	void (*msm_i2c_config_gpio)(int iface, int config_type);
+	bool active_only;
+	uint32_t master_id;
 };
 
 struct msm_i2c_ssbi_platform_data {
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
index 1809456..fae0777 100644
--- a/arch/arm/mach-msm/include/mach/clk.h
+++ b/arch/arm/mach-msm/include/mach/clk.h
@@ -25,6 +25,7 @@
 #define CLKFLAG_MAX			0x00000800
 #define CLKFLAG_INIT_DONE		0x00001000
 #define CLKFLAG_INIT_ERR		0x00002000
+#define CLKFLAG_NO_RATE_CACHE		0x00004000
 
 struct clk_lookup;
 struct clk;
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index decf9bb..06f5215 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -186,6 +186,22 @@
 	int attach_count;
 };
 
+struct msm_iommu_context_regs {
+	uint32_t far;
+	uint32_t par;
+	uint32_t fsr;
+	uint32_t fsynr0;
+	uint32_t fsynr1;
+	uint32_t ttbr0;
+	uint32_t ttbr1;
+	uint32_t sctlr;
+	uint32_t actlr;
+	uint32_t prrr;
+	uint32_t nmrr;
+};
+
+void print_ctx_regs(struct msm_iommu_context_regs *regs);
+
 /*
  * Interrupt handler for the IOMMU context fault interrupt. Hooking the
  * interrupt is not supported in the API yet, but this will print an error
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 676df66..7b73333 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -81,16 +81,6 @@
 #define MSM_LPASS_CLK_CTL_BASE	IOMEM(0xFA015000)	/*  4K	*/
 #define MSM_HFPLL_BASE		IOMEM(0xFA016000)	/*  4K	*/
 #define MSM_TLMM_BASE		IOMEM(0xFA017000)	/* 16K	*/
-#define MSM_SHARED_RAM_BASE	IOMEM(0xFA400000)	/*  2M  */
-#define MSM_SIC_NON_SECURE_BASE	IOMEM(0xFA600000)	/* 64K	*/
-#define MSM_HDMI_BASE		IOMEM(0xFA800000)	/*  4K  */
-#define MSM_RPM_BASE		IOMEM(0xFA801000)	/*  4K	*/
-#define MSM_RPM_MPM_BASE	IOMEM(0xFA802000)	/*  4K	*/
-#define MSM_QFPROM_BASE		IOMEM(0xFA700000)	/*  4K  */
-#define MSM_L2CC_BASE		IOMEM(0xFA701000)	/*  4K  */
-#define MSM_APCS_GLB_BASE	IOMEM(0xFA702000)	/*  4K  */
-#define MSM_SAW2_BASE		IOMEM(0xFA703000)	/*  4k  */
-#define MSM_SAW3_BASE		IOMEM(0xFA704000)	/*  4k  */
 #define MSM_VIC_BASE		IOMEM(0xFA100000)	/*  4K */
 #define MSM_CSR_BASE		IOMEM(0xFA101000)	/*  4K */
 #define MSM_GPIO1_BASE		IOMEM(0xFA102000)	/*  4K */
@@ -99,7 +89,16 @@
 #define MSM_CFG_CTL_BASE	IOMEM(0xFA105000)	/*  4K */
 #define MSM_CLK_CTL_SH2_BASE	IOMEM(0xFA106000)	/*  4K */
 #define MSM_MPM2_PSHOLD_BASE	IOMEM(0xFA107000)	/*  4k */
-#define MSM_MDC_BASE		IOMEM(0xFA400000)	/*  1M */
+#define MSM_SHARED_RAM_BASE	IOMEM(0xFA400000)	/*  2M  */
+#define MSM_SIC_NON_SECURE_BASE	IOMEM(0xFA600000)	/* 64K	*/
+#define MSM_QFPROM_BASE		IOMEM(0xFA700000)	/*  4K  */
+#define MSM_L2CC_BASE		IOMEM(0xFA701000)	/*  4K  */
+#define MSM_APCS_GLB_BASE	IOMEM(0xFA702000)	/*  4K  */
+#define MSM_SAW2_BASE		IOMEM(0xFA703000)	/*  4k  */
+#define MSM_SAW3_BASE		IOMEM(0xFA704000)	/*  4k  */
+#define MSM_HDMI_BASE		IOMEM(0xFA800000)	/*  4K  */
+#define MSM_RPM_BASE		IOMEM(0xFA801000)	/*  4K	*/
+#define MSM_RPM_MPM_BASE	IOMEM(0xFA802000)	/*  4K	*/
 #define MSM_AD5_BASE		IOMEM(0xFA900000)	/*  13M (D00000)
 							  0xFB600000 */
 /* MSM9625 has unaligned imem so we need to map excess 2K virtually
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_router.h b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
index 894379e..5dc1095 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_router.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
@@ -46,9 +46,6 @@
 	spinlock_t port_lock;
 	struct comm_mode_info mode_info;
 
-	struct list_head incomplete;
-	struct mutex incomplete_lock;
-
 	struct list_head port_rx_q;
 	struct mutex port_rx_q_lock;
 	char rx_wakelock_name[MAX_WAKELOCK_NAME_SZ];
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 3bf05e6..5c8f525 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2011, 2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,15 @@
 	MEMTYPE_MAX,
 };
 
+enum {
+	SYS_MEMORY = 1,        /* system memory*/
+	BOOT_REGION_MEMORY1,   /* boot loader memory 1*/
+	BOOT_REGION_MEMORY2,   /* boot loader memory 2,reserved*/
+	APPSBL_MEMORY,         /* apps boot loader memory*/
+	APPS_MEMORY,           /* apps  usage memory*/
+};
+
+
 void msm_reserve(void);
 
 #define MEMTYPE_FLAGS_FIXED	0x1
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index c5ad35d..3332701 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -1271,6 +1271,15 @@
 int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
 		u32 tb_sel, u32 desc_sel);
 
+/**
+ * Vote for or relinquish BAM DMA clock
+ *
+ * @clk_on - to turn on or turn off the clock
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_ctrl_bam_dma_clk(bool clk_on);
 #else
 static inline int sps_register_bam_device(const struct sps_bam_props
 			*bam_props, u32 *dev_handle)
@@ -1433,6 +1442,11 @@
 {
 	return -EPERM;
 }
+
+static inline int sps_ctrl_bam_dma_clk(bool clk_on)
+{
+	return -EPERM;
+}
 #endif
 
 #endif /* _SPS_H_ */
diff --git a/arch/arm/mach-msm/trace_msm_low_power.h b/arch/arm/mach-msm/include/mach/trace_msm_low_power.h
similarity index 98%
rename from arch/arm/mach-msm/trace_msm_low_power.h
rename to arch/arm/mach-msm/include/mach/trace_msm_low_power.h
index 4e9da85..faa4209 100644
--- a/arch/arm/mach-msm/trace_msm_low_power.h
+++ b/arch/arm/mach-msm/include/mach/trace_msm_low_power.h
@@ -149,6 +149,6 @@
 );
 #endif
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_PATH mach
 #define TRACE_INCLUDE_FILE trace_msm_low_power
 #include <trace/define_trace.h>
diff --git a/arch/arm/mach-msm/trace_rpm_smd.h b/arch/arm/mach-msm/include/mach/trace_rpm_smd.h
similarity index 98%
rename from arch/arm/mach-msm/trace_rpm_smd.h
rename to arch/arm/mach-msm/include/mach/trace_rpm_smd.h
index eff4860..1b019d8 100644
--- a/arch/arm/mach-msm/trace_rpm_smd.h
+++ b/arch/arm/mach-msm/include/mach/trace_rpm_smd.h
@@ -74,6 +74,6 @@
 );
 #endif
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_PATH mach
 #define TRACE_INCLUDE_FILE trace_rpm_smd
 #include <trace/define_trace.h>
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 73e960f..7fb2c88 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -69,7 +69,6 @@
 	MSM_CHIP_DEVICE(GPIO2, MSM7XXX),
 	MSM_CHIP_DEVICE(CLK_CTL, MSM7XXX),
 	MSM_CHIP_DEVICE(AD5, MSM7XXX),
-	MSM_CHIP_DEVICE(MDC, MSM7XXX),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_DEVICE(DEBUG_UART),
@@ -117,7 +116,6 @@
 	MSM_DEVICE(SIRC),
 	MSM_DEVICE(SCPLL),
 	MSM_DEVICE(AD5),
-	MSM_DEVICE(MDC),
 	MSM_DEVICE(TCSR),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
@@ -353,7 +351,6 @@
 	MSM_CHIP_DEVICE(CLK_CTL, MSM7X30),
 	MSM_CHIP_DEVICE(CLK_CTL_SH2, MSM7X30),
 	MSM_CHIP_DEVICE(AD5, MSM7X30),
-	MSM_CHIP_DEVICE(MDC, MSM7X30),
 	MSM_CHIP_DEVICE(ACC0, MSM7X30),
 	MSM_CHIP_DEVICE(SAW0, MSM7X30),
 	MSM_CHIP_DEVICE(APCS_GCC, MSM7X30),
@@ -476,7 +473,6 @@
 	MSM_CHIP_DEVICE(SAW2, MSM8625),
 	MSM_CHIP_DEVICE(SAW3, MSM8625),
 	MSM_CHIP_DEVICE(AD5, MSM7XXX),
-	MSM_CHIP_DEVICE(MDC, MSM7XXX),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
 	MSM_DEVICE(DEBUG_UART),
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index f95ef3b..573b9a3 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -115,7 +115,6 @@
 #define SRV_HASH_SIZE 32
 static struct list_head server_list[SRV_HASH_SIZE];
 static DEFINE_MUTEX(server_list_lock);
-static wait_queue_head_t newserver_wait;
 
 struct msm_ipc_server {
 	struct list_head list;
@@ -182,9 +181,6 @@
 static DEFINE_MUTEX(routing_table_lock);
 static int routing_table_inited;
 
-static LIST_HEAD(msm_ipc_board_dev_list);
-static DEFINE_MUTEX(msm_ipc_board_dev_list_lock);
-
 static void do_read_data(struct work_struct *work);
 
 #define RR_STATE_IDLE    0
@@ -586,8 +582,6 @@
 	}
 
 	spin_lock_init(&port_ptr->port_lock);
-	INIT_LIST_HEAD(&port_ptr->incomplete);
-	mutex_init(&port_ptr->incomplete_lock);
 	INIT_LIST_HEAD(&port_ptr->port_rx_q);
 	mutex_init(&port_ptr->port_rx_q_lock);
 	init_waitqueue_head(&port_ptr->port_rx_wait_q);
@@ -3120,7 +3114,6 @@
 	}
 	mutex_unlock(&routing_table_lock);
 
-	init_waitqueue_head(&newserver_wait);
 	init_waitqueue_head(&subsystem_restart_wait);
 	ret = msm_ipc_router_init_sockets();
 	if (ret < 0)
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 624a27c..1d9c539 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -23,11 +23,12 @@
 #include <linux/tick.h>
 #include <mach/mpm.h>
 #include <mach/rpm-smd.h>
+#include <mach/trace_msm_low_power.h>
 #include "spm.h"
 #include "lpm_resources.h"
 #include "rpm-notifier.h"
 #include "idle.h"
-#include "trace_msm_low_power.h"
+
 
 /*Debug Definitions*/
 enum {
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 1680993..d7d3081 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -384,7 +384,28 @@
 	return 0;
 }
 
-/* This function scans the device tree to populate the memory hole table */
+/* Function to remove any meminfo blocks which are of size zero */
+static void merge_meminfo(void)
+{
+	int i = 0;
+
+	while (i < meminfo.nr_banks) {
+		struct membank *bank = &meminfo.bank[i];
+
+		if (bank->size == 0) {
+			memmove(bank, bank + 1,
+			(meminfo.nr_banks - i) * sizeof(*bank));
+			meminfo.nr_banks--;
+			continue;
+		}
+		i++;
+	}
+}
+
+/*
+ * Function to scan the device tree and adjust the meminfo table to
+ * reflect the memory holes.
+ */
 int __init dt_scan_for_memory_hole(unsigned long node, const char *uname,
 		int depth, void *data)
 {
@@ -413,16 +434,6 @@
 		hole_start = be32_to_cpu(memory_remove_prop[0]);
 		hole_size = be32_to_cpu(memory_remove_prop[1]);
 
-		if (hole_start + hole_size <= MAX_HOLE_ADDRESS) {
-			if (memory_hole_start == 0 && memory_hole_end == 0) {
-				memory_hole_start = hole_start;
-				memory_hole_end = hole_start + hole_size;
-			} else if ((memory_hole_end - memory_hole_start)
-							<= hole_size) {
-				memory_hole_start = hole_start;
-				memory_hole_end = hole_start + hole_size;
-			}
-		}
 		adjust_meminfo(hole_start, hole_size);
 	}
 
@@ -452,6 +463,7 @@
 			bank[1].start = (start + size);
 			bank[1].size -= (bank->size + size);
 			bank[1].highmem = 0;
+			merge_meminfo();
 		}
 	}
 }
diff --git a/arch/arm/mach-msm/memory_topology.c b/arch/arm/mach-msm/memory_topology.c
index 97195e3..de90427 100644
--- a/arch/arm/mach-msm/memory_topology.c
+++ b/arch/arm/mach-msm/memory_topology.c
@@ -20,12 +20,44 @@
 #include <mach/msm_memtypes.h>
 #include <mach/socinfo.h>
 #include <mach/msm_smem.h>
-#include "smd_private.h"
 
 #if defined(CONFIG_ARCH_MSM8960)
 #include "rpm_resources.h"
 #endif
 
+struct smem_ram_ptn {
+	char name[16];
+	unsigned start;
+	unsigned size;
+
+	/* RAM Partition attribute: READ_ONLY, READWRITE etc.  */
+	unsigned attr;
+
+	/* RAM Partition category: EBI0, EBI1, IRAM, IMEM */
+	unsigned category;
+
+	/* RAM Partition domain: APPS, MODEM, APPS & MODEM (SHARED) etc. */
+	unsigned domain;
+
+	/* RAM Partition type: system, bootloader, appsboot, apps etc. */
+	unsigned type;
+
+	/* reserved for future expansion without changing version number */
+	unsigned reserved2, reserved3, reserved4, reserved5;
+} __attribute__ ((__packed__));
+
+
+struct smem_ram_ptable {
+	#define _SMEM_RAM_PTABLE_MAGIC_1 0x9DA5E0A8
+	#define _SMEM_RAM_PTABLE_MAGIC_2 0xAF9EC4E2
+	unsigned magic[2];
+	unsigned version;
+	unsigned reserved1;
+	unsigned len;
+	struct smem_ram_ptn parts[32];
+	unsigned buf;
+} __attribute__ ((__packed__));
+
 static struct mem_region_t {
 	u64 start;
 	u64 size;
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 9b18c59..153864d 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -759,7 +759,7 @@
 	return -EINVAL;
 }
 
-#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
+#if defined(CONFIG_MSM_OCMEM_DEBUG_ALWAYS_ON)
 static int ocmem_core_set_default_state(void)
 {
 	int rc = 0;
@@ -775,7 +775,14 @@
 
 	return 0;
 }
+#else
+static int ocmem_core_set_default_state(void)
+{
+	return 0;
+}
+#endif
 
+#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
 /* Initializes a region to be turned ON in wide mode */
 static int ocmem_region_set_default_state(unsigned int r_num)
 {
@@ -800,15 +807,9 @@
 {
 	return 0;
 }
-
-static int ocmem_core_set_default_state(void)
-{
-	return 0;
-}
 #endif
 
 #if defined(CONFIG_MSM_OCMEM_POWER_DEBUG)
-
 static int read_hw_region_state(unsigned region_num)
 {
 	int state;
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 19b5671..6cd6ffe 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -176,12 +176,25 @@
 
 static int pil_lpass_reset_trusted(struct pil_desc *pil)
 {
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	int ret;
+
+	ret = clk_prepare_enable(drv->axi_clk);
+	if (ret)
+		return ret;
 	return pas_auth_and_reset(PAS_Q6);
 }
 
 static int pil_lpass_shutdown_trusted(struct pil_desc *pil)
 {
-	return pas_shutdown(PAS_Q6);
+	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	int ret;
+
+	ret = pas_shutdown(PAS_Q6);
+	if (ret)
+		return ret;
+	clk_disable_unprepare(drv->axi_clk);
+	return 0;
 }
 
 static struct pil_reset_ops pil_lpass_ops_trusted = {
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 5e44a4e..4a54dd4 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -35,6 +35,8 @@
 #include <mach/system.h>
 #include <mach/scm.h>
 #include <mach/socinfo.h>
+#define CREATE_TRACE_POINTS
+#include <mach/trace_msm_low_power.h>
 #include <mach/msm-krait-l2-accessors.h>
 #include <mach/msm_bus.h>
 #include <asm/cacheflush.h>
@@ -56,8 +58,7 @@
 #include "timer.h"
 #include "pm-boot.h"
 #include <mach/event_timer.h>
-#define CREATE_TRACE_POINTS
-#include "trace_msm_low_power.h"
+
 #define SCM_L2_RETENTION	(0x2)
 #define SCM_CMD_TERMINATE_PC	(0x2)
 
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 1eb66f4..38ed867 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -36,9 +36,9 @@
 #include <mach/socinfo.h>
 #include <mach/msm_smd.h>
 #include <mach/rpm-smd.h>
-#include "rpm-notifier.h"
 #define CREATE_TRACE_POINTS
-#include "trace_rpm_smd.h"
+#include <mach/trace_rpm_smd.h>
+#include "rpm-notifier.h"
 /* Debug Definitions */
 
 enum {
diff --git a/arch/arm/mach-msm/sdio_al_dloader.c b/arch/arm/mach-msm/sdio_al_dloader.c
index b0cb88f..f3effa8 100644
--- a/arch/arm/mach-msm/sdio_al_dloader.c
+++ b/arch/arm/mach-msm/sdio_al_dloader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -228,6 +228,7 @@
 static unsigned long lock_flags2;
 
 static atomic_t sdio_dld_in_use = ATOMIC_INIT(0);
+static atomic_t sdio_dld_setup_done = ATOMIC_INIT(0);
 
 /*
  * sdio_op_mode sets the operation mode of the sdio_dloader -
@@ -2388,6 +2389,14 @@
 	if (atomic_read(&sdio_dld_in_use) == 1)
 		return -EBUSY;
 
+	/*
+	 * If the setup is already complete tear down the existing
+	 * one and reinitialize. This might happen during modem restarts
+	 * in boot phase.
+	 */
+	if (atomic_read(&sdio_dld_setup_done) == 1)
+		sdio_dld_tear_down(NULL);
+
 	if (num_of_devices == 0 || num_of_devices > MAX_NUM_DEVICES) {
 		pr_err(MODULE_NAME ": %s - invalid number of devices\n",
 		       __func__);
@@ -2478,6 +2487,7 @@
 		pr_err(MODULE_NAME ": %s - tty_register_device() "
 			"failed\n", __func__);
 		tty_unregister_driver(sdio_dld->tty_drv);
+		put_tty_driver(sdio_dld->tty_drv);
 		kfree(sdio_dld);
 		return PTR_ERR(tty_dev);
 	}
@@ -2518,6 +2528,7 @@
 		goto exit_err;
 	}
 
+	atomic_set(&sdio_dld_setup_done, 1);
 	return 0;
 
 exit_err:
@@ -2526,7 +2537,9 @@
 	if (result)
 		pr_err(MODULE_NAME ": %s - tty_unregister_driver() "
 		       "failed. result=%d\n", __func__, -result);
+	put_tty_driver(sdio_dld->tty_drv);
 	kfree(sdio_dld);
+	atomic_set(&sdio_dld_setup_done, 0);
 	return status;
 }
 
@@ -2534,22 +2547,24 @@
 {
 	int status = 0;
 
-	del_timer_sync(&sdio_dld->timer);
-	del_timer_sync(&sdio_dld->push_timer);
-
-	sdio_dld_dealloc_local_buffers();
+	if (atomic_read(&sdio_dld_in_use) == 1) {
+		del_timer_sync(&sdio_dld->timer);
+		del_timer_sync(&sdio_dld->push_timer);
+		sdio_dld_dealloc_local_buffers();
+	}
 
 	tty_unregister_device(sdio_dld->tty_drv, 0);
 
 	status = tty_unregister_driver(sdio_dld->tty_drv);
-
 	if (status) {
 		pr_err(MODULE_NAME ": %s - tty_unregister_driver() failed\n",
 		       __func__);
 	}
 
+	put_tty_driver(sdio_dld->tty_drv);
 	kfree(sdio_dld);
 	atomic_set(&sdio_dld_in_use, 0);
+	atomic_set(&sdio_dld_setup_done, 0);
 }
 
 MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 4fe9592..2096063 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -155,27 +155,6 @@
 
 struct smd_half_channel_access *get_half_ch_funcs(unsigned ch_type);
 
-struct smem_ram_ptn {
-	char name[16];
-	unsigned start;
-	unsigned size;
-
-	/* RAM Partition attribute: READ_ONLY, READWRITE etc.  */
-	unsigned attr;
-
-	/* RAM Partition category: EBI0, EBI1, IRAM, IMEM */
-	unsigned category;
-
-	/* RAM Partition domain: APPS, MODEM, APPS & MODEM (SHARED) etc. */
-	unsigned domain;
-
-	/* RAM Partition type: system, bootloader, appsboot, apps etc. */
-	unsigned type;
-
-	/* reserved for future expansion without changing version number */
-	unsigned reserved2, reserved3, reserved4, reserved5;
-} __attribute__ ((__packed__));
-
 struct smd_channel {
 	volatile void __iomem *send; /* some variant of smd_half_channel */
 	volatile void __iomem *recv; /* some variant of smd_half_channel */
@@ -217,54 +196,6 @@
 	struct smd_half_channel_access *half_ch;
 };
 
-struct smem_ram_ptable {
-	#define _SMEM_RAM_PTABLE_MAGIC_1 0x9DA5E0A8
-	#define _SMEM_RAM_PTABLE_MAGIC_2 0xAF9EC4E2
-	unsigned magic[2];
-	unsigned version;
-	unsigned reserved1;
-	unsigned len;
-	struct smem_ram_ptn parts[32];
-	unsigned buf;
-} __attribute__ ((__packed__));
-
-/* SMEM RAM Partition */
-enum {
-	DEFAULT_ATTRB = ~0x0,
-	READ_ONLY = 0x0,
-	READWRITE,
-};
-
-enum {
-	DEFAULT_CATEGORY = ~0x0,
-	SMI = 0x0,
-	EBI1,
-	EBI2,
-	QDSP6,
-	IRAM,
-	IMEM,
-	EBI0_CS0,
-	EBI0_CS1,
-	EBI1_CS0,
-	EBI1_CS1,
-	SDRAM = 0xE,
-};
-
-enum {
-	DEFAULT_DOMAIN = 0x0,
-	APPS_DOMAIN,
-	MODEM_DOMAIN,
-	SHARED_DOMAIN,
-};
-
-enum {
-	SYS_MEMORY = 1,        /* system memory*/
-	BOOT_REGION_MEMORY1,   /* boot loader memory 1*/
-	BOOT_REGION_MEMORY2,   /* boot loader memory 2,reserved*/
-	APPSBL_MEMORY,         /* apps boot loader memory*/
-	APPS_MEMORY,           /* apps  usage memory*/
-};
-
 extern spinlock_t smem_lock;
 
 
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 928f5cb..575cb49 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -327,6 +327,9 @@
 	[158] = MSM_CPU_8226,
 	[159] = MSM_CPU_8226,
 	[198] = MSM_CPU_8226,
+	[199] = MSM_CPU_8226,
+	[200] = MSM_CPU_8226,
+	[205] = MSM_CPU_8226,
 
 	/* 8092 IDs */
 	[146] = MSM_CPU_8092,
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 26b92d4..34cb153 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -395,32 +395,29 @@
 	unsigned long hole_end_virt;
 
 	/*
-	 * Find the start and end of the hole, using meminfo
-	 * if it hasnt been found already.
+	 * Find the start and end of the hole, using meminfo.
 	 */
-	if (memory_hole_start == 0 && memory_hole_end == 0) {
-		for (i = 0; i < (meminfo.nr_banks - 1); i++) {
-			if ((meminfo.bank[i].start + meminfo.bank[i].size) !=
+	for (i = 0; i < (meminfo.nr_banks - 1); i++) {
+		if ((meminfo.bank[i].start + meminfo.bank[i].size) !=
 						meminfo.bank[i+1].start) {
-				if (meminfo.bank[i].start + meminfo.bank[i].size
+			if (meminfo.bank[i].start + meminfo.bank[i].size
 							<= MAX_HOLE_ADDRESS) {
 
-					hole_start = meminfo.bank[i].start +
+				hole_start = meminfo.bank[i].start +
 							meminfo.bank[i].size;
-					hole_size = meminfo.bank[i+1].start -
+				hole_size = meminfo.bank[i+1].start -
 								hole_start;
 
-					if (memory_hole_start == 0 &&
+				if (memory_hole_start == 0 &&
 							memory_hole_end == 0) {
-						memory_hole_start = hole_start;
-						memory_hole_end = hole_start +
+					memory_hole_start = hole_start;
+					memory_hole_end = hole_start +
 								hole_size;
-					} else if ((memory_hole_end -
+				} else if ((memory_hole_end -
 					memory_hole_start) <= hole_size) {
-						memory_hole_start = hole_start;
-						memory_hole_end = hole_start +
+					memory_hole_start = hole_start;
+					memory_hole_end = hole_start +
 								hole_size;
-					}
 				}
 			}
 		}
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 235a340..85c28d4 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -80,6 +80,8 @@
  */
 static DEFINE_MUTEX(dbs_mutex);
 
+static struct workqueue_struct *dbs_wq;
+
 static struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int sampling_down_factor;
@@ -455,7 +457,7 @@
 
 	dbs_check_cpu(dbs_info);
 
-	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
+	queue_delayed_work_on(cpu, dbs_wq, &dbs_info->work, delay);
 	mutex_unlock(&dbs_info->timer_mutex);
 }
 
@@ -467,7 +469,7 @@
 
 	dbs_info->enable = 1;
 	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
-	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
+	queue_delayed_work_on(dbs_info->cpu, dbs_wq, &dbs_info->work, delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
@@ -602,12 +604,19 @@
 
 static int __init cpufreq_gov_dbs_init(void)
 {
+	dbs_wq = alloc_workqueue("conservative_dbs_wq", WQ_HIGHPRI, 0);
+	if (!dbs_wq) {
+		printk(KERN_ERR "Failed to create conservative_dbs_wq workqueue\n");
+		return -EFAULT;
+	}
+
 	return cpufreq_register_governor(&cpufreq_gov_conservative);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_conservative);
+	destroy_workqueue(dbs_wq);
 }
 
 
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 7b01432..79f7174 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -116,7 +116,7 @@
  */
 static DEFINE_MUTEX(dbs_mutex);
 
-static struct workqueue_struct *input_wq;
+static struct workqueue_struct *dbs_wq;
 
 struct dbs_work_struct {
 	struct work_struct work;
@@ -376,8 +376,8 @@
 			cancel_delayed_work_sync(&dbs_info->work);
 			mutex_lock(&dbs_info->timer_mutex);
 
-			schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
-						 usecs_to_jiffies(new_rate));
+			queue_delayed_work_on(dbs_info->cpu, dbs_wq,
+				&dbs_info->work, usecs_to_jiffies(new_rate));
 
 		}
 		mutex_unlock(&dbs_info->timer_mutex);
@@ -941,7 +941,7 @@
 			dbs_info->freq_lo, CPUFREQ_RELATION_H);
 		delay = dbs_info->freq_lo_jiffies;
 	}
-	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
+	queue_delayed_work_on(cpu, dbs_wq, &dbs_info->work, delay);
 	mutex_unlock(&dbs_info->timer_mutex);
 }
 
@@ -955,7 +955,7 @@
 
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
 	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
-	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
+	queue_delayed_work_on(dbs_info->cpu, dbs_wq, &dbs_info->work, delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
@@ -1036,7 +1036,7 @@
 		&per_cpu(dbs_sync_work, target_cpu);
 	sync_work->src_cpu = (unsigned int)arg;
 
-	queue_work_on(target_cpu, input_wq,
+	queue_work_on(target_cpu, dbs_wq,
 		&per_cpu(dbs_sync_work, target_cpu).work);
 
 	return NOTIFY_OK;
@@ -1127,7 +1127,7 @@
 	}
 
 	for_each_online_cpu(i)
-		queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i).work);
+		queue_work_on(i, dbs_wq, &per_cpu(dbs_refresh_work, i).work);
 }
 
 static int dbs_input_connect(struct input_handler *handler,
@@ -1325,9 +1325,9 @@
 			MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
 	}
 
-	input_wq = create_workqueue("iewq");
-	if (!input_wq) {
-		printk(KERN_ERR "Failed to create iewq workqueue\n");
+	dbs_wq = alloc_workqueue("ondemand_dbs_wq", WQ_HIGHPRI, 0);
+	if (!dbs_wq) {
+		printk(KERN_ERR "Failed to create ondemand_dbs_wq workqueue\n");
 		return -EFAULT;
 	}
 	for_each_possible_cpu(i) {
@@ -1361,7 +1361,7 @@
 			&per_cpu(od_cpu_dbs_info, i);
 		mutex_destroy(&this_dbs_info->timer_mutex);
 	}
-	destroy_workqueue(input_wq);
+	destroy_workqueue(dbs_wq);
 }
 
 
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 99ace44..3422f05 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -306,7 +306,7 @@
 config CRYPTO_DEV_QCE
 	tristate "Qualcomm Crypto Engine (QCE) module"
 	select  CRYPTO_DEV_QCE40 if ARCH_MSM8960 || ARCH_MSM9615
-	select  CRYPTO_DEV_QCE50 if ARCH_MSM8974 || ARCH_MSM9625 || ARCH_MSM8226
+	select  CRYPTO_DEV_QCE50 if ARCH_MSM8974 || ARCH_MSM9625 || ARCH_MSM8226 || ARCH_MSM8610
 	default n
 	help
           This driver supports Qualcomm Crypto Engine in MSM7x30, MSM8660
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 9870648..a18fb8b 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1943,13 +1943,11 @@
 		podev->platform_support.bus_scale_table = NULL;
 		podev->platform_support.sha_hmac = 1;
 
-		if (podev->ce_support.is_shared == false) {
-			podev->platform_support.bus_scale_table =
-				(struct msm_bus_scale_pdata *)
-						msm_bus_cl_get_pdata(pdev);
-			if (!podev->platform_support.bus_scale_table)
-				pr_err("bus_scale_table is NULL\n");
-		}
+		podev->platform_support.bus_scale_table =
+			(struct msm_bus_scale_pdata *)
+					msm_bus_cl_get_pdata(pdev);
+		if (!podev->platform_support.bus_scale_table)
+			pr_err("bus_scale_table is NULL\n");
 	} else {
 		platform_support =
 			(struct msm_ce_hw_support *)pdev->dev.platform_data;
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index a4bb2f1..375516b 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -3393,13 +3393,11 @@
 		cp->platform_support.bus_scale_table =	NULL;
 		cp->platform_support.sha_hmac = 1;
 
-		if (cp->ce_support.is_shared == false) {
-			cp->platform_support.bus_scale_table =
-				(struct msm_bus_scale_pdata *)
-						msm_bus_cl_get_pdata(pdev);
-			if (!cp->platform_support.bus_scale_table)
-				pr_warn("bus_scale_table is NULL\n");
-		}
+		cp->platform_support.bus_scale_table =
+			(struct msm_bus_scale_pdata *)
+					msm_bus_cl_get_pdata(pdev);
+		if (!cp->platform_support.bus_scale_table)
+			pr_warn("bus_scale_table is NULL\n");
 	} else {
 		platform_support =
 			(struct msm_ce_hw_support *)pdev->dev.platform_data;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 992f88d..9de3410 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -29,6 +29,8 @@
 #include <linux/io.h>
 #include <mach/socinfo.h>
 #include <linux/mman.h>
+#include <linux/sort.h>
+#include <asm/cacheflush.h>
 
 #include "kgsl.h"
 #include "kgsl_debugfs.h"
@@ -674,7 +676,7 @@
 	list_del(&private->list);
 	mutex_unlock(&kgsl_driver.process_mutex);
 
-	if (private->kobj.parent)
+	if (private->kobj.ktype)
 		kgsl_process_uninit_sysfs(private);
 	if (private->debug_root)
 		debugfs_remove_recursive(private->debug_root);
@@ -791,7 +793,7 @@
 		}
 	}
 
-	if (!private->kobj.parent)
+	if (!private->kobj.ktype)
 		kgsl_process_init_sysfs(private);
 	if (!private->debug_root)
 		kgsl_process_init_debugfs(private);
@@ -2104,6 +2106,97 @@
 	return ret;
 }
 
+static int mem_id_cmp(const void *_a, const void *_b)
+{
+	const unsigned int *a = _a, *b = _b;
+	int cmp = a - b;
+	return (cmp < 0) ? -1 : (cmp > 0);
+}
+
+static long
+kgsl_ioctl_gpumem_sync_cache_bulk(struct kgsl_device_private *dev_priv,
+	unsigned int cmd, void *data)
+{
+	int i;
+	struct kgsl_gpumem_sync_cache_bulk *param = data;
+	struct kgsl_process_private *private = dev_priv->process_priv;
+	unsigned int id, last_id = 0, *id_list = NULL, actual_count = 0;
+	struct kgsl_mem_entry **entries = NULL;
+	long ret = 0;
+	size_t op_size = 0;
+	bool full_flush = false;
+
+	if (param->id_list == NULL || param->count == 0
+			|| param->count > (UINT_MAX/sizeof(unsigned int)))
+		return -EINVAL;
+
+	id_list = kzalloc(param->count * sizeof(unsigned int), GFP_KERNEL);
+	if (id_list == NULL)
+		return -ENOMEM;
+
+	entries = kzalloc(param->count * sizeof(*entries), GFP_KERNEL);
+	if (entries == NULL) {
+		ret = -ENOMEM;
+		goto end;
+	}
+
+	if (copy_from_user(id_list, param->id_list,
+				param->count * sizeof(unsigned int))) {
+		ret = -EFAULT;
+		goto end;
+	}
+	/* sort the ids so we can weed out duplicates */
+	sort(id_list, param->count, sizeof(int), mem_id_cmp, NULL);
+
+	for (i = 0; i < param->count; i++) {
+		unsigned int cachemode;
+		struct kgsl_mem_entry *entry = NULL;
+
+		id = id_list[i];
+		/* skip 0 ids or duplicates */
+		if (id == last_id)
+			continue;
+
+		entry = kgsl_sharedmem_find_id(private, id);
+		if (entry == NULL)
+			continue;
+
+		/* skip uncached memory */
+		cachemode = kgsl_memdesc_get_cachemode(&entry->memdesc);
+		if (cachemode != KGSL_CACHEMODE_WRITETHROUGH &&
+		    cachemode != KGSL_CACHEMODE_WRITEBACK) {
+			kgsl_mem_entry_put(entry);
+			continue;
+		}
+
+		op_size += entry->memdesc.size;
+		entries[actual_count++] = entry;
+
+		/* If we exceed the breakeven point, flush the entire cache */
+		if (op_size >= kgsl_driver.full_cache_threshold &&
+		    param->op == KGSL_GPUMEM_CACHE_FLUSH) {
+			full_flush = true;
+			break;
+		}
+		last_id = id;
+	}
+	if (full_flush) {
+		trace_kgsl_mem_sync_full_cache(actual_count, op_size,
+					       param->op);
+		__cpuc_flush_kern_all();
+	}
+
+	for (i = 0; i < actual_count; i++) {
+		if (!full_flush)
+			_kgsl_gpumem_sync_cache(entries[i], param->op);
+		kgsl_mem_entry_put(entries[i]);
+	}
+end:
+	kfree(entries);
+	kfree(id_list);
+	return ret;
+}
+
 /* Legacy cache function, does a flush (clean  + invalidate) */
 
 static long
@@ -2510,6 +2603,8 @@
 			kgsl_ioctl_gpumem_get_info, 0),
 	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE,
 			kgsl_ioctl_gpumem_sync_cache, 0),
+	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK,
+			kgsl_ioctl_gpumem_sync_cache_bulk, 0),
 };
 
 static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
@@ -2952,6 +3047,11 @@
 	.devlock = __MUTEX_INITIALIZER(kgsl_driver.devlock),
 	.memfree_hist_mutex =
 		__MUTEX_INITIALIZER(kgsl_driver.memfree_hist_mutex),
+	/*
+	 * Full cache flushes are faster than line by line on at least
+	 * 8064 and 8974 once the region to be flushed is > 16mb.
+	 */
+	.full_cache_threshold = SZ_16M,
 };
 EXPORT_SYMBOL(kgsl_driver);
 
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index c7cbaf8..de3f619 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -134,6 +134,7 @@
 		unsigned int mapped_max;
 		unsigned int histogram[16];
 	} stats;
+	unsigned int full_cache_threshold;
 };
 
 extern struct kgsl_driver kgsl_driver;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 52340cc..05d24e9 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -76,6 +76,10 @@
 	},
 };
 
+static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
+					  int requested_state);
+static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state);
+
 /* Update the elapsed time at a particular clock level
  * if the device is active(on_time = true).Otherwise
  * store it as sleep time.
@@ -671,6 +675,87 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", device->reset_counter);
 }
 
+static void __force_on(struct kgsl_device *device, int flag, int on)
+{
+	if (on) {
+		switch (flag) {
+		case KGSL_PWRFLAGS_CLK_ON:
+			kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON,
+				KGSL_STATE_ACTIVE);
+			break;
+		case KGSL_PWRFLAGS_AXI_ON:
+			kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
+			break;
+		}
+		set_bit(flag, &device->pwrctrl.ctrl_flags);
+	} else {
+		clear_bit(flag, &device->pwrctrl.ctrl_flags);
+	}
+}
+
+static int __force_on_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf, int flag)
+{
+	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	int i = test_bit(flag, &device->pwrctrl.ctrl_flags);
+	return snprintf(buf, PAGE_SIZE, "%d\n", i);
+}
+
+static int __force_on_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count,
+					int flag)
+{
+	char temp[20];
+	unsigned long val;
+	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	int rc;
+
+	if (device == NULL)
+		return 0;
+
+	snprintf(temp, sizeof(temp), "%.*s",
+			(int)min(count, sizeof(temp) - 1), buf);
+	rc = kstrtoul(temp, 0, &val);
+	if (rc)
+		return rc;
+
+	mutex_lock(&device->mutex);
+	__force_on(device, flag, val);
+	mutex_unlock(&device->mutex);
+
+	return count;
+}
+
+static int kgsl_pwrctrl_force_clk_on_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_CLK_ON);
+}
+
+static int kgsl_pwrctrl_force_clk_on_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_CLK_ON);
+}
+
+static int kgsl_pwrctrl_force_bus_on_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_AXI_ON);
+}
+
+static int kgsl_pwrctrl_force_bus_on_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_AXI_ON);
+}
+
 DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store);
 DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
 	kgsl_pwrctrl_max_gpuclk_store);
@@ -702,6 +787,12 @@
 DEVICE_ATTR(reset_count, 0444,
 	kgsl_pwrctrl_reset_count_show,
 	NULL);
+DEVICE_ATTR(force_clk_on, 0644,
+	kgsl_pwrctrl_force_clk_on_show,
+	kgsl_pwrctrl_force_clk_on_store);
+DEVICE_ATTR(force_bus_on, 0644,
+	kgsl_pwrctrl_force_bus_on_show,
+	kgsl_pwrctrl_force_bus_on_store);
 
 static const struct device_attribute *pwrctrl_attr_list[] = {
 	&dev_attr_gpuclk,
@@ -717,6 +808,8 @@
 	&dev_attr_num_pwrlevels,
 	&dev_attr_pmqos_latency,
 	&dev_attr_reset_count,
+	&dev_attr_force_clk_on,
+	&dev_attr_force_bus_on,
 	NULL
 };
 
@@ -766,11 +859,15 @@
 	}
 }
 
-void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
+static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
 					  int requested_state)
 {
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	int i = 0;
+
+	if (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->ctrl_flags))
+		return;
+
 	if (state == KGSL_PWRFLAGS_OFF) {
 		if (test_and_clear_bit(KGSL_PWRFLAGS_CLK_ON,
 			&pwr->power_flags)) {
@@ -824,10 +921,13 @@
 	}
 }
 
-void kgsl_pwrctrl_axi(struct kgsl_device *device, int state)
+static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state)
 {
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 
+	if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->ctrl_flags))
+		return;
+
 	if (state == KGSL_PWRFLAGS_OFF) {
 		if (test_and_clear_bit(KGSL_PWRFLAGS_AXI_ON,
 			&pwr->power_flags)) {
@@ -858,7 +958,7 @@
 	}
 }
 
-void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state)
+static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state)
 {
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 2b986c8..7bc849d 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -69,6 +69,7 @@
 	struct clk *ebi1_clk;
 	struct clk *grp_clks[KGSL_MAX_CLKS];
 	unsigned long power_flags;
+	unsigned long ctrl_flags;
 	struct kgsl_pwrlevel pwrlevels[KGSL_MAX_PWRLEVELS];
 	unsigned int active_pwrlevel;
 	int thermal_pwrlevel;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 4071b37..1691762 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -234,6 +234,29 @@
 	return len;
 }
 
+static int kgsl_drv_full_cache_threshold_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	int ret;
+	unsigned int thresh;
+	ret = sscanf(buf, "%d", &thresh);
+	if (ret != 1)
+		return count;
+
+	kgsl_driver.full_cache_threshold = thresh;
+
+	return count;
+}
+
+static int kgsl_drv_full_cache_threshold_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			kgsl_driver.full_cache_threshold);
+}
+
 DEVICE_ATTR(vmalloc, 0444, kgsl_drv_memstat_show, NULL);
 DEVICE_ATTR(vmalloc_max, 0444, kgsl_drv_memstat_show, NULL);
 DEVICE_ATTR(page_alloc, 0444, kgsl_drv_memstat_show, NULL);
@@ -243,6 +266,9 @@
 DEVICE_ATTR(mapped, 0444, kgsl_drv_memstat_show, NULL);
 DEVICE_ATTR(mapped_max, 0444, kgsl_drv_memstat_show, NULL);
 DEVICE_ATTR(histogram, 0444, kgsl_drv_histogram_show, NULL);
+DEVICE_ATTR(full_cache_threshold, 0644,
+		kgsl_drv_full_cache_threshold_show,
+		kgsl_drv_full_cache_threshold_store);
 
 static const struct device_attribute *drv_attr_list[] = {
 	&dev_attr_vmalloc,
@@ -254,6 +280,7 @@
 	&dev_attr_mapped,
 	&dev_attr_mapped_max,
 	&dev_attr_histogram,
+	&dev_attr_full_cache_threshold,
 	NULL
 };
 
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 08677ef..6917883 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -539,6 +539,33 @@
 	)
 );
 
+TRACE_EVENT(kgsl_mem_sync_full_cache,
+
+	TP_PROTO(unsigned int num_bufs, unsigned int bulk_size,
+		unsigned int op),
+
+	TP_ARGS(num_bufs, bulk_size, op),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, num_bufs)
+		__field(unsigned int, bulk_size)
+		__field(unsigned int, op)
+	),
+
+	TP_fast_assign(
+		__entry->num_bufs = num_bufs;
+		__entry->bulk_size = bulk_size;
+		__entry->op = op;
+	),
+
+	TP_printk(
+		"num_bufs=%d bulk_size=%d op=%c%c",
+		__entry->num_bufs, __entry->bulk_size,
+		(__entry->op & KGSL_GPUMEM_CACHE_CLEAN) ? 'c' : '.',
+		(__entry->op & KGSL_GPUMEM_CACHE_INV) ? 'i' : '.'
+	)
+);
+
 DECLARE_EVENT_CLASS(kgsl_mem_timestamp_template,
 
 	TP_PROTO(struct kgsl_device *device, struct kgsl_mem_entry *mem_entry,
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index a77dacb..b96349e 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -37,6 +37,7 @@
 #include <linux/of_gpio.h>
 #include <mach/board.h>
 #include <mach/gpiomux.h>
+#include <mach/msm_bus_board.h>
 
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("0.2");
@@ -142,6 +143,22 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+/**
+ * qup_i2c_clk_path_vote: data to use bus scaling driver for clock path vote
+ *
+ * @client_hdl when zero, client is not registered with the bus scaling driver,
+ *      and bus scaling functionality should not be used. When non zero, it
+ *      is a bus scaling client id and may be used to vote for clock path.
+ * @reg_err when true, registration error was detected and an error message was
+ *      logged. i2c will attempt to re-register but will log error only once.
+ *      once registration succeed, the flag is set to false.
+ */
+struct qup_i2c_clk_path_vote {
+	u32                         client_hdl;
+	struct msm_bus_scale_pdata *pdata;
+	bool                        reg_err;
+};
+
 struct qup_i2c_dev {
 	struct device                *dev;
 	void __iomem                 *base;		/* virtual */
@@ -172,6 +189,7 @@
 	struct mutex                 mlock;
 	void                         *complete;
 	int                          i2c_gpios[ARRAY_SIZE(i2c_rsrcs)];
+	struct qup_i2c_clk_path_vote clk_path_vote;
 };
 
 #ifdef DEBUG
@@ -333,11 +351,160 @@
 	mb();
 }
 
+#define MSM_I2C_CLK_PATH_SUSPEND (0)
+#define MSM_I2C_CLK_PATH_RESUME  (1)
+#define MSM_I2C_CLK_PATH_MAX_BW(dev) ((dev->pdata->src_clk_rate * 8) / 1000)
+
+static int i2c_qup_clk_path_init(struct platform_device *pdev,
+							struct qup_i2c_dev *dev)
+{
+	struct msm_bus_vectors *paths    = NULL;
+	struct msm_bus_paths   *usecases = NULL;
+
+	if (!dev->pdata->master_id)
+		return 0;
+
+	dev_dbg(&pdev->dev, "initialises bus-scaling clock voting");
+
+	paths = devm_kzalloc(&pdev->dev, sizeof(*paths) * 2, GFP_KERNEL);
+	if (!paths) {
+		dev_err(&pdev->dev,
+		"msm_bus_paths.paths memory allocation failed");
+		return -ENOMEM;
+	}
+
+	usecases = devm_kzalloc(&pdev->dev, sizeof(*usecases) * 2, GFP_KERNEL);
+	if (!usecases) {
+		dev_err(&pdev->dev,
+		"msm_bus_scale_pdata.usecases memory allocation failed");
+		goto path_init_err;
+	}
+
+	dev->clk_path_vote.pdata = devm_kzalloc(&pdev->dev,
+					    sizeof(*dev->clk_path_vote.pdata),
+					    GFP_KERNEL);
+	if (!dev->clk_path_vote.pdata) {
+		dev_err(&pdev->dev,
+		"msm_bus_scale_pdata memory allocation failed");
+		goto path_init_err;
+	}
+
+	paths[MSM_I2C_CLK_PATH_SUSPEND] = (struct msm_bus_vectors) {
+		dev->pdata->master_id, MSM_BUS_SLAVE_EBI_CH0, 0, 0
+	};
+
+	paths[MSM_I2C_CLK_PATH_RESUME]  = (struct msm_bus_vectors) {
+		dev->pdata->master_id, MSM_BUS_SLAVE_EBI_CH0, 0,
+						MSM_I2C_CLK_PATH_MAX_BW(dev)
+	};
+
+	usecases[MSM_I2C_CLK_PATH_SUSPEND] = (struct msm_bus_paths) {
+		.num_paths = 1,
+		.vectors   = &paths[MSM_I2C_CLK_PATH_SUSPEND],
+	};
+
+	usecases[MSM_I2C_CLK_PATH_RESUME] = (struct msm_bus_paths) {
+		.num_paths = 1,
+		.vectors   = &paths[MSM_I2C_CLK_PATH_RESUME],
+	};
+
+	*dev->clk_path_vote.pdata = (struct msm_bus_scale_pdata) {
+		.active_only  = dev->pdata->active_only,
+		.name         = pdev->name,
+		.num_usecases = 2,
+		.usecase      = usecases,
+	};
+
+	return 0;
+
+path_init_err:
+	devm_kfree(&pdev->dev, paths);
+	devm_kfree(&pdev->dev, usecases);
+	devm_kfree(&pdev->dev, dev->clk_path_vote.pdata);
+	dev->clk_path_vote.pdata = NULL;
+	return -ENOMEM;
+}
+
+static void i2c_qup_clk_path_teardown(struct qup_i2c_dev *dev)
+{
+	if (dev->clk_path_vote.client_hdl) {
+		msm_bus_scale_unregister_client(dev->clk_path_vote.client_hdl);
+		dev->clk_path_vote.client_hdl = 0;
+	}
+}
+
+static void i2c_qup_clk_path_vote(struct qup_i2c_dev *dev)
+{
+	if (dev->clk_path_vote.client_hdl)
+		msm_bus_scale_client_update_request(
+						dev->clk_path_vote.client_hdl,
+						MSM_I2C_CLK_PATH_RESUME);
+}
+
+static void i2c_qup_clk_path_unvote(struct qup_i2c_dev *dev)
+{
+	if (dev->clk_path_vote.client_hdl)
+		msm_bus_scale_client_update_request(
+						dev->clk_path_vote.client_hdl,
+						MSM_I2C_CLK_PATH_SUSPEND);
+}
+
+/**
+ * i2c_qup_clk_path_postponed_register: reg with bus-scaling after it is probed
+ *
+ * Workaround: i2c driver may be probed before the bus scaling driver. Thus,
+ * this function should be called not from probe but from a later context.
+ * This function may be called more then once before register succeed. At
+ * this case only one error message will be logged. At boot time all clocks
+ * are on, so earlier i2c transactions should succeed.
+ */
+static void i2c_qup_clk_path_postponed_register(struct qup_i2c_dev *dev)
+{
+	/*
+	 * bail out if path voting is diabled (master_id == 0) or if it is
+	 * already registered (client_hdl != 0)
+	 */
+	if (!dev->pdata->master_id || dev->clk_path_vote.client_hdl)
+		return;
+
+	dev->clk_path_vote.client_hdl = msm_bus_scale_register_client(
+						dev->clk_path_vote.pdata);
+
+	if (dev->clk_path_vote.client_hdl) {
+		if (dev->clk_path_vote.reg_err) {
+			/* log a success message if an error msg was logged */
+			dev->clk_path_vote.reg_err = false;
+			dev_info(dev->dev,
+				"msm_bus_scale_register_client(mstr-id:%d "
+				"actv-only:%d):0x%x",
+				dev->pdata->master_id, dev->pdata->active_only,
+				dev->clk_path_vote.client_hdl);
+		}
+
+		if (dev->pdata->active_only)
+			i2c_qup_clk_path_vote(dev);
+	} else {
+		/* guard to log only one error on multiple failure */
+		if (!dev->clk_path_vote.reg_err) {
+			dev->clk_path_vote.reg_err = true;
+
+			dev_info(dev->dev,
+				"msm_bus_scale_register_client(mstr-id:%d "
+				"actv-only:%d):0",
+				dev->pdata->master_id, dev->pdata->active_only);
+		}
+	}
+}
+
 static void
 qup_i2c_pwr_mgmt(struct qup_i2c_dev *dev, unsigned int state)
 {
 	dev->pwr_state = state;
 	if (state != 0) {
+		i2c_qup_clk_path_postponed_register(dev);
+		if (!dev->pdata->active_only)
+			i2c_qup_clk_path_vote(dev);
+
 		clk_prepare_enable(dev->clk);
 		if (!dev->pdata->keep_ahb_clk_on)
 			clk_prepare_enable(dev->pclk);
@@ -347,6 +514,8 @@
 		qup_config_core_on_en(dev);
 		if (!dev->pdata->keep_ahb_clk_on)
 			clk_disable_unprepare(dev->pclk);
+		if (!dev->pdata->active_only)
+			i2c_qup_clk_path_unvote(dev);
 	}
 }
 
@@ -1099,11 +1268,12 @@
 enum msm_i2c_dt_entry_type {
 	DT_U32,
 	DT_GPIO,
+	DT_BOOL,
 };
 
 struct msm_i2c_dt_to_pdata_map {
 	const char                  *dt_name;
-	int                         *ptr_data;
+	void                        *ptr_data;
 	enum msm_i2c_dt_entry_status status;
 	enum msm_i2c_dt_entry_type   type;
 	int                          default_val;
@@ -1119,28 +1289,42 @@
 	{"qcom,i2c-bus-freq", &pdata->clk_freq    , DT_REQUIRED , DT_U32 ,  0},
 	{"cell-index"       , &pdev->id           , DT_REQUIRED , DT_U32 , -1},
 	{"qcom,i2c-src-freq", &pdata->src_clk_rate, DT_SUGGESTED, DT_U32,   0},
+	{"qcom,master-id"   , &pdata->master_id   , DT_SUGGESTED, DT_U32,   0},
 	{"qcom,scl-gpio"    , gpios               , DT_OPTIONAL , DT_GPIO, -1},
 	{"qcom,sda-gpio"    , gpios + 1           , DT_OPTIONAL , DT_GPIO, -1},
+	{"qcom,active-only" , &pdata->active_only , DT_OPTIONAL , DT_BOOL,  0},
 	{NULL               , NULL                , 0           , 0      ,  0},
 	};
 
 	for (itr = map; itr->dt_name ; ++itr) {
-		if (itr->type == DT_GPIO) {
+		switch (itr->type) {
+		case DT_GPIO:
 			ret = of_get_named_gpio(node, itr->dt_name, 0);
 			if (ret >= 0) {
-				*itr->ptr_data = ret;
+				*((int *) itr->ptr_data) = ret;
 				ret = 0;
 			}
-		} else {
+			break;
+		case DT_U32:
 			ret = of_property_read_u32(node, itr->dt_name,
-								itr->ptr_data);
+							 (u32 *) itr->ptr_data);
+			break;
+		case DT_BOOL:
+			*((bool *) itr->ptr_data) =
+				of_property_read_bool(node, itr->dt_name);
+			ret = 0;
+			break;
+		default:
+			dev_err(&pdev->dev, "%d is an unknown DT entry type\n",
+								itr->type);
+			ret = -EBADE;
 		}
 
 		dev_dbg(&pdev->dev, "DT entry ret:%d name:%s val:%d\n",
-					ret, itr->dt_name, *itr->ptr_data);
+				ret, itr->dt_name, *((int *)itr->ptr_data));
 
 		if (ret) {
-			*itr->ptr_data = itr->default_val;
+			*((int *)itr->ptr_data) = itr->default_val;
 
 			if (itr->status < DT_OPTIONAL) {
 				dev_err(&pdev->dev, "Missing '%s' DT entry\n",
@@ -1326,6 +1510,14 @@
 	dev->clk_ctl = 0;
 	dev->pos = 0;
 
+	ret = i2c_qup_clk_path_init(pdev, dev);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"Failed to init clock path-voting data structs. err:%d", ret);
+		/* disable i2c_qup_clk_path_xxx() functionality */
+		dev->pdata->master_id = 0;
+	}
+
 	if (dev->pdata->src_clk_rate <= 0) {
 		dev_info(&pdev->dev,
 			"No src_clk_rate specified in platfrom data\n");
@@ -1443,6 +1635,7 @@
 err_reset_failed:
 	clk_disable_unprepare(dev->clk);
 	clk_disable_unprepare(dev->pclk);
+	i2c_qup_clk_path_teardown(dev);
 err_gsbi_failed:
 	iounmap(dev->base);
 err_ioremap_failed:
@@ -1488,6 +1681,11 @@
 		clk_put(dev->pclk);
 	}
 	clk_put(dev->clk);
+
+	if (dev->pdata->active_only)
+		i2c_qup_clk_path_unvote(dev);
+	i2c_qup_clk_path_teardown(dev);
+
 	if (dev->gsbi)
 		iounmap(dev->gsbi);
 	iounmap(dev->base);
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index 10fa5b1..eadbd64 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -1281,7 +1281,7 @@
 	return 0;
 }
 
-static void print_ctx_regs(void __iomem *base, int ctx)
+static void __print_ctx_regs(void __iomem *base, int ctx)
 {
 	unsigned int fsr = GET_FSR(base, ctx);
 	pr_err("FAR    = %08x    PAR    = %08x\n",
@@ -1347,7 +1347,7 @@
 			pr_err("name    = %s\n", drvdata->name);
 			pr_err("context = %s (%d)\n", ctx_drvdata->name, num);
 			pr_err("Interesting registers:\n");
-			print_ctx_regs(base, num);
+			__print_ctx_regs(base, num);
 		}
 
 		SET_FSR(base, num, fsr);
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index f90bf6c..5ee8794 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -783,10 +783,12 @@
 	return 0;
 }
 
-static void print_ctx_regs(void __iomem *base, int ctx, unsigned int fsr)
+void print_ctx_regs(struct msm_iommu_context_regs *regs)
 {
+	uint32_t fsr = regs->fsr;
+
 	pr_err("FAR    = %08x    PAR    = %08x\n",
-		 GET_FAR(base, ctx), GET_PAR(base, ctx));
+		 regs->far, regs->par);
 	pr_err("FSR    = %08x [%s%s%s%s%s%s%s%s%s]\n", fsr,
 			(fsr & 0x02) ? "TF " : "",
 			(fsr & 0x04) ? "AFF " : "",
@@ -799,13 +801,31 @@
 			(fsr & 0x80000000) ? "MULTI " : "");
 
 	pr_err("FSYNR0 = %08x    FSYNR1 = %08x\n",
-		 GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
+		 regs->fsynr0, regs->fsynr1);
 	pr_err("TTBR0  = %08x    TTBR1  = %08x\n",
-		 GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
+		 regs->ttbr0, regs->ttbr1);
 	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
-		 GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
+		 regs->sctlr, regs->actlr);
 	pr_err("PRRR   = %08x    NMRR   = %08x\n",
-		 GET_PRRR(base, ctx), GET_NMRR(base, ctx));
+		 regs->prrr, regs->nmrr);
+}
+
+static void __print_ctx_regs(void __iomem *base, int ctx, unsigned int fsr)
+{
+	struct msm_iommu_context_regs regs = {
+		.far = GET_FAR(base, ctx),
+		.par = GET_PAR(base, ctx),
+		.fsr = fsr,
+		.fsynr0 = GET_FSYNR0(base, ctx),
+		.fsynr1 = GET_FSYNR1(base, ctx),
+		.ttbr0 = GET_TTBR0(base, ctx),
+		.ttbr1 = GET_TTBR1(base, ctx),
+		.sctlr = GET_SCTLR(base, ctx),
+		.actlr = GET_ACTLR(base, ctx),
+		.prrr = GET_PRRR(base, ctx),
+		.nmrr = GET_NMRR(base, ctx),
+	};
+	print_ctx_regs(&regs);
 }
 
 irqreturn_t msm_iommu_fault_handler_v2(int irq, void *dev_id)
@@ -861,7 +881,7 @@
 			pr_err("context = %s (%d)\n", ctx_drvdata->name,
 							ctx_drvdata->num);
 			pr_err("Interesting registers:\n");
-			print_ctx_regs(drvdata->base, ctx_drvdata->num, fsr);
+			__print_ctx_regs(drvdata->base, ctx_drvdata->num, fsr);
 		}
 
 		SET_FSR(drvdata->base, ctx_drvdata->num, fsr);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 0f238b2..9101a3d 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -166,7 +166,8 @@
 #define LED_MPP_EN_CTRL(base)		(base + 0x46)
 #define LED_MPP_SINK_CTRL(base)		(base + 0x4C)
 
-#define LED_MPP_CURRENT_DEFAULT		10
+#define LED_MPP_CURRENT_DEFAULT		5
+#define LED_MPP_CURRENT_PER_SETTING	5
 #define LED_MPP_SOURCE_SEL_DEFAULT	LED_MPP_MODE_ENABLE
 
 #define LED_MPP_SINK_MASK		0x07
@@ -258,6 +259,7 @@
 enum led_mode {
 	PWM_MODE = 0,
 	LPG_MODE,
+	MANUAL_MODE,
 };
 
 static u8 wled_debug_regs[] = {
@@ -290,6 +292,24 @@
 };
 
 /**
+ *  pwm_config_data - pwm configuration data
+ *  @lut_params - lut parameters to be used by pwm driver
+ *  @pwm_device - pwm device
+ *  @pwm_channel - pwm channel to be configured for led
+ *  @pwm_period_us - period for pwm, in us
+ *  @mode - mode the led operates in
+ */
+struct pwm_config_data {
+	struct lut_params	lut_params;
+	struct pwm_device	*pwm_dev;
+	int			pwm_channel;
+	u32			pwm_period_us;
+	struct pwm_duty_cycles	*duty_cycles;
+	u8	mode;
+	u8	enable;
+};
+
+/**
  *  wled_config_data - wled configuration data
  *  @num_strings - number of wled strings supported
  *  @ovp_val - over voltage protection threshold
@@ -314,12 +334,18 @@
 
 /**
  *  mpp_config_data - mpp configuration data
+ *  @pwm_cfg - device pwm configuration
  *  @current_setting - current setting, 5ma-40ma in 5ma increments
+ *  @source_sel - source selection
+ *  @mode_ctrl - mode control
+ *  @pwm_mode - pwm mode in use
  */
 struct mpp_config_data {
+	struct pwm_config_data	*pwm_cfg;
 	u8	current_setting;
 	u8	source_sel;
 	u8	mode_ctrl;
+	u8 pwm_mode;
 };
 
 /**
@@ -354,38 +380,25 @@
 
 /**
  *  kpdbl_config_data - kpdbl configuration data
- *  @pwm_device - pwm device
- *  @pwm_channel - pwm channel to be configured for led
- *  @pwm_period_us - period for pwm, in us
+ *  @pwm_cfg - device pwm configuration
  *  @row_src_sel_val - select source, 0 for vph_pwr and 1 for vbst
  *  @row_scan_en - enable row scan
  *  @row_scan_val - map to enable needed rows
  */
 struct kpdbl_config_data {
-	struct pwm_device	*pwm_dev;
-	int	pwm_channel;
-	u32	pwm_period_us;
+	struct pwm_config_data	*pwm_cfg;
 	u32	row_src_sel_val;
 	u32	row_scan_en;
 	u32	row_scan_val;
-	u8	mode;
 };
 
 /**
  *  rgb_config_data - rgb configuration data
- *  @lut_params - lut parameters to be used by pwm driver
- *  @pwm_device - pwm device
- *  @pwm_channel - pwm channel to be configured for led
- *  @pwm_period_us - period for pwm, in us
- *  @mode - mode the led operates in
+ *  @pwm_cfg - device pwm configuration
+ *  @enable - bits to enable led
  */
 struct rgb_config_data {
-	struct lut_params	lut_params;
-	struct pwm_device	*pwm_dev;
-	int			pwm_channel;
-	u32			pwm_period_us;
-	struct pwm_duty_cycles	*duty_cycles;
-	u8	mode;
+	struct pwm_config_data	*pwm_cfg;
 	u8	enable;
 };
 
@@ -542,24 +555,33 @@
 static int qpnp_mpp_set(struct qpnp_led_data *led)
 {
 	int rc, val;
+	int duty_us;
 
 	if (led->cdev.brightness) {
-		val = (led->cdev.brightness * LED_MPP_SINK_MASK) / LED_FULL;
-		rc = qpnp_led_masked_write(led,
-				LED_MPP_SINK_CTRL(led->base),
-				LED_MPP_SINK_MASK, val);
-		if (rc) {
-			dev_err(&led->spmi_dev->dev,
-				"Failed to write led enable reg\n");
-			return rc;
+		if (led->mpp_cfg->pwm_mode == PWM_MODE) {
+			pwm_disable(led->mpp_cfg->pwm_cfg->pwm_dev);
+			duty_us = (led->mpp_cfg->pwm_cfg->pwm_period_us *
+					led->cdev.brightness) / LED_FULL;
+			/*config pwm for brightness scaling*/
+			rc = pwm_config(led->mpp_cfg->pwm_cfg->pwm_dev,
+					duty_us,
+					led->mpp_cfg->pwm_cfg->pwm_period_us);
+			if (rc < 0) {
+				dev_err(&led->spmi_dev->dev, "Failed to " \
+					"configure pwm for new values\n");
+				return rc;
+			}
 		}
 
+		if (led->mpp_cfg->pwm_mode != MANUAL_MODE)
+			pwm_enable(led->mpp_cfg->pwm_cfg->pwm_dev);
+
 		val = (led->mpp_cfg->source_sel & LED_MPP_SRC_MASK) |
 			(led->mpp_cfg->mode_ctrl & LED_MPP_MODE_CTRL_MASK);
 
 		rc = qpnp_led_masked_write(led,
-		LED_MPP_MODE_CTRL(led->base), LED_MPP_MODE_MASK,
-		val);
+			LED_MPP_MODE_CTRL(led->base), LED_MPP_MODE_MASK,
+			val);
 		if (rc) {
 			dev_err(&led->spmi_dev->dev,
 					"Failed to write led mode reg\n");
@@ -569,13 +591,15 @@
 		rc = qpnp_led_masked_write(led,
 				LED_MPP_EN_CTRL(led->base), LED_MPP_EN_MASK,
 				LED_MPP_EN_ENABLE);
-			if (rc) {
-				dev_err(&led->spmi_dev->dev,
-						"Failed to write led enable " \
-						"reg\n");
-				return rc;
-			}
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+					"Failed to write led enable " \
+					"reg\n");
+			return rc;
+		}
 	} else {
+		if (led->mpp_cfg->pwm_mode != MANUAL_MODE)
+			pwm_disable(led->mpp_cfg->pwm_cfg->pwm_dev);
 		rc = qpnp_led_masked_write(led,
 					LED_MPP_MODE_CTRL(led->base),
 					LED_MPP_MODE_MASK,
@@ -831,21 +855,21 @@
 	if (led->cdev.brightness) {
 		rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
 				KPDBL_MODULE_EN_MASK, KPDBL_MODULE_EN);
-		duty_us = (led->kpdbl_cfg->pwm_period_us *
+		duty_us = (led->kpdbl_cfg->pwm_cfg->pwm_period_us *
 			led->cdev.brightness) / KPDBL_MAX_LEVEL;
-		rc = pwm_config(led->kpdbl_cfg->pwm_dev, duty_us,
-				led->kpdbl_cfg->pwm_period_us);
+		rc = pwm_config(led->kpdbl_cfg->pwm_cfg->pwm_dev, duty_us,
+				led->kpdbl_cfg->pwm_cfg->pwm_period_us);
 		if (rc < 0) {
 			dev_err(&led->spmi_dev->dev, "pwm config failed\n");
 			return rc;
 		}
-		rc = pwm_enable(led->kpdbl_cfg->pwm_dev);
+		rc = pwm_enable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
 		if (rc < 0) {
 			dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
 			return rc;
 		}
 	} else {
-		pwm_disable(led->kpdbl_cfg->pwm_dev);
+		pwm_disable(led->kpdbl_cfg->pwm_cfg->pwm_dev);
 		rc = qpnp_led_masked_write(led, KPDBL_ENABLE(led->base),
 				KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS);
 		if (rc) {
@@ -866,11 +890,11 @@
 	int rc;
 
 	if (led->cdev.brightness) {
-		if (led->rgb_cfg->mode == PWM_MODE) {
-			duty_us = (led->rgb_cfg->pwm_period_us *
+		if (led->rgb_cfg->pwm_cfg->mode == PWM_MODE) {
+			duty_us = (led->rgb_cfg->pwm_cfg->pwm_period_us *
 				led->cdev.brightness) / LED_FULL;
-			rc = pwm_config(led->rgb_cfg->pwm_dev, duty_us,
-					led->rgb_cfg->pwm_period_us);
+			rc = pwm_config(led->rgb_cfg->pwm_cfg->pwm_dev, duty_us,
+					led->rgb_cfg->pwm_cfg->pwm_period_us);
 			if (rc < 0) {
 				dev_err(&led->spmi_dev->dev,
 					"pwm config failed\n");
@@ -885,13 +909,14 @@
 				"Failed to write led enable reg\n");
 			return rc;
 		}
-		rc = pwm_enable(led->rgb_cfg->pwm_dev);
+
+		rc = pwm_enable(led->rgb_cfg->pwm_cfg->pwm_dev);
 		if (rc < 0) {
 			dev_err(&led->spmi_dev->dev, "pwm enable failed\n");
 			return rc;
 		}
 	} else {
-		pwm_disable(led->rgb_cfg->pwm_dev);
+		pwm_disable(led->rgb_cfg->pwm_cfg->pwm_dev);
 		rc = qpnp_led_masked_write(led,
 			RGB_LED_EN_CTL(led->base),
 			led->rgb_cfg->enable, RGB_LED_DISABLE);
@@ -1299,6 +1324,63 @@
 	return 0;
 }
 
+static int __devinit qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
+					struct spmi_device *spmi_dev,
+					const char *name)
+{
+	int rc, start_idx, idx_len;
+
+	if (pwm_cfg->pwm_channel != -1) {
+		pwm_cfg->pwm_dev =
+			pwm_request(pwm_cfg->pwm_channel, name);
+
+		if (IS_ERR_OR_NULL(pwm_cfg->pwm_dev)) {
+			dev_err(&spmi_dev->dev,
+				"could not acquire PWM Channel %d, " \
+				"error %ld\n",
+				pwm_cfg->pwm_channel,
+				PTR_ERR(pwm_cfg->pwm_dev));
+			pwm_cfg->pwm_dev = NULL;
+			return -ENODEV;
+		}
+
+		if (pwm_cfg->mode == LPG_MODE) {
+			start_idx =
+			pwm_cfg->duty_cycles->start_idx;
+			idx_len =
+			pwm_cfg->duty_cycles->num_duty_pcts;
+
+			if (idx_len >= PWM_LUT_MAX_SIZE &&
+					start_idx) {
+				dev_err(&spmi_dev->dev,
+					"Wrong LUT size or index\n");
+				return -EINVAL;
+			}
+			if ((start_idx + idx_len) >
+					PWM_LUT_MAX_SIZE) {
+				dev_err(&spmi_dev->dev,
+					"Exceed LUT limit\n");
+				return -EINVAL;
+			}
+			rc = pwm_lut_config(pwm_cfg->pwm_dev,
+				PM_PWM_PERIOD_MIN, /* ignored by hardware */
+				pwm_cfg->duty_cycles->duty_pcts,
+				pwm_cfg->lut_params);
+			if (rc < 0) {
+				dev_err(&spmi_dev->dev, "Failed to " \
+					"configure pwm LUT\n");
+				return rc;
+			}
+		}
+	} else {
+		dev_err(&spmi_dev->dev,
+			"Invalid PWM channel\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int __devinit qpnp_kpdbl_init(struct qpnp_led_data *led)
 {
 	int rc;
@@ -1348,24 +1430,12 @@
 		return rc;
 	}
 
-	if (led->kpdbl_cfg->pwm_channel != -1) {
-		led->kpdbl_cfg->pwm_dev =
-			pwm_request(led->kpdbl_cfg->pwm_channel,
-						led->cdev.name);
-
-		if (IS_ERR_OR_NULL(led->kpdbl_cfg->pwm_dev)) {
-			dev_err(&led->spmi_dev->dev,
-				"could not acquire PWM Channel %d, " \
-				"error %ld\n",
-				led->kpdbl_cfg->pwm_channel,
-				PTR_ERR(led->kpdbl_cfg->pwm_dev));
-			led->kpdbl_cfg->pwm_dev = NULL;
-			return -ENODEV;
-		}
-	} else {
+	rc = qpnp_pwm_init(led->kpdbl_cfg->pwm_cfg, led->spmi_dev,
+				led->cdev.name);
+	if (rc) {
 		dev_err(&led->spmi_dev->dev,
-			"Invalid PWM channel\n");
-		return -EINVAL;
+			"Failed to initialize pwm\n");
+		return rc;
 	}
 
 	/* dump kpdbl registers */
@@ -1376,7 +1446,7 @@
 
 static int __devinit qpnp_rgb_init(struct qpnp_led_data *led)
 {
-	int rc, start_idx, idx_len;
+	int rc;
 
 	rc = qpnp_led_masked_write(led, RGB_LED_SRC_SEL(led->base),
 		RGB_LED_SRC_MASK, RGB_LED_SOURCE_VPH_PWR);
@@ -1386,55 +1456,13 @@
 		return rc;
 	}
 
-	if (led->rgb_cfg->pwm_channel != -1) {
-		led->rgb_cfg->pwm_dev =
-			pwm_request(led->rgb_cfg->pwm_channel,
-						led->cdev.name);
-
-		if (IS_ERR_OR_NULL(led->rgb_cfg->pwm_dev)) {
-			dev_err(&led->spmi_dev->dev,
-				"could not acquire PWM Channel %d, " \
-				"error %ld\n",
-				led->rgb_cfg->pwm_channel,
-				PTR_ERR(led->rgb_cfg->pwm_dev));
-			led->rgb_cfg->pwm_dev = NULL;
-			return -ENODEV;
-		}
-
-		if (led->rgb_cfg->mode == LPG_MODE) {
-			start_idx =
-			led->rgb_cfg->duty_cycles->start_idx;
-			idx_len =
-			led->rgb_cfg->duty_cycles->num_duty_pcts;
-
-			if (idx_len >= PWM_LUT_MAX_SIZE &&
-					start_idx) {
-				dev_err(&led->spmi_dev->dev,
-					"Wrong LUT size or index\n");
-				return -EINVAL;
-			}
-			if ((start_idx + idx_len) >
-					PWM_LUT_MAX_SIZE) {
-				dev_err(&led->spmi_dev->dev,
-					"Exceed LUT limit\n");
-				return -EINVAL;
-			}
-			rc = pwm_lut_config(led->rgb_cfg->pwm_dev,
-				PM_PWM_PERIOD_MIN, /* ignored by hardware */
-				led->rgb_cfg->duty_cycles->duty_pcts,
-				led->rgb_cfg->lut_params);
-			if (rc < 0) {
-				dev_err(&led->spmi_dev->dev, "Failed to " \
-					"configure pwm LUT\n");
-				return rc;
-			}
-		}
-	} else {
+	rc = qpnp_pwm_init(led->rgb_cfg->pwm_cfg, led->spmi_dev,
+				led->cdev.name);
+	if (rc) {
 		dev_err(&led->spmi_dev->dev,
-			"Invalid PWM channel\n");
-		return -EINVAL;
+			"Failed to initialize pwm\n");
+		return rc;
 	}
-
 	/* Initialize led for use in auto trickle charging mode */
 	rc = qpnp_led_masked_write(led, RGB_LED_ATC_CTL(led->base),
 		led->rgb_cfg->enable, led->rgb_cfg->enable);
@@ -1442,6 +1470,36 @@
 	return 0;
 }
 
+static int __devinit qpnp_mpp_init(struct qpnp_led_data *led)
+{
+	int rc, val;
+
+	val = (led->mpp_cfg->current_setting / LED_MPP_CURRENT_PER_SETTING) - 1;
+
+	if (val < 0)
+		val = 0;
+
+	rc = qpnp_led_masked_write(led, LED_MPP_SINK_CTRL(led->base),
+		LED_MPP_SINK_MASK, val);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"Failed to write led enable reg\n");
+		return rc;
+	}
+
+	if (led->mpp_cfg->pwm_mode != MANUAL_MODE) {
+		rc = qpnp_pwm_init(led->mpp_cfg->pwm_cfg, led->spmi_dev,
+					led->cdev.name);
+		if (rc) {
+			dev_err(&led->spmi_dev->dev,
+				"Failed to initialize pwm\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 static int __devinit qpnp_led_initialize(struct qpnp_led_data *led)
 {
 	int rc = 0;
@@ -1469,6 +1527,10 @@
 				"RGB initialize failed(%d)\n", rc);
 		break;
 	case QPNP_ID_LED_MPP:
+		rc = qpnp_mpp_init(led);
+		if (rc)
+			dev_err(&led->spmi_dev->dev,
+				"MPP initialize failed(%d)\n", rc);
 		break;
 	case QPNP_ID_KPDBL:
 		rc = qpnp_kpdbl_init(led);
@@ -1669,11 +1731,138 @@
 	return 0;
 }
 
+static int __devinit qpnp_get_config_pwm(struct pwm_config_data *pwm_cfg,
+				struct spmi_device *spmi_dev,
+				struct device_node *node)
+{
+	struct property *prop;
+	int rc, i;
+	u32 val;
+	u8 *temp_cfg;
+
+	rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
+	if (!rc)
+		pwm_cfg->pwm_channel = val;
+	else
+		return rc;
+
+	if (pwm_cfg->mode == PWM_MODE) {
+		rc = of_property_read_u32(node, "qcom,pwm-us", &val);
+		if (!rc)
+			pwm_cfg->pwm_period_us = val;
+		else
+			return rc;
+	}
+
+	if (pwm_cfg->mode == LPG_MODE) {
+		pwm_cfg->duty_cycles =
+			devm_kzalloc(&spmi_dev->dev,
+			sizeof(struct pwm_duty_cycles), GFP_KERNEL);
+		if (!pwm_cfg->duty_cycles) {
+			dev_err(&spmi_dev->dev,
+				"Unable to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		prop = of_find_property(node, "qcom,duty-pcts",
+			&pwm_cfg->duty_cycles->num_duty_pcts);
+		if (!prop) {
+			dev_err(&spmi_dev->dev, "Looking up property " \
+				"node qcom,duty-pcts failed\n");
+			return -ENODEV;
+		} else if (!pwm_cfg->duty_cycles->num_duty_pcts) {
+			dev_err(&spmi_dev->dev, "Invalid length of " \
+				"duty pcts\n");
+			return -EINVAL;
+		}
+
+		pwm_cfg->duty_cycles->duty_pcts =
+			devm_kzalloc(&spmi_dev->dev,
+			sizeof(int) * pwm_cfg->duty_cycles->num_duty_pcts,
+			GFP_KERNEL);
+		if (!pwm_cfg->duty_cycles->duty_pcts) {
+			dev_err(&spmi_dev->dev,
+				"Unable to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		temp_cfg = devm_kzalloc(&spmi_dev->dev,
+				pwm_cfg->duty_cycles->num_duty_pcts *
+				sizeof(u8), GFP_KERNEL);
+		if (!temp_cfg) {
+			dev_err(&spmi_dev->dev, "Failed to allocate " \
+				"memory for duty pcts\n");
+			return -ENOMEM;
+		}
+
+		memcpy(temp_cfg, prop->value,
+			pwm_cfg->duty_cycles->num_duty_pcts);
+
+		for (i = 0; i < pwm_cfg->duty_cycles->num_duty_pcts; i++)
+			pwm_cfg->duty_cycles->duty_pcts[i] =
+				(int) temp_cfg[i];
+
+		rc = of_property_read_u32(node, "qcom,start-idx", &val);
+		if (!rc) {
+			pwm_cfg->lut_params.start_idx = val;
+			pwm_cfg->duty_cycles->start_idx = val;
+		} else
+			return rc;
+
+		pwm_cfg->lut_params.lut_pause_hi = 0;
+		rc = of_property_read_u32(node, "qcom,pause-hi", &val);
+		if (!rc)
+			pwm_cfg->lut_params.lut_pause_hi = val;
+		else if (rc != -EINVAL)
+			return rc;
+
+		pwm_cfg->lut_params.lut_pause_lo = 0;
+		rc = of_property_read_u32(node, "qcom,pause-lo", &val);
+		if (!rc)
+			pwm_cfg->lut_params.lut_pause_lo = val;
+		else if (rc != -EINVAL)
+			return rc;
+
+		pwm_cfg->lut_params.ramp_step_ms =
+				QPNP_LUT_RAMP_STEP_DEFAULT;
+		rc = of_property_read_u32(node, "qcom,ramp-step-ms", &val);
+		if (!rc)
+			pwm_cfg->lut_params.ramp_step_ms = val;
+		else if (rc != -EINVAL)
+			return rc;
+
+		pwm_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
+		rc = of_property_read_u32(node, "qcom,lut-flags", &val);
+		if (!rc)
+			pwm_cfg->lut_params.flags = (u8) val;
+		else if (rc != -EINVAL)
+			return rc;
+
+		pwm_cfg->lut_params.idx_len =
+			pwm_cfg->duty_cycles->num_duty_pcts;
+	}
+	return 0;
+};
+
+static int qpnp_led_get_mode(const char *mode)
+{
+	if (strncmp(mode, "manual", strlen(mode)) == 0)
+		return MANUAL_MODE;
+	else if (strncmp(mode, "pwm", strlen(mode)) == 0)
+		return PWM_MODE;
+	else if (strncmp(mode, "lpg", strlen(mode)) == 0)
+		return LPG_MODE;
+	else
+		return -EINVAL;
+};
+
 static int __devinit qpnp_get_config_kpdbl(struct qpnp_led_data *led,
 				struct device_node *node)
 {
 	int rc;
 	u32 val;
+	u8 led_mode;
+	const char *mode;
 
 	led->kpdbl_cfg = devm_kzalloc(&led->spmi_dev->dev,
 				sizeof(struct kpdbl_config_data), GFP_KERNEL);
@@ -1681,28 +1870,28 @@
 		dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
 		return -ENOMEM;
 	}
-
-	rc = of_property_read_u32(node, "qcom,mode", &val);
-	if (!rc)
-		led->kpdbl_cfg->mode = (u8) val;
-	else
+	rc = of_property_read_string(node, "qcom,mode", &mode);
+	if (!rc) {
+		led_mode = qpnp_led_get_mode(mode);
+		if ((led_mode == MANUAL_MODE) || (led_mode == -EINVAL)) {
+			dev_err(&led->spmi_dev->dev, "Selected mode not " \
+				"supported for kpdbl.\n");
+			return -EINVAL;
+		}
+		led->kpdbl_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+					sizeof(struct pwm_config_data),
+					GFP_KERNEL);
+		if (!led->kpdbl_cfg->pwm_cfg) {
+			dev_err(&led->spmi_dev->dev,
+				"Unable to allocate memory\n");
+			return -ENOMEM;
+		}
+		led->kpdbl_cfg->pwm_cfg->mode = led_mode;
+	} else
 		return rc;
 
-	if (led->kpdbl_cfg->mode == LPG_MODE) {
-		dev_err(&led->spmi_dev->dev, "LPG mode not supported\n");
-		return -EINVAL;
-	}
-
-	rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
-	if (!rc)
-		led->kpdbl_cfg->pwm_channel = (u8) val;
-	else
-		return rc;
-
-	rc = of_property_read_u32(node, "qcom,pwm-us", &val);
-	if (!rc)
-		led->kpdbl_cfg->pwm_period_us = val;
-	else
+	rc = qpnp_get_config_pwm(led->kpdbl_cfg->pwm_cfg, led->spmi_dev,  node);
+	if (rc < 0)
 		return rc;
 
 	rc = of_property_read_u32(node, "qcom,row-src-sel-val", &val);
@@ -1729,10 +1918,9 @@
 static int __devinit qpnp_get_config_rgb(struct qpnp_led_data *led,
 				struct device_node *node)
 {
-	struct property *prop;
-	int rc, i;
-	u32 val;
-	u8 *temp_cfg;
+	int rc;
+	u8 led_mode;
+	const char *mode;
 
 	led->rgb_cfg = devm_kzalloc(&led->spmi_dev->dev,
 				sizeof(struct rgb_config_data), GFP_KERNEL);
@@ -1750,113 +1938,29 @@
 	else
 		return -EINVAL;
 
-	rc = of_property_read_u32(node, "qcom,mode", &val);
-	if (!rc)
-		led->rgb_cfg->mode = (u8) val;
-	else
-		return rc;
-
-	rc = of_property_read_u32(node, "qcom,pwm-channel", &val);
-	if (!rc)
-		led->rgb_cfg->pwm_channel = val;
-	else
-		return rc;
-
-	if (led->rgb_cfg->mode == PWM_MODE) {
-		rc = of_property_read_u32(node, "qcom,pwm-us", &val);
-		if (!rc)
-			led->rgb_cfg->pwm_period_us = val;
-		else
-			return rc;
-	}
-
-	if (led->rgb_cfg->mode == LPG_MODE) {
-		led->rgb_cfg->duty_cycles =
-			devm_kzalloc(&led->spmi_dev->dev,
-			sizeof(struct pwm_duty_cycles), GFP_KERNEL);
-		if (!led->rgb_cfg->duty_cycles) {
-			dev_err(&led->spmi_dev->dev,
-				"Unable to allocate memory\n");
-			return -ENOMEM;
-		}
-
-		prop = of_find_property(node, "qcom,duty-pcts",
-			&led->rgb_cfg->duty_cycles->num_duty_pcts);
-		if (!prop) {
-			dev_err(&led->spmi_dev->dev, "Looking up property " \
-				"node qcom,duty-pcts failed\n");
-			return -ENODEV;
-		} else if (!led->rgb_cfg->duty_cycles->num_duty_pcts) {
-			dev_err(&led->spmi_dev->dev, "Invalid length of " \
-				"duty pcts\n");
+	rc = of_property_read_string(node, "qcom,mode", &mode);
+	if (!rc) {
+		led_mode = qpnp_led_get_mode(mode);
+		if ((led_mode == MANUAL_MODE) || (led_mode == -EINVAL)) {
+			dev_err(&led->spmi_dev->dev, "Selected mode not " \
+				"supported for rgb.\n");
 			return -EINVAL;
 		}
-
-		led->rgb_cfg->duty_cycles->duty_pcts =
-			devm_kzalloc(&led->spmi_dev->dev,
-			sizeof(int) * led->rgb_cfg->duty_cycles->num_duty_pcts,
-			GFP_KERNEL);
-		if (!led->rgb_cfg->duty_cycles->duty_pcts) {
+		led->rgb_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+					sizeof(struct pwm_config_data),
+					GFP_KERNEL);
+		if (!led->rgb_cfg->pwm_cfg) {
 			dev_err(&led->spmi_dev->dev,
 				"Unable to allocate memory\n");
 			return -ENOMEM;
 		}
+		led->rgb_cfg->pwm_cfg->mode = led_mode;
+	} else
+		return rc;
 
-		temp_cfg = devm_kzalloc(&led->spmi_dev->dev,
-				led->rgb_cfg->duty_cycles->num_duty_pcts *
-				sizeof(u8), GFP_KERNEL);
-		if (!temp_cfg) {
-			dev_err(&led->spmi_dev->dev, "Failed to allocate " \
-				"memory for duty pcts\n");
-			return -ENOMEM;
-		}
-
-		memcpy(temp_cfg, prop->value,
-			led->rgb_cfg->duty_cycles->num_duty_pcts);
-
-		for (i = 0; i < led->rgb_cfg->duty_cycles->num_duty_pcts; i++)
-			led->rgb_cfg->duty_cycles->duty_pcts[i] =
-				(int) temp_cfg[i];
-
-		rc = of_property_read_u32(node, "qcom,start-idx", &val);
-		if (!rc) {
-			led->rgb_cfg->lut_params.start_idx = val;
-			led->rgb_cfg->duty_cycles->start_idx = val;
-		} else
-			return rc;
-
-		led->rgb_cfg->lut_params.lut_pause_hi = 0;
-		rc = of_property_read_u32(node, "qcom,pause-hi", &val);
-		if (!rc)
-			led->rgb_cfg->lut_params.lut_pause_hi = val;
-		else if (rc != -EINVAL)
-			return rc;
-
-		led->rgb_cfg->lut_params.lut_pause_lo = 0;
-		rc = of_property_read_u32(node, "qcom,pause-lo", &val);
-		if (!rc)
-			led->rgb_cfg->lut_params.lut_pause_lo = val;
-		else if (rc != -EINVAL)
-			return rc;
-
-		led->rgb_cfg->lut_params.ramp_step_ms =
-				QPNP_LUT_RAMP_STEP_DEFAULT;
-		rc = of_property_read_u32(node, "qcom,ramp-step-ms", &val);
-		if (!rc)
-			led->rgb_cfg->lut_params.ramp_step_ms = val;
-		else if (rc != -EINVAL)
-			return rc;
-
-		led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
-		rc = of_property_read_u32(node, "qcom,lut-flags", &val);
-		if (!rc)
-			led->rgb_cfg->lut_params.flags = val;
-		else if (rc != -EINVAL)
-			return rc;
-
-		led->rgb_cfg->lut_params.idx_len =
-			led->rgb_cfg->duty_cycles->num_duty_pcts;
-	}
+	rc = qpnp_get_config_pwm(led->rgb_cfg->pwm_cfg, led->spmi_dev, node);
+	if (rc < 0)
+		return rc;
 
 	return 0;
 }
@@ -1866,6 +1970,8 @@
 {
 	int rc;
 	u32 val;
+	u8 led_mode;
+	const char *mode;
 
 	led->mpp_cfg = devm_kzalloc(&led->spmi_dev->dev,
 			sizeof(struct mpp_config_data), GFP_KERNEL);
@@ -1895,6 +2001,33 @@
 	else if (rc != -EINVAL)
 		return rc;
 
+	rc = of_property_read_string(node, "qcom,mode", &mode);
+	if (!rc) {
+		led_mode = qpnp_led_get_mode(mode);
+		led->mpp_cfg->pwm_mode = led_mode;
+		if (led_mode == MANUAL_MODE)
+			return MANUAL_MODE;
+		else if (led_mode == -EINVAL) {
+			dev_err(&led->spmi_dev->dev, "Selected mode not " \
+				"supported for mpp.\n");
+			return -EINVAL;
+		}
+		led->mpp_cfg->pwm_cfg = devm_kzalloc(&led->spmi_dev->dev,
+					sizeof(struct pwm_config_data),
+					GFP_KERNEL);
+		if (!led->mpp_cfg->pwm_cfg) {
+			dev_err(&led->spmi_dev->dev,
+				"Unable to allocate memory\n");
+			return -ENOMEM;
+		}
+		led->mpp_cfg->pwm_cfg->mode = led_mode;
+	} else
+		return rc;
+
+	rc = qpnp_get_config_pwm(led->mpp_cfg->pwm_cfg, led->spmi_dev, node);
+	if (rc < 0)
+		return rc;
+
 	return 0;
 }
 
@@ -2005,6 +2138,7 @@
 			if (rc < 0) {
 				dev_err(&led->spmi_dev->dev,
 						"Unable to read mpp config data\n");
+				goto fail_id_check;
 			}
 		} else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) {
 			rc = qpnp_get_config_kpdbl(led, temp);
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 d56a5252..28ade1a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1155,6 +1155,7 @@
 		s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table(
 			s_ctrl->sensor_i2c_client, &s_ctrl->stop_setting);
 		kfree(s_ctrl->stop_setting.reg_setting);
+		s_ctrl->stop_setting.reg_setting = NULL;
 	}
 	mutex_unlock(s_ctrl->msm_sensor_mutex);
 	return;
@@ -1395,6 +1396,8 @@
 		break;
 
 	case CFG_POWER_DOWN:
+		kfree(s_ctrl->stop_setting.reg_setting);
+		s_ctrl->stop_setting.reg_setting = NULL;
 		if (s_ctrl->sensor_state != MSM_SENSOR_POWER_UP) {
 			pr_err("%s:%d failed: invalid state %d\n", __func__,
 				__LINE__, s_ctrl->sensor_state);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 5b385a0..d07387e 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -4606,11 +4606,11 @@
 		mpq_demux->sdmx_filter_count, mpq_demux->filters_status);
 
 	process_end_time = current_kernel_time();
-	mpq_dmx_update_sdmx_stat(mpq_demux, prev_fill_count,
-		&process_start_time, &process_end_time);
-
 	bytes_read = prev_fill_count - fill_count;
 
+	mpq_dmx_update_sdmx_stat(mpq_demux, bytes_read,
+			&process_start_time, &process_end_time);
+
 	MPQ_DVB_DBG_PRINT(
 		"%s: SDMX result=%d, input_fill_count=%u, read_offset=%u, read %d bytes from input, status=0x%X, errors=0x%X\n",
 		__func__, sdmx_res, fill_count, read_offset, bytes_read,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 5e14d0c..a2ce428 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -54,14 +54,16 @@
 #define TSPP_RAW_TTS_SIZE		192
 #define TSPP_RAW_SIZE			188
 
-#define MAX_BAM_DESCRIPTOR_SIZE	(32*1024 - 1)
+#define MAX_BAM_DESCRIPTOR_SIZE	(32 * 1024 - 1)
+
+#define MAX_BAM_DESCRIPTOR_COUNT	(8 * 1024 - 2)
 
 #define TSPP_BUFFER_SIZE		(500 * 1024) /* 500KB */
 
 #define TSPP_DESCRIPTOR_SIZE	(TSPP_RAW_TTS_SIZE)
 
 #define TSPP_BUFFER_COUNT(buffer_size)	\
-	((buffer_size) / TSPP_RAW_TTS_SIZE)
+	((buffer_size) / TSPP_DESCRIPTOR_SIZE)
 
 /* When TSPP notifies demux that new packets are received.
  * Using max descriptor size (170 packets).
@@ -1799,6 +1801,11 @@
 		mpq_dmx_tspp_info.tsif[i].buffer_count =
 				TSPP_BUFFER_COUNT(tspp_out_buffer_size);
 
+		if (mpq_dmx_tspp_info.tsif[i].buffer_count >
+			MAX_BAM_DESCRIPTOR_COUNT)
+			mpq_dmx_tspp_info.tsif[i].buffer_count =
+				MAX_BAM_DESCRIPTOR_COUNT;
+
 		mpq_dmx_tspp_info.tsif[i].aggregate_ids =
 			vzalloc(mpq_dmx_tspp_info.tsif[i].buffer_count *
 				sizeof(int));
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9bc77be..c60537a 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -45,7 +45,6 @@
 #include "qseecom_kernel.h"
 
 #define QSEECOM_DEV			"qseecom"
-#define QSEOS_VERSION_13		0x13
 #define QSEOS_VERSION_14		0x14
 #define QSEEE_VERSION_00		0x400000
 #define QSEE_VERSION_01			0x401000
@@ -90,11 +89,6 @@
 static dev_t qseecom_device_no;
 static struct cdev qseecom_cdev;
 
-/* Data structures used in legacy support */
-static void *pil;
-static uint32_t pil_ref_cnt;
-static DEFINE_MUTEX(pil_access_lock);
-
 static DEFINE_MUTEX(qsee_bw_mutex);
 static DEFINE_MUTEX(app_access_lock);
 static DEFINE_MUTEX(clk_access_lock);
@@ -1004,27 +998,8 @@
 	return ret;
 }
 
-static int __qseecom_send_cmd_req_clean_up(
-			struct qseecom_send_modfd_cmd_req *req)
-{
-	char *field;
-	uint32_t *update;
-	int ret = 0;
-	int i = 0;
-
-	for (i = 0; i < MAX_ION_FD; i++) {
-		if (req->ifd_data[i].fd > 0) {
-			field = (char *)req->cmd_req_buf +
-					req->ifd_data[i].cmd_buf_offset;
-			update = (uint32_t *) field;
-			*update = 0;
-		}
-	}
-	return ret;
-}
-
-static int __qseecom_update_with_phy_addr(
-			struct qseecom_send_modfd_cmd_req *req)
+static int __qseecom_update_cmd_buf(struct qseecom_send_modfd_cmd_req *req,
+								bool cleanup)
 {
 	struct ion_handle *ihandle;
 	char *field;
@@ -1063,7 +1038,11 @@
 			if (sg_ptr->nents == 1) {
 				uint32_t *update;
 				update = (uint32_t *) field;
-				*update = (uint32_t)sg_dma_address(sg_ptr->sgl);
+				if (cleanup)
+					*update = 0;
+				else
+					*update = (uint32_t)sg_dma_address(
+								sg_ptr->sgl);
 			} else {
 				struct qseecom_sg_entry *update;
 				struct scatterlist *sg;
@@ -1071,9 +1050,14 @@
 				update = (struct qseecom_sg_entry *) field;
 				sg = sg_ptr->sgl;
 				for (j = 0; j < sg_ptr->nents; j++) {
-					update->phys_addr = (uint32_t)
-						sg_dma_address(sg);
-					update->len = (uint32_t)sg->length;
+					if (cleanup) {
+						update->phys_addr = 0;
+						update->len = 0;
+					} else {
+						update->phys_addr = (uint32_t)
+							sg_dma_address(sg);
+						update->len = sg->length;
+					}
 					update++;
 					sg = sg_next(sg);
 				}
@@ -1107,15 +1091,15 @@
 	send_cmd_req.resp_buf = req.resp_buf;
 	send_cmd_req.resp_len = req.resp_len;
 
-	ret = __qseecom_update_with_phy_addr(&req);
+	ret = __qseecom_update_cmd_buf(&req, false);
 	if (ret)
 		return ret;
-
 	ret = __qseecom_send_cmd(data, &send_cmd_req);
-	__qseecom_send_cmd_req_clean_up(&req);
 	if (ret)
 		return ret;
-
+	ret = __qseecom_update_cmd_buf(&req, true);
+	if (ret)
+		return ret;
 	pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
 			req.resp_len, req.resp_buf);
 	return ret;
@@ -1483,34 +1467,26 @@
 		*handle = NULL;
 		return -EINVAL;
 	}
-
+	mutex_lock(&app_access_lock);
 	if (qseecom.qsee_version > QSEEE_VERSION_00) {
-		mutex_lock(&app_access_lock);
 		if (qseecom.commonlib_loaded == false) {
 			ret = qseecom_load_commonlib_image(data);
 			if (ret == 0)
 				qseecom.commonlib_loaded = true;
 		}
-		mutex_unlock(&app_access_lock);
 	}
-
 	if (ret) {
 		pr_err("Failed to load commonlib image\n");
-		kfree(data);
-		kfree(*handle);
-		*handle = NULL;
-		return -EIO;
+		ret = -EIO;
+		goto err;
 	}
 
 	app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
 	memcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
 	ret = __qseecom_check_app_exists(app_ireq);
-	if (ret < 0) {
-		kzfree(data);
-		kfree(*handle);
-		*handle = NULL;
-		return -EINVAL;
-	}
+	if (ret < 0)
+		goto err;
+
 	data->client.app_id = ret;
 	if (ret > 0) {
 		pr_warn("App id %d for [%s] app exists\n", ret,
@@ -1533,26 +1509,17 @@
 		/* load the app and get the app_id  */
 		pr_debug("%s: Loading app for the first time'\n",
 				qseecom.pdev->init_name);
-		mutex_lock(&app_access_lock);
 		ret = __qseecom_load_fw(data, app_name);
-		mutex_unlock(&app_access_lock);
-
-		if (ret < 0) {
-			kfree(*handle);
-			kfree(data);
-			*handle = NULL;
-			return ret;
-		}
+		if (ret < 0)
+			goto err;
 		data->client.app_id = ret;
 	}
 	if (!found_app) {
 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 		if (!entry) {
-			pr_err("kmalloc failed\n");
-			kfree(data);
-			kfree(*handle);
-			*handle = NULL;
-			return -ENOMEM;
+			pr_err("kmalloc for app entry failed\n");
+			ret =  -ENOMEM;
+			goto err;
 		}
 		entry->app_id = ret;
 		entry->ref_cnt = 1;
@@ -1577,7 +1544,8 @@
 	kclient_entry = kzalloc(sizeof(*kclient_entry), GFP_KERNEL);
 	if (!kclient_entry) {
 		pr_err("kmalloc failed\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err;
 	}
 	kclient_entry->handle = *handle;
 
@@ -1586,7 +1554,15 @@
 			&qseecom.registered_kclient_list_head);
 	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
 
+	mutex_unlock(&app_access_lock);
 	return 0;
+
+err:
+	kfree(data);
+	kfree(*handle);
+	*handle = NULL;
+	mutex_unlock(&app_access_lock);
+	return ret;
 }
 EXPORT_SYMBOL(qseecom_start_app);
 
@@ -3023,10 +2999,10 @@
 		}
 		qseecom.qseos_version = QSEOS_VERSION_14;
 	} else {
-		qseecom.qseos_version = QSEOS_VERSION_13;
-		qseecom.qsee_version = 0;
-		pil = NULL;
-		pil_ref_cnt = 0;
+		pr_err("QSEE legacy version is not supported:");
+		pr_err("Support for TZ1.3 and earlier is deprecated\n");
+		rc = -EINVAL;
+		goto err;
 	}
 	qseecom.commonlib_loaded = false;
 	qseecom.pdev = class_dev;
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 501da4c8..e0fffbd 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -62,9 +62,8 @@
 /*
  * BAM descriptor FIFO size (in number of descriptors).
  * Max number of descriptors allowed by SPS which is 8K-1.
- * Restrict it to half of this to save DMA memory.
  */
-#define TSPP_SPS_DESCRIPTOR_COUNT      (4 * 1024 - 1)
+#define TSPP_SPS_DESCRIPTOR_COUNT      (8 * 1024 - 1)
 #define TSPP_PACKET_LENGTH             188
 #define TSPP_MIN_BUFFER_SIZE           (TSPP_PACKET_LENGTH)
 
@@ -2236,6 +2235,12 @@
 		return -EINVAL;
 	}
 
+	if (count > TSPP_NUM_BUFFERS) {
+		pr_err("%s: tspp requires a maximum of %i buffers\n",
+			__func__, TSPP_NUM_BUFFERS);
+		return -EINVAL;
+	}
+
 	channel = &pdev->channels[channel_id];
 
 	/* allow buffer allocation only if there was no previous buffer
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 3efea77..4f9bbad 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -51,6 +51,7 @@
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 static void sdhci_tuning_timer(unsigned long data);
+static bool sdhci_check_state(struct sdhci_host *);
 
 #ifdef CONFIG_PM_RUNTIME
 static int sdhci_runtime_pm_get(struct sdhci_host *host);
@@ -292,7 +293,7 @@
 
 	spin_lock_irqsave(&host->lock, flags);
 
-	if (host->runtime_suspended)
+	if (host->runtime_suspended || sdhci_check_state(host))
 		goto out;
 
 	if (brightness == LED_OFF)
@@ -1395,7 +1396,8 @@
 	struct mmc_host *mmc = host->mmc;
 
 	if (!host->clock || !host->pwr ||
-	    pm_runtime_suspended(mmc->parent))
+	    (mmc_use_core_runtime_pm(mmc) ?
+	     pm_runtime_suspended(mmc->parent) : 0))
 		return true;
 	else
 		return false;
@@ -2887,6 +2889,8 @@
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 
+	spin_lock_init(&host->lock);
+
 	return host;
 }
 
@@ -3232,8 +3236,6 @@
 		return -ENODEV;
 	}
 
-	spin_lock_init(&host->lock);
-
 	/*
 	 * Maximum number of segments. Depends on if the hardware
 	 * can do scatter/gather or not.
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index fa71efc..0d77741 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -536,6 +536,8 @@
 				__func__);
 		return -EFAULT;
 	}
+	if (sps_ctrl_bam_dma_clk(true))
+		WARN_ON(1);
 	memset(&connect_params, 0, sizeof(struct ipa_sys_connect_params));
 	connect_params.client = IPA_CLIENT_A2_TETHERED_CONS;
 	connect_params.notify = ipa_tethered_notify;
@@ -606,6 +608,8 @@
 	ipa_bridge_teardown(IPA_BRIDGE_DIR_UL, IPA_BRIDGE_TYPE_TETHERED,
 			a2_mux_ctx->tethered_prod);
 bridge_tethered_ul_failed:
+	if (sps_ctrl_bam_dma_clk(false))
+		WARN_ON(1);
 	return ret;
 }
 
@@ -647,6 +651,8 @@
 				__func__, ret);
 		return ret;
 	}
+	if (sps_ctrl_bam_dma_clk(false))
+		WARN_ON(1);
 	verify_tx_queue_is_empty(__func__);
 	(void) ipa_rm_release_resource(IPA_RM_RESOURCE_A2_PROD);
 	if (a2_mux_ctx->disconnect_ack)
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 35b2561..6495db4 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1738,22 +1738,6 @@
 		result = -ENOMEM;
 		goto fail_rt_tbl_cache;
 	}
-	ipa_ctx->tx_pkt_wrapper_cache =
-	   kmem_cache_create("IPA TX PKT WRAPPER",
-			   sizeof(struct ipa_tx_pkt_wrapper), 0, 0, NULL);
-	if (!ipa_ctx->tx_pkt_wrapper_cache) {
-		IPAERR(":ipa tx pkt wrapper cache create failed\n");
-		result = -ENOMEM;
-		goto fail_tx_pkt_wrapper_cache;
-	}
-	ipa_ctx->rx_pkt_wrapper_cache =
-	   kmem_cache_create("IPA RX PKT WRAPPER",
-			   sizeof(struct ipa_rx_pkt_wrapper), 0, 0, NULL);
-	if (!ipa_ctx->rx_pkt_wrapper_cache) {
-		IPAERR(":ipa rx pkt wrapper cache create failed\n");
-		result = -ENOMEM;
-		goto fail_rx_pkt_wrapper_cache;
-	}
 	ipa_ctx->tree_node_cache =
 	   kmem_cache_create("IPA TREE", sizeof(struct ipa_tree_node), 0, 0,
 			   NULL);
@@ -1822,6 +1806,8 @@
 	mutex_init(&ipa_ctx->lock);
 	mutex_init(&ipa_ctx->nat_mem.lock);
 
+	skb_queue_head_init(&ipa_ctx->rx_list);
+
 	for (i = 0; i < IPA_A5_SYS_MAX; i++) {
 		INIT_LIST_HEAD(&ipa_ctx->sys[i].head_desc_list);
 		spin_lock_init(&ipa_ctx->sys[i].spinlock);
@@ -1835,15 +1821,15 @@
 			atomic_set(&ipa_ctx->sys[i].curr_polling_state, 0);
 	}
 
-	ipa_ctx->rx_wq = create_singlethread_workqueue("ipa rx wq");
+	ipa_ctx->rx_wq = alloc_workqueue("ipa rx wq", WQ_MEM_RECLAIM |
+			WQ_CPU_INTENSIVE, 1);
 	if (!ipa_ctx->rx_wq) {
 		IPAERR(":fail to create rx wq\n");
 		result = -ENOMEM;
 		goto fail_rx_wq;
 	}
 
-	ipa_ctx->tx_wq = alloc_workqueue("ipa tx wq", WQ_MEM_RECLAIM |
-			WQ_CPU_INTENSIVE, 2);
+	ipa_ctx->tx_wq = create_singlethread_workqueue("ipa tx wq");
 	if (!ipa_ctx->tx_wq) {
 		IPAERR(":fail to create tx wq\n");
 		result = -ENOMEM;
@@ -1996,10 +1982,6 @@
 fail_dma_pool:
 	kmem_cache_destroy(ipa_ctx->tree_node_cache);
 fail_tree_node_cache:
-	kmem_cache_destroy(ipa_ctx->rx_pkt_wrapper_cache);
-fail_rx_pkt_wrapper_cache:
-	kmem_cache_destroy(ipa_ctx->tx_pkt_wrapper_cache);
-fail_tx_pkt_wrapper_cache:
 	kmem_cache_destroy(ipa_ctx->rt_tbl_cache);
 fail_rt_tbl_cache:
 	kmem_cache_destroy(ipa_ctx->hdr_offset_cache);
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index 919a119..83c4db0 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -45,19 +45,23 @@
 #define IPA_UL_DESC_FIFO_SZ 0x530
 #define IPA_DL_DATA_FIFO_SZ 0x2400
 #define IPA_DL_DESC_FIFO_SZ 0x8a0
+#define IPA_DL_EMB_DATA_FIFO_SZ 0x1800
+#define IPA_DL_EMB_DESC_FIFO_SZ 0x4e8
 
-#define IPA_SMEM_UL_DATA_FIFO_OFST 0x3dd0
-#define IPA_SMEM_UL_DESC_FIFO_OFST 0x49d0
-#define IPA_SMEM_DL_DATA_FIFO_OFST 0x4f00
-#define IPA_SMEM_DL_DESC_FIFO_OFST 0x7300
+#define IPA_SMEM_UL_DATA_FIFO_OFST 0
+#define IPA_SMEM_UL_DESC_FIFO_OFST 0xc00
+#define IPA_SMEM_DL_DATA_FIFO_OFST 0x1130
+#define IPA_SMEM_DL_DESC_FIFO_OFST 0x3530
+#define IPA_SMEM_UL_EMB_DATA_FIFO_OFST 0x3dd0
+#define IPA_SMEM_UL_EMB_DESC_FIFO_OFST 0x49d0
 
-#define IPA_OCIMEM_UL_DATA_FIFO_OFST 0
-#define IPA_OCIMEM_UL_DESC_FIFO_OFST (IPA_OCIMEM_UL_DATA_FIFO_OFST + \
-		IPA_UL_DATA_FIFO_SZ)
-#define IPA_OCIMEM_DL_DATA_FIFO_OFST (IPA_OCIMEM_UL_DESC_FIFO_OFST + \
-		IPA_UL_DESC_FIFO_SZ)
-#define IPA_OCIMEM_DL_DESC_FIFO_OFST (IPA_OCIMEM_DL_DATA_FIFO_OFST + \
-		IPA_DL_DATA_FIFO_SZ)
+#define IPA_OCIMEM_DL_A2_DATA_FIFO_OFST 0
+#define IPA_OCIMEM_DL_A2_DESC_FIFO_OFST (IPA_OCIMEM_DL_A2_DATA_FIFO_OFST + \
+		IPA_DL_EMB_DATA_FIFO_SZ)
+#define IPA_OCIMEM_DL_IPA_DATA_FIFO_OFST (IPA_OCIMEM_DL_A2_DESC_FIFO_OFST + \
+		IPA_DL_EMB_DESC_FIFO_SZ)
+#define IPA_OCIMEM_DL_IPA_DESC_FIFO_OFST (IPA_OCIMEM_DL_IPA_DATA_FIFO_OFST + \
+		IPA_DL_EMB_DATA_FIFO_SZ)
 
 enum ipa_pipe_type {
 	IPA_DL_FROM_A2,
@@ -116,7 +120,7 @@
 		if (dir == IPA_BRIDGE_DIR_UL)
 			sz = IPA_UL_DESC_FIFO_SZ;
 		else
-			sz = IPA_DL_DESC_FIFO_SZ;
+			sz = IPA_DL_EMB_DESC_FIFO_SZ;
 	}
 
 	return sz;
@@ -136,7 +140,7 @@
 		if (dir == IPA_BRIDGE_DIR_UL)
 			sz = IPA_UL_DATA_FIFO_SZ;
 		else
-			sz = IPA_DL_DATA_FIFO_SZ;
+			sz = IPA_DL_EMB_DATA_FIFO_SZ;
 	}
 
 	return sz;
@@ -162,6 +166,38 @@
 	return ep;
 }
 
+int ipa_setup_ipa_dma_fifos(enum ipa_bridge_dir dir,
+		enum ipa_bridge_type type,
+		struct sps_mem_buffer *desc,
+		struct sps_mem_buffer *data)
+{
+	int ret;
+
+	ret = sps_setup_bam2bam_fifo(data,
+			IPA_OCIMEM_DL_IPA_DATA_FIFO_OFST,
+			ipa_get_data_fifo_sz(dir, type), 1);
+	if (ret) {
+		IPAERR("DAFIFO setup fail %d dir %d type %d\n",
+				ret, dir, type);
+		return ret;
+	}
+
+	ret = sps_setup_bam2bam_fifo(desc,
+			IPA_OCIMEM_DL_IPA_DESC_FIFO_OFST,
+			ipa_get_desc_fifo_sz(dir, type), 1);
+	if (ret) {
+		IPAERR("DEFIFO setup fail %d dir %d type %d\n",
+				ret, dir, type);
+		return ret;
+	}
+
+	IPADBG("dir=%d type=%d Dpa=%x Dsz=%u Dva=%p dpa=%x dsz=%u dva=%p\n",
+			dir, type, data->phys_base, data->size, data->base,
+			desc->phys_base, desc->size, desc->base);
+
+	return 0;
+}
+
 int ipa_setup_a2_dma_fifos(enum ipa_bridge_dir dir,
 		enum ipa_bridge_type type,
 		struct sps_mem_buffer *desc,
@@ -169,7 +205,7 @@
 {
 	int ret;
 
-	if (type == IPA_BRIDGE_TYPE_EMBEDDED) {
+	if (type == IPA_BRIDGE_TYPE_TETHERED) {
 		if (dir == IPA_BRIDGE_DIR_UL) {
 			desc->base = ipa_ctx->smem_pipe_mem +
 				IPA_SMEM_UL_DESC_FIFO_OFST;
@@ -191,26 +227,17 @@
 		}
 	} else {
 		if (dir == IPA_BRIDGE_DIR_UL) {
-			ret = sps_setup_bam2bam_fifo(data,
-					IPA_OCIMEM_UL_DATA_FIFO_OFST,
-					ipa_get_data_fifo_sz(dir, type), 1);
-			if (ret) {
-				IPAERR("DAFIFO setup fail %d dir %d type %d\n",
-						ret, dir, type);
-				return ret;
-			}
-
-			ret = sps_setup_bam2bam_fifo(desc,
-					IPA_OCIMEM_UL_DESC_FIFO_OFST,
-					ipa_get_desc_fifo_sz(dir, type), 1);
-			if (ret) {
-				IPAERR("DEFIFO setup fail %d dir %d type %d\n",
-						ret, dir, type);
-				return ret;
-			}
+			desc->base = ipa_ctx->smem_pipe_mem +
+				IPA_SMEM_UL_EMB_DESC_FIFO_OFST;
+			desc->phys_base = smem_virt_to_phys(desc->base);
+			desc->size = ipa_get_desc_fifo_sz(dir, type);
+			data->base = ipa_ctx->smem_pipe_mem +
+				IPA_SMEM_UL_EMB_DATA_FIFO_OFST;
+			data->phys_base = smem_virt_to_phys(data->base);
+			data->size = ipa_get_data_fifo_sz(dir, type);
 		} else {
 			ret = sps_setup_bam2bam_fifo(data,
-					IPA_OCIMEM_DL_DATA_FIFO_OFST,
+					IPA_OCIMEM_DL_A2_DATA_FIFO_OFST,
 					ipa_get_data_fifo_sz(dir, type), 1);
 			if (ret) {
 				IPAERR("DAFIFO setup fail %d dir %d type %d\n",
@@ -219,7 +246,7 @@
 			}
 
 			ret = sps_setup_bam2bam_fifo(desc,
-					IPA_OCIMEM_DL_DESC_FIFO_OFST,
+					IPA_OCIMEM_DL_A2_DESC_FIFO_OFST,
 					ipa_get_desc_fifo_sz(dir, type), 1);
 			if (ret) {
 				IPAERR("DEFIFO setup fail %d dir %d type %d\n",
@@ -289,6 +316,15 @@
 	ipa_in_params.desc_fifo_sz = ipa_get_desc_fifo_sz(dir, type);
 	ipa_in_params.data_fifo_sz = ipa_get_data_fifo_sz(dir, type);
 
+	if (type == IPA_BRIDGE_TYPE_EMBEDDED && dir == IPA_BRIDGE_DIR_DL) {
+		if (ipa_setup_ipa_dma_fifos(dir, type, &ipa_in_params.desc,
+					&ipa_in_params.data)) {
+			IPAERR("fail to setup IPA-DMA FIFOs dir=%d type=%d\n",
+					dir, type);
+			goto fail_get_a2_prop;
+		}
+	}
+
 	if (ipa_connect(&ipa_in_params, &sps_out_params, clnt_hdl)) {
 		IPAERR("ipa connect failed dir=%d type=%d\n", dir, type);
 		goto fail_get_a2_prop;
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index d707648..b0fb940 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -187,13 +187,6 @@
 		return;
 
 	switch (ep->client) {
-	case IPA_CLIENT_HSIC1_CONS:
-	case IPA_CLIENT_HSIC2_CONS:
-	case IPA_CLIENT_HSIC3_CONS:
-	case IPA_CLIENT_HSIC4_CONS:
-		hol_en = ipa_ctx->hol_en;
-		hol_tmr = ipa_ctx->hol_timer;
-		break;
 	case IPA_CLIENT_A2_TETHERED_CONS:
 	case IPA_CLIENT_A2_EMBEDDED_CONS:
 		hol_en = IPA_A2_HOLB_TMR_EN;
@@ -257,6 +250,26 @@
 
 	memset(&ipa_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa_ep_context));
 
+	if (IPA_CLIENT_IS_CONS(in->client)) {
+		ep->cmd = kzalloc(sizeof(struct ipa_ip_packet_init),
+				GFP_KERNEL);
+		if (!ep->cmd) {
+			IPAERR("failed to alloc immediate command object\n");
+			result = -ENOMEM;
+			goto fail;
+		}
+		ep->cmd->destination_pipe_index = ipa_ep_idx;
+		ep->dma_addr = dma_map_single(NULL, ep->cmd,
+				sizeof(struct ipa_ip_packet_init),
+				DMA_TO_DEVICE);
+		if (ep->dma_addr == 0 || ep->dma_addr == ~0) {
+			IPAERR("failed to DMA MAP pkt_init\n");
+			result = -ENOMEM;
+			kfree(ep->cmd);
+			goto fail;
+		}
+	}
+
 	ep->valid = 1;
 	ep->client = in->client;
 	ep->client_notify = in->notify;
@@ -433,6 +446,13 @@
 		return -EPERM;
 	}
 
+	if (IPA_CLIENT_IS_CONS(ep->client)) {
+		dma_unmap_single(NULL, ep->dma_addr,
+				sizeof(struct ipa_ip_packet_init),
+				DMA_TO_DEVICE);
+		kfree(ep->cmd);
+	}
+
 	ipa_enable_data_path(clnt_hdl);
 	memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
 
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 1b6181f..c564922 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -19,18 +19,20 @@
 
 #define list_next_entry(pos, member) \
 	list_entry(pos->member.next, typeof(*pos), member)
-#define IPA_LAST_DESC_CNT 0xFFFF
 #define POLLING_INACTIVITY_RX 40
-#define POLLING_MIN_SLEEP_RX 950
-#define POLLING_MAX_SLEEP_RX 1050
-#define POLLING_INACTIVITY_TX 40
-#define POLLING_MIN_SLEEP_TX 400
-#define POLLING_MAX_SLEEP_TX 500
+#define POLLING_MIN_SLEEP_RX 2350
+#define POLLING_MAX_SLEEP_RX 2450
+#define POLLING_INACTIVITY_TX 10
+#define POLLING_MIN_SLEEP_TX 100
+#define POLLING_MAX_SLEEP_TX 200
+#define RX_MAX_IND 40
 
 static void replenish_rx_work_func(struct work_struct *work);
 static struct delayed_work replenish_rx_work;
 static void ipa_wq_handle_rx(struct work_struct *work);
 static DECLARE_WORK(rx_work, ipa_wq_handle_rx);
+static void ipa_wq_handle_tx(struct work_struct *work);
+static DECLARE_WORK(tx_work, ipa_wq_handle_tx);
 
 /**
  * ipa_write_done() - this function will be (eventually) called when a Tx
@@ -81,7 +83,7 @@
 	if (tx_pkt->callback)
 		tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
 
-	kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+	kfree(tx_pkt);
 }
 
 int ipa_handle_tx_core(struct ipa_sys_context *sys, bool process_all,
@@ -119,23 +121,13 @@
 
 		IPADBG("--curr_cnt=%d\n", sys->len);
 
-		if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
-			dma_pool_free(ipa_ctx->dma_pool,
-					tx_pkt->bounce,
-					tx_pkt->mem.phys_base);
-		else
+		if (tx_pkt->callback) {
 			dma_unmap_single(NULL, tx_pkt->mem.phys_base,
-					tx_pkt->mem.size,
-					DMA_TO_DEVICE);
-
-		if (tx_pkt->callback)
+					tx_pkt->mem.size, DMA_TO_DEVICE);
 			tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
+		}
 
-		if (tx_pkt->cnt > 1 && tx_pkt->cnt != IPA_LAST_DESC_CNT)
-			dma_pool_free(ipa_ctx->dma_pool, tx_pkt->mult.base,
-					tx_pkt->mult.phys_base);
-
-		kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+		kfree(tx_pkt);
 		cnt++;
 	};
 
@@ -154,11 +146,6 @@
 		goto fail;
 	}
 
-	ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
-	if (ret) {
-		IPAERR("sps_get_config() failed %d\n", ret);
-		goto fail;
-	}
 	sys->event.options = SPS_O_EOT;
 	ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
 	if (ret) {
@@ -205,9 +192,7 @@
 
 static void ipa_wq_handle_tx(struct work_struct *work)
 {
-	struct ipa_tx_pkt_wrapper *tx_pkt;
-	tx_pkt = container_of(work, struct ipa_tx_pkt_wrapper, work);
-	ipa_handle_tx(tx_pkt->sys);
+	ipa_handle_tx(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT]);
 }
 
 /**
@@ -240,7 +225,7 @@
 	if (unlikely(!in_atomic))
 		mem_flag = GFP_KERNEL;
 
-	tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache, mem_flag);
+	tx_pkt = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), mem_flag);
 	if (!tx_pkt) {
 		IPAERR("failed to alloc tx wrapper\n");
 		goto fail_mem_alloc;
@@ -296,14 +281,11 @@
 		IPADBG("sending cmd=%d pyld_len=%d sps_flags=%x\n",
 				desc->opcode, desc->len, sps_flags);
 		IPA_DUMP_BUFF(desc->pyld, dma_address, desc->len);
-		INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
 	} else {
 		len = desc->len;
-		INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
 	}
 
-	if (unlikely(ipa_ctx->polling_mode))
-		INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
+	INIT_WORK(&tx_pkt->work, ipa_wq_write_done);
 
 	spin_lock_irqsave(&sys->spinlock, irq_flags);
 	list_add_tail(&tx_pkt->link, &sys->head_desc_list);
@@ -327,192 +309,12 @@
 	else
 		dma_unmap_single(NULL, dma_address, desc->len, DMA_TO_DEVICE);
 fail_dma_map:
-	kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
+	kfree(tx_pkt);
 fail_mem_alloc:
 	return -EFAULT;
 }
 
 /**
- * ipa_send() - Send multiple descriptors in one HW transaction
- * @sys: system pipe context
- * @num_desc: number of packets
- * @desc: packets to send (may be immediate command or data)
- * @in_atomic:  whether caller is in atomic context
- *
- * This function is used for system-to-bam connection.
- * - SPS driver expect struct sps_transfer which will contain all the data
- *   for a transaction
- * - The sps_transfer struct will be pointing to bounce buffers for
- *   its DMA command (immediate command and data)
- * - ipa_tx_pkt_wrapper will be used for each ipa
- *   descriptor (allocated from wrappers cache)
- * - The wrapper struct will be configured for each ipa-desc payload and will
- *   contain information which will be later used by the user callbacks
- * - each transfer will be made by calling to sps_transfer()
- * - Each packet (command or data) that will be sent will also be saved in
- *   ipa_sys_context for later check that all data was sent
- *
- * Return codes: 0: success, -EFAULT: failure
- */
-int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
-		bool in_atomic)
-{
-	struct ipa_tx_pkt_wrapper *tx_pkt;
-	struct ipa_tx_pkt_wrapper *next_pkt;
-	struct sps_transfer transfer = { 0 };
-	struct sps_iovec *iovec;
-	unsigned long irq_flags;
-	dma_addr_t dma_addr;
-	int i = 0;
-	int j;
-	int result;
-	int fail_dma_wrap = 0;
-	uint size = num_desc * sizeof(struct sps_iovec);
-	u32 mem_flag = GFP_ATOMIC;
-
-	if (unlikely(!in_atomic))
-		mem_flag = GFP_KERNEL;
-
-	transfer.iovec = dma_pool_alloc(ipa_ctx->dma_pool, mem_flag, &dma_addr);
-	transfer.iovec_phys = dma_addr;
-	transfer.iovec_count = num_desc;
-	spin_lock_irqsave(&sys->spinlock, irq_flags);
-	if (!transfer.iovec) {
-		IPAERR("fail to alloc DMA mem for sps xfr buff\n");
-		goto failure_coherent;
-	}
-
-	for (i = 0; i < num_desc; i++) {
-		fail_dma_wrap = 0;
-		tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache,
-					   mem_flag);
-		if (!tx_pkt) {
-			IPAERR("failed to alloc tx wrapper\n");
-			goto failure;
-		}
-		/*
-		 * first desc of set is "special" as it holds the count and
-		 * other info
-		 */
-		if (i == 0) {
-			transfer.user = tx_pkt;
-			tx_pkt->mult.phys_base = dma_addr;
-			tx_pkt->mult.base = transfer.iovec;
-			tx_pkt->mult.size = size;
-			tx_pkt->cnt = num_desc;
-			INIT_WORK(&tx_pkt->work, ipa_wq_handle_tx);
-		}
-
-		iovec = &transfer.iovec[i];
-		iovec->flags = 0;
-
-		INIT_LIST_HEAD(&tx_pkt->link);
-		tx_pkt->type = desc[i].type;
-
-		tx_pkt->mem.base = desc[i].pyld;
-		tx_pkt->mem.size = desc[i].len;
-
-		if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
-			WARN_ON(tx_pkt->mem.size > 512);
-
-			/*
-			 * Due to a HW limitation, we need to make sure that the
-			 * packet does not cross a 1KB boundary
-			 */
-			tx_pkt->bounce =
-			   dma_pool_alloc(ipa_ctx->dma_pool,
-					   mem_flag,
-					   &tx_pkt->mem.phys_base);
-			if (!tx_pkt->bounce) {
-				tx_pkt->mem.phys_base = 0;
-			} else {
-				WARN_ON(!ipa_straddle_boundary(
-						(u32)tx_pkt->mem.phys_base,
-						(u32)tx_pkt->mem.phys_base +
-						tx_pkt->mem.size - 1, 1024));
-				memcpy(tx_pkt->bounce, tx_pkt->mem.base,
-						tx_pkt->mem.size);
-			}
-		} else {
-			tx_pkt->mem.phys_base =
-			   dma_map_single(NULL, tx_pkt->mem.base,
-					   tx_pkt->mem.size,
-					   DMA_TO_DEVICE);
-		}
-		if (!tx_pkt->mem.phys_base) {
-			IPAERR("failed to alloc tx wrapper\n");
-			fail_dma_wrap = 1;
-			goto failure;
-		}
-
-		tx_pkt->sys = sys;
-		tx_pkt->callback = desc[i].callback;
-		tx_pkt->user1 = desc[i].user1;
-		tx_pkt->user2 = desc[i].user2;
-
-		/*
-		 * Point the iovec to the bounce buffer and
-		 * add this packet to system pipe context.
-		 */
-		iovec->addr = tx_pkt->mem.phys_base;
-		list_add_tail(&tx_pkt->link, &sys->head_desc_list);
-
-		/*
-		 * Special treatment for immediate commands, where the structure
-		 * of the descriptor is different
-		 */
-		if (desc[i].type == IPA_IMM_CMD_DESC) {
-			iovec->size = desc[i].opcode;
-			iovec->flags |= SPS_IOVEC_FLAG_IMME;
-		} else {
-			iovec->size = desc[i].len;
-		}
-
-		if (i == (num_desc - 1)) {
-			iovec->flags |= SPS_IOVEC_FLAG_EOT;
-			/* "mark" the last desc */
-			tx_pkt->cnt = IPA_LAST_DESC_CNT;
-		}
-	}
-
-	result = sps_transfer(sys->ep->ep_hdl, &transfer);
-	if (result) {
-		IPAERR("sps_transfer failed rc=%d\n", result);
-		goto failure;
-	}
-
-	spin_unlock_irqrestore(&sys->spinlock, irq_flags);
-	return 0;
-
-failure:
-	tx_pkt = transfer.user;
-	for (j = 0; j < i; j++) {
-		next_pkt = list_next_entry(tx_pkt, link);
-		list_del(&tx_pkt->link);
-		if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
-			dma_pool_free(ipa_ctx->dma_pool,
-					tx_pkt->bounce,
-					tx_pkt->mem.phys_base);
-		else
-			dma_unmap_single(NULL, tx_pkt->mem.phys_base,
-					tx_pkt->mem.size,
-					DMA_TO_DEVICE);
-		kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
-		tx_pkt = next_pkt;
-	}
-	if (i < num_desc)
-		/* last desc failed */
-		if (fail_dma_wrap)
-			kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
-	if (transfer.iovec_phys)
-		dma_pool_free(ipa_ctx->dma_pool, transfer.iovec,
-				  transfer.iovec_phys);
-failure_coherent:
-	spin_unlock_irqrestore(&sys->spinlock, irq_flags);
-	return -EFAULT;
-}
-
-/**
  * ipa_sps_irq_cmd_ack - callback function which will be called by SPS driver after an
  * immediate command is complete.
  * @user1:	pointer to the descriptor of the transfer
@@ -543,7 +345,6 @@
  */
 int ipa_send_cmd(u16 num_desc, struct ipa_desc *descr)
 {
-	struct ipa_desc *desc;
 	int result = 0;
 
 	ipa_inc_client_enable_clks();
@@ -563,22 +364,10 @@
 		}
 		wait_for_completion(&descr->xfer_done);
 	} else {
-		desc = &descr[num_desc - 1];
-		init_completion(&desc->xfer_done);
-
-		if (desc->callback || desc->user1)
-			WARN_ON(1);
-
-		desc->callback = ipa_sps_irq_cmd_ack;
-		desc->user1 = desc;
-		if (ipa_send(&ipa_ctx->sys[IPA_A5_CMD], num_desc,
-					descr, false)) {
-			IPAERR("fail to send multiple immediate command set\n");
+		IPAERR("unsupported chaining multiple IC\n");
 			result = -EFAULT;
 			goto bail;
 		}
-		wait_for_completion(&desc->xfer_done);
-	}
 
 	IPA_STATS_INC_IC_CNT(num_desc, descr, ipa_ctx->stats.imm_cmds);
 bail:
@@ -597,21 +386,13 @@
 static void ipa_sps_irq_tx_notify(struct sps_event_notify *notify)
 {
 	struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT];
-	struct ipa_tx_pkt_wrapper *tx_pkt;
 	int ret;
 
 	IPADBG("event %d notified\n", notify->event_id);
 
 	switch (notify->event_id) {
 	case SPS_EVENT_EOT:
-		tx_pkt = notify->data.transfer.user;
 		if (!atomic_read(&sys->curr_polling_state)) {
-			ret = sps_get_config(sys->ep->ep_hdl,
-					&sys->ep->connect);
-			if (ret) {
-				IPAERR("sps_get_config() failed %d\n", ret);
-				break;
-			}
 			sys->ep->connect.options = SPS_O_AUTO_ENABLE |
 				SPS_O_ACK_TRANSFERS | SPS_O_POLL;
 			ret = sps_set_config(sys->ep->ep_hdl,
@@ -621,7 +402,7 @@
 				break;
 			}
 			atomic_set(&sys->curr_polling_state, 1);
-			queue_work(ipa_ctx->tx_wq, &tx_pkt->work);
+			queue_work(ipa_ctx->tx_wq, &tx_work);
 		}
 		break;
 	default:
@@ -654,6 +435,47 @@
 	}
 }
 
+static void ipa_handle_tag_rsp(struct ipa_a5_mux_hdr *mux_hdr)
+{
+	struct completion *compl;
+	struct ipa_tree_node *node;
+
+	/* retrieve the compl object from tag value */
+	mux_hdr++;
+	compl = (struct completion *) ntohl(*((u32 *)mux_hdr));
+	IPADBG("%x %x %p\n", *(u32 *)mux_hdr, *((u32 *)mux_hdr + 1), compl);
+
+	mutex_lock(&ipa_ctx->lock);
+	node = ipa_search(&ipa_ctx->tag_tree, (u32)compl);
+	if (node) {
+		complete_all(compl);
+		rb_erase(&node->node, &ipa_ctx->tag_tree);
+		kmem_cache_free(ipa_ctx->tree_node_cache, node);
+	} else {
+		WARN_ON(1);
+	}
+	mutex_unlock(&ipa_ctx->lock);
+}
+
+static void ipa_dejitter(bool limit)
+{
+	struct sk_buff *skb;
+	int len = skb_queue_len(&ipa_ctx->rx_list);
+	int i;
+	void *cookie;
+	ipa_notify_cb cb;
+
+	if (limit && len >= RX_MAX_IND)
+		len = RX_MAX_IND;
+
+	for (i = len; i > 0; i--) {
+		skb = __skb_dequeue(&ipa_ctx->rx_list);
+		cb = (ipa_notify_cb)*(u32 *)&(skb->cb[0]);
+		cookie = (void *)*(u32 *)&(skb->cb[4]);
+		cb(cookie, IPA_RECEIVE, (unsigned long)skb);
+	}
+}
+
 /**
  * ipa_handle_rx_core() - The core functionality of packet reception. This
  * function is read from multiple code paths.
@@ -675,13 +497,9 @@
 	struct ipa_rx_pkt_wrapper *rx_pkt;
 	struct sk_buff *rx_skb;
 	struct sps_iovec iov;
-	unsigned int pull_len;
-	unsigned int padding;
 	int ret;
 	struct ipa_ep_context *ep;
 	int cnt = 0;
-	struct completion *compl;
-	struct ipa_tree_node *node;
 	unsigned int src_pipe;
 
 	while ((in_poll_state ? atomic_read(&sys->curr_polling_state) :
@@ -721,7 +539,7 @@
 		rx_skb->tail = rx_skb->data + rx_pkt->len;
 		rx_skb->len = rx_pkt->len;
 		rx_skb->truesize = rx_pkt->len + sizeof(struct sk_buff);
-		kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
+		kfree(rx_pkt);
 
 		mux_hdr = (struct ipa_a5_mux_hdr *)rx_skb->data;
 
@@ -736,29 +554,9 @@
 		IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
 		IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
 
-		if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
-			if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
-				/* retrieve the compl object from tag value */
-				mux_hdr++;
-				compl = (struct completion *)
-					ntohl(*((u32 *)mux_hdr));
-				IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
-						*((u32 *)mux_hdr + 1), compl);
-
-				mutex_lock(&ipa_ctx->lock);
-				node = ipa_search(&ipa_ctx->tag_tree,
-						(u32)compl);
-				if (node) {
-					complete_all(compl);
-					rb_erase(&node->node,
-							&ipa_ctx->tag_tree);
-					kmem_cache_free(
-						ipa_ctx->tree_node_cache, node);
-				} else {
-					WARN_ON(1);
-				}
-				mutex_unlock(&ipa_ctx->lock);
-			}
+		if (mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG) {
+			if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL)
+				ipa_handle_tag_rsp(mux_hdr);
 			dev_kfree_skb(rx_skb);
 			ipa_replenish_rx_cache();
 			++cnt;
@@ -769,38 +567,22 @@
 		 * Any packets arriving over AMPDU_TX should be dispatched
 		 * to the regular WLAN RX data-path.
 		 */
-		if (unlikely(src_pipe == WLAN_AMPDU_TX_EP))
+		if (src_pipe == WLAN_AMPDU_TX_EP)
 			src_pipe = WLAN_PROD_TX_EP;
 
-		if (unlikely(src_pipe >= IPA_NUM_PIPES ||
-			!ipa_ctx->ep[src_pipe].valid ||
-			!ipa_ctx->ep[src_pipe].client_notify)) {
-			IPAERR("drop pipe=%d ep_valid=%d client_notify=%p\n",
-			  src_pipe, ipa_ctx->ep[src_pipe].valid,
-			  ipa_ctx->ep[src_pipe].client_notify);
-			dev_kfree_skb(rx_skb);
-			ipa_replenish_rx_cache();
-			++cnt;
-			continue;
-		}
+		WARN_ON(src_pipe >= IPA_NUM_PIPES);
 
 		ep = &ipa_ctx->ep[src_pipe];
-		pull_len = sizeof(struct ipa_a5_mux_hdr);
-
-		/*
-		 * IP packet starts on word boundary
-		 * remove the MUX header and any padding and pass the frame to
-		 * the client which registered a rx callback on the "src pipe"
-		 */
-		padding = ep->cfg.hdr.hdr_len & 0x3;
-		if (padding)
-			pull_len += 4 - padding;
-
-		IPADBG("pulling %d bytes from skb\n", pull_len);
-		skb_pull(rx_skb, pull_len);
+		IPADBG("pulling %d bytes from skb\n", ep->pull_len);
+		skb_pull(rx_skb, ep->pull_len);
 		ipa_replenish_rx_cache();
-		ep->client_notify(ep->priv, IPA_RECEIVE,
-				(unsigned long)(rx_skb));
+		if (ep->client_notify) {
+			__skb_queue_tail(&ipa_ctx->rx_list, rx_skb);
+			*(u32 *)&(rx_skb->cb[0]) = (u32)ep->client_notify;
+			*(u32 *)&(rx_skb->cb[4]) = (u32)ep->priv;
+		} else {
+			dev_kfree_skb(rx_skb);
+		}
 		cnt++;
 	};
 
@@ -819,11 +601,6 @@
 		goto fail;
 	}
 
-	ret = sps_get_config(sys->ep->ep_hdl, &sys->ep->connect);
-	if (ret) {
-		IPAERR("sps_get_config() failed %d\n", ret);
-		goto fail;
-	}
 	sys->event.options = SPS_O_EOT;
 	ret = sps_register_event(sys->ep->ep_hdl, &sys->event);
 	if (ret) {
@@ -870,12 +647,6 @@
 	switch (notify->event_id) {
 	case SPS_EVENT_EOT:
 		if (!atomic_read(&sys->curr_polling_state)) {
-			ret = sps_get_config(sys->ep->ep_hdl,
-					&sys->ep->connect);
-			if (ret) {
-				IPAERR("sps_get_config() failed %d\n", ret);
-				break;
-			}
 			sys->ep->connect.options = SPS_O_AUTO_ENABLE |
 				SPS_O_ACK_TRANSFERS | SPS_O_POLL;
 			ret = sps_set_config(sys->ep->ep_hdl,
@@ -925,8 +696,10 @@
 		} else {
 			inactive_cycles = 0;
 		}
+		ipa_dejitter(true);
 	} while (inactive_cycles <= POLLING_INACTIVITY_RX);
 
+	ipa_dejitter(false);
 	ipa_rx_switch_to_intr_mode(sys);
 	ipa_dec_client_disable_clks();
 }
@@ -1062,6 +835,7 @@
 		break;
 	case 2:
 		sys_idx = ipa_ep_idx;
+		ipa_ctx->sys[sys_idx].max_len = sys_in->desc_fifo_sz / 8 - 2;
 		INIT_DELAYED_WORK(&ipa_ctx->sys[sys_idx].switch_to_intr_work,
 				switch_to_intr_tx_work_func);
 		break;
@@ -1176,9 +950,87 @@
 		dev_kfree_skb(skb);
 }
 
-static void ipa_tx_cmd_comp(void *user1, void *user2)
+static int ipa_send_two(struct sk_buff *skb, struct ipa_sys_context *sys,
+		int dst_ep_idx)
 {
-	kfree(user1);
+	struct ipa_tx_pkt_wrapper *tx_pktc;
+	struct ipa_tx_pkt_wrapper *tx_pktd;
+	struct ipa_ep_context *ep = &ipa_ctx->ep[dst_ep_idx];
+	unsigned long irq_flags;
+	dma_addr_t dma_addrd;
+	int rc = -ENOMEM;
+
+	tx_pktc = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
+	if (!tx_pktc) {
+		IPAERR("failed to alloc tx wrapper C\n");
+		goto fail_mem_alloc_c;
+	}
+
+	tx_pktd = kmalloc(sizeof(struct ipa_tx_pkt_wrapper), GFP_ATOMIC);
+	if (!tx_pktd) {
+		IPAERR("failed to alloc tx wrapper D\n");
+		goto fail_mem_alloc_d;
+	}
+
+	dma_addrd = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
+	if (!dma_addrd) {
+		IPAERR("failed to DMA wrap\n");
+		goto fail_dma_map_d;
+	}
+
+	INIT_LIST_HEAD(&tx_pktc->link);
+	tx_pktc->callback = NULL;
+
+	INIT_LIST_HEAD(&tx_pktd->link);
+	tx_pktd->mem.phys_base = dma_addrd;
+	tx_pktd->mem.base = skb->data;
+	tx_pktd->mem.size = skb->len;
+	tx_pktd->callback = ipa_tx_comp_usr_notify_release;
+	tx_pktd->user1 = skb;
+	tx_pktd->user2 = (void *)dst_ep_idx;
+
+	spin_lock_irqsave(&sys->spinlock, irq_flags);
+	if (sys->len >= sys->max_len)
+		goto fail_oom;
+	list_add_tail(&tx_pktc->link, &sys->head_desc_list);
+	if (sps_transfer_one(sys->ep->ep_hdl, ep->dma_addr, IPA_IP_PACKET_INIT,
+			tx_pktc, SPS_IOVEC_FLAG_IMME |
+			SPS_IOVEC_FLAG_NO_SUBMIT))
+		IPAERR("sps_transfer_one 0 failed\n");
+	list_add_tail(&tx_pktd->link, &sys->head_desc_list);
+	if (sps_transfer_one(sys->ep->ep_hdl, dma_addrd, skb->len, tx_pktd,
+			SPS_IOVEC_FLAG_EOT | SPS_IOVEC_FLAG_INT))
+		IPAERR("sps_transfer_one 1 failed\n");
+	sys->len += 2;
+	spin_unlock_irqrestore(&sys->spinlock, irq_flags);
+	return 0;
+
+fail_oom:
+	dma_unmap_single(NULL, dma_addrd, skb->len, DMA_TO_DEVICE);
+fail_dma_map_d:
+	kfree(tx_pktd);
+fail_mem_alloc_d:
+	kfree(tx_pktc);
+fail_mem_alloc_c:
+	return rc;
+}
+
+static int ipa_send_data_hw_path(struct sk_buff *skb,
+		struct ipa_sys_context *sys, int dst_ep_idx)
+{
+	struct ipa_desc desc;
+
+	desc.pyld = skb->data;
+	desc.len = skb->len;
+	desc.type = IPA_DATA_DESC_SKB;
+	desc.callback = ipa_tx_comp_usr_notify_release;
+	desc.user1 = skb;
+	desc.user2 = (void *)dst_ep_idx;
+
+	if (ipa_send_one(sys, &desc, true))
+		return -EFAULT;
+
+	return 0;
 }
 
 /**
@@ -1211,76 +1063,42 @@
 int ipa_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
 		struct ipa_tx_meta *meta)
 {
-	struct ipa_desc desc[2];
 	int ipa_ep_idx;
-	struct ipa_ip_packet_init *cmd;
-
-	memset(&desc, 0, 2 * sizeof(struct ipa_desc));
 
 	ipa_ep_idx = ipa_get_ep_mapping(ipa_ctx->mode, dst);
 	if (unlikely(ipa_ep_idx == -1)) {
 		IPAERR("dest EP does not exist.\n");
-		goto fail_gen;
+		goto fail;
 	}
 
 	if (unlikely(ipa_ctx->ep[ipa_ep_idx].valid == 0)) {
 		IPAERR("dest EP not valid.\n");
-		goto fail_gen;
+		goto fail;
 	}
 
 	if (IPA_CLIENT_IS_CONS(dst)) {
-		cmd = kzalloc(sizeof(struct ipa_ip_packet_init), GFP_ATOMIC);
-		if (!cmd) {
-			IPAERR("failed to alloc immediate command object\n");
-			goto fail_mem_alloc;
-		}
-
-		cmd->destination_pipe_index = ipa_ep_idx;
-		if (meta && meta->mbim_stream_id_valid)
-			cmd->metadata = meta->mbim_stream_id;
-		desc[0].opcode = IPA_IP_PACKET_INIT;
-		desc[0].pyld = cmd;
-		desc[0].len = sizeof(struct ipa_ip_packet_init);
-		desc[0].type = IPA_IMM_CMD_DESC;
-		desc[0].callback = ipa_tx_cmd_comp;
-		desc[0].user1 = cmd;
-		desc[1].pyld = skb->data;
-		desc[1].len = skb->len;
-		desc[1].type = IPA_DATA_DESC_SKB;
-		desc[1].callback = ipa_tx_comp_usr_notify_release;
-		desc[1].user1 = skb;
-		desc[1].user2 = (void *)ipa_ep_idx;
-
-		if (ipa_send(&ipa_ctx->sys[IPA_A5_LAN_WAN_OUT], 2, desc,
-					true)) {
-			IPAERR("fail to send immediate command\n");
-			goto fail_send;
+		if (ipa_send_two(skb, &ipa_ctx->sys[IPA_A5_LAN_WAN_OUT],
+					ipa_ep_idx)) {
+			IPAERR("fail to send pkt_init+skb dst=%d skb=%p\n",
+					dst, skb);
+			goto fail;
 		}
 		IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
 	} else if (dst == IPA_CLIENT_A5_WLAN_AMPDU_PROD) {
-		desc[0].pyld = skb->data;
-		desc[0].len = skb->len;
-		desc[0].type = IPA_DATA_DESC_SKB;
-		desc[0].callback = ipa_tx_comp_usr_notify_release;
-		desc[0].user1 = skb;
-		desc[0].user2 = (void *)ipa_ep_idx;
-
-		if (ipa_send_one(&ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
-					&desc[0], true)) {
-			IPAERR("fail to send skb\n");
-			goto fail_gen;
+		if (ipa_send_data_hw_path(skb,
+					&ipa_ctx->sys[IPA_A5_WLAN_AMPDU_OUT],
+					ipa_ep_idx)) {
+			IPAERR("fail to send skb dst=%d skb=%p\n", dst, skb);
+			goto fail;
 		}
 	} else {
 		IPAERR("%d PROD is not supported.\n", dst);
-		goto fail_gen;
+		goto fail;
 	}
 
 	return 0;
 
-fail_send:
-	kfree(cmd);
-fail_mem_alloc:
-fail_gen:
+fail:
 	return -EFAULT;
 }
 EXPORT_SYMBOL(ipa_tx_dp);
@@ -1316,8 +1134,7 @@
 	rx_len_cached = sys->len;
 
 	while (rx_len_cached < IPA_RX_POOL_CEIL) {
-		rx_pkt = kmem_cache_zalloc(ipa_ctx->rx_pkt_wrapper_cache,
-					   flag);
+		rx_pkt = kmalloc(sizeof(struct ipa_rx_pkt_wrapper), flag);
 		if (!rx_pkt) {
 			IPAERR("failed to alloc rx wrapper\n");
 			goto fail_kmem_cache_alloc;
@@ -1365,7 +1182,7 @@
 fail_dma_mapping:
 	dev_kfree_skb(rx_pkt->skb);
 fail_skb_alloc:
-	kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
+	kfree(rx_pkt);
 fail_kmem_cache_alloc:
 	if (rx_len_cached == 0) {
 		IPA_STATS_INC_CNT(ipa_ctx->stats.rx_repl_repost);
@@ -1397,7 +1214,7 @@
 		dma_unmap_single(NULL, rx_pkt->dma_address, IPA_RX_SKB_SIZE,
 				 DMA_FROM_DEVICE);
 		dev_kfree_skb(rx_pkt->skb);
-		kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
+		kfree(rx_pkt);
 	}
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index b57194e..a818931 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -363,6 +363,9 @@
 	bool desc_fifo_client_allocated;
 	bool data_fifo_client_allocated;
 	bool suspended;
+	unsigned int pull_len;
+	struct ipa_ip_packet_init *cmd;
+	dma_addr_t dma_addr;
 };
 
 /**
@@ -378,6 +381,7 @@
 struct ipa_sys_context {
 	struct list_head head_desc_list;
 	u32 len;
+	u32 max_len;
 	spinlock_t spinlock;
 	struct sps_register_event event;
 	struct ipa_ep_context *ep;
@@ -636,8 +640,6 @@
 	struct kmem_cache *hdr_cache;
 	struct kmem_cache *hdr_offset_cache;
 	struct kmem_cache *rt_tbl_cache;
-	struct kmem_cache *tx_pkt_wrapper_cache;
-	struct kmem_cache *rx_pkt_wrapper_cache;
 	struct kmem_cache *tree_node_cache;
 	unsigned long rt_idx_bitmap[IPA_IP_MAX];
 	struct mutex lock;
@@ -687,6 +689,7 @@
 	/* store HOLB configuration for WLAN TX pipes */
 	u32 hol_en;
 	u32 hol_timer;
+	struct sk_buff_head rx_list;
 };
 
 /**
@@ -775,8 +778,6 @@
 		u32 *consumer_handle);
 int ipa_send_one(struct ipa_sys_context *sys, struct ipa_desc *desc,
 		bool in_atomic);
-int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
-		bool in_atomic);
 int ipa_get_ep_mapping(enum ipa_operating_mode mode,
 		       enum ipa_client_type client);
 int ipa_get_client_mapping(enum ipa_operating_mode mode, int pipe_idx);
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index 264de0d..046c4d4 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -32,6 +32,24 @@
 	{ 19, -1, -1, -1, -1, 11, 15, 8, 6, 2, 1, 5, 14, 16, 17, 18, -1, 10, 9, 7, 3, 4 },
 };
 
+static unsigned int ipa_calc_pull_len(u32 hdr_len)
+{
+	unsigned int pull_len, padding;
+
+	pull_len = sizeof(struct ipa_a5_mux_hdr);
+
+	/*
+	 * IP packet starts on word boundary
+	 * remove the MUX header and any padding and pass the frame to
+	 * the client which registered a rx callback on the "src pipe"
+	 */
+	padding = hdr_len & 0x3;
+	if (padding)
+		pull_len += 4 - padding;
+
+	return pull_len;
+}
+
 /**
  * ipa_cfg_route() - configure IPA route
  * @route: IPA route
@@ -751,6 +769,9 @@
 		ipa_write_reg(ipa_ctx->mmio,
 			IPA_ENDP_INIT_HDR_n_OFST_v2(clnt_hdl), val);
 
+	if (IPA_CLIENT_IS_PROD(ep->client))
+		ep->pull_len = ipa_calc_pull_len(ipa_ep_cfg->hdr_len);
+
 	return 0;
 }
 EXPORT_SYMBOL(ipa_cfg_ep_hdr);
@@ -1263,4 +1284,3 @@
 	else
 		return 0;
 }
-
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index add9522..93f2366 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -1683,6 +1683,12 @@
 		return -EINVAL;
 	}
 
+	res = teth_request_resource();
+	if (res) {
+		TETH_ERR("request_resource() failed.\n");
+		return res;
+	}
+
 	memcpy(&teth_ctx->aggr_params,
 	       aggr_params,
 	       sizeof(struct teth_aggr_params));
@@ -1693,6 +1699,8 @@
 	res = teth_set_aggregation();
 	if (res)
 		TETH_ERR("Failed setting aggregation params\n");
+
+	ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_BRIDGE_PROD);
 	TETH_DBG_FUNC_EXIT();
 
 	return res;
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 9e3bab3..ac0b1d9 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/log2.h>
+#include <linux/qpnp/power-on.h>
 
 /* Common PNP defines */
 #define QPNP_PON_REVISION2(base)		(base + 0x01)
@@ -42,6 +43,7 @@
 #define QPNP_PON_RESIN_S2_CNTL(base)		(base + 0x46)
 #define QPNP_PON_PS_HOLD_RST_CTL(base)		(base + 0x5A)
 #define QPNP_PON_PS_HOLD_RST_CTL2(base)		(base + 0x5B)
+#define QPNP_PON_TRIGGER_EN(base)		(base + 0x80)
 
 #define QPNP_PON_WARM_RESET_TFT			BIT(4)
 
@@ -239,6 +241,39 @@
 }
 EXPORT_SYMBOL(qpnp_pon_is_warm_reset);
 
+/**
+ * qpnp_pon_trigger_config - Configures (enable/disable) the PON trigger source
+ * @pon_src: PON source to be configured
+ * @enable: to enable or disable the PON trigger
+ *
+ * This function configures the power-on trigger capability of a
+ * PON source. If a specific PON trigger is disabled it cannot act
+ * as a power-on source to the PMIC.
+ */
+
+int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable)
+{
+	struct qpnp_pon *pon = sys_reset_dev;
+	int rc;
+
+	if (!pon)
+		return -EPROBE_DEFER;
+
+	if (pon_src < PON_SMPL || pon_src > PON_KPDPWR_N) {
+		dev_err(&pon->spmi->dev, "Invalid PON source\n");
+		return -EINVAL;
+	}
+
+	rc = qpnp_pon_masked_write(pon, QPNP_PON_TRIGGER_EN(pon->base),
+				BIT(pon_src), enable ? BIT(pon_src) : 0);
+	if (rc)
+		dev_err(&pon->spmi->dev, "Unable to write to addr=%x, rc(%d)\n",
+					QPNP_PON_TRIGGER_EN(pon->base), rc);
+
+	return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_trigger_config);
+
 static struct qpnp_pon_config *
 qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type)
 {
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 81d80e6..2e77114 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1985,6 +1985,35 @@
 EXPORT_SYMBOL(sps_get_unused_desc_num);
 
 /**
+ * Vote for or relinquish BAM DMA clock
+ *
+ */
+int sps_ctrl_bam_dma_clk(bool clk_on)
+{
+	int ret;
+
+	SPS_DBG("sps:%s.", __func__);
+
+	if (!sps->is_ready)
+		return -EPROBE_DEFER;
+
+	if (clk_on == true) {
+		SPS_DBG("sps:vote for bam dma clk.\n");
+		ret = clk_prepare_enable(sps->bamdma_clk);
+		if (ret) {
+			SPS_ERR("sps:fail to enable bamdma_clk:ret=%d\n", ret);
+			return ret;
+		}
+	} else {
+		SPS_DBG("sps:relinquish bam dma clk.\n");
+		clk_disable_unprepare(sps->bamdma_clk);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sps_ctrl_bam_dma_clk);
+
+/**
  * Register a BAM device
  *
  */
@@ -2525,11 +2554,13 @@
 		SPS_ERR("sps:sps_device_init err.");
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
 		clk_disable_unprepare(sps->dfab_clk);
+		clk_disable_unprepare(sps->bamdma_clk);
 #endif
 		goto sps_device_init_err;
 	}
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
 	clk_disable_unprepare(sps->dfab_clk);
+	clk_disable_unprepare(sps->bamdma_clk);
 #endif
 	sps->is_ready = true;
 
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index af5442a..55cbfe9 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -137,6 +137,7 @@
 	int connect_complete;
 	bool lpm_wait_pipes;
 	int bus_suspend;
+	bool disconnected;
 	bool in_lpm[MAX_BAMS];
 
 	int (*wake_cb)(void *);
@@ -170,6 +171,7 @@
 static struct usb_bam_ctx_type ctx;
 
 static struct device *hsic_host_dev;
+static bool hsic_host_dev_resumed_from_cons_request;
 
 static int __usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
 	void *param, bool trigger_cb_per_pipe);
@@ -758,11 +760,19 @@
 
 	mutex_lock(&info.suspend_resume_mutex);
 
-	/* If resume was called don't finish this work */
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	/* If cable was disconnected, let disconnection seq do everything */
+	if (info.disconnected || info.cons_stopped) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		mutex_unlock(&info.suspend_resume_mutex);
+		pr_debug("%s: Cable disconnected\n", __func__);
+		return;
+	}
+
+	/* If resume was called don't finish this work */
 	if (!info.bus_suspend) {
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
-		pr_err("%s: Bus suspend in progress\n", __func__);
+		pr_err("%s: Bus resume in progress\n", __func__);
 		goto no_lpm;
 	}
 	spin_unlock(&usb_bam_ipa_handshake_info_lock);
@@ -785,8 +795,8 @@
 				ipa_rm_resource_cons[cur_bam]);
 		}
 		ipa_suspend_pipes();
-		mutex_unlock(&info.suspend_resume_mutex);
 		usb_bam_start_lpm(0);
+		mutex_unlock(&info.suspend_resume_mutex);
 		return;
 	}
 
@@ -888,6 +898,8 @@
 
 		break;
 	case HSIC_BAM:
+			hsic_host_dev_resumed_from_cons_request = true;
+
 			usb_bam_resume_hsic_host();
 
 			/*
@@ -937,13 +949,29 @@
 	}
 	spin_unlock(&usb_bam_lock);
 
-	spin_lock(&usb_bam_ipa_handshake_info_lock);
-	if (cur_bam == HSUSB_BAM && info.bus_suspend)
-		queue_work(ctx.usb_bam_wq, &info.finish_suspend_work);
-	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	if (cur_bam == HSUSB_BAM) {
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		if (info.bus_suspend)
+			queue_work(ctx.usb_bam_wq, &info.finish_suspend_work);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 
-	pr_debug("%s: EINPROGRESS cons_release", __func__);
-	return -EINPROGRESS;
+		pr_debug("%s: EINPROGRESS cons_release", __func__);
+		return -EINPROGRESS;
+	} else if (cur_bam == HSIC_BAM) {
+
+		/*
+		 * Allow to go to lpm for now. Actual state will be checked
+		 * in msm_bam_hsic_lpm_ok() just before going to lpm.
+		 */
+		if (hsic_host_dev && !info.in_lpm[HSIC_BAM]) {
+			pr_debug("%s: Putting hsic device %x\n", __func__,
+			(int)hsic_host_dev);
+			pm_runtime_put(hsic_host_dev);
+			info.in_lpm[HSIC_BAM] = true;
+		}
+	}
+
+	return 0;
 }
 
 static int hsic_cons_release_resource(void)
@@ -1034,7 +1062,7 @@
 	pr_debug("%s: Waiting for CONS\n", __func__);
 	if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_GRANTED) {
 		if (!wait_for_completion_timeout(&info.cons_avail[cur_bam],
-						USB_BAM_TIMEOUT*6))
+						USB_BAM_TIMEOUT))
 			pr_err("%s: Timeout wainting for CONS_REQUEST\n",
 			__func__);
 		pr_err("%s: Finished waiting for CONS\n", __func__);
@@ -1158,11 +1186,21 @@
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 	}
 
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	/* If cable was disconnected, let disconnection seq do everything */
+	if (info.disconnected) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_debug("%s: Cable disconnected\n", __func__);
+		return;
+	}
+
 	/* Don't go to LPM if data in the pipes */
 	if (!check_pipes_empty(src_idx, dst_idx)) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: pipes not empty, won't start suspend", __func__);
 		return;
 	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
 
 	queue_work(ctx.usb_bam_wq, &info.suspend_work);
 }
@@ -1173,9 +1211,18 @@
 	mutex_lock(&info.suspend_resume_mutex);
 
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	/* If cable was disconnected, let disconnection seq do everything */
+	if (info.disconnected) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		mutex_unlock(&info.suspend_resume_mutex);
+		pr_debug("%s: Cable disconnected\n", __func__);
+		return;
+	}
+
 	if (!info.bus_suspend) {
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Resume started, not suspending", __func__);
+		mutex_unlock(&info.suspend_resume_mutex);
 		return;
 	}
 
@@ -1286,6 +1333,9 @@
 
 void msm_bam_wait_for_hsic_prod_granted(void)
 {
+	if (hsic_host_dev_resumed_from_cons_request)
+		return;
+
 	ctx.is_bam_inactivity[HSIC_BAM] = false;
 
 	/* Get back to resume state including wakeup ipa */
@@ -1303,8 +1353,11 @@
 	 * and clocked on. Therefore we can now set the inactivity
 	 * timer to the hsic bam hw.
 	 */
-	if (ctx.inactivity_timer_ms[HSIC_BAM])
+	if (ctx.inactivity_timer_ms[HSIC_BAM] &&
+	    !hsic_host_dev_resumed_from_cons_request)
 		usb_bam_set_inactivity_timer(HSIC_BAM);
+
+	hsic_host_dev_resumed_from_cons_request = false;
 }
 
 bool msm_bam_hsic_lpm_ok(void)
@@ -1317,18 +1370,6 @@
 		pr_debug("%s: Starting hsic full suspend sequence\n",
 			__func__);
 
-		info.lpm_wait_handshake[HSIC_BAM] = true;
-
-		wait_for_prod_release(HSIC_BAM);
-		pr_debug("%s: complete wait on hsic producer s=%d\n",
-			__func__, info.cur_prod_state[HSIC_BAM]);
-
-		wait_for_cons_release(HSIC_BAM);
-		pr_debug("%s: complete wait on hsic consumer s=%d\n",
-			__func__, info.cur_cons_state[HSIC_BAM]);
-
-		info.lpm_wait_handshake[HSIC_BAM] = false;
-
 		/*
 		 * Start low power mode by releasing the device
 		 * only in case that indeed the resources were released
@@ -1338,9 +1379,6 @@
 		 */
 		spin_lock(&usb_bam_lock);
 
-		pr_debug("%s: goto lpm?, inactivity=%d\n",
-			__func__, ctx.is_bam_inactivity[HSIC_BAM]);
-
 		if (info.cur_cons_state[HSIC_BAM] ==
 			IPA_RM_RESOURCE_RELEASED &&
 		    info.cur_prod_state[HSIC_BAM] ==
@@ -1369,14 +1407,18 @@
 			return true;
 		}
 
-		/* We not allow lpm, therefore renew our vote here */
+		/* We don't allow lpm, therefore renew our vote here */
 		if (info.in_lpm[HSIC_BAM]) {
-			pr_debug("%s: Getting hsic device %x\n", __func__,
-			(int)hsic_host_dev);
+			pr_err("%s: Not allow lpm while ref count=0\n",
+				__func__);
+			pr_err("%s: inactivity=%d, c_s=%d p_s=%d lpm=%d\n",
+				__func__, ctx.is_bam_inactivity[HSIC_BAM],
+				info.cur_cons_state[HSIC_BAM],
+				info.cur_prod_state[HSIC_BAM],
+				info.in_lpm[HSIC_BAM]);
 			pm_runtime_get(hsic_host_dev);
 			info.in_lpm[HSIC_BAM] = false;
 			spin_unlock(&usb_bam_lock);
-			wait_for_prod_granted(HSIC_BAM, false);
 		} else
 			spin_unlock(&usb_bam_lock);
 
@@ -1431,6 +1473,7 @@
 			spin_lock(&usb_bam_ipa_handshake_info_lock);
 			info.lpm_wait_handshake[HSUSB_BAM] = true;
 			info.connect_complete = 0;
+			info.disconnected = 0;
 			info.lpm_wait_pipes = 1;
 			info.bus_suspend = 0;
 			info.cons_stopped = 0;
@@ -1623,21 +1666,28 @@
 		}
 		spin_unlock(&usb_bam_lock);
 
+		/* Notify about the inactivity to the USB class driver */
+		if (callback)
+			callback(param);
+
+		wait_for_prod_release(pipe_connect->bam_type);
+		pr_debug("%s: complete wait on hsic producer s=%d\n",
+			__func__, info.cur_prod_state[pipe_connect->bam_type]);
+
 		/*
-		 * Allow to go to lpm for now. Actual state will be checked
-		 * in msm_bam_hsic_lpm_ok() just before going to lpm.
+		 * Allow to go to lpm for now if also consumer is down.
+		 * If consumer is up, we will wait to the release consumer
+		 * notification.
 		 */
-		if (hsic_host_dev) {
+		if (hsic_host_dev &&
+		    info.cur_cons_state[HSIC_BAM] ==
+		    IPA_RM_RESOURCE_RELEASED && !info.in_lpm[HSIC_BAM]) {
 			pr_debug("%s: Putting hsic device %x\n", __func__,
 			(int)hsic_host_dev);
 			pm_runtime_put(hsic_host_dev);
 			info.in_lpm[HSIC_BAM] = true;
 		}
 
-		/* Notify about the inactivity to the USB class driver */
-		if (callback)
-			callback(param);
-
 		break;
 	default:
 		pr_err("%s: unknown usb bam event type %d\n", __func__,
@@ -1671,21 +1721,6 @@
 		 */
 		ctx.is_bam_inactivity[bam] = false;
 
-		/*
-		 * In case that this wakeup event occured while we are
-		 * waiting to release of the resurces in order to get into
-		 * low power mode, just cancle the waiting.
-		 */
-		if (info.lpm_wait_handshake[bam]) {
-			pr_debug("%s: cancel waiting for lpm\n", __func__);
-			if (info.cur_prod_state[bam] !=
-			    IPA_RM_RESOURCE_RELEASED)
-				complete_all(&info.prod_released[bam]);
-			if (info.cur_cons_state[bam] !=
-			    IPA_RM_RESOURCE_RELEASED)
-				complete_all(&info.cons_released[bam]);
-		}
-
 		queue_work(ctx.usb_bam_wq, &event_info->event_w);
 	}
 
@@ -1942,6 +1977,9 @@
 		/* Do the release handshake with the A2 via RM */
 		cur_bam = pipe_connect->bam_type;
 		info.lpm_wait_pipes = 1;
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		info.disconnected = 1;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		wait_for_prod_release(cur_bam);
 		/* close USB -> IPA pipe */
 		usb_bam_resume_core(cur_bam);
@@ -2004,8 +2042,8 @@
 				ipa_rm_resource_cons[cur_bam]);
 		}
 		pr_debug("%s Ended disconnect sequence\n", __func__);
-		mutex_unlock(&info.suspend_resume_mutex);
 		usb_bam_start_lpm(1);
+		mutex_unlock(&info.suspend_resume_mutex);
 		return 0;
 	}
 
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 9a642d6..03aa280 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -229,6 +229,7 @@
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_RESISTANCE,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 };
 
@@ -860,21 +861,23 @@
 }
 
 /**
- * calculate_cc-
+ * calculate_cc() - converts a hardware coulomb counter reading into uah
  * @chip:		the bms chip pointer
  * @cc:			the cc reading from bms h/w
- * @val:		return value
- * @coulomb_counter:	adjusted coulomb counter for 100%
+ * @clear_cc:		whether this function should clear the hardware counter
+ *			after reading
  *
- * RETURNS: in val pointer coulomb counter based charger in uAh
- *          (micro Amp hour)
+ * Converts the 64 bit hardware coulomb counter into microamp-hour by taking
+ * into account hardware resolution and adc errors.
+ *
+ * Return: the coulomb counter based charge in uAh (micro-amp hour)
  */
-static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc)
+static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc, bool clear_cc)
 {
 	struct qpnp_iadc_calib calibration;
 	struct qpnp_vadc_result result;
 	int64_t cc_voltage_uv, cc_pvh, cc_uah;
-	int ibat_ua, rc;
+	int rc;
 
 	rc = qpnp_vadc_read(DIE_TEMP, &result);
 	if (rc) {
@@ -882,12 +885,6 @@
 		return chip->software_cc_uah;
 	}
 
-	rc = get_battery_current(chip, &ibat_ua);
-	if (rc) {
-		pr_err("could not read battery current: %d\n", rc);
-		return chip->software_cc_uah;
-	}
-
 	qpnp_iadc_get_gain_and_offset(&calibration);
 	pr_debug("cc = %lld, die_temp = %lld\n", cc, result.physical);
 	cc_voltage_uv = cc_reading_to_uv(cc);
@@ -901,9 +898,14 @@
 	rc = qpnp_iadc_comp_result(&cc_uah);
 	if (rc)
 		pr_debug("error compensation failed: %d\n", rc);
-	chip->software_cc_uah += cc_uah;
-	reset_cc(chip);
-	return (int)chip->software_cc_uah;
+
+	if (clear_cc) {
+		chip->software_cc_uah += cc_uah;
+		reset_cc(chip);
+		return (int)chip->software_cc_uah;
+	} else {
+		return chip->software_cc_uah + cc_uah;
+	}
 }
 
 static int get_rbatt(struct qpnp_bms_chip *chip,
@@ -1232,7 +1234,7 @@
 	pr_debug("ocv_charge_uah = %uuAh\n", params->ocv_charge_uah);
 
 	/* calculate cc micro_volt_hour */
-	params->cc_uah = calculate_cc(chip, raw->cc);
+	params->cc_uah = calculate_cc(chip, raw->cc, true);
 	pr_debug("cc_uah = %duAh raw->cc = %llx\n", params->cc_uah, raw->cc);
 
 	soc_rbatt = ((params->ocv_charge_uah - params->cc_uah) * 100)
@@ -1242,10 +1244,10 @@
 	params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
 	pr_debug("rbatt_mohm = %d\n", params->rbatt_mohm);
 
-	if (params->rbatt_mohm != chip->rbatt_mohm
-			&& chip->bms_psy.name != NULL) {
+	if (params->rbatt_mohm != chip->rbatt_mohm) {
 		chip->rbatt_mohm = params->rbatt_mohm;
-		power_supply_changed(&chip->bms_psy);
+		if (chip->bms_psy.name != NULL)
+			power_supply_changed(&chip->bms_psy);
 	}
 
 	calculate_iavg(chip, params->cc_uah, &params->iavg_ua,
@@ -1359,12 +1361,200 @@
 
 module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
 
+static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
+				int soc)
+{
+	u8 temp;
+	int rc;
+	int iavg_ma = chip->prev_uuc_iavg_ma;
+
+	if (iavg_ma > IAVG_START)
+		temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
+	else
+		temp = 0;
+
+	rc = qpnp_write_wrapper(chip, &temp,
+			chip->base + IAVG_STORAGE_REG, 1);
+
+	temp = soc;
+
+	/* don't store soc if temperature is below 5degC */
+	if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
+		rc = qpnp_write_wrapper(chip, &temp,
+				chip->base + SOC_STORAGE_REG, 1);
+}
+
+static int scale_soc_while_chg(struct qpnp_bms_chip *chip, int chg_time_sec,
+				int catch_up_sec, int new_soc, int prev_soc)
+{
+	int scaled_soc;
+	int numerator;
+
+	/*
+	 * Don't report a high value immediately slowly scale the
+	 * value from prev_soc to the new soc based on a charge time
+	 * weighted average
+	 */
+	pr_debug("cts = %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
+	if (catch_up_sec == 0)
+		return new_soc;
+
+	if (chg_time_sec > catch_up_sec)
+		return new_soc;
+
+	numerator = (catch_up_sec - chg_time_sec) * prev_soc
+			+ chg_time_sec * new_soc;
+	scaled_soc = numerator / catch_up_sec;
+
+	pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
+			chg_time_sec, new_soc, prev_soc, scaled_soc);
+
+	return scaled_soc;
+}
+
+/*
+ * bms_fake_battery is set in setups where a battery emulator is used instead
+ * of a real battery. This makes the bms driver report a different/fake value
+ * regardless of the calculated state of charge.
+ */
+static int bms_fake_battery = -EINVAL;
+module_param(bms_fake_battery, int, 0644);
+
+static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
+{
+	pr_debug("Reported voltage based soc = %d\n",
+			chip->prev_voltage_based_soc);
+	return chip->prev_voltage_based_soc;
+}
+
+#define SOC_CATCHUP_SEC_MAX		600
+#define SOC_CATCHUP_SEC_PER_PERCENT	60
+#define MAX_CATCHUP_SOC	(SOC_CATCHUP_SEC_MAX / SOC_CATCHUP_SEC_PER_PERCENT)
+#define SOC_CHANGE_PER_SEC	20
+static int report_cc_based_soc(struct qpnp_bms_chip *chip)
+{
+	int soc, soc_change;
+	int time_since_last_change_sec, charge_time_sec = 0;
+	unsigned long last_change_sec;
+	struct timespec now;
+	struct qpnp_vadc_result result;
+	int batt_temp;
+	int rc;
+	bool charging, charging_since_last_report;
+
+	soc = chip->calculated_soc;
+
+	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
+
+	if (rc) {
+		pr_err("error reading adc channel = %d, rc = %d\n",
+					LR_MUX1_BATT_THERM, rc);
+		return rc;
+	}
+	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
+						result.measurement);
+	batt_temp = (int)result.physical;
+
+	mutex_lock(&chip->last_soc_mutex);
+	last_change_sec = chip->last_soc_change_sec;
+	calculate_delta_time(&last_change_sec, &time_since_last_change_sec);
+
+	charging = is_battery_charging(chip);
+	charging_since_last_report = charging || (chip->last_soc_unbound
+			&& chip->was_charging_at_sleep);
+	/*
+	 * account for charge time - limit it to SOC_CATCHUP_SEC to
+	 * avoid overflows when charging continues for extended periods
+	 */
+	if (charging) {
+		if (chip->charge_start_tm_sec == 0) {
+			/*
+			 * calculating soc for the first time
+			 * after start of chg. Initialize catchup time
+			 */
+			if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
+				chip->catch_up_time_sec =
+				(soc - chip->last_soc)
+					* SOC_CATCHUP_SEC_PER_PERCENT;
+			else
+				chip->catch_up_time_sec = SOC_CATCHUP_SEC_MAX;
+
+			if (chip->catch_up_time_sec < 0)
+				chip->catch_up_time_sec = 0;
+			chip->charge_start_tm_sec = last_change_sec;
+		}
+
+		charge_time_sec = min(SOC_CATCHUP_SEC_MAX, (int)last_change_sec
+				- chip->charge_start_tm_sec);
+
+		/* end catchup if calculated soc and last soc are same */
+		if (chip->last_soc == soc)
+			chip->catch_up_time_sec = 0;
+	}
+
+	if (chip->last_soc != -EINVAL) {
+		/*
+		 * last_soc < soc  ... if we have not been charging at all
+		 * since the last time this was called, report previous SoC.
+		 * Otherwise, scale and catch up.
+		 */
+		if (chip->last_soc < soc && !charging_since_last_report)
+			soc = chip->last_soc;
+		else if (chip->last_soc < soc && soc != 100)
+			soc = scale_soc_while_chg(chip, charge_time_sec,
+					chip->catch_up_time_sec,
+					soc, chip->last_soc);
+
+		soc_change = min((int)abs(chip->last_soc - soc),
+			time_since_last_change_sec / SOC_CHANGE_PER_SEC);
+		if (chip->last_soc_unbound) {
+			chip->last_soc_unbound = false;
+		} else {
+			/*
+			 * if soc have not been unbound by resume,
+			 * only change reported SoC by 1.
+			 */
+			soc_change = min(1, soc_change);
+		}
+
+		if (soc < chip->last_soc && soc != 0)
+			soc = chip->last_soc - soc_change;
+		if (soc > chip->last_soc && soc != 100)
+			soc = chip->last_soc + soc_change;
+	}
+
+	if (chip->last_soc != soc)
+		chip->last_soc_change_sec = last_change_sec;
+
+	pr_debug("last_soc = %d, calculated_soc = %d, soc = %d, time since last change = %d\n",
+			chip->last_soc, chip->calculated_soc,
+			soc, time_since_last_change_sec);
+	chip->last_soc = bound_soc(soc);
+	backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
+	pr_debug("Reported SOC = %d\n", chip->last_soc);
+	chip->t_soc_queried = now;
+	mutex_unlock(&chip->last_soc_mutex);
+
+	return soc;
+}
+
+static int report_state_of_charge(struct qpnp_bms_chip *chip)
+{
+	if (bms_fake_battery != -EINVAL) {
+		pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
+		return bms_fake_battery;
+	} else if (chip->use_voltage_soc)
+		return report_voltage_based_soc(chip);
+	else
+		return report_cc_based_soc(chip);
+}
+
 #define VBATT_ERROR_MARGIN	20000
 static int charging_adjustments(struct qpnp_bms_chip *chip,
 				struct soc_params *params, int soc,
 				int vbat_uv, int ibat_ua, int batt_temp)
 {
-	int chg_soc, batt_terminal_uv;
+	int chg_soc, soc_ibat, batt_terminal_uv, weight_ibat, weight_cc;
 
 	batt_terminal_uv = vbat_uv + VBATT_ERROR_MARGIN
 				+ (ibat_ua * chip->r_conn_mohm) / 1000;
@@ -1402,10 +1592,16 @@
 		return chip->prev_chg_soc;
 	}
 
-	chg_soc = linear_interpolate(chip->soc_at_cv, chip->ibat_at_cv_ua,
+	soc_ibat = bound_soc(linear_interpolate(chip->soc_at_cv,
+					chip->ibat_at_cv_ua,
 					100, -1 * chip->chg_term_ua,
-					ibat_ua);
-	chg_soc = bound_soc(chg_soc);
+					ibat_ua));
+	weight_ibat = bound_soc(linear_interpolate(1, chip->soc_at_cv,
+					100, 100, chip->prev_chg_soc));
+	weight_cc = 100 - weight_ibat;
+	chg_soc = bound_soc((soc_ibat * weight_ibat + weight_cc * soc)/100);
+	pr_debug("weight_ibat = %d, weight_cc = %d, soc_ibat = %d, soc_cc = %d\n",
+			weight_ibat, weight_cc, soc_ibat, soc);
 
 	/* always report a higher soc */
 	if (chg_soc > chip->prev_chg_soc) {
@@ -1736,12 +1932,6 @@
 					new_calculated_soc);
 
 done_calculating:
-	if (new_calculated_soc != chip->calculated_soc
-			&& chip->bms_psy.name != NULL) {
-		power_supply_changed(&chip->bms_psy);
-		pr_debug("power supply changed\n");
-	}
-
 	chip->calculated_soc = new_calculated_soc;
 	pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
 	mutex_lock(&chip->last_soc_mutex);
@@ -1765,6 +1955,20 @@
 				params.delta_time_s);
 	}
 	mutex_unlock(&chip->last_soc_mutex);
+
+	if (new_calculated_soc != chip->calculated_soc
+			&& chip->bms_psy.name != NULL) {
+		power_supply_changed(&chip->bms_psy);
+		pr_debug("power supply changed\n");
+	} else {
+		/*
+		 * Call report state of charge anyways to periodically update
+		 * reported SoC. This prevents reported SoC from being stuck
+		 * when calculated soc doesn't change.
+		 */
+		report_state_of_charge(chip);
+	}
+
 	get_current_time(&chip->last_recalc_time);
 	chip->first_time_calc_soc = 0;
 	return chip->calculated_soc;
@@ -1861,196 +2065,6 @@
 			(chip->calculate_soc_ms)));
 }
 
-static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
-				int soc)
-{
-	u8 temp;
-	int rc;
-	int iavg_ma = chip->prev_uuc_iavg_ma;
-
-	if (iavg_ma > IAVG_START)
-		temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
-	else
-		temp = 0;
-
-	rc = qpnp_write_wrapper(chip, &temp,
-			chip->base + IAVG_STORAGE_REG, 1);
-
-	temp = soc;
-
-	/* don't store soc if temperature is below 5degC */
-	if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
-		rc = qpnp_write_wrapper(chip, &temp,
-				chip->base + SOC_STORAGE_REG, 1);
-}
-
-#define SOC_CATCHUP_SEC_MAX		600
-#define SOC_CATCHUP_SEC_PER_PERCENT	60
-#define MAX_CATCHUP_SOC	(SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
-static int scale_soc_while_chg(struct qpnp_bms_chip *chip, int chg_time_sec,
-				int catch_up_sec, int new_soc, int prev_soc)
-{
-	int scaled_soc;
-	int numerator;
-
-	/*
-	 * Don't report a high value immediately slowly scale the
-	 * value from prev_soc to the new soc based on a charge time
-	 * weighted average
-	 */
-	pr_debug("cts = %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
-	if (catch_up_sec == 0)
-		return new_soc;
-	/*
-	 * if charging for more than catch_up time, simply return
-	 * new soc
-	 */
-	if (chg_time_sec > catch_up_sec)
-		return new_soc;
-
-	numerator = (catch_up_sec - chg_time_sec) * prev_soc
-			+ chg_time_sec * new_soc;
-	scaled_soc = numerator / catch_up_sec;
-
-	pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
-			chg_time_sec, new_soc, prev_soc, scaled_soc);
-
-	return scaled_soc;
-}
-
-/*
- * bms_fake_battery is set in setups where a battery emulator is used instead
- * of a real battery. This makes the bms driver report a different/fake value
- * regardless of the calculated state of charge.
- */
-static int bms_fake_battery = -EINVAL;
-module_param(bms_fake_battery, int, 0644);
-
-static int report_voltage_based_soc(struct qpnp_bms_chip *chip)
-{
-	pr_debug("Reported voltage based soc = %d\n",
-			chip->prev_voltage_based_soc);
-	return chip->prev_voltage_based_soc;
-}
-
-#define SOC_CHANGE_PER_SEC	20
-static int report_cc_based_soc(struct qpnp_bms_chip *chip)
-{
-	int soc, soc_change;
-	int time_since_last_change_sec, charge_time_sec = 0;
-	unsigned long last_change_sec;
-	struct timespec now;
-	struct qpnp_vadc_result result;
-	int batt_temp;
-	int rc;
-	bool charging, charging_since_last_report;
-
-	soc = chip->calculated_soc;
-
-	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
-
-	if (rc) {
-		pr_err("error reading adc channel = %d, rc = %d\n",
-					LR_MUX1_BATT_THERM, rc);
-		return rc;
-	}
-	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
-						result.measurement);
-	batt_temp = (int)result.physical;
-
-	mutex_lock(&chip->last_soc_mutex);
-	last_change_sec = chip->last_soc_change_sec;
-	calculate_delta_time(&last_change_sec, &time_since_last_change_sec);
-
-	charging = is_battery_charging(chip);
-	charging_since_last_report = charging || (chip->last_soc_unbound
-			&& chip->was_charging_at_sleep);
-	/*
-	 * account for charge time - limit it to SOC_CATCHUP_SEC to
-	 * avoid overflows when charging continues for extended periods
-	 */
-	if (charging) {
-		if (chip->charge_start_tm_sec == 0) {
-			/*
-			 * calculating soc for the first time
-			 * after start of chg. Initialize catchup time
-			 */
-			if (abs(soc - chip->last_soc) < MAX_CATCHUP_SOC)
-				chip->catch_up_time_sec =
-				(soc - chip->last_soc)
-					* SOC_CATCHUP_SEC_PER_PERCENT;
-			else
-				chip->catch_up_time_sec = SOC_CATCHUP_SEC_MAX;
-
-			if (chip->catch_up_time_sec < 0)
-				chip->catch_up_time_sec = 0;
-			chip->charge_start_tm_sec = last_change_sec;
-		}
-
-		charge_time_sec = min(SOC_CATCHUP_SEC_MAX, (int)last_change_sec
-				- chip->charge_start_tm_sec);
-
-		/* end catchup if calculated soc and last soc are same */
-		if (chip->last_soc == soc)
-			chip->catch_up_time_sec = 0;
-	}
-
-	if (chip->last_soc != -EINVAL) {
-		/* last_soc < soc  ... if we have not been charging at all
-		 * since the last time this was called, report previous SoC.
-		 * Otherwise, scale and catch up.
-		 */
-		if (chip->last_soc < soc && !charging_since_last_report)
-			soc = chip->last_soc;
-		else if (chip->last_soc < soc && soc != 100)
-			soc = scale_soc_while_chg(chip, charge_time_sec,
-					chip->catch_up_time_sec,
-					soc, chip->last_soc);
-
-		soc_change = min((int)abs(chip->last_soc - soc),
-			time_since_last_change_sec / SOC_CHANGE_PER_SEC);
-		if (chip->last_soc_unbound) {
-			chip->last_soc_unbound = false;
-		} else {
-			/*
-			 * if soc have not been unbound by resume,
-			 * only change reported SoC by 1.
-			 */
-			soc_change = min(1, soc_change);
-		}
-
-		if (soc < chip->last_soc && soc != 0)
-			soc = chip->last_soc - soc_change;
-		if (soc > chip->last_soc && soc != 100)
-			soc = chip->last_soc + soc_change;
-	}
-
-	if (chip->last_soc != soc)
-		chip->last_soc_change_sec = last_change_sec;
-
-	pr_debug("last_soc = %d, calculated_soc = %d, soc = %d, time since last change = %d\n",
-			chip->last_soc, chip->calculated_soc,
-			soc, time_since_last_change_sec);
-	chip->last_soc = bound_soc(soc);
-	backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
-	pr_debug("Reported SOC = %d\n", chip->last_soc);
-	chip->t_soc_queried = now;
-	mutex_unlock(&chip->last_soc_mutex);
-
-	return soc;
-}
-
-static int report_state_of_charge(struct qpnp_bms_chip *chip)
-{
-	if (bms_fake_battery != -EINVAL) {
-		pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
-		return bms_fake_battery;
-	} else if (chip->use_voltage_soc)
-		return report_voltage_based_soc(chip);
-	else
-		return report_cc_based_soc(chip);
-}
-
 static void configure_vbat_monitor_low(struct qpnp_bms_chip *chip)
 {
 	mutex_lock(&chip->vbat_monitor_mutex);
@@ -2269,8 +2283,10 @@
 	mutex_lock(&chip->last_ocv_uv_mutex);
 	chip->soc_at_cv = -EINVAL;
 	chip->prev_chg_soc = -EINVAL;
-	if (get_battery_status(chip) == POWER_SUPPLY_STATUS_FULL)
+	if (get_battery_status(chip) == POWER_SUPPLY_STATUS_FULL) {
 		chip->done_charging = true;
+		chip->last_soc_invalid = true;
+	}
 	mutex_unlock(&chip->last_ocv_uv_mutex);
 }
 
@@ -2341,6 +2357,20 @@
 	return result_ua;
 }
 
+/* Returns coulomb counter in uAh */
+static int get_prop_bms_charge_counter(struct qpnp_bms_chip *chip)
+{
+	int64_t cc_raw;
+
+	mutex_lock(&chip->bms_output_lock);
+	lock_output_data(chip);
+	read_cc_raw(chip, &cc_raw);
+	unlock_output_data(chip);
+	mutex_unlock(&chip->bms_output_lock);
+
+	return calculate_cc(chip, cc_raw, false);
+}
+
 /* Returns full charge design in uAh */
 static int get_prop_bms_charge_full_design(struct qpnp_bms_chip *chip)
 {
@@ -2373,6 +2403,9 @@
 	case POWER_SUPPLY_PROP_RESISTANCE:
 		val->intval = get_prop_bms_batt_resistance(chip);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+		val->intval = get_prop_bms_charge_counter(chip);
+		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_bms_charge_full_design(chip);
 		break;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 24825ea..a5da421 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -25,6 +25,9 @@
 #include <linux/power_supply.h>
 #include <linux/bitops.h>
 #include <linux/ratelimit.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
 
 /* Interrupt offsets */
 #define INT_RT_STS(base)			(base + 0x10)
@@ -92,8 +95,12 @@
 #define SEC_ACCESS				0xD0
 #define BAT_IF_VREF_BAT_THM_CTRL		0x4A
 #define BAT_IF_BPD_CTRL				0x48
+#define BOOST_VSET				0x41
+#define BOOST_ENABLE_CONTROL			0x46
+#define COMP_OVR1				0xEA
 
 #define REG_OFFSET_PERP_SUBTYPE			0x05
+
 /* SMBB peripheral subtype values */
 #define SMBB_CHGR_SUBTYPE			0x01
 #define SMBB_BUCK_SUBTYPE			0x02
@@ -132,6 +139,7 @@
 #define REV_BST_DETECTED		BIT(0)
 #define BAT_THM_EN			BIT(1)
 #define BAT_ID_EN			BIT(0)
+#define BOOST_PWR_EN			BIT(7)
 
 /* Interrupt definitions */
 /* smbb_chg_interrupts */
@@ -183,12 +191,18 @@
 
 /* Workaround flags */
 #define CHG_FLAGS_VCP_WA		BIT(0)
+#define BOOST_FLASH_WA			BIT(1)
 
 struct qpnp_chg_irq {
 	unsigned int		irq;
 	unsigned long		disabled;
 };
 
+struct qpnp_chg_regulator {
+	struct regulator_desc			rdesc;
+	struct regulator_dev			*rdev;
+};
+
 /**
  * struct qpnp_chg_chip - device information
  * @dev:			device pointer to access the parent
@@ -263,6 +277,7 @@
 	bool				batt_present;
 	bool				charging_disabled;
 	bool				use_default_batt_values;
+	bool				duty_cycle_100p;
 	unsigned int			bpd_detection;
 	unsigned int			max_bat_chg_current;
 	unsigned int			warm_bat_chg_ma;
@@ -295,6 +310,8 @@
 	struct delayed_work		arb_stop_work;
 	struct delayed_work		eoc_work;
 	struct wake_lock		eoc_wake_lock;
+	struct qpnp_chg_regulator	otg_vreg;
+	struct qpnp_chg_regulator	boost_vreg;
 };
 
 
@@ -425,6 +442,25 @@
 }
 
 static int
+qpnp_chg_is_boost_en_set(struct qpnp_chg_chip *chip)
+{
+	u8 boost_en_ctl;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &boost_en_ctl,
+		chip->boost_base + BOOST_ENABLE_CONTROL, 1);
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+				chip->boost_base + BOOST_ENABLE_CONTROL, rc);
+		return rc;
+	}
+
+	pr_debug("boost en 0x%x\n", boost_en_ctl);
+
+	return (boost_en_ctl & BOOST_PWR_EN) ? 1 : 0;
+}
+
+static int
 qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
 {
 	u8 batt_pres_rt_sts;
@@ -610,6 +646,32 @@
 			disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
 }
 
+#define BUCK_DUTY_MASK_100P	0x30
+static int
+qpnp_buck_set_100_duty_cycle_enable(struct qpnp_chg_chip *chip, int enable)
+{
+	int rc;
+
+	pr_debug("enable: %d\n", enable);
+
+	rc = qpnp_chg_masked_write(chip,
+		chip->buck_base + SEC_ACCESS, 0xA5, 0xA5, 1);
+	if (rc) {
+		pr_debug("failed to write sec access rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_chg_masked_write(chip,
+		chip->buck_base + BUCK_TEST_SMBC_MODES,
+			BUCK_DUTY_MASK_100P, enable ? 0x00 : 0x10, 1);
+	if (rc) {
+		pr_debug("failed enable 100p duty cycle rc=%d\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
 #define COMPATATOR_OVERRIDE_0	0x80
 static int
 qpnp_chg_toggle_chg_done_logic(struct qpnp_chg_chip *chip, int enable)
@@ -1215,21 +1277,6 @@
 		chip->bms_psy = power_supply_get_by_name("bms");
 
 	chip->usb_psy->get_property(chip->usb_psy,
-			  POWER_SUPPLY_PROP_SCOPE, &ret);
-	if (ret.intval) {
-		if ((ret.intval == POWER_SUPPLY_SCOPE_SYSTEM)
-				&& !qpnp_chg_is_otg_en_set(chip)) {
-			switch_usb_to_host_mode(chip);
-			return;
-		}
-		if ((ret.intval == POWER_SUPPLY_SCOPE_DEVICE)
-				&& qpnp_chg_is_otg_en_set(chip)) {
-			switch_usb_to_charge_mode(chip);
-			return;
-		}
-	}
-
-	chip->usb_psy->get_property(chip->usb_psy,
 			  POWER_SUPPLY_PROP_ONLINE, &ret);
 
 	/* Only honour requests while USB is present */
@@ -1457,6 +1504,48 @@
 	return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
 }
 
+#define BOOST_MIN_UV	4200000
+#define BOOST_MAX_UV	5500000
+#define BOOST_STEP_UV	50000
+#define BOOST_MIN	16
+#define N_BOOST_V	((BOOST_MAX_UV - BOOST_MIN_UV) / BOOST_STEP_UV + 1)
+static int
+qpnp_boost_vset(struct qpnp_chg_chip *chip, int voltage)
+{
+	u8 reg = 0;
+
+	if (voltage < BOOST_MIN_UV || voltage > BOOST_MAX_UV) {
+		pr_err("invalid voltage requested %d uV\n", voltage);
+		return -EINVAL;
+	}
+
+	reg = DIV_ROUND_UP(voltage - BOOST_MIN_UV, BOOST_STEP_UV) + BOOST_MIN;
+
+	pr_debug("voltage=%d setting %02x\n", voltage, reg);
+	return qpnp_chg_write(chip, &reg, chip->boost_base + BOOST_VSET, 1);
+}
+
+static int
+qpnp_boost_vget_uv(struct qpnp_chg_chip *chip)
+{
+	int rc;
+	u8 boost_reg;
+
+	rc = qpnp_chg_read(chip, &boost_reg,
+		 chip->boost_base + BOOST_VSET, 1);
+	if (rc) {
+		pr_err("failed to read BOOST_VSET rc=%d\n", rc);
+		return rc;
+	}
+
+	if (boost_reg < BOOST_MIN) {
+		pr_err("Invalid reading from 0x%x\n", boost_reg);
+		return -EINVAL;
+	}
+
+	return BOOST_MIN_UV + ((boost_reg - BOOST_MIN) * BOOST_STEP_UV);
+}
+
 /* JEITA compliance logic */
 static void
 qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
@@ -1519,6 +1608,228 @@
 	}
 }
 
+/* OTG regulator operations */
+static int
+qpnp_chg_regulator_otg_enable(struct regulator_dev *rdev)
+{
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+	return switch_usb_to_host_mode(chip);
+}
+
+static int
+qpnp_chg_regulator_otg_disable(struct regulator_dev *rdev)
+{
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+	return switch_usb_to_charge_mode(chip);
+}
+
+static int
+qpnp_chg_regulator_otg_is_enabled(struct regulator_dev *rdev)
+{
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+	return qpnp_chg_is_otg_en_set(chip);
+}
+
+static int
+qpnp_chg_regulator_boost_enable(struct regulator_dev *rdev)
+{
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+	int rc;
+
+	if (qpnp_chg_is_usb_chg_plugged_in(chip) &&
+			(chip->flags & BOOST_FLASH_WA)) {
+		qpnp_chg_usb_suspend_enable(chip, 1);
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->usb_chgpth_base + SEC_ACCESS,
+			0xFF,
+			0xA5, 1);
+		if (rc) {
+			pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->usb_chgpth_base + COMP_OVR1,
+			0xFF,
+			0x2F, 1);
+		if (rc) {
+			pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	return qpnp_chg_masked_write(chip,
+		chip->boost_base + BOOST_ENABLE_CONTROL,
+		BOOST_PWR_EN,
+		BOOST_PWR_EN, 1);
+}
+
+/* Boost regulator operations */
+#define ABOVE_VBAT_WEAK		BIT(1)
+static int
+qpnp_chg_regulator_boost_disable(struct regulator_dev *rdev)
+{
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+	int rc;
+	u8 vbat_sts;
+
+	rc = qpnp_chg_masked_write(chip,
+		chip->boost_base + BOOST_ENABLE_CONTROL,
+		BOOST_PWR_EN,
+		0, 1);
+	if (rc) {
+		pr_err("failed to disable boost rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_chg_read(chip, &vbat_sts,
+			chip->chgr_base + CHGR_VBAT_STATUS, 1);
+	if (rc) {
+		pr_err("failed to read bat sts rc=%d\n", rc);
+		return rc;
+	}
+
+	if (!(vbat_sts & ABOVE_VBAT_WEAK) && (chip->flags & BOOST_FLASH_WA)) {
+		rc = qpnp_chg_masked_write(chip,
+			chip->chgr_base + SEC_ACCESS,
+			0xFF,
+			0xA5, 1);
+		if (rc) {
+			pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->chgr_base + COMP_OVR1,
+			0xFF,
+			0x20, 1);
+		if (rc) {
+			pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+			return rc;
+		}
+
+		usleep(2000);
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->chgr_base + SEC_ACCESS,
+			0xFF,
+			0xA5, 1);
+		if (rc) {
+			pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->chgr_base + COMP_OVR1,
+			0xFF,
+			0x00, 1);
+		if (rc) {
+			pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	if (qpnp_chg_is_usb_chg_plugged_in(chip)
+			&& (chip->flags & BOOST_FLASH_WA)) {
+		rc = qpnp_chg_masked_write(chip,
+			chip->usb_chgpth_base + SEC_ACCESS,
+			0xFF,
+			0xA5, 1);
+		if (rc) {
+			pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->usb_chgpth_base + COMP_OVR1,
+			0xFF,
+			0x00, 1);
+		if (rc) {
+			pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+			return rc;
+		}
+
+		usleep(1000);
+
+		qpnp_chg_usb_suspend_enable(chip, 0);
+	}
+
+	return rc;
+}
+
+static int
+qpnp_chg_regulator_boost_is_enabled(struct regulator_dev *rdev)
+{
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+	return qpnp_chg_is_boost_en_set(chip);
+}
+
+static int
+qpnp_chg_regulator_boost_set_voltage(struct regulator_dev *rdev,
+		int min_uV, int max_uV, unsigned *selector)
+{
+	int uV = min_uV;
+	int rc;
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+	if (uV < BOOST_MIN_UV && max_uV >= BOOST_MIN_UV)
+		uV = BOOST_MIN_UV;
+
+
+	if (uV < BOOST_MIN_UV || uV > BOOST_MAX_UV) {
+		pr_err("request %d uV is out of bounds\n", uV);
+		return -EINVAL;
+	}
+
+	*selector = DIV_ROUND_UP(uV - BOOST_MIN_UV, BOOST_STEP_UV);
+	if ((*selector * BOOST_STEP_UV + BOOST_MIN_UV) > max_uV) {
+		pr_err("no available setpoint [%d, %d] uV\n", min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	rc = qpnp_boost_vset(chip, uV);
+
+	return rc;
+}
+
+static int
+qpnp_chg_regulator_boost_get_voltage(struct regulator_dev *rdev)
+{
+	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
+
+	return qpnp_boost_vget_uv(chip);
+}
+
+static int
+qpnp_chg_regulator_boost_list_voltage(struct regulator_dev *rdev,
+			unsigned selector)
+{
+	if (selector >= N_BOOST_V)
+		return 0;
+
+	return BOOST_MIN_UV + (selector * BOOST_STEP_UV);
+}
+
+static struct regulator_ops qpnp_chg_otg_reg_ops = {
+	.enable			= qpnp_chg_regulator_otg_enable,
+	.disable		= qpnp_chg_regulator_otg_disable,
+	.is_enabled		= qpnp_chg_regulator_otg_is_enabled,
+};
+
+static struct regulator_ops qpnp_chg_boost_reg_ops = {
+	.enable			= qpnp_chg_regulator_boost_enable,
+	.disable		= qpnp_chg_regulator_boost_disable,
+	.is_enabled		= qpnp_chg_regulator_boost_is_enabled,
+	.set_voltage		= qpnp_chg_regulator_boost_set_voltage,
+	.get_voltage		= qpnp_chg_regulator_boost_get_voltage,
+	.list_voltage		= qpnp_chg_regulator_boost_list_voltage,
+};
+
 #define CONSECUTIVE_COUNT	3
 static void
 qpnp_eoc_work(struct work_struct *work)
@@ -1705,6 +2016,8 @@
 {
 	if (chip->revision > 0 && chip->type == SMBB)
 		chip->flags |= CHG_FLAGS_VCP_WA;
+	if (chip->type == SMBB)
+		chip->flags |= BOOST_FLASH_WA;
 }
 
 static int
@@ -1906,6 +2219,8 @@
 {
 	int rc = 0;
 	u8 reg = 0;
+	struct regulator_init_data *init_data;
+	struct regulator_desc *rdesc;
 
 	switch (subtype) {
 	case SMBB_CHGR_SUBTYPE:
@@ -2022,6 +2337,38 @@
 			}
 		}
 
+		init_data = of_get_regulator_init_data(chip->dev,
+						       spmi_resource->of_node);
+		if (!init_data) {
+			pr_err("unable to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		if (init_data->constraints.name) {
+			if (of_get_property(chip->dev->of_node,
+						"otg-parent-supply", NULL))
+				init_data->supply_regulator = "otg-parent";
+
+			rdesc			= &(chip->otg_vreg.rdesc);
+			rdesc->owner		= THIS_MODULE;
+			rdesc->type		= REGULATOR_VOLTAGE;
+			rdesc->ops		= &qpnp_chg_otg_reg_ops;
+			rdesc->name		= init_data->constraints.name;
+
+			init_data->constraints.valid_ops_mask
+				|= REGULATOR_CHANGE_STATUS;
+
+			chip->otg_vreg.rdev = regulator_register(rdesc,
+					chip->dev, init_data, chip,
+					spmi_resource->of_node);
+			if (IS_ERR(chip->otg_vreg.rdev)) {
+				rc = PTR_ERR(chip->otg_vreg.rdev);
+				if (rc != -EPROBE_DEFER)
+					pr_err("OTG reg failed, rc=%d\n", rc);
+				return rc;
+			}
+		}
+
 		rc = qpnp_chg_masked_write(chip,
 			chip->usb_chgpth_base + USB_OVP_CTL,
 			USB_VALID_DEB_20MS,
@@ -2047,6 +2394,38 @@
 		break;
 	case SMBB_BOOST_SUBTYPE:
 	case SMBBP_BOOST_SUBTYPE:
+		init_data = of_get_regulator_init_data(chip->dev,
+					       spmi_resource->of_node);
+		if (!init_data) {
+			pr_err("unable to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		if (init_data->constraints.name) {
+			if (of_get_property(chip->dev->of_node,
+						"boost-parent-supply", NULL))
+				init_data->supply_regulator = "boost-parent";
+
+			rdesc			= &(chip->boost_vreg.rdesc);
+			rdesc->owner		= THIS_MODULE;
+			rdesc->type		= REGULATOR_VOLTAGE;
+			rdesc->ops		= &qpnp_chg_boost_reg_ops;
+			rdesc->name		= init_data->constraints.name;
+
+			init_data->constraints.valid_ops_mask
+				|= REGULATOR_CHANGE_STATUS
+					| REGULATOR_CHANGE_VOLTAGE;
+
+			chip->boost_vreg.rdev = regulator_register(rdesc,
+					chip->dev, init_data, chip,
+					spmi_resource->of_node);
+			if (IS_ERR(chip->boost_vreg.rdev)) {
+				rc = PTR_ERR(chip->boost_vreg.rdev);
+				if (rc != -EPROBE_DEFER)
+					pr_err("boost reg failed, rc=%d\n", rc);
+				return rc;
+			}
+		}
 		break;
 	case SMBB_MISC_SUBTYPE:
 	case SMBBP_MISC_SUBTYPE:
@@ -2149,6 +2528,18 @@
 	chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
 					"qcom,charging-disabled");
 
+	/* Get the duty-cycle-100p property */
+	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 =
 			of_property_read_bool(chip->spmi->dev.of_node,
@@ -2298,7 +2689,8 @@
 			chip->usb_chgpth_base = resource->start;
 			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
 			if (rc) {
-				pr_err("Failed to init subtype 0x%x rc=%d\n",
+				if (rc != -EPROBE_DEFER)
+					pr_err("Failed to init subtype 0x%x rc=%d\n",
 						subtype, rc);
 				goto fail_chg_enable;
 			}
@@ -2317,7 +2709,8 @@
 			chip->boost_base = resource->start;
 			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
 			if (rc) {
-				pr_err("Failed to init subtype 0x%x rc=%d\n",
+				if (rc != -EPROBE_DEFER)
+					pr_err("Failed to init subtype 0x%x rc=%d\n",
 						subtype, rc);
 				goto fail_chg_enable;
 			}
@@ -2470,6 +2863,12 @@
 	cancel_work_sync(&chip->adc_measure_work);
 	cancel_delayed_work_sync(&chip->eoc_work);
 
+	if (chip->otg_vreg.rdev)
+		regulator_unregister(chip->otg_vreg.rdev);
+
+	if (chip->boost_vreg.rdev)
+		regulator_unregister(chip->boost_vreg.rdev);
+
 	dev_set_drvdata(&spmi->dev, NULL);
 	kfree(chip);
 
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b7762e1..5f21c7a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -603,16 +603,11 @@
 	case UTP_CMD_TYPE_SCSI:
 	case UTP_CMD_TYPE_DEV_MANAGE:
 		ufshcd_prepare_req_desc(lrbp, &upiu_flags);
-		if (lrbp->cmd && lrbp->command_type == UTP_CMD_TYPE_SCSI)
+		if (lrbp->command_type == UTP_CMD_TYPE_SCSI)
 			ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
-		else if (lrbp->cmd)
+		else
 			ufshcd_prepare_utp_query_req_upiu(hba, lrbp,
 								upiu_flags);
-		else {
-			dev_err(hba->dev, "%s: Invalid UPIU request\n",
-				__func__);
-			ret = -EINVAL;
-		}
 		break;
 	case UTP_CMD_TYPE_UFS:
 		/* For UFS native command implementation */
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index f01a078..52608af 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/thermal.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
@@ -258,6 +259,7 @@
 
 struct tsens_tm_device {
 	struct platform_device		*pdev;
+	struct workqueue_struct		*tsens_wq;
 	bool				prev_reading_avail;
 	bool				calibration_less_mode;
 	bool				tsens_local_init;
@@ -655,7 +657,7 @@
 		}
 		if (upper_thr || lower_thr) {
 			/* Notify user space */
-			schedule_work(&tm->sensor[i].work);
+			queue_work(tm->tsens_wq, &tm->sensor[i].work);
 			rc = tsens_get_sw_id_mapping(
 					tm->sensor[i].sensor_hw_num,
 					&sensor_sw_id);
@@ -673,7 +675,7 @@
 
 static irqreturn_t tsens_isr(int irq, void *data)
 {
-	schedule_work(&tmdev->tsens_work);
+	queue_work(tmdev->tsens_wq, &tmdev->tsens_work);
 
 	return IRQ_HANDLED;
 }
@@ -1506,6 +1508,12 @@
 		return -ENODEV;
 
 	tmdev->pdev = pdev;
+	tmdev->tsens_wq = alloc_workqueue("tsens_wq", WQ_HIGHPRI, 0);
+	if (!tmdev->tsens_wq) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
 	rc = tsens_calib_sensors();
 	if (rc < 0) {
 		pr_err("Calibration failed\n");
@@ -1520,6 +1528,8 @@
 
 	return 0;
 fail:
+	if (tmdev->tsens_wq)
+		destroy_workqueue(tmdev->tsens_wq);
 	if (tmdev->tsens_calib_addr)
 		iounmap(tmdev->tsens_calib_addr);
 	if (tmdev->res_calib_mem)
@@ -1610,6 +1620,7 @@
 		release_mem_region(tmdev->res_tsens_mem->start,
 			tmdev->tsens_len);
 	free_irq(tmdev->tsens_irq, tmdev);
+	destroy_workqueue(tmdev->tsens_wq);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 8760603..d1545dc 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -1,6 +1,6 @@
 /* drivers/tty/n_smux.c
  *
- * 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
@@ -259,6 +259,8 @@
 	unsigned powerdown_enabled;
 	unsigned power_ctl_remote_req_received;
 	struct list_head power_queue;
+	unsigned remote_initiated_wakeup_count;
+	unsigned local_initiated_wakeup_count;
 };
 
 
@@ -279,6 +281,7 @@
 	[SMUX_CMD_CLOSE_LCH] = "CLOSE",
 	[SMUX_CMD_STATUS] = "STATUS",
 	[SMUX_CMD_PWR_CTL] = "PWR",
+	[SMUX_CMD_DELAY] = "DELAY",
 	[SMUX_CMD_BYTE] = "Raw Byte",
 };
 
@@ -1908,6 +1911,7 @@
 		/* wakeup system */
 		SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
 				smux.power_state, SMUX_PWR_ON);
+		smux.remote_initiated_wakeup_count++;
 		smux.power_state = SMUX_PWR_ON;
 		queue_work(smux_tx_wq, &smux_wakeup_work);
 		queue_work(smux_tx_wq, &smux_tx_work);
@@ -2163,6 +2167,62 @@
 }
 
 /**
+ * Sends a delay command to the remote side.
+ *
+ * @ms: Time in milliseconds for the remote side to delay
+ *
+ * This command defines the delay that the remote side will use
+ * to slow the response time for DATA commands.
+ */
+void smux_set_loopback_data_reply_delay(uint32_t ms)
+{
+	struct smux_lch_t *ch = &smux_lch[SMUX_TEST_LCID];
+	struct smux_pkt_t *pkt;
+
+	pkt = smux_alloc_pkt();
+	if (!pkt) {
+		pr_err("%s: unable to allocate packet\n", __func__);
+		return;
+	}
+
+	pkt->hdr.lcid = ch->lcid;
+	pkt->hdr.cmd = SMUX_CMD_DELAY;
+	pkt->hdr.flags = 0;
+	pkt->hdr.payload_len = sizeof(uint32_t);
+	pkt->hdr.pad_len = 0;
+
+	if (smux_alloc_pkt_payload(pkt)) {
+		pr_err("%s: unable to allocate payload\n", __func__);
+		smux_free_pkt(pkt);
+		return;
+	}
+	memcpy(pkt->payload, &ms, sizeof(uint32_t));
+
+	smux_tx_queue(pkt, ch, 1);
+}
+
+/**
+ * Retrieve wakeup counts.
+ *
+ * @local_cnt: Pointer to local wakeup count
+ * @remote_cnt: Pointer to remote wakeup count
+ */
+void smux_get_wakeup_counts(int *local_cnt, int *remote_cnt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+
+	if (local_cnt)
+		*local_cnt = smux.local_initiated_wakeup_count;
+
+	if (remote_cnt)
+		*remote_cnt = smux.remote_initiated_wakeup_count;
+
+	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+}
+
+/**
  * Add channel to transmit-ready list and trigger transmit worker.
  *
  * @ch Channel to add
@@ -2744,6 +2804,7 @@
 				SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
 						smux.power_state,
 						SMUX_PWR_TURNING_ON);
+				smux.local_initiated_wakeup_count++;
 				smux.power_state = SMUX_PWR_TURNING_ON;
 				spin_unlock_irqrestore(&smux.tx_lock_lha2,
 						flags);
diff --git a/drivers/tty/smux_private.h b/drivers/tty/smux_private.h
index 8fdec86..b9a2e89 100644
--- a/drivers/tty/smux_private.h
+++ b/drivers/tty/smux_private.h
@@ -1,6 +1,6 @@
 /* drivers/tty/smux_private.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
@@ -122,6 +122,7 @@
 	SMUX_CMD_CLOSE_LCH = 0x2,
 	SMUX_CMD_STATUS = 0x3,
 	SMUX_CMD_PWR_CTL = 0x4,
+	SMUX_CMD_DELAY = 0x5,
 
 	SMUX_CMD_BYTE, /* for internal usage */
 	SMUX_NUM_COMMANDS
@@ -181,6 +182,8 @@
 void smuxld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			   char *fp, int count);
 bool smux_remote_is_active(void);
+void smux_set_loopback_data_reply_delay(uint32_t ms);
+void smux_get_wakeup_counts(int *local_cnt, int *remote_cnt);
 
 /* testing parameters */
 extern int smux_byte_loopback;
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index e1d9975..8d17674 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -1,6 +1,6 @@
 /* drivers/tty/smux_test.c
  *
- * 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
@@ -20,11 +20,17 @@
 #include <linux/delay.h>
 #include <linux/completion.h>
 #include <linux/termios.h>
+#include <linux/sched.h>
 #include <linux/smux.h>
 #include <mach/subsystem_restart.h>
 #include "smux_private.h"
 
 #define DEBUG_BUFMAX 4096
+#define RED_ZONE_SIZE	16
+#define RED_ZONE_PRE_CH	0xAB
+#define RED_ZONE_POS_CH	0xBA
+#define SMUX_REMOTE_INACTIVITY_TIME_MS	50
+#define SMUX_REMOTE_DELAY_TIME_MS		250
 
 /**
  * Unit test assertion for logging test cases.
@@ -138,7 +144,7 @@
 /**
  * Allocates a new buffer for SMUX for every call.
  */
-int get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
+static int get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
 {
 	void *rx_buf;
 
@@ -216,7 +222,7 @@
  *
  * @cb  Mock callback data
  */
-void mock_cb_data_init(struct smux_mock_callback *cb)
+static void mock_cb_data_init(struct smux_mock_callback *cb)
 {
 	init_completion(&cb->cb_completion);
 	spin_lock_init(&cb->lock);
@@ -232,7 +238,7 @@
  *
  * All packets are freed and counters reset to zero.
  */
-void mock_cb_data_reset(struct smux_mock_callback *cb)
+static void mock_cb_data_reset(struct smux_mock_callback *cb)
 {
 	cb->cb_count = 0;
 	INIT_COMPLETION(cb->cb_completion);
@@ -341,7 +347,7 @@
  * Mock object event callback.  Used to logs events for analysis in the unit
  * tests.
  */
-void smux_mock_cb(void *priv, int event, const void *metadata)
+static void smux_mock_cb(void *priv, int event, const void *metadata)
 {
 	struct smux_mock_callback *cb_data_ptr;
 	struct mock_write_event *write_event_meta;
@@ -518,12 +524,17 @@
 		for (; vectors->data != NULL; ++vectors) {
 			const char *test_data = vectors->data;
 			const unsigned test_len = vectors->len;
+			unsigned long long start_t;
+			unsigned long long end_t;
+			unsigned long long val;
+			unsigned long rem;
 
 			i += scnprintf(buf + i, max - i,
-					"Writing vector %p len %d\n",
+					"Writing vector %p len %d: ",
 					test_data, test_len);
 
 			/* write data */
+			start_t = sched_clock();
 			msm_smux_write(SMUX_TEST_LCID, (void *)0xCAFEFACE,
 					test_data, test_len);
 			UT_ASSERT_INT(ret, ==, 0);
@@ -538,6 +549,7 @@
 					(int)wait_for_completion_timeout(
 						&cb_data.cb_completion, HZ),
 					>, 0);
+			end_t = sched_clock();
 
 			UT_ASSERT_INT(cb_data.cb_count, >=, 1);
 			UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
@@ -569,16 +581,28 @@
 				hex_dump_to_buffer(test_data, test_len,
 					16, 1, linebuff, sizeof(linebuff), 1);
 				i += scnprintf(buf + i, max - i,
-						"Expected:\n%s\n\n", linebuff);
+					"Failed\nExpected:\n%s\n\n", linebuff);
 
 				hex_dump_to_buffer(read_event->meta.buffer,
 					read_event->meta.len,
 					16, 1, linebuff, sizeof(linebuff), 1);
 				i += scnprintf(buf + i, max - i,
-						"Actual:\n%s\n", linebuff);
+					"Failed\nActual:\n%s\n", linebuff);
 				failed = 1;
 				break;
 			}
+
+			/* calculate throughput stats */
+			val = end_t - start_t;
+			rem = do_div(val, 1000);
+			i += scnprintf(buf + i, max - i,
+				"OK - %u us",
+				(unsigned int)val);
+
+			val = 1000000000LL * 2 * test_len;
+			rem = do_div(val, end_t - start_t);
+			i += scnprintf(buf + i, max - i,
+				" (%u kB/sec)\n", (unsigned int)val);
 			mock_cb_data_reset(&cb_data);
 		}
 
@@ -682,7 +706,7 @@
  * Run a basic loopback test followed by a subsystem restart and then another
  * loopback test.
  */
-static int smux_ut_remote_ssr_basic(char *buf, int max)
+static int smux_ut_ssr_remote_basic(char *buf, int max)
 {
 	const struct test_vector test_data[] = {
 		{"hello\0world\n", sizeof("hello\0world\n")},
@@ -723,7 +747,7 @@
 /**
  * Verify Subsystem Restart Support During Port Open
  */
-static int smux_ut_remote_ssr_open(char *buf, int max)
+static int smux_ut_ssr_remote_open(char *buf, int max)
 {
 	static struct smux_mock_callback cb_data;
 	static int cb_initialized;
@@ -805,7 +829,7 @@
  *
  * @returns Number of bytes written to @buf
  */
-static int smux_ut_remote_ssr_rx_buff_retry(char *buf, int max)
+static int smux_ut_ssr_remote_rx_buff_retry(char *buf, int max)
 {
 	static struct smux_mock_callback cb_data;
 	static int cb_initialized;
@@ -897,9 +921,10 @@
 	mock_cb_data_reset(&cb_data);
 	return i;
 }
+
 /**
  * Fill test pattern into provided buffer including an optional
- * redzone 16 bytes before and 16 bytes after the buffer.
+ * redzone before and after the buffer.
  *
  * buf ---------
  *      redzone
@@ -909,70 +934,75 @@
  *      redzone
  *     ---------
  *
- * @buf  Pointer to the buffer of size len or len+32 (redzone)
- * @len  Length of the *data* buffer (excluding 32-byte redzone)
+ * @buf  Pointer to the buffer of size len or len+2*RED_ZONE_SIZE (redzone)
+ * @len  Length of the *data* buffer (excluding the extra redzone buffers)
  * @redzone If true, adds redzone data
  *
- * @returns pointer to buffer (buf + 16 if redzone enabled)
+ * @returns pointer to buffer (buf + RED_ZONE_SIZE if redzone enabled)
  */
-uint8_t *test_pattern_fill(char *buf, int len, int redzone)
+static uint8_t *test_pattern_fill(char *buf, int len, int redzone)
 {
-	void *ret;
+	char *buf_ptr;
 	uint8_t ch;
 
-	ret = buf;
 	if (redzone) {
-		memset((char *)buf, 0xAB, 16);
-		memset((char *)buf + len, 0xBA, 16);
-		ret += 16;
+		memset(buf, RED_ZONE_PRE_CH, RED_ZONE_SIZE);
+		buf += RED_ZONE_SIZE;
+		memset(buf + len, RED_ZONE_POS_CH, RED_ZONE_SIZE);
 	}
 
-	/* fill with test pattern */
-	for (ch = 0; len > 0; --len, ++ch)
-		*buf++ = (char)ch;
+	for (ch = 0, buf_ptr = buf; len > 0; --len, ++ch)
+		*buf_ptr++ = (char)ch;
 
-	return ret;
+	return buf;
 }
 
 /**
  * Verify test pattern generated by test_pattern_fill.
  *
  * @buf_ptr    Pointer to buffer pointer
- * @len        Length of the *data* buffer (excluding 32-byte redzone)
+ * @len        Length of the *data* buffer (excluding redzone bytes)
  * @redzone    If true, verifies redzone and adjusts *buf_ptr
  * @errmsg     Buffer for error message
  * @errmsg_max Size of error message buffer
  *
  * @returns    0 for success; length of error message otherwise
  */
-unsigned test_pattern_verify(char **buf_ptr, int len, int redzone,
+static unsigned test_pattern_verify(char **buf_ptr, int len, int redzone,
 					char *errmsg, int errmsg_max)
 {
 	int n;
 	int i = 0;
 	char linebuff[80];
+	char *zone_ptr;
 
 	if (redzone) {
-		*buf_ptr -= 16;
+		*buf_ptr -= RED_ZONE_SIZE;
+		zone_ptr = *buf_ptr;
 
 		/* verify prefix redzone */
-		for (n = 0; n < 16; ++n) {
-			if (*buf_ptr[n] != 0xAB) {
-				hex_dump_to_buffer(*buf_ptr, 16,
-					16, 1, linebuff, sizeof(linebuff), 1);
+		for (n = 0; n < RED_ZONE_SIZE; ++n) {
+			if (zone_ptr[n] != RED_ZONE_PRE_CH) {
+				hex_dump_to_buffer(zone_ptr, RED_ZONE_SIZE,
+					RED_ZONE_SIZE, 1, linebuff,
+					sizeof(linebuff), 1);
 				i += scnprintf(errmsg + i, errmsg_max - i,
-					"Redzone violation: %s\n", linebuff);
+					"Pre-redzone violation: %s\n",
+					linebuff);
 				break;
 			}
 		}
 
 		/* verify postfix redzone */
-		for (n = 0; n < 16; ++n) {
-			if (*buf_ptr[len + n] != 0xBA) {
-				hex_dump_to_buffer(&(*buf_ptr)[len], 16,
-					16, 1, linebuff, sizeof(linebuff), 1);
+		zone_ptr = *buf_ptr + RED_ZONE_SIZE + len;
+		for (n = 0; n < RED_ZONE_SIZE; ++n) {
+			if (zone_ptr[n] != RED_ZONE_POS_CH) {
+				hex_dump_to_buffer(zone_ptr, RED_ZONE_SIZE,
+					RED_ZONE_SIZE, 1, linebuff,
+					sizeof(linebuff), 1);
 				i += scnprintf(errmsg + i, errmsg_max - i,
-					"Redzone violation: %s\n", linebuff);
+					"Post-redzone violation: %s\n",
+					linebuff);
 				break;
 			}
 		}
@@ -1001,6 +1031,7 @@
 		{0, 256},
 		{0, 512},
 		{0, 1024},
+		{0, 1500},
 		{0, 2048},
 		{0, 4096},
 		{0, 0},
@@ -1011,9 +1042,7 @@
 
 	/* generate test data */
 	for (tv = test_data; tv->len > 0; ++tv) {
-		tv->data = kmalloc(tv->len + 32, GFP_KERNEL);
-		pr_err("%s: allocating %p len %d\n",
-				__func__, tv->data, tv->len);
+		tv->data = kmalloc(tv->len + 2 * RED_ZONE_SIZE, GFP_KERNEL);
 		if (!tv->data) {
 			i += scnprintf(buf + i, max - i,
 					"%s: Unable to allocate %d bytes\n",
@@ -1021,7 +1050,7 @@
 			failed = 1;
 			goto out;
 		}
-		test_pattern_fill((uint8_t *)tv->data, tv->len, 1);
+		tv->data = test_pattern_fill((uint8_t *)tv->data, tv->len, 1);
 	}
 
 	/* run test */
@@ -1038,11 +1067,9 @@
 	}
 
 	for (tv = test_data; tv->len > 0; ++tv) {
-		if (!tv->data) {
+		if (tv->data) {
 			i += test_pattern_verify((char **)&tv->data,
 						tv->len, 1, buf + i, max - i);
-			pr_err("%s: freeing %p len %d\n", __func__,
-							tv->data, tv->len);
 			kfree(tv->data);
 		}
 	}
@@ -1112,6 +1139,59 @@
 }
 
 /**
+ * Run a large packet test for throughput metrics.
+ *
+ * Repeatedly send a packet for 100 iterations to get throughput metrics.
+ */
+static int smux_ut_remote_throughput(char *buf, int max)
+{
+	struct test_vector test_data[] = {
+		{0, 1500},
+		{0, 0},
+	};
+	int failed = 0;
+	int i = 0;
+	int loop = 0;
+	struct test_vector *tv;
+	int ret;
+
+	/* generate test data */
+	for (tv = test_data; tv->len > 0; ++tv) {
+		tv->data = kmalloc(tv->len, GFP_KERNEL);
+		if (!tv->data) {
+			i += scnprintf(buf + i, max - i,
+					"%s: Unable to allocate %d bytes\n",
+					__func__, tv->len);
+			failed = 1;
+			goto out;
+		}
+		test_pattern_fill((uint8_t *)tv->data, tv->len, 0);
+	}
+
+	/* run test */
+	i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
+	while (!failed && loop < 100) {
+		ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
+				SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
+		UT_ASSERT_INT(ret, ==, 0);
+
+		i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
+		++loop;
+	}
+
+out:
+	if (failed) {
+		pr_err("%s: Failed\n", __func__);
+		i += scnprintf(buf + i, max - i, "\tFailed\n");
+	}
+
+	for (tv = test_data; tv->len > 0; ++tv)
+			kfree(tv->data);
+
+	return i;
+}
+
+/**
  * Verify set and get operations for each TIOCM bit.
  *
  * @buf  Buffer for status message
@@ -2083,6 +2163,126 @@
 	return i;
 }
 
+/**
+ * Verify Remote-initiated wakeup test case.
+ *
+ * @buf       Output buffer for failure/status messages
+ * @max       Size of @buf
+ */
+static int smux_ut_remote_initiated_wakeup(char *buf, int max)
+{
+	int i = 0;
+	int failed = 0;
+	static struct smux_mock_callback cb_data;
+	static int cb_initialized;
+	int ret;
+
+	if (!cb_initialized)
+		mock_cb_data_init(&cb_data);
+
+	smux_set_loopback_data_reply_delay(SMUX_REMOTE_DELAY_TIME_MS);
+	mock_cb_data_reset(&cb_data);
+	do {
+		unsigned long start_j;
+		unsigned transfer_time;
+		unsigned lwakeups_start;
+		unsigned rwakeups_start;
+		unsigned lwakeups_end;
+		unsigned rwakeups_end;
+		unsigned lwakeup_delta;
+		unsigned rwakeup_delta;
+
+		/* open port */
+		ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
+					get_rx_buffer);
+		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);
+		UT_ASSERT_INT(cb_data.event_connected, ==, 1);
+		mock_cb_data_reset(&cb_data);
+
+		/* do local wakeup test and send echo packet */
+		msleep(SMUX_REMOTE_INACTIVITY_TIME_MS);
+		smux_get_wakeup_counts(&lwakeups_start, &rwakeups_start);
+		msm_smux_write(SMUX_TEST_LCID, (void *)0x12345678,
+				"Hello", 5);
+		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);
+		UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
+		mock_cb_data_reset(&cb_data);
+
+		/* verify local initiated wakeup */
+		smux_get_wakeup_counts(&lwakeups_end, &rwakeups_end);
+		if (lwakeups_end > lwakeups_start)
+			i += scnprintf(buf + i, max - i,
+					"\tGood - have Apps-initiated wakeup\n");
+		else
+			i += scnprintf(buf + i, max - i,
+					"\tBad - no Apps-initiated wakeup\n");
+
+		/* verify remote wakeup and echo response */
+		smux_get_wakeup_counts(&lwakeups_start, &rwakeups_start);
+		start_j = jiffies;
+		INIT_COMPLETION(cb_data.cb_completion);
+		if (!cb_data.event_read_done)
+			UT_ASSERT_INT(
+				(int)wait_for_completion_timeout(
+					&cb_data.cb_completion,
+					SMUX_REMOTE_DELAY_TIME_MS * 2),
+				>, 0);
+		transfer_time = (unsigned)jiffies_to_msecs(jiffies - start_j);
+		UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
+		UT_ASSERT_INT_IN_RANGE(transfer_time,
+			SMUX_REMOTE_DELAY_TIME_MS -
+			SMUX_REMOTE_INACTIVITY_TIME_MS,
+			SMUX_REMOTE_DELAY_TIME_MS +
+			SMUX_REMOTE_INACTIVITY_TIME_MS);
+		smux_get_wakeup_counts(&lwakeups_end, &rwakeups_end);
+
+		lwakeup_delta = lwakeups_end - lwakeups_end;
+		rwakeup_delta = rwakeups_end - rwakeups_end;
+		if (rwakeup_delta && lwakeup_delta) {
+			i += scnprintf(buf + i, max - i,
+					"\tBoth local and remote wakeup - re-run test (transfer time %d ms)\n",
+					transfer_time);
+			failed = 1;
+			break;
+		} else if (lwakeup_delta) {
+			i += scnprintf(buf + i, max - i,
+					"\tLocal wakeup only (transfer time %d ms) - FAIL\n",
+					transfer_time);
+			failed = 1;
+			break;
+		} else {
+			i += scnprintf(buf + i, max - i,
+					"\tRemote wakeup verified (transfer time %d ms) - OK\n",
+					transfer_time);
+		}
+	} while (0);
+
+	if (!failed) {
+		i += scnprintf(buf + i, max - i, "\tOK\n");
+	} else {
+		pr_err("%s: Failed\n", __func__);
+		i += scnprintf(buf + i, max - i, "\tFailed\n");
+		i += mock_cb_data_print(&cb_data, buf + i, max - i);
+	}
+
+	mock_cb_data_reset(&cb_data);
+	msm_smux_close(SMUX_TEST_LCID);
+	wait_for_completion_timeout(&cb_data.cb_completion, HZ);
+
+	mock_cb_data_reset(&cb_data);
+	smux_set_loopback_data_reply_delay(0);
+
+	return i;
+}
+
 static char debug_buffer[DEBUG_BUFMAX];
 
 static ssize_t debug_read(struct file *file, char __user *buf,
@@ -2148,15 +2348,18 @@
 			smux_ut_local_get_rx_buff_retry);
 	debug_create("ut_local_get_rx_buff_retry_auto", 0444, dent,
 			smux_ut_local_get_rx_buff_retry_auto);
-	debug_create("ut_remote_ssr_basic", 0444, dent,
-			smux_ut_remote_ssr_basic);
-	debug_create("ut_remote_ssr_open", 0444, dent,
-			smux_ut_remote_ssr_open);
-	debug_create("ut_remote_ssr_rx_buff_retry", 0444, dent,
-			smux_ut_remote_ssr_rx_buff_retry);
+	debug_create("ut_ssr_remote_basic", 0444, dent,
+			smux_ut_ssr_remote_basic);
+	debug_create("ut_ssr_remote_open", 0444, dent,
+			smux_ut_ssr_remote_open);
+	debug_create("ut_ssr_remote_rx_buff_retry", 0444, dent,
+			smux_ut_ssr_remote_rx_buff_retry);
 	debug_create("ut_remote_tx_stop", 0444, dent,
 			smux_ut_remote_tx_stop);
-
+	debug_create("ut_remote_throughput", 0444, dent,
+			smux_ut_remote_throughput);
+	debug_create("ut_remote_initiated_wakeup", 0444, dent,
+			smux_ut_remote_initiated_wakeup);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 678627a..af82656 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -79,7 +79,7 @@
  *****************************************************************************/
 
 #define DMA_ADDR_INVALID	(~(dma_addr_t)0)
-#define USB_MAX_TIMEOUT		100 /* 100msec timeout */
+#define USB_MAX_TIMEOUT		25 /* 25msec timeout */
 #define EP_PRIME_CHECK_DELAY	(jiffies + msecs_to_jiffies(1000))
 #define MAX_PRIME_CHECK_RETRY	3 /*Wait for 3sec for EP prime failure */
 
@@ -2275,8 +2275,11 @@
 	gadget->otg_srp_reqd = 0;
 
 	udc->driver->disconnect(gadget);
+
+	spin_lock_irqsave(udc->lock, flags);
 	_ep_nuke(&udc->ep0out);
 	_ep_nuke(&udc->ep0in);
+	spin_unlock_irqrestore(udc->lock, flags);
 
 	if (udc->ep0in.last_zptr) {
 		dma_pool_free(udc->ep0in.td_pool, udc->ep0in.last_zptr,
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index a1b02be..e48f94c 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -1497,6 +1497,11 @@
 	mbim->not_port.notify_req->context = mbim;
 	mbim->not_port.notify_req->complete = mbim_notify_complete;
 
+	if (mbim->xport == USB_GADGET_XPORT_BAM2BAM_IPA)
+		mbb_desc.wMaxSegmentSize = cpu_to_le16(0x800);
+	else
+		mbb_desc.wMaxSegmentSize = cpu_to_le16(0xfe0);
+
 	/* copy descriptors, and track endpoint copies */
 	f->descriptors = usb_copy_descriptors(mbim_fs_function);
 	if (!f->descriptors)
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index 0c0d58a..37189d8 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -50,7 +50,7 @@
 #define STATE_ERROR                 4   /* error from completion routine */
 
 /* number of tx and rx requests to allocate */
-#define TX_REQ_MAX 4
+#define MTP_TX_REQ_MAX 8
 #define RX_REQ_MAX 2
 #define INTR_REQ_MAX 5
 
@@ -70,6 +70,12 @@
 unsigned int mtp_rx_req_len = MTP_BULK_BUFFER_SIZE;
 module_param(mtp_rx_req_len, uint, S_IRUGO | S_IWUSR);
 
+unsigned int mtp_tx_req_len = MTP_BULK_BUFFER_SIZE;
+module_param(mtp_tx_req_len, uint, S_IRUGO | S_IWUSR);
+
+unsigned int mtp_tx_reqs = MTP_TX_REQ_MAX;
+module_param(mtp_tx_reqs, uint, S_IRUGO | S_IWUSR);
+
 static const char mtp_shortname[] = "mtp_usb";
 
 struct mtp_dev {
@@ -488,11 +494,22 @@
 	ep->driver_data = dev;		/* claim the endpoint */
 	dev->ep_intr = ep;
 
+retry_tx_alloc:
+	if (mtp_tx_req_len > MTP_BULK_BUFFER_SIZE)
+		mtp_tx_reqs = 4;
+
 	/* now allocate requests for our endpoints */
-	for (i = 0; i < TX_REQ_MAX; i++) {
-		req = mtp_request_new(dev->ep_in, MTP_BULK_BUFFER_SIZE);
-		if (!req)
-			goto fail;
+	for (i = 0; i < mtp_tx_reqs; i++) {
+		req = mtp_request_new(dev->ep_in, mtp_tx_req_len);
+		if (!req) {
+			if (mtp_tx_req_len <= MTP_BULK_BUFFER_SIZE)
+				goto fail;
+			while ((req = mtp_req_get(dev, &dev->tx_idle)))
+				mtp_request_free(req, dev->ep_in);
+			mtp_tx_req_len = MTP_BULK_BUFFER_SIZE;
+			mtp_tx_reqs = MTP_TX_REQ_MAX;
+			goto retry_tx_alloc;
+		}
 		req->complete = mtp_complete_in;
 		mtp_req_put(dev, &dev->tx_idle, req);
 	}
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 1288bfd..32d4011 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -71,7 +71,7 @@
 MODULE_PARM_DESC(rndis_multipacket_dl_disable,
 	"Disable RNDIS Multi-packet support in DownLink");
 
-static unsigned int rndis_ul_max_pkt_per_xfer = 1;
+static unsigned int rndis_ul_max_pkt_per_xfer = 3;
 module_param(rndis_ul_max_pkt_per_xfer, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer,
 	"Maximum packets per transfer for UL aggregation");
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index bff7eb1..e662bfc 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1074,14 +1074,6 @@
 		struct sk_buff		*skb2;
 		u32		msg_len, data_offset, data_len;
 
-		/* some rndis hosts send extra byte to avoid zlp, ignore it */
-		if (skb->len == 1) {
-			if (num_pkts > rndis_ul_max_pkt_per_xfer_rcvd)
-				rndis_ul_max_pkt_per_xfer_rcvd = num_pkts;
-			dev_kfree_skb_any(skb);
-			return 0;
-		}
-
 		if (skb->len < sizeof *hdr) {
 			pr_err("invalid rndis pkt: skblen:%u hdr_len:%u",
 					skb->len, sizeof *hdr);
@@ -1115,7 +1107,8 @@
 
 		skb_pull(skb, data_offset + 8);
 
-		if (msg_len == skb->len) {
+		if (data_len == skb->len ||
+				data_len == (skb->len - 1)) {
 			skb_trim(skb, data_len);
 			break;
 		}
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 0ea9778..c5304e1 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1062,6 +1062,7 @@
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
 	int retval;
 
 	mehci->timer = USB_HS_GPTIMER_BASE;
@@ -1092,8 +1093,14 @@
 
 	/* bursts of unspecified length. */
 	writel_relaxed(0, USB_AHBBURST);
-	/* Use the AHB transactor */
-	writel_relaxed(0x08, USB_AHBMODE);
+
+	/* Use the AHB transactor and configure async bridge bypass */
+#define MSM_USB_ASYNC_BRIDGE_BYPASS BIT(31)
+	if (pdata->ahb_async_bridge_bypass)
+		writel_relaxed(0x08 | MSM_USB_ASYNC_BRIDGE_BYPASS, USB_AHBMODE);
+	else
+		writel_relaxed(0x08, USB_AHBMODE);
+
 	/* Disable streaming mode and select host mode */
 	writel_relaxed(0x13, USB_USBMODE);
 
@@ -1882,6 +1889,8 @@
 				"qcom,disable-park-mode"));
 	pdata->consider_ipa_handshake = (of_property_read_bool(node,
 				"hsic,consider-ipa-handshake"));
+	pdata->ahb_async_bridge_bypass = of_property_read_bool(node,
+				"qcom,ahb-async-bridge-bypass");
 
 	return pdata;
 }
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index e46ea3b..bb5d3ca 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -104,8 +104,14 @@
 
 	kfree(panel_private->on_cmds);
 	kfree(panel_private->off_cmds);
+
 	kfree(panel_private);
 	panel_private = NULL;
+
+	if (bl_led_trigger) {
+		led_trigger_unregister_simple(bl_led_trigger);
+		bl_led_trigger = NULL;
+	}
 }
 int dsi_panel_power(int enable)
 {
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 5223e66..65c9e90 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -290,12 +290,16 @@
 static void mdp3_bus_scale_unregister(void)
 {
 	int i;
+
+	if (!mdp3_res->bus_handle)
+		return;
+
 	for (i = 0; i < MDP3_BUS_HANDLE_MAX; i++) {
 		pr_debug("unregister index=%d bus_handle=%x\n",
 			i, mdp3_res->bus_handle[i].handle);
 		if (mdp3_res->bus_handle[i].handle) {
 			msm_bus_scale_unregister_client(
-			   mdp3_res->bus_handle[i].handle);
+				mdp3_res->bus_handle[i].handle);
 			mdp3_res->bus_handle[i].handle = 0;
 		}
 	}
@@ -484,11 +488,20 @@
 
 static void mdp3_clk_remove(void)
 {
-	clk_put(mdp3_res->clocks[MDP3_CLK_AHB]);
-	clk_put(mdp3_res->clocks[MDP3_CLK_CORE]);
-	clk_put(mdp3_res->clocks[MDP3_CLK_VSYNC]);
-	clk_put(mdp3_res->clocks[MDP3_CLK_LCDC]);
-	clk_put(mdp3_res->clocks[MDP3_CLK_DSI]);
+	if (!IS_ERR_OR_NULL(mdp3_res->clocks[MDP3_CLK_AHB]))
+		clk_put(mdp3_res->clocks[MDP3_CLK_AHB]);
+
+	if (!IS_ERR_OR_NULL(mdp3_res->clocks[MDP3_CLK_CORE]))
+		clk_put(mdp3_res->clocks[MDP3_CLK_CORE]);
+
+	if (!IS_ERR_OR_NULL(mdp3_res->clocks[MDP3_CLK_VSYNC]))
+		clk_put(mdp3_res->clocks[MDP3_CLK_VSYNC]);
+
+	if (!IS_ERR_OR_NULL(mdp3_res->clocks[MDP3_CLK_LCDC]))
+		clk_put(mdp3_res->clocks[MDP3_CLK_LCDC]);
+
+	if (!IS_ERR_OR_NULL(mdp3_res->clocks[MDP3_CLK_DSI]))
+		clk_put(mdp3_res->clocks[MDP3_CLK_DSI]);
 }
 
 int mdp3_clk_enable(int enable)
@@ -519,6 +532,7 @@
 		return ret;
 	}
 	disable_irq(mdp3_res->irq);
+	mdp3_res->irq_registered = true;
 	return 0;
 }
 
@@ -556,7 +570,8 @@
 	struct mdp3_iommu_ctx_map *context_map;
 	struct mdp3_iommu_domain_map *domain_map;
 
-	if (context >= MDP3_IOMMU_CTX_MAX)
+	if (!mdp3_res->iommu_contexts ||
+		context >= MDP3_IOMMU_CTX_MAX)
 		return -EINVAL;
 
 	context_map = mdp3_res->iommu_contexts + context;
@@ -595,10 +610,13 @@
 
 		mdp3_iommu_domains[i].domain_idx = domain_idx;
 		mdp3_iommu_domains[i].domain = msm_get_iommu_domain(domain_idx);
-		if (!mdp3_iommu_domains[i].domain) {
+		if (IS_ERR_OR_NULL(mdp3_iommu_domains[i].domain)) {
 			pr_err("unable to get iommu domain(%d)\n",
 				domain_idx);
-			return -EINVAL;
+			if (!mdp3_iommu_domains[i].domain)
+				return -EINVAL;
+			else
+				return PTR_ERR(mdp3_iommu_domains[i].domain);
 		}
 		iommu_set_fault_handler(mdp3_iommu_domains[i].domain,
 					mdp3_iommu_fault_handler,
@@ -623,10 +641,13 @@
 		mdp3_iommu_contexts[i].ctx =
 			msm_iommu_get_ctx(mdp3_iommu_contexts[i].ctx_name);
 
-		if (!mdp3_iommu_contexts[i].ctx) {
+		if (IS_ERR_OR_NULL(mdp3_iommu_contexts[i].ctx)) {
 			pr_warn("unable to get iommu ctx(%s)\n",
 				mdp3_iommu_contexts[i].ctx_name);
-			return -EINVAL;
+			if (!mdp3_iommu_contexts[i].ctx)
+				return -EINVAL;
+			else
+				return PTR_ERR(mdp3_iommu_contexts[i].ctx);
 		}
 	}
 
@@ -653,6 +674,19 @@
 	return ret;
 }
 
+void mdp3_iommu_deinit(void)
+{
+	int i;
+
+	if (!mdp3_res->domains)
+		return;
+
+	for (i = 0; i < MDP3_IOMMU_DOMAIN_MAX; i++) {
+		if (!IS_ERR_OR_NULL(mdp3_res->domains[i].domain))
+			msm_unregister_domain(mdp3_res->domains[i].domain);
+	}
+}
+
 static int mdp3_check_version(void)
 {
 	int rc;
@@ -742,6 +776,21 @@
 	return rc;
 }
 
+static void mdp3_res_deinit(void)
+{
+	mdp3_bus_scale_unregister();
+	mdp3_iommu_dettach(MDP3_IOMMU_CTX_DMA_0);
+	mdp3_iommu_deinit();
+
+	if (!IS_ERR_OR_NULL(mdp3_res->ion_client))
+		ion_client_destroy(mdp3_res->ion_client);
+
+	mdp3_clk_remove();
+
+	if (mdp3_res->irq_registered)
+		devm_free_irq(&mdp3_res->pdev->dev, mdp3_res->irq, mdp3_res);
+}
+
 static int mdp3_parse_dt(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -847,7 +896,10 @@
 		data->srcp_ihdl = ion_import_dma_buf(iclient, img->memory_id);
 		if (IS_ERR_OR_NULL(data->srcp_ihdl)) {
 			pr_err("error on ion_import_fd\n");
-			ret = PTR_ERR(data->srcp_ihdl);
+			if (!data->srcp_ihdl)
+				ret = -EINVAL;
+			else
+				ret = PTR_ERR(data->srcp_ihdl);
 			data->srcp_ihdl = NULL;
 			return ret;
 		}
@@ -1002,6 +1054,11 @@
 
 probe_done:
 	if (IS_ERR_VALUE(rc)) {
+		mdp3_res_deinit();
+
+		if (mdp3_res->mdp_base)
+			devm_iounmap(&pdev->dev, mdp3_res->mdp_base);
+
 		devm_kfree(&pdev->dev, mdp3_res);
 		mdp3_res = NULL;
 	}
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 878fe25..e52f7bc 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -119,6 +119,8 @@
 	u32 irq_mask;
 	struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
 
+	int irq_registered;
+
 	struct early_suspend suspend_handler;
 };
 
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index b5134a7..037ab51 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -192,13 +192,9 @@
 
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 
-	rc = wait_for_completion_interruptible_timeout(
-				&mdp3_session->vsync_comp,
-				msecs_to_jiffies(VSYNC_PERIOD * 5));
-	if (rc <= 0) {
-		pr_warn("vsync wait on fb%d interrupted (%d)\n",
-			mfd->index, rc);
-	}
+	rc = wait_for_completion_interruptible(&mdp3_session->vsync_comp);
+	if (rc < 0)
+		return rc;
 
 	spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
 	vsync_ticks = ktime_to_ns(mdp3_session->vsync_time);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index e2d8cf6..5445137 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1725,7 +1725,7 @@
 
 	if (!mdp_instance) {
 		pr_err("mdss mdp resource not initialized yet\n");
-		return -ENODEV;
+		return -EPROBE_DEFER;
 	}
 
 	node = of_parse_phandle(pdev->dev.of_node, "qcom,mdss-fb-map", 0);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index c96464a..4a03e13 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1286,20 +1286,14 @@
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	unsigned long flags;
 	u64 vsync_ticks;
-	unsigned long timeout;
 	int ret;
 
 	if (!mdp5_data->ctl || !mdp5_data->ctl->power_on)
 		return 0;
 
-	timeout = msecs_to_jiffies(VSYNC_PERIOD * 5);
-	ret = wait_for_completion_interruptible_timeout(&mdp5_data->vsync_comp,
-			timeout);
-	if (ret <= 0) {
-		pr_debug("Sending current time as vsync timestamp for fb%d\n",
-				mfd->index);
-		mdp5_data->vsync_time = ktime_get();
-	}
+	ret = wait_for_completion_interruptible(&mdp5_data->vsync_comp);
+	if (ret < 0)
+		return ret;
 
 	spin_lock_irqsave(&mdp5_data->vsync_lock, flags);
 	vsync_ticks = ktime_to_ns(mdp5_data->vsync_time);
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index e8de769..ae88807 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -781,6 +781,27 @@
 
 #define IOCTL_KGSL_PERFCOUNTER_READ \
 	_IOWR(KGSL_IOC_TYPE, 0x3B, struct kgsl_perfcounter_read)
+/*
+ * struct kgsl_gpumem_sync_cache_bulk - argument to
+ * IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK
+ * @id_list: list of GPU buffer ids of the buffers to sync
+ * @count: number of GPU buffer ids in id_list
+ * @op: a mask of KGSL_GPUMEM_CACHE_* values
+ *
+ * Sync the cache for memory headed to and from the GPU. Certain
+ * optimizations can be made on the cache operation based on the total
+ * size of the working set of memory to be managed.
+ */
+struct kgsl_gpumem_sync_cache_bulk {
+	unsigned int *id_list;
+	unsigned int count;
+	unsigned int op;
+/* private: reserved for future use */
+	unsigned int __pad[2]; /* For future binary compatibility */
+};
+
+#define IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK \
+	_IOWR(KGSL_IOC_TYPE, 0x3C, struct kgsl_gpumem_sync_cache_bulk)
 
 #ifdef __KERNEL__
 #ifdef CONFIG_MSM_KGSL_DRM
diff --git a/include/linux/qpnp/power-on.h b/include/linux/qpnp/power-on.h
index 6394988..5e87259 100644
--- a/include/linux/qpnp/power-on.h
+++ b/include/linux/qpnp/power-on.h
@@ -15,12 +15,38 @@
 
 #include <linux/errno.h>
 
+/**
+ * enum pon_trigger_source: List of PON trigger sources
+ * %PON_SMPL:		PON triggered by SMPL - Sudden Momentary Power Loss
+ * %PON_RTC:		PON triggered by RTC alarm
+ * %PON_DC_CHG:		PON triggered by insertion of DC charger
+ * %PON_USB_CHG:	PON triggered by insertion of USB
+ * %PON_PON1:		PON triggered by other PMIC (multi-PMIC option)
+ * %PON_CBLPWR_N:	PON triggered by power-cable insertion
+ * %PON_KPDPWR_N:	PON triggered by long press of the power-key
+ */
+enum pon_trigger_source {
+	PON_SMPL = 1,
+	PON_RTC,
+	PON_DC_CHG,
+	PON_USB_CHG,
+	PON_PON1,
+	PON_CBLPWR_N,
+	PON_KPDPWR_N,
+};
+
 #ifdef CONFIG_QPNP_POWER_ON
 int qpnp_pon_system_pwr_off(bool reset);
 int qpnp_pon_is_warm_reset(void);
+int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable);
 #else
 static int qpnp_pon_system_pwr_off(bool reset) { return -ENODEV; }
 static inline int qpnp_pon_is_warm_reset(void) { return -ENODEV; }
+static inline int qpnp_pon_trigger_config(enum pon_trigger_source pon_src,
+							bool enable)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 92a89f0..c2d9c17 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -118,7 +118,7 @@
 #define SD_MC_INIT (struct sched_domain) {				\
 	.min_interval		= 1,					\
 	.max_interval		= 4,					\
-	.busy_factor		= 64,					\
+	.busy_factor		= 1,					\
 	.imbalance_pct		= 125,					\
 	.cache_nice_tries	= 1,					\
 	.busy_idx		= 2,					\
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 209062b..f9729c4 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -425,6 +425,7 @@
 	bool enable_hbm;
 	bool disable_park_mode;
 	bool consider_ipa_handshake;
+	bool ahb_async_bridge_bypass;
 };
 
 struct msm_usb_host_platform_data {
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index f8317df..8f32475 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1604,7 +1604,6 @@
 	struct task_struct *next_task;
 	struct rq *lowest_rq;
 	int ret = 0;
-	bool moved = false;
 
 	if (!rq->rt.overloaded)
 		return 0;
@@ -1674,7 +1673,6 @@
 
 	deactivate_task(rq, next_task, 0);
 	set_task_cpu(next_task, lowest_rq->cpu);
-	moved = true;
 	activate_task(lowest_rq, next_task, 0);
 	ret = 1;
 
@@ -1685,11 +1683,6 @@
 out:
 	put_task_struct(next_task);
 
-	if (moved && task_notify_on_migrate(next_task))
-		atomic_notifier_call_chain(&migration_notifier_head,
-					   cpu_of(lowest_rq),
-					   (void *)cpu_of(rq));
-
 	return ret;
 }
 
@@ -1703,10 +1696,8 @@
 static int pull_rt_task(struct rq *this_rq)
 {
 	int this_cpu = this_rq->cpu, ret = 0, cpu;
-	struct task_struct *p = NULL;
+	struct task_struct *p;
 	struct rq *src_rq;
-	bool moved = false;
-	int src_cpu = 0;
 
 	if (likely(!rt_overloaded(this_rq)))
 		return 0;
@@ -1767,10 +1758,6 @@
 			deactivate_task(src_rq, p, 0);
 			set_task_cpu(p, this_cpu);
 			activate_task(this_rq, p, 0);
-
-			moved = true;
-			src_cpu = cpu_of(src_rq);
-
 			/*
 			 * We continue with the search, just in
 			 * case there's an even higher prio task
@@ -1782,11 +1769,6 @@
 		double_unlock_balance(this_rq, src_rq);
 	}
 
-	if (moved && task_notify_on_migrate(p))
-		atomic_notifier_call_chain(&migration_notifier_head,
-					   this_cpu,
-					   (void *)src_cpu);
-
 	return ret;
 }
 
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 155585a..8d6dee3 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -456,4 +456,8 @@
 	tristate
 
 config SND_SOC_MSM_HDMI_CODEC_RX
-	tristate
+	bool "HDMI Audio Playback"
+	depends on FB_MSM_MDSS_HDMI_PANEL && SND_SOC_MSM8974
+	help
+	HDMI audio drivers should be built only if the platform
+        supports hdmi panel.
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f0cd026..c0469e3 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -104,7 +104,7 @@
 
 snd-soc-timpani-objs := timpani.o
 snd-soc-msm-stub-objs := msm_stub.o
-snd-soc-msm-hdmi-rx-objs := msm_hdmi_codec_rx.o
+obj-$(CONFIG_SND_SOC_MSM_HDMI_CODEC_RX) := msm_hdmi_codec_rx.o
 
 # Amp
 snd-soc-max9877-objs := max9877.o
@@ -214,7 +214,6 @@
 obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
 obj-$(CONFIG_SND_SOC_MSM_STUB)  += snd-soc-msm-stub.o
-obj-$(CONFIG_SND_SOC_MSM_HDMI_CODEC_RX)  += snd-soc-msm-hdmi-rx.o
 
 # Amp
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index e1a904f..1a11997 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -1784,9 +1784,7 @@
 	} else {
 		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_TOP_CLK_CTL,
 				    0x0f, 0x00);
-		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_MCLK_CTL,
-				    0x01, 0x01);
-		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_MCLK_CTL,
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_PDM_CTL,
 				    0x03, 0x00);
 	}
 	return 0;
diff --git a/sound/soc/codecs/wcd9320-tables.c b/sound/soc/codecs/wcd9320-tables.c
index 0885c09..e834b80 100644
--- a/sound/soc/codecs/wcd9320-tables.c
+++ b/sound/soc/codecs/wcd9320-tables.c
@@ -671,6 +671,16 @@
 	[TAIKO_A_CDC_MAD_BEACON_CTL_8] = 1,
 	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR] = 1,
 	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL0] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL1] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL2] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL3] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL4] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL5] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL6] = 1,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL7] = 1,
+
 };
 
 const u8 taiko_reset_reg_defaults[TAIKO_CACHE_SIZE] = {
@@ -1356,4 +1366,14 @@
 	    TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR__POR,
 	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL] =
 	    TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL] =
+		TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL0] = TAIKO_A_CDC_SPKR_CLIPDET_VAL0__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL1] = TAIKO_A_CDC_SPKR_CLIPDET_VAL1__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL2] = TAIKO_A_CDC_SPKR_CLIPDET_VAL2__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL3] = TAIKO_A_CDC_SPKR_CLIPDET_VAL3__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL4] = TAIKO_A_CDC_SPKR_CLIPDET_VAL4__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL5] = TAIKO_A_CDC_SPKR_CLIPDET_VAL5__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL6] = TAIKO_A_CDC_SPKR_CLIPDET_VAL6__POR,
+	[TAIKO_A_CDC_SPKR_CLIPDET_VAL7] = TAIKO_A_CDC_SPKR_CLIPDET_VAL7__POR,
 };
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index cc22fd4..bfd496b 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -1551,6 +1551,9 @@
 		wcd9xxx_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
 		wcd9xxx_schedule_hs_detect_plug(mbhc,
 						&mbhc->correct_plug_swch);
+	} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
+		wcd9xxx_schedule_hs_detect_plug(mbhc,
+						&mbhc->correct_plug_swch);
 	} else {
 		pr_debug("%s: Valid plug found, determine plug type %d\n",
 			 __func__, plug_type);
@@ -2151,6 +2154,9 @@
 				wcd9xxx_report_plug(mbhc, 1,
 						    SND_JACK_HEADPHONE);
 			}
+		} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
+			pr_debug("%s: High HPH detected, continue polling\n",
+				  __func__);
 		} else {
 			if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
 				pt_gnd_mic_swap_cnt++;
@@ -2189,6 +2195,11 @@
 		}
 	}
 
+	if (plug_type == PLUG_TYPE_HIGH_HPH) {
+		pr_debug("%s: polling is done, still HPH, so enabling MIC trigger\n",
+			 __func__);
+		wcd9xxx_find_plug_and_report(mbhc, plug_type);
+	}
 	/* Turn off override */
 	if (!correction)
 		wcd9xxx_turn_onoff_override(codec, false);
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 66c475f..7fd62f1 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -180,7 +180,6 @@
 	select SND_SOC_MSM_STUB
 	select SND_SOC_MSM_HOSTLESS_PCM
 	select SND_SOC_WCD9320
-	select SND_SOC_MSM_HDMI_CODEC_RX
 	select SND_DYNAMIC_MINORS
 	select AUDIO_OCMEM
 	select DOLBY_DAP
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index e54f8b7..373090e 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -1302,7 +1302,7 @@
 			}
 			rc = wait_event_timeout(the_locks.flush_wait,
 				prtd->cmd_ack, 5 * HZ);
-			if (rc < 0)
+			if (!rc)
 				pr_err("Flush cmd timeout\n");
 			prtd->pcm_irq_pos = 0;
 		}
diff --git a/sound/soc/msm/msm-lowlatency-pcm-q6.c b/sound/soc/msm/msm-lowlatency-pcm-q6.c
index d5281e4..28e112c 100644
--- a/sound/soc/msm/msm-lowlatency-pcm-q6.c
+++ b/sound/soc/msm/msm-lowlatency-pcm-q6.c
@@ -434,7 +434,7 @@
 				__func__, atomic_read(&prtd->out_count));
 	ret = wait_event_timeout(the_locks.write_wait,
 			(atomic_read(&prtd->out_count)), 5 * HZ);
-	if (ret < 0) {
+	if (!ret) {
 		pr_err("%s: wait_event_timeout failed\n", __func__);
 		goto fail;
 	}
@@ -487,7 +487,7 @@
 	dir = IN;
 	ret = wait_event_timeout(the_locks.eos_wait,
 				prtd->cmd_ack, 5 * HZ);
-	if (ret < 0)
+	if (!ret)
 		pr_err("%s: CMD_EOS failed\n", __func__);
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 	q6asm_audio_client_buf_free_contiguous(dir,
@@ -525,7 +525,7 @@
 
 	ret = wait_event_timeout(the_locks.read_wait,
 			(atomic_read(&prtd->in_count)), 5 * HZ);
-	if (ret < 0) {
+	if (!ret) {
 		pr_debug("%s: wait_event_timeout failed\n", __func__);
 		goto fail;
 	}
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 26bf3d9..d620099 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -537,7 +537,7 @@
 				__func__, atomic_read(&prtd->out_count));
 	ret = wait_event_timeout(the_locks.write_wait,
 			(atomic_read(&prtd->out_count)), 5 * HZ);
-	if (ret < 0) {
+	if (!ret) {
 		pr_err("%s: wait_event_timeout failed\n", __func__);
 		goto fail;
 	}
@@ -590,7 +590,7 @@
 	dir = IN;
 	ret = wait_event_timeout(the_locks.eos_wait,
 				prtd->cmd_ack, 5 * HZ);
-	if (ret < 0)
+	if (!ret)
 		pr_err("%s: CMD_EOS failed\n", __func__);
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 	q6asm_audio_client_buf_free_contiguous(dir,
@@ -629,7 +629,7 @@
 
 	ret = wait_event_timeout(the_locks.read_wait,
 			(atomic_read(&prtd->in_count)), 5 * HZ);
-	if (ret < 0) {
+	if (!ret) {
 		pr_debug("%s: wait_event_timeout failed\n", __func__);
 		goto fail;
 	}
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 95c5cd7..bfab124 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -382,7 +382,7 @@
 		pr_debug("%s\n", __func__);
 		rc = wait_event_timeout(the_locks.eos_wait,
 			prtd->cmd_ack, 5 * HZ);
-		if (rc < 0)
+		if (!rc)
 			pr_err("EOS cmd timeout\n");
 		prtd->pcm_irq_pos = 0;
 	}
@@ -537,7 +537,7 @@
 			pr_err("%s: flush cmd failed rc=%d\n", __func__, rc);
 		rc = wait_event_timeout(the_locks.eos_wait,
 			prtd->cmd_ack, 5 * HZ);
-		if (rc < 0)
+		if (!rc)
 			pr_err("Flush cmd timeout\n");
 		prtd->pcm_irq_pos = 0;
 		break;
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 1d15c11..c37e932 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -419,7 +419,7 @@
 				__func__, atomic_read(&prtd->out_count));
 	ret = wait_event_timeout(the_locks.write_wait,
 			(atomic_read(&prtd->out_count)), 5 * HZ);
-	if (ret < 0) {
+	if (!ret) {
 		pr_err("%s: wait_event_timeout failed\n", __func__);
 		goto fail;
 	}
@@ -472,7 +472,7 @@
 	dir = IN;
 	ret = wait_event_timeout(the_locks.eos_wait,
 				prtd->cmd_ack, 5 * HZ);
-	if (ret < 0)
+	if (!ret)
 		pr_err("%s: CMD_EOS failed\n", __func__);
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 	q6asm_audio_client_buf_free_contiguous(dir,
@@ -510,7 +510,7 @@
 
 	ret = wait_event_timeout(the_locks.read_wait,
 			(atomic_read(&prtd->in_count)), 5 * HZ);
-	if (ret < 0) {
+	if (!ret) {
 		pr_debug("%s: wait_event_timeout failed\n", __func__);
 		goto fail;
 	}
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index 4db3ea5..02f6ff1 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -613,6 +613,21 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	{/* hw:x,13 */
+		.name = "Voice2",
+		.stream_name = "Voice2",
+		.cpu_dai_name   = "Voice2",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
 	/* Backend I2S DAI Links */
 	{
 		.name = LPASS_BE_SEC_MI2S_RX,
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 9558fa4..c4851f3 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -840,7 +840,7 @@
 	ret = wait_event_timeout(this_afe.wait,
 		(atomic_read(&this_afe.state) == 0),
 			msecs_to_jiffies(TIMEOUT_MS));
-	if (ret < 0) {
+	if (!ret) {
 		pr_err("%s: wait_event timeout\n", __func__);
 		ret = -EINVAL;
 		goto fail_cmd;
@@ -918,7 +918,7 @@
 	ret = wait_event_timeout(this_afe.wait,
 		(atomic_read(&this_afe.state) == 0),
 			msecs_to_jiffies(TIMEOUT_MS));
-	if (ret < 0) {
+	if (!ret) {
 		pr_err("%s: wait_event timeout\n", __func__);
 		ret = -EINVAL;
 		goto fail_cmd;
@@ -979,7 +979,7 @@
 	ret = wait_event_timeout(this_afe.wait,
 		(atomic_read(&this_afe.state) == 0),
 			msecs_to_jiffies(TIMEOUT_MS));
-	if (ret < 0) {
+	if (!ret) {
 		pr_err("%s: wait_event timeout\n", __func__);
 		ret = -EINVAL;
 		goto fail_cmd;
@@ -1731,7 +1731,7 @@
 	ret = wait_event_timeout(this_afe.wait,
 		(atomic_read(&this_afe.state) == 0),
 			msecs_to_jiffies(TIMEOUT_MS));
-	if (ret < 0) {
+	if (!ret) {
 		pr_err("%s: wait_event timeout\n", __func__);
 		ret = -EINVAL;
 		goto fail_cmd;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 95f31c4..6bccdb7 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -125,7 +125,6 @@
 	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) {
@@ -150,15 +149,9 @@
 		/*
 		 * check for underrun
 		 */
-		snd_pcm_stream_lock_irq(substream);
-		if (snd_pcm_playback_empty(substream)) {
+		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
+			pr_err("render stopped");
 			runtime->render_flag |= SNDRV_RENDER_STOPPED;
-			stop_playback = 1;
-		}
-		snd_pcm_stream_unlock_irq(substream);
-
-		if (stop_playback) {
-			pr_err("%s empty buffer, stop writes\n", __func__);
 			break;
 		}
 
@@ -629,10 +622,18 @@
 int compressed_set_volume(unsigned volume)
 {
 	int rc = 0;
+	int avg_vol = 0;
 	if (compressed_audio.prtd && compressed_audio.prtd->audio_client) {
-		rc = q6asm_set_lrgain(compressed_audio.prtd->audio_client,
-						(volume >> 16) & 0xFFFF,
-						volume & 0xFFFF);
+		if (compressed_audio.prtd->channel_mode > 2) {
+			avg_vol = (((volume >> 16) & 0xFFFF) +
+				   (volume & 0xFFFF)) / 2;
+			rc = q6asm_set_volume(
+				compressed_audio.prtd->audio_client, avg_vol);
+		} else {
+			rc = q6asm_set_lrgain(
+				compressed_audio.prtd->audio_client,
+				(volume >> 16) & 0xFFFF, volume & 0xFFFF);
+		}
 		if (rc < 0) {
 			pr_err("%s: Send Volume command failed rc=%d\n",
 						__func__, rc);
@@ -740,9 +741,17 @@
 	struct msm_audio *prtd = runtime->private_data;
 	struct audio_client *ac = prtd->audio_client;
 	struct audio_port_data *apd = ac->port;
-	struct audio_buffer *ab = &(apd[IN].buf[0]);
+	struct audio_buffer *ab;
+	int dir = -1;
+
 	prtd->mmap_flag = 1;
 
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dir = IN;
+	else
+		dir = OUT;
+	ab = &(apd[dir].buf[0]);
+
 	return msm_audio_ion_mmap(ab, vma);
 }
 
@@ -792,6 +801,11 @@
 			prtd->audio_client->perf_mode,
 			prtd->session_id,
 			substream->stream);
+		/* the number of channels are required to call volume api
+		   accoridngly. So, get channels from hw params */
+		if ((params_channels(params) > 0) &&
+		    (params_periods(params) <= runtime->hw.channels_max))
+			prtd->channel_mode = params_channels(params);
 
 		ret = compressed_set_volume(0);
 		if (ret < 0)
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
index e6934f6..9ace410 100644
--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -641,7 +641,7 @@
 		DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
 	int port_id = dolby_dap_params_states.port_id;
 	if (port_id == DOLBY_INVALID_PORT_ID) {
-		pr_err("%s, port_id not set, returning error", __func__);
+		pr_debug("%s, port_id not set, returning error", __func__);
 		ucontrol->value.integer.value[0] = 0;
 		return -EINVAL;
 	}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 2a64ae2..c4b44fe 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/msm_audio_ion.h>
 
 #include <sound/core.h>
 #include <sound/soc.h>
@@ -517,21 +518,21 @@
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct pcm_afe_info *prtd = runtime->private_data;
-	int result = 0;
+	struct afe_audio_client *ac = prtd->audio_client;
+	struct afe_audio_port_data *apd = ac->port;
+	struct afe_audio_buffer *ab;
+	int dir = -1;
 
 	pr_debug("%s\n", __func__);
 	prtd->mmap_flag = 1;
-	if (runtime->dma_addr && runtime->dma_bytes) {
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-		result = remap_pfn_range(vma, vma->vm_start,
-				runtime->dma_addr >> PAGE_SHIFT,
-				runtime->dma_bytes,
-				vma->vm_page_prot);
-	} else {
-		pr_err("Physical address or size of buf is NULL");
-		return -EINVAL;
-	}
-	return result;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dir = IN;
+	else
+		dir = OUT;
+	ab = &(apd[dir].buf[0]);
+
+	return msm_audio_ion_mmap((struct audio_buffer *)ab, vma);
 }
 static int msm_afe_trigger(struct snd_pcm_substream *substream, int cmd)
 {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 7055c57..9899f97 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -427,9 +427,17 @@
 	struct msm_audio *prtd = runtime->private_data;
 	struct audio_client *ac = prtd->audio_client;
 	struct audio_port_data *apd = ac->port;
-	struct audio_buffer *ab = &(apd[IN].buf[0]);
+	struct audio_buffer *ab;
+	int dir = -1;
+
 	prtd->mmap_flag = 1;
 
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dir = IN;
+	else
+		dir = OUT;
+	ab = &(apd[dir].buf[0]);
+
 	return msm_audio_ion_mmap(ab, vma);
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index f4ca5b8..0592d10 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -633,9 +633,17 @@
 	struct msm_audio *prtd = runtime->private_data;
 	struct audio_client *ac = prtd->audio_client;
 	struct audio_port_data *apd = ac->port;
-	struct audio_buffer *ab = &(apd[IN].buf[0]);
+	struct audio_buffer *ab;
+	int dir = -1;
+
 	prtd->mmap_flag = 1;
 
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dir = IN;
+	else
+		dir = OUT;
+	ab = &(apd[dir].buf[0]);
+
 	return msm_audio_ion_mmap(ab, vma);
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 70db200..d7148f1 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -410,7 +410,8 @@
 				msm_bedais[i].port_id;
 			port_id = srs_port_id = msm_bedais[i].port_id;
 			srs_send_params(srs_port_id, 1, 0);
-			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+			    (!perf_mode))
 				if (dolby_dap_init(port_id,
 						msm_bedais[i].channel) < 0)
 					pr_err("%s: Err init dolby dap\n",
@@ -453,7 +454,8 @@
 		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
 			adm_close(msm_bedais[i].port_id,
 				test_bit(fedai_id, &msm_bedais[i].perf_mode));
-			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+			    (!test_bit(fedai_id, &msm_bedais[i].perf_mode)))
 				dolby_dap_deinit(msm_bedais[i].port_id);
 		}
 	}
@@ -544,7 +546,8 @@
 				perf_mode);
 			port_id = srs_port_id = msm_bedais[reg].port_id;
 			srs_send_params(srs_port_id, 1, 0);
-			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+			    (!perf_mode))
 				if (dolby_dap_init(port_id, channels) < 0)
 					pr_err("%s: Err init dolby dap\n",
 						__func__);
@@ -558,7 +561,8 @@
 			INVALID_SESSION) {
 			perf_mode = test_bit(val, &msm_bedais[reg].perf_mode);
 			adm_close(msm_bedais[reg].port_id, perf_mode);
-			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+			    (!perf_mode))
 				dolby_dap_deinit(msm_bedais[reg].port_id);
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type,
@@ -3451,9 +3455,10 @@
 			adm_close(bedai->port_id,
 				test_bit(i, &(bedai->perf_mode)));
 			srs_port_id = -1;
-			clear_bit(i, &(bedai->perf_mode));
-			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+			    (!test_bit(i, &(bedai->perf_mode))))
 				dolby_dap_deinit(bedai->port_id);
+			clear_bit(i, &(bedai->perf_mode));
 		}
 	}
 
@@ -3539,7 +3544,8 @@
 				perf_mode);
 			port_id = srs_port_id = bedai->port_id;
 			srs_send_params(srs_port_id, 1, 0);
-			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
+			    (!perf_mode))
 				if (dolby_dap_init(port_id, channels) < 0)
 					pr_err("%s: Err init dolby dap\n",
 						__func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 9b3cc8d..f17fe5b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -109,10 +109,9 @@
 	wait_queue_head_t in_wait;
 
 	struct mutex lock;
-	struct mutex in_lock;
-	struct mutex out_lock;
 
 	spinlock_t dsp_lock;
+	spinlock_t dsp_ul_lock;
 
 	uint32_t mode;
 	uint32_t rate_type;
@@ -272,7 +271,7 @@
 		return;
 
 	/* Copy up-link packet into out_queue. */
-	spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
+	spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
 
 	/* discarding UL packets till start is received */
 	if (!list_empty(&prtd->free_out_queue) && prtd->capture_start) {
@@ -325,10 +324,10 @@
 		pr_debug("ul_pkt: pkt_len =%d, frame.len=%d\n", pkt_len,
 			buf_node->frame.len);
 		prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
-		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
+		spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 		snd_pcm_period_elapsed(prtd->capture_substream);
 	} else {
-		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
+		spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 		pr_err("UL data dropped\n");
 	}
 
@@ -526,6 +525,7 @@
 	struct voip_buf_node *buf_node = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
+	unsigned long dsp_flags;
 
 	int count = frames_to_bytes(runtime, frames);
 	pr_debug("%s: count = %d, frames=%d\n", __func__, count, (int)frames);
@@ -535,12 +535,13 @@
 				prtd->state == VOIP_STOPPED),
 				1 * HZ);
 	if (ret > 0) {
-		mutex_lock(&prtd->in_lock);
 		if (count <= VOIP_MAX_VOC_PKT_SIZE) {
+			spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
 			buf_node =
 				list_first_entry(&prtd->free_in_queue,
 						struct voip_buf_node, list);
 			list_del(&buf_node->list);
+			spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 			if (prtd->mode == MODE_PCM) {
 				ret = copy_from_user(&buf_node->frame.voc_pkt,
 							buf, count);
@@ -548,14 +549,15 @@
 			} else
 				ret = copy_from_user(&buf_node->frame,
 							buf, count);
+			spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
 			list_add_tail(&buf_node->list, &prtd->in_queue);
+			spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 		} else {
 			pr_err("%s: Write cnt %d is > VOIP_MAX_VOC_PKT_SIZE\n",
 				__func__, count);
 			ret = -ENOMEM;
 		}
 
-		mutex_unlock(&prtd->in_lock);
 	} else if (ret == 0) {
 		pr_err("%s: No free DL buffs\n", __func__);
 		ret = -ETIMEDOUT;
@@ -574,6 +576,7 @@
 	struct voip_buf_node *buf_node = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
+	unsigned long dsp_flags;
 
 	count = frames_to_bytes(runtime, frames);
 
@@ -585,12 +588,13 @@
 				1 * HZ);
 
 	if (ret > 0) {
-		mutex_lock(&prtd->out_lock);
 
 		if (count <= VOIP_MAX_VOC_PKT_SIZE) {
+			spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
 			buf_node = list_first_entry(&prtd->out_queue,
 					struct voip_buf_node, list);
 			list_del(&buf_node->list);
+			spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 			if (prtd->mode == MODE_PCM)
 				ret = copy_to_user(buf,
 						   &buf_node->frame.voc_pkt,
@@ -604,15 +608,17 @@
 					__func__, ret);
 				ret = -EFAULT;
 			}
+			spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
 			list_add_tail(&buf_node->list,
 						&prtd->free_out_queue);
+			spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
+
 		} else {
 			pr_err("%s: Read count %d > VOIP_MAX_VOC_PKT_SIZE\n",
 				__func__, count);
 			ret = -ENOMEM;
 		}
 
-		mutex_unlock(&prtd->out_lock);
 
 	} else if (ret == 0) {
 		pr_err("%s: No UL data available\n", __func__);
@@ -646,6 +652,7 @@
 	struct snd_pcm_substream *p_substream, *c_substream;
 	struct snd_pcm_runtime *runtime;
 	struct voip_drv_info *prtd;
+	unsigned long dsp_flags;
 
 	if (substream == NULL) {
 		pr_err("substream is NULL\n");
@@ -684,7 +691,7 @@
 			goto capt;
 		}
 		if (p_dma_buf->area != NULL) {
-			mutex_lock(&prtd->in_lock);
+			spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
 			list_for_each_safe(ptr, next, &prtd->in_queue) {
 				buf_node = list_entry(ptr,
 						struct voip_buf_node, list);
@@ -695,11 +702,11 @@
 						struct voip_buf_node, list);
 				list_del(&buf_node->list);
 			}
+			spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 			dma_free_coherent(p_substream->pcm->card->dev,
 				runtime->hw.buffer_bytes_max, p_dma_buf->area,
 				p_dma_buf->addr);
 			p_dma_buf->area = NULL;
-			mutex_unlock(&prtd->in_lock);
 		}
 		/* release out_queue and free_out_queue */
 capt:		c_substream = prtd->capture_substream;
@@ -713,7 +720,7 @@
 			goto done;
 		}
 		if (c_dma_buf->area != NULL) {
-			mutex_lock(&prtd->out_lock);
+			spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
 			list_for_each_safe(ptr, next, &prtd->out_queue) {
 				buf_node = list_entry(ptr,
 						struct voip_buf_node, list);
@@ -724,11 +731,11 @@
 						struct voip_buf_node, list);
 				list_del(&buf_node->list);
 			}
+			spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 			dma_free_coherent(c_substream->pcm->card->dev,
 				runtime->hw.buffer_bytes_max, c_dma_buf->area,
 				c_dma_buf->addr);
 			c_dma_buf->area = NULL;
-			mutex_unlock(&prtd->out_lock);
 		}
 done:
 		prtd->capture_substream = NULL;
@@ -899,19 +906,15 @@
 		for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
 			buf_node = (void *)dma_buf->area + offset;
 
-			mutex_lock(&voip_info.in_lock);
 			list_add_tail(&buf_node->list,
 					&voip_info.free_in_queue);
-			mutex_unlock(&voip_info.in_lock);
 			offset = offset + sizeof(struct voip_buf_node);
 		}
 	} else {
 		for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
 			buf_node = (void *) dma_buf->area + offset;
-			mutex_lock(&voip_info.out_lock);
 			list_add_tail(&buf_node->list,
 					&voip_info.free_out_queue);
-			mutex_unlock(&voip_info.out_lock);
 			offset = offset + sizeof(struct voip_buf_node);
 		}
 	}
@@ -1164,10 +1167,9 @@
 	memset(&voip_info, 0, sizeof(voip_info));
 	voip_info.mode = MODE_PCM;
 	mutex_init(&voip_info.lock);
-	mutex_init(&voip_info.in_lock);
-	mutex_init(&voip_info.out_lock);
 
 	spin_lock_init(&voip_info.dsp_lock);
+	spin_lock_init(&voip_info.dsp_ul_lock);
 
 	init_waitqueue_head(&voip_info.out_wait);
 	init_waitqueue_head(&voip_info.in_wait);
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index ed4e090..5f9d4db 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1187,24 +1187,7 @@
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
-	if (perf_mode) {
-		for (i = 0; i < num_copps; i++) {
-			int tmp;
-
-			tmp = afe_get_port_index(port_id[i]);
-			if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
-				rtac_add_adm_device(port_id[i], atomic_read(
-					&this_adm.copp_low_latency_id[tmp]),
-					path, session_id);
-				pr_debug("%s, copp_id: %d\n", __func__,
-					atomic_read(
-					&this_adm.copp_low_latency_id[tmp]));
-			} else {
-				pr_debug("%s: Invalid port index %d",
-					__func__, tmp);
-			}
-		}
-	} else {
+	if (!perf_mode) {
 		for (i = 0; i < num_copps; i++)
 			send_adm_cal(port_id[i], path);
 
@@ -1473,8 +1456,8 @@
 			goto fail_cmd;
 		}
 	}
-	if (!atomic_read(&this_adm.copp_cnt[index]) &&
-		!atomic_read(&this_adm.copp_low_latency_cnt[index])) {
+
+	if (!perf_mode) {
 		pr_debug("%s: remove adm device from rtac\n", __func__);
 		rtac_remove_adm_device(port_id);
 	}
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index f05f772..6615940 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -1948,6 +1948,7 @@
 		goto fail_cmd;
 	}
 	pr_debug("%s: mmap handle 0x%x\n", __func__, this_afe.mmap_handle);
+	kfree(mmap_region_cmd);
 	return 0;
 fail_cmd:
 	kfree(mmap_region_cmd);
@@ -2013,6 +2014,7 @@
 	if (ret)
 		pr_err("%s: AFE memory map cmd failed %d\n",
 		       __func__, ret);
+	kfree(mmap_region_cmd);
 	return ret;
 }
 int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 60999fa..26d9d48 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -4769,4 +4769,4 @@
 	return rc;
 }
 
-device_initcall(voice_init);
+late_initcall(voice_init);