Merge "msm: camera: Create v4l2 subdevice for flash modules"
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm-stats.txt
index 1b21007..3137e91 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm-stats.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-stats.txt
@@ -14,7 +14,7 @@
 
 Example:
 
-qcom,rpm-stats@0xfc19dbd0{
+qcom,rpm-stats@fc19dbd0 {
 		compatible = "qcom,rpm-stats";
 		reg = <0xfc19dbd0 0x1000>;
 		reg-names = "phys_addr_base";
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index a981eed..46173a0 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -12,41 +12,41 @@
   - interrupt-names : indicates interrupts passed to driver (via interrupts property) by name.
   "core_irq" is mandatory, "bam_irq" is mandatory only when BAM DMA engine is used,
   "status_irq" and "sdiowakeup_irq" are optional.
-  - qcom,sdcc-clk-rates : specifies supported SDCC clock frequencies, Units - Hz.
-  - qcom,sdcc-sup-voltages: specifies supported voltage ranges for card. Should always be
+  - qcom,clk-rates : specifies supported SDCC clock frequencies, Units - Hz.
+  - qcom,sup-voltages: specifies supported voltage ranges for card. Should always be
 			specified in pairs (min, max), Units - mV.
   - <supply-name>-supply: phandle to the regulator device tree node
   "supply-name" examples are "vdd", "vdd-io".
 
 Optional Properties:
 	- cell-index - defines slot ID.
-	- qcom,sdcc-bus-width - defines the bus I/O width that controller supports.
+	- qcom,bus-width - defines the bus I/O width that controller supports.
 	- wp-gpios - specify GPIO for write protect switch detection.
 	- cd-gpios - specify GPIO for card detection.
-	- qcom,sdcc-nonremovable - specifies whether the card in slot is
+	- qcom,nonremovable - specifies whether the card in slot is
 				hot pluggable or hard wired.
-	- qcom,sdcc-disable_cmd23 - disable sending CMD23 to card when controller can't support it.
-	- qcom,sdcc-bus-speed-mode - specifies supported bus speed modes by host.
-	- qcom,sdcc-current-limit - specifies max. current the host can drive.
-	- qcom,sdcc-xpc - specifies if the host can supply more than 150mA for SDXC cards.
+	- qcom,disable-cmd23 - disable sending CMD23 to card when controller can't support it.
+	- qcom,bus-speed-mode - specifies supported bus speed modes by host.
+	- qcom,current-limit - specifies max. current the host can drive.
+	- qcom,xpc - specifies if the host can supply more than 150mA for SDXC cards.
 	- qcom,dat1-mpm-int - specifies MPM interrupt number corresponding to DAT1 line of SDCC
 					(used only if slot has dedicated DAT1 MSM pin (not GPIO))
 
 In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage).
-	- qcom,sdcc-<supply>-always_on - specifies whether supply should be kept "on" always.
-	- qcom,sdcc-<supply>-lpm_sup - specifies whether supply can be kept in low power mode (lpm).
-	- qcom,sdcc-<supply>-voltage_level - specifies voltage levels for supply. Should be
+	- qcom,<supply>-always-on - specifies whether supply should be kept "on" always.
+	- qcom,<supply>-lpm-sup - specifies whether supply can be kept in low power mode (lpm).
+	- qcom,<supply>-voltage-level - specifies voltage levels for supply. Should be
 	specified in pairs (min, max), units uV.
-	- qcom,sdcc-<supply>-current_level - specifies load levels for supply in lpm or
+	- qcom,<supply>-current-level - specifies load levels for supply in lpm or
 	high power mode (hpm). Should be specified in pairs (lpm, hpm), units uA.
 
 	- gpios - specifies gpios assigned for sdcc slot.
-	- qcom,sdcc-gpio-names -  a list of strings that map in order to the list of gpios
+	- qcom,gpio-names -  a list of strings that map in order to the list of gpios
 	A slot has either gpios or dedicated tlmm pins as represented below.
-	- qcom,sdcc-pad-pull-on - Active pull configuration for sdc tlmm pins
-	- qcom,sdcc-pad-pull-off - Suspend pull configuration for sdc tlmm pins.
-	- qcom,sdcc-pad-drv-on - Active drive strength configuration for sdc tlmm pins.
-	- qcom,sdcc-pad-drv-off - Suspend drive strength configuration for sdc tlmm pins.
+	- qcom,pad-pull-on - Active pull configuration for sdc tlmm pins
+	- qcom,pad-pull-off - Suspend pull configuration for sdc tlmm pins.
+	- qcom,pad-drv-on - Active drive strength configuration for sdc tlmm pins.
+	- qcom,pad-drv-off - Suspend drive strength configuration for sdc tlmm pins.
 	Tlmm pins are specified as <clk cmd data>
 
 	- qcom,bus-bw-vectors-bps - specifies array of throughput values in Bytes/sec. The
@@ -71,10 +71,10 @@
 		0xf9602000 0x2000> // BAM register interface
 
 	interrupts = <123>;
-	qcom,sdcc-clk-rates = <400000 24000000 48000000>;
-	qcom,sdcc-sup-voltages = <2700 3300>;
-	qcom,sdcc-bus-width = <8>; //8-bit wide
-	qcom,sdcc-nonremovable;
+	qcom,clk-rates = <400000 24000000 48000000>;
+	qcom,sup-voltages = <2700 3300>;
+	qcom,bus-width = <8>; //8-bit wide
+	qcom,nonremovable;
 
 	qcom,msm-bus,name = "sdcc2";
 	qcom,msm-bus,num-cases = <7>;
diff --git a/Documentation/devicetree/bindings/power/smb137c-charger.txt b/Documentation/devicetree/bindings/power/smb137c-charger.txt
new file mode 100644
index 0000000..c0c4333
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/smb137c-charger.txt
@@ -0,0 +1,86 @@
+Summit SMB137C Battery Charger
+
+The SMB137C is controlled via an I2C bus.  Its 7-bit I2C slave address is
+programmed during manufacturing.
+
+Required properties:
+- compatible:		Must be "summit,smb137c".
+- reg:			The device's 7-bit I2C address.
+
+Optional properties:
+- summit,chg-current-ma		Maximum battery charging current in milliamps.
+				Supported values are: 500, 650, 750, 850, 950,
+				1100, 1300, and 1500.
+- summit,term-current-ma	Charging terminaton current in milliamps.
+				Supported values are: 0, 35, 50, 100, and 150.
+				A value of 0 means no termination current is
+				used.
+- summit,pre-chg-current-ma	Maximum battery pre-charging current in
+				milliamps.  This current limit is applied while
+				the battery voltage is below the pre-charge /
+				fast-charge threshold.  Supported values are:
+				50, 100, 150, and 200.
+- summit,float-voltage-mv	Battery voltage threshold in millivolts at which
+				point charging switches from constant current to
+				constant voltage.  Supported values are: 3460 up
+				through 4730 in 10 mV steps.
+- summit,thresh-voltage-mv	Threshold voltage in millivolts which is used to
+				switch between pre-charge and fast-charge
+				current limits.  Supported values are: 2400 up
+				to 3100 in 100 mV steps.
+- summit,recharge-thresh-mv	Specifies the minimum voltage drop in millivolts
+				below the float voltage that is required in
+				order to initiate a new charging cycle.
+				Supported values are: 75 and 120.
+- summit,system-voltage-mv	Regulated voltage output on the VOUTL pin in
+				millivolts.  Supported values are 4250 and 4460.
+- summit,charging-timeout	Maximum duration in minutes that a single charge
+				cycle may last.  Supported values are: 0, 382,
+				764, and 1527.  A value of 0 means that no
+				charge cycle timeout is used and charging can
+				continue indefinitely.
+- summit,pre-charge-timeout	Maximum time in minutes spent in the pre-charge
+				state in any given charge cycle.  Supports
+				values are: 0, 48, 95, and 191.  A value of 0
+				means that there is no limit to the amount of
+				time that may be spent in the pre-charge state.
+- summit,therm-current-ua	Thermistor current in microamps to be used for
+				battery temperature monitoring.  Supported
+				values are 10, 20, 40, and 100.  These values
+				correspond to 100, 50, 25, and 10 kohm NTC
+				thermistors respectively.
+- summit,temperature-min	Specifies the minimum temperature at which
+				charging is allowed.  Supported values are
+				0 to 7.  These values correspond to -20 C to
+				+15 C in 5 C increments for an NTC thermistor
+				with beta = 4400.
+- summit,temperature-max	Specifies the maximum temperature at which
+				charging is allowed.  Supported values are
+				0 to 7.  These values correspond to +30 C to
+				+65 C in 5 C increments for an NTC thermistor
+				with beta = 4400.
+
+Note: If an optional property is not specified, then the hardware default value
+will be used.
+
+Example:
+/ {
+	i2c@f9925000 {
+		charger@57 {
+			compatible = "summit,smb137c";
+			reg = <0x57>;
+			summit,chg-current-ma = <1500>;
+			summit,term-current-ma = <50>;
+			summit,pre-chg-current-ma = <100>;
+			summit,float-voltage-mv = <4200>;
+			summit,thresh-voltage-mv = <3000>;
+			summit,recharge-thresh-mv = <75>;
+			summit,system-voltage-mv = <4250>;
+			summit,charging-timeout = <382>;
+			summit,pre-charge-timeout = <48>;
+			summit,therm-current-ua = <10>;
+			summit,temperature-min = <4>; /*  0 C */
+			summit,temperature-max = <3>; /* 45 C */
+		};
+	};
+};
diff --git a/Documentation/trace/events-msm-low-power.txt b/Documentation/trace/events-msm-low-power.txt
new file mode 100644
index 0000000..5414146
--- /dev/null
+++ b/Documentation/trace/events-msm-low-power.txt
@@ -0,0 +1,57 @@
+Subsystem Trace Points: msm_low_power
+
+The msm_low_power tracing system captures the events during the entry
+and exit of various low power modes like power collapse, standalone
+power collapse, retention and wfi. The tracing system adds the following
+events to capture the state of the low power mode.
+
+1) msm_pm_enter
+===================
+msm_pm_enter: cpu: %u latency: %uus sleep: %uus
+msm_pm_enter_pc: cpu: %u latency: %uus sleep: %uus wake_up: %u
+msm_pm_enter_ret: cpu: %u latency: %uus sleep: %uus wake_up: %u
+msm_pm_enter_spc: cpu: %u latency: %uus sleep: %uus wake_up: %u
+msm_pm_enter_wfi: cpu: %u latency: %uus sleep: %uus wake_up: %u
+
+The event captures various parameters during the entry into low power
+modes.
+
+The 'cpu' parameter represents the cpu on which the low power mode is
+chosen.
+
+The 'latency_us' parameter represents the system latency at the time of
+choosing the low power mode.
+
+The 'sleep_us' parameter tells the maximum amount of time the kernel can
+sleep in this low power mode.
+
+The 'wake_up' parameter tells if there was any immediate wakeup required
+before entering low power mode.
+
+2) msm_pm_exit
+=================
+msm_pm_exit: cpu:%u success:%d
+msm_pm_exit_pc: cpu:%u success:%d
+msm_pm_exit_ret: cpu:%u success:%d
+msm_pm_exit_spc: cpu:%u success:%d
+msm_pm_exit_wfi: cpu:%u success:%d
+
+The event captures parameters during the exit of the low power modes.
+
+The 'cpu' parameter represents the cpu on which the low power mode is chosen.
+
+The 'success' parameter shows the state of power collapse/standalone power
+collapse. It will be set if power collapse/standalone power collapse were
+successful. For the rest of the low power modes it is set to one.
+
+3) lpm_resources
+=================
+lpm_resources: name:%s sleep_value:%d
+
+This event captures parameters for each of the lpm resources.
+
+The 'name' parameter represents the name of the lpm resource and it can hold
+l2, pxo, vdd mem, vdd dig depending on the resource chosen during power
+collapse.
+
+The 'sleep_value' parameter corresponds to the sleep value set for the resource.
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 7398b25..7961b78 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -238,16 +238,16 @@
 		interrupts = <0 123 0>;
 		interrupt-names = "core_irq";
 
-		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
-		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+		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 = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <8>;
-		qcom,sdcc-nonremovable;
-		qcom,sdcc-bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <8>;
+		qcom,nonremovable;
+		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
 	};
 
 	sdcc2: qcom,sdcc@f98a4000 {
@@ -258,17 +258,17 @@
 		interrupts = <0 125 0>;
 		interrupt-names = "core_irq";
 
-		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
-		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+		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 = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <4>;
-		qcom,sdcc-xpc;
-		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-		qcom,sdcc-current-limit = <800>;
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <4>;
+		qcom,xpc;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+		qcom,current-limit = <800>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 21d8c8c..4ec5684 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -136,14 +136,14 @@
 						<0x0 0x10 0x6>,
 						<0x0 0x10 0x7>;
 
-				interrupt-names =	"chg-done",
-							"chg-failed",
-							"fast-chg-on",
-							"trkl-chg-on",
-							"state-change",
-							"chgwdog",
+				interrupt-names =	"vbat-det-lo",
 							"vbat-det-hi",
-							"vbat-det-lo";
+							"chgwdog",
+							"state-change",
+							"trkl-chg-on",
+							"fast-chg-on",
+							"chg-failed",
+							"chg-done";
 			};
 
 			qcom,chg-buck@1100 {
@@ -157,13 +157,13 @@
 						<0x0 0x11 0x5>,
 						<0x0 0x11 0x6>;
 
-				interrupt-names =	"vdd-loop",
-							"ibat-loop",
-							"ichg-loop",
-							"vchg-loop",
+				interrupt-names =	"vbat-ov",
+							"vreg-ov",
 							"overtemp",
-							"vref-ov",
-							"vbat-ov";
+							"vchg-loop",
+							"ichg-loop",
+							"ibat-loop",
+							"vdd-loop";
 			};
 
 			qcom,chg-bat-if@1200 {
@@ -175,11 +175,12 @@
 						<0x0 0x12 0x3>,
 						<0x0 0x12 0x4>;
 
-				interrupt-names =	"psi",
-							"vcp-on",
-							"bat-fet-on",
+				interrupt-names =	"batt-pres",
 							"bat-temp-ok",
-							"batt-pres";
+							"bat-fet-on",
+							"vcp-on",
+							"psi";
+
 			};
 
 			qcom,chg-usb-chgpth@1300 {
@@ -200,8 +201,8 @@
 				interrupts =	<0x0 0x14 0x0>,
 						<0x0 0x14 0x1>;
 
-				interrupt-names =	"dcin-valid",
-							"coarse-det-dc";
+				interrupt-names =	"coarse-det-dc",
+							"dcin-valid";
 			};
 
 			qcom,chg-boost@1500 {
@@ -210,8 +211,8 @@
 				interrupts =	<0x0 0x15 0x0>,
 						<0x0 0x15 0x1>;
 
-				interrupt-names =	"limit-error",
-							"boost-pwr-ok";
+				interrupt-names =	"boost-pwr-ok",
+							"limit-error";
 			};
 
 			qcom,chg-misc@1600 {
diff --git a/arch/arm/boot/dts/msm8226-ion.dtsi b/arch/arm/boot/dts/msm8226-ion.dtsi
index beaffe5..b06ad42 100644
--- a/arch/arm/boot/dts/msm8226-ion.dtsi
+++ b/arch/arm/boot/dts/msm8226-ion.dtsi
@@ -19,5 +19,33 @@
 		qcom,ion-heap@30 { /* SYSTEM HEAP */
 			reg = <30>;
 		};
+
+		qcom,ion-heap@8 { /* CP_MM HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <8>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+			qcom,memory-reservation-size = <0x3800000>;
+		};
+
+		qcom,ion-heap@25 { /* IOMMU HEAP */
+			reg = <25>;
+		};
+
+		qcom,ion-heap@27 { /* QSECOM HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <27>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+			qcom,memory-reservation-size = <0x780000>;
+		};
+
+		qcom,ion-heap@28 { /* AUDIO HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <28>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+			qcom,memory-reservation-size = <0x314000>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index 7c25680..41ac69d 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -12,7 +12,6 @@
 
 /dts-v1/;
 /include/ "msm8226.dtsi"
-/include/ "msm8226-ion.dtsi"
 /include/ "msm8226-camera.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index db2bfb3..f0e950a 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -11,6 +11,7 @@
  */
 
 /include/ "skeleton.dtsi"
+/include/ "msm8226-ion.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226";
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index a2e1338..1f3c1d8 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -51,6 +51,9 @@
 		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0>;
 		interrupt-names = "core_irq";
+		HSUSB_VDDCX-supply = <&pm8110_s1>;
+		HSUSB_1p8-supply = <&pm8110_l10>;
+		HSUSB_3p3-supply = <&pm8110_l20>;
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
@@ -70,16 +73,16 @@
 		interrupts = <0 123 0>;
 		interrupt-names = "core_irq";
 
-		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
-		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+		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 = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <8>;
-		qcom,sdcc-nonremovable;
-		qcom,sdcc-bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <8>;
+		qcom,nonremovable;
+		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
 	};
 
 	sdcc2: qcom,sdcc@f98a4000 {
@@ -90,17 +93,17 @@
 		interrupts = <0 125 0>;
 		interrupt-names = "core_irq";
 
-		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
-		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+		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 = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <4>;
-		qcom,sdcc-xpc;
-		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-		qcom,sdcc-current-limit = <800>;
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <4>;
+		qcom,xpc;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+		qcom,current-limit = <800>;
 	};
 
 };
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 93f92c7..938bc22 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -155,7 +155,7 @@
 };
 
 &sdcc1 {
-	qcom,sdcc-bus-width = <4>;
+	qcom,bus-width = <4>;
 };
 
 &sdcc2 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 002332b..68207af 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -180,6 +180,10 @@
 	};
 };
 
+&usb3 {
+	qcom,charging-disabled;
+};
+
 &pm8941_mvs1 {
 	parent-supply = <&ext_5v>;
 };
diff --git a/arch/arm/boot/dts/msm8974-rumi.dtsi b/arch/arm/boot/dts/msm8974-rumi.dtsi
index d4b7793..5a16be7 100644
--- a/arch/arm/boot/dts/msm8974-rumi.dtsi
+++ b/arch/arm/boot/dts/msm8974-rumi.dtsi
@@ -24,11 +24,11 @@
 	};
 
 	qcom,sdcc@f9824000 {
-                qcom,sdcc-clk-rates = <400000 19200000>;
+                qcom,clk-rates = <400000 19200000>;
         };
 
         qcom,sdcc@f98a4000 {
-                qcom,sdcc-clk-rates = <400000 19200000>;
+                qcom,clk-rates = <400000 19200000>;
         };
 
 	qcom,sps@f998000 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 83e1141..98f0b3b 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -137,25 +137,25 @@
 		vdd-supply = <&pm8941_l20>;
 		vdd-io-supply = <&pm8941_s3>;
 
-		qcom,sdcc-vdd-always_on;
-		qcom,sdcc-vdd-lpm_sup;
-		qcom,sdcc-vdd-voltage_level = <2950000 2950000>;
-		qcom,sdcc-vdd-current_level = <800 500000>;
+		qcom,vdd-always-on;
+		qcom,vdd-lpm-sup;
+		qcom,vdd-voltage-level = <2950000 2950000>;
+		qcom,vdd-current-level = <800 500000>;
 
-		qcom,sdcc-vdd-io-always_on;
-		qcom,sdcc-vdd-io-voltage_level = <1800000 1800000>;
-		qcom,sdcc-vdd-io-current_level = <250 154000>;
+		qcom,vdd-io-always-on;
+		qcom,vdd-io-voltage-level = <1800000 1800000>;
+		qcom,vdd-io-current-level = <250 154000>;
 
-		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
-		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+		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 = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <8>;
-		qcom,sdcc-nonremovable;
-		qcom,sdcc-bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <8>;
+		qcom,nonremovable;
+		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
 
 		qcom,msm-bus,name = "sdcc1";
 		qcom,msm-bus,num-cases = <7>;
@@ -184,25 +184,25 @@
 		vdd-supply = <&pm8941_l21>;
 		vdd-io-supply = <&pm8941_l13>;
 
-		qcom,sdcc-vdd-voltage_level = <2950000 2950000>;
-		qcom,sdcc-vdd-current_level = <9000 800000>;
+		qcom,vdd-voltage-level = <2950000 2950000>;
+		qcom,vdd-current-level = <9000 800000>;
 
-		qcom,sdcc-vdd-io-always_on;
-		qcom,sdcc-vdd-io-lpm_sup;
-		qcom,sdcc-vdd-io-voltage_level = <1800000 2950000>;
-		qcom,sdcc-vdd-io-current_level = <6 22000>;
+		qcom,vdd-io-always-on;
+		qcom,vdd-io-lpm-sup;
+		qcom,vdd-io-voltage-level = <1800000 2950000>;
+		qcom,vdd-io-current-level = <6 22000>;
 
-		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
-		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+		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 = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <4>;
-		qcom,sdcc-xpc;
-		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-		qcom,sdcc-current-limit = <800>;
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <4>;
+		qcom,xpc;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+		qcom,current-limit = <800>;
 
 		qcom,msm-bus,name = "sdcc2";
 		qcom,msm-bus,num-cases = <7>;
@@ -242,12 +242,12 @@
 			<&msmgpio 37 0>, /* DATA1 */
 			<&msmgpio 36 0>, /* DATA2 */
 			<&msmgpio 35 0>; /* DATA3 */
-		qcom,sdcc-gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
-		qcom,sdcc-sup-voltages = <1800 1800>;
-		qcom,sdcc-bus-width = <4>;
-		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50";
+		qcom,clk-rates = <400000 25000000 50000000 100000000>;
+		qcom,sup-voltages = <1800 1800>;
+		qcom,bus-width = <4>;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50";
 
 		qcom,msm-bus,name = "sdcc3";
 		qcom,msm-bus,num-cases = <7>;
@@ -287,12 +287,12 @@
 			<&msmgpio 95 0>, /* DATA1 */
 			<&msmgpio 94 0>, /* DATA2 */
 			<&msmgpio 92 0>; /* DATA3 */
-		qcom,sdcc-gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
-		qcom,sdcc-sup-voltages = <1800 1800>;
-		qcom,sdcc-bus-width = <4>;
-		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50";
+		qcom,clk-rates = <400000 25000000 50000000 100000000>;
+		qcom,sup-voltages = <1800 1800>;
+		qcom,bus-width = <4>;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50";
 
 		qcom,msm-bus,name = "sdcc4";
 		qcom,msm-bus,num-cases = <7>;
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 86e0cf7..d62f7e7 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -204,4 +204,11 @@
 		qcom,pc-mode = <2>; /*MSM_PC_TZ_L2_EXT */
 		qcom,use-sync-timer;
 	};
+
+	qcom,rpm-stats@fc19dbd0 {
+		compatible = "qcom,rpm-stats";
+		reg = <0xfc19dbd0 0x1000>;
+		reg-names = "phys_addr_base";
+		qcom,sleep-stats-version = <2>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm9625-regulator.dtsi b/arch/arm/boot/dts/msm9625-regulator.dtsi
index dccc723..ec8864f 100644
--- a/arch/arm/boot/dts/msm9625-regulator.dtsi
+++ b/arch/arm/boot/dts/msm9625-regulator.dtsi
@@ -215,7 +215,7 @@
 		status = "okay";
 		pm8019_l12: regulator-l12 {
 			parent-supply = <&pm8019_s3>;
-			regulator-min-microvolt = <750000>;
+			regulator-min-microvolt = <675000>;
 			regulator-max-microvolt = <1050000>;
 			status = "okay";
 		};
@@ -224,10 +224,20 @@
 			regulator-name = "8019_l12_ao";
 			qcom,set = <1>;
 			parent-supply = <&pm8019_s3_ao>;
-			regulator-min-microvolt = <750000>;
+			regulator-min-microvolt = <675000>;
 			regulator-max-microvolt = <1050000>;
 			status = "okay";
 		};
+		pm8019_l12_so: regulator-l12-so {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8019_l12_so";
+			qcom,set = <2>;
+			parent-supply = <&pm8019_s3>;
+			regulator-min-microvolt = <675000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,init-voltage = <675000>;
+			status = "okay";
+		};
 	};
 
 	rpm-regulator-ldoa13 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 3d2515d..c54b3f6 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -184,22 +184,22 @@
 		vdd-supply = <&ext_2p95v>;
 
 		vdd-io-supply = <&pm8019_l13>;
-		qcom,sdcc-vdd-io-always_on;
-		qcom,sdcc-vdd-io-lpm_sup;
-		qcom,sdcc-vdd-io-voltage_level = <1800000 2950000>;
-		qcom,sdcc-vdd-io-current_level = <6 22000>;
+		qcom,vdd-io-always-on;
+		qcom,vdd-io-lpm-sup;
+		qcom,vdd-io-voltage-level = <1800000 2950000>;
+		qcom,vdd-io-current-level = <6 22000>;
 
-		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>;
-		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>;
-		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>;
-		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>;
+		qcom,pad-pull-on = <0x0 0x3 0x3>;
+		qcom,pad-pull-off = <0x0 0x3 0x3>;
+		qcom,pad-drv-on = <0x7 0x4 0x4>;
+		qcom,pad-drv-off = <0x0 0x0 0x0>;
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <4>;
-		qcom,sdcc-xpc;
-		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
-		qcom,sdcc-current-limit = <800>;
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <4>;
+		qcom,xpc;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+		qcom,current-limit = <800>;
 
 		interrupt-parent = <&sdcc2>;
 		#address-cells = <0>;
@@ -229,12 +229,12 @@
 			<&msmgpio 17 0>,
 			<&msmgpio 18 0>,
 			<&msmgpio 19 0>;
-		qcom,sdcc-gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
 
-		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
-		qcom,sdcc-sup-voltages = <2950 2950>;
-		qcom,sdcc-bus-width = <4>;
-		qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50";
+		qcom,clk-rates = <400000 25000000 50000000 100000000>;
+		qcom,sup-voltages = <2950 2950>;
+		qcom,bus-width = <4>;
+		qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50";
 	};
 
 	qcom,bam_dmux@fc834000 {
@@ -328,4 +328,10 @@
 		qcom,hw-settle-time = <0>;
 		qcom,fast-avg-setup = <0>;
 	};
+
+	qcom,msm-rng@f9bff000 {
+		compatible = "qcom,msm-rng";
+		reg = <0xf9bff000 0x200>;
+		qcom,msm-rng-iface-clk;
+	};
 };
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index fe6a7da..5876a0f 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -102,6 +102,8 @@
 # CONFIG_HWMON is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_STUB=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
 CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
 CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index a613932..33c7718 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -464,6 +464,7 @@
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
 CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 0d63836..8c11368 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -467,6 +467,7 @@
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
 CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 7bfe3fe..5e1fa4a 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -48,6 +48,7 @@
 CONFIG_MSM_BAM_DMUX=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index af832cb..4d68a72 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -46,6 +46,7 @@
 CONFIG_MSM_BAM_DMUX=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_SYSMON_COMM=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 176696c..dbb4328 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -266,6 +266,7 @@
 	select MSM_RUN_QUEUE_STATS
 	select MEMORY_HOLE_CARVEOUT
 	select MSM_RPM_STATS_LOG
+	select QMI_ENCDEC
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
@@ -347,6 +348,7 @@
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MSM_MULTIMEDIA_USE_ION
+	select MSM_RPM_STATS_LOG
 
 config ARCH_MSM8910
 	bool "MSM8910"
@@ -1516,6 +1518,17 @@
 	help
 	  SMD Transport Layer for IPC Router
 
+config MSM_QMI_INTERFACE
+	depends on MSM_IPC_ROUTER
+	depends on QMI_ENCDEC
+	default n
+	bool "MSM QMI Interface Library"
+	help
+	  Library to send and receive QMI messages over IPC Router.
+	  This library provides interface functions to the kernel drivers
+	  to perform QMI message marshaling and transport them over IPC
+	  Router.
+
 config MSM_ONCRPCROUTER_DEBUG
 	depends on MSM_ONCRPCROUTER
 	default y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 403c32c..88ed433 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -138,6 +138,7 @@
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_device.o
 obj-$(CONFIG_MSM_IPC_ROUTER) += ipc_router.o
 obj-$(CONFIG_MSM_IPC_ROUTER)+= ipc_socket.o
+obj-$(CONFIG_MSM_QMI_INTERFACE) += msm_qmi_interface.o
 obj-$(CONFIG_DEBUG_FS) += smd_rpc_sym.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_servers.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
diff --git a/arch/arm/mach-msm/acpuclock-9625.c b/arch/arm/mach-msm/acpuclock-9625.c
index 7fd00e6..b0556c3 100644
--- a/arch/arm/mach-msm/acpuclock-9625.c
+++ b/arch/arm/mach-msm/acpuclock-9625.c
@@ -386,7 +386,7 @@
 {
 	unsigned long max_cpu_khz = 0;
 	struct resource *res;
-	int i;
+	int i, rc;
 	u32 regval;
 
 	mutex_init(&drv_data.lock);
@@ -447,12 +447,43 @@
 				acpu_freq_tbl[i].use_for_scaling; i++)
 		max_cpu_khz = acpu_freq_tbl[i].khz;
 
+	/* Initialize regulators */
+	rc = increase_vdd(acpu_freq_tbl[i].vdd_cpu, acpu_freq_tbl[i].vdd_mem);
+	if (rc)
+		goto err_vdd;
+
+	rc = regulator_enable(drv_data.vdd_mem);
+	if (rc) {
+		dev_err(&pdev->dev, "regulator_enable for a5_mem failed\n");
+		goto err_vdd;
+	}
+
+	rc = regulator_enable(drv_data.vdd_cpu);
+	if (rc) {
+		dev_err(&pdev->dev, "regulator_enable for a5_cpu failed\n");
+		goto err_vdd_cpu;
+	}
+
 	acpuclk_9625_set_rate(smp_processor_id(), max_cpu_khz, SETRATE_INIT);
 
 	acpuclk_register(&acpuclk_9625_data);
 	cpufreq_table_init();
 
 	return 0;
+
+err_vdd_cpu:
+	regulator_disable(drv_data.vdd_mem);
+err_vdd:
+	regulator_put(drv_data.vdd_mem);
+	regulator_put(drv_data.vdd_cpu);
+
+	for (i = 0; i < NUM_SRC; i++) {
+		if (!src_clocks[i].name)
+			continue;
+		clk_unprepare(src_clocks[i].clk);
+		clk_put(src_clocks[i].clk);
+	}
+	return rc;
 }
 
 static struct of_device_id acpuclk_9625_match_table[] = {
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 4ea9d8e..58f6f66 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1388,7 +1388,7 @@
 	/* T6 Object */
 	0, 0, 0, 0, 0, 0,
 	/* T38 Object */
-	14, 3, 0, 5, 7, 12, 0, 0, 0, 0,
+	14, 4, 0, 5, 11, 12, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1396,7 +1396,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0,
 	/* T7 Object */
-	32, 10, 50,
+	32, 8, 50,
 	/* T8 Object */
 	25, 0, 20, 20, 0, 0, 0, 0, 0, 0,
 	/* T9 Object */
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 980f312..e5263c7 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -43,6 +43,21 @@
 #include "board-dt.h"
 #include "clock.h"
 
+static struct memtype_reserve msm8226_reserve_table[] __initdata = {
+	[MEMTYPE_SMI] = {
+	},
+	[MEMTYPE_EBI0] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+	[MEMTYPE_EBI1] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+static int msm8226_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
 static struct clk_lookup msm_clocks_dummy[] = {
 	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
 	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
@@ -55,6 +70,23 @@
 	.size = ARRAY_SIZE(msm_clocks_dummy),
 };
 
+static struct reserve_info msm8226_reserve_info __initdata = {
+	.memtype_reserve_table = msm8226_reserve_table,
+	.paddr_to_memtype = msm8226_paddr_to_memtype,
+};
+
+static void __init msm8226_early_memory(void)
+{
+	reserve_info = &msm8226_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8226_reserve_table);
+}
+
+static void __init msm8226_reserve(void)
+{
+	msm_reserve();
+}
+
+
 void __init msm8226_init(void)
 {
 	msm8226_init_gpiomux();
@@ -78,4 +110,6 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_dt_timer,
 	.dt_compat = msm8226_dt_match,
+	.reserve = msm8226_reserve,
+	.init_very_early = msm8226_early_memory
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index cef967c..e5b7678 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -37,7 +37,7 @@
 
 static struct gpiomux_setting gsbi5 = {
 	.func = GPIOMUX_FUNC_1,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 2f3ab7f..e0a6b4d 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -762,6 +762,7 @@
 	.disable_reset_on_disconnect	= true,
 	.enable_lpm_on_dev_suspend	= true,
 	.core_clk_always_on_workaround = true,
+	.delay_lpm_on_disconnect = true,
 };
 
 
@@ -907,6 +908,7 @@
 	&msm_cpu_fe,
 	&msm_stub_codec,
 	&msm_voice,
+	&msm_dtmf,
 	&msm_voip,
 	&msm_i2s_cpudai0,
 	&msm_i2s_cpudai1,
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index c4e174b..cb977fa 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -36,6 +36,12 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting gpio_i2c_config = {
+	.func = GPIOMUX_FUNC_3,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
 	{
 		.gpio      = 8,	       /* BLSP1 UART TX */
@@ -50,6 +56,18 @@
 		},
 	},
 	{
+		.gpio      = 10,		/* BLSP1 QUP3 I2C_DAT */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
+	{
+		.gpio      = 11,		/* BLSP1 QUP3 I2C_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
+	{
 		.gpio      = 69,		/* BLSP6 QUP SPI_CS_N */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index a41fc06..3e5fc9d 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -35,6 +35,7 @@
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
 #include "board-dt.h"
+#include <mach/msm_bus_board.h>
 #include "clock.h"
 #include "modem_notifier.h"
 #include "lpm_resources.h"
@@ -253,6 +254,97 @@
 	}
 };
 
+#define BIMC_BASE	0xfc380000
+#define BIMC_SIZE	0x0006A000
+#define SYS_NOC_BASE	0xfc460000
+#define PERIPH_NOC_BASE 0xFC468000
+#define CONFIG_NOC_BASE	0xfc480000
+#define NOC_SIZE	0x00004000
+
+static struct resource bimc_res[] = {
+	{
+		.start = BIMC_BASE,
+		.end = BIMC_BASE + BIMC_SIZE,
+		.flags = IORESOURCE_MEM,
+		.name = "bimc_mem",
+	},
+};
+
+static struct resource sys_noc_res[] = {
+	{
+		.start = SYS_NOC_BASE,
+		.end = SYS_NOC_BASE + NOC_SIZE,
+		.flags = IORESOURCE_MEM,
+		.name = "sys_noc_mem",
+	},
+};
+
+static struct resource config_noc_res[] = {
+	{
+		.start = CONFIG_NOC_BASE,
+		.end = CONFIG_NOC_BASE + NOC_SIZE,
+		.flags = IORESOURCE_MEM,
+		.name = "config_noc_mem",
+	},
+};
+
+static struct resource periph_noc_res[] = {
+	{
+		.start = PERIPH_NOC_BASE,
+		.end = PERIPH_NOC_BASE + NOC_SIZE,
+		.flags = IORESOURCE_MEM,
+		.name = "periph_noc_mem",
+	},
+};
+
+static struct platform_device msm_bus_sys_noc = {
+	.name  = "msm_bus_fabric",
+	.id    =  MSM_BUS_FAB_SYS_NOC,
+	.num_resources = ARRAY_SIZE(sys_noc_res),
+	.resource = sys_noc_res,
+};
+
+static struct platform_device msm_bus_bimc = {
+	.name  = "msm_bus_fabric",
+	.id    = MSM_BUS_FAB_BIMC,
+	.num_resources = ARRAY_SIZE(bimc_res),
+	.resource = bimc_res,
+};
+
+static struct platform_device msm_bus_periph_noc = {
+	.name  = "msm_bus_fabric",
+	.id    = MSM_BUS_FAB_PERIPH_NOC,
+	.num_resources = ARRAY_SIZE(periph_noc_res),
+	.resource = periph_noc_res,
+};
+
+static struct platform_device msm_bus_config_noc = {
+	.name  = "msm_bus_fabric",
+	.id    = MSM_BUS_FAB_CONFIG_NOC,
+	.num_resources = ARRAY_SIZE(config_noc_res),
+	.resource = config_noc_res,
+};
+
+static struct platform_device *msm_bus_9625_devices[] = {
+	&msm_bus_sys_noc,
+	&msm_bus_bimc,
+	&msm_bus_periph_noc,
+	&msm_bus_config_noc,
+};
+
+static void __init msm9625_init_buses(void)
+{
+#ifdef CONFIG_MSM_BUS_SCALING
+	msm_bus_sys_noc.dev.platform_data =
+		&msm_bus_9625_sys_noc_pdata;
+	msm_bus_bimc.dev.platform_data = &msm_bus_9625_bimc_pdata;
+	msm_bus_periph_noc.dev.platform_data = &msm_bus_9625_periph_noc_pdata;
+	msm_bus_config_noc.dev.platform_data = &msm_bus_9625_config_noc_pdata;
+#endif
+	platform_add_devices(msm_bus_9625_devices,
+				ARRAY_SIZE(msm_bus_9625_devices));
+}
+
 void __init msm9625_add_devices(void)
 {
 	platform_device_register(&msm_device_smd_9625);
@@ -273,6 +365,7 @@
 	rpm_regulator_smd_driver_init();
 	msm_spm_device_init();
 	msm_clock_init(&msm9625_clock_init_data);
+	msm9625_init_buses();
 }
 
 void __init msm9625_init(void)
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3c417c3..a73246d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -3510,24 +3510,26 @@
 		.ctl_val = CC_BANKED(9, 6, n), \
 	}
 
-static struct clk_freq_tbl clk_tbl_gfx3d_8960ab[] = {
-	F_GFX3D(        0, gnd,  0,  0),
-	F_GFX3D( 27000000, pxo,  0,  0),
-	F_GFX3D( 48000000, pll8, 1,  8),
-	F_GFX3D( 54857000, pll8, 1,  7),
-	F_GFX3D( 64000000, pll8, 1,  6),
-	F_GFX3D( 76800000, pll8, 1,  5),
-	F_GFX3D( 96000000, pll8, 1,  4),
-	F_GFX3D(128000000, pll8, 1,  3),
-	F_GFX3D(145455000, pll2, 2, 11),
-	F_GFX3D(160000000, pll2, 1,  5),
-	F_GFX3D(177778000, pll2, 2,  9),
-	F_GFX3D(200000000, pll2, 1,  4),
-	F_GFX3D(228571000, pll2, 2,  7),
-	F_GFX3D(266667000, pll2, 1,  3),
-	F_GFX3D(320000000, pll2, 2,  5),
-	F_GFX3D(325000000, pll3, 1,  2),
-	F_GFX3D(400000000, pll2, 1,  2),
+/*Shared by 8064, 8930, and 8960ab*/
+static struct clk_freq_tbl clk_tbl_gfx3d[] = {
+	F_GFX3D(        0, gnd,   0,  0),
+	F_GFX3D( 27000000, pxo,   0,  0),
+	F_GFX3D( 48000000, pll8,  1,  8),
+	F_GFX3D( 54857000, pll8,  1,  7),
+	F_GFX3D( 64000000, pll8,  1,  6),
+	F_GFX3D( 76800000, pll8,  1,  5),
+	F_GFX3D( 96000000, pll8,  1,  4),
+	F_GFX3D(128000000, pll8,  1,  3),
+	F_GFX3D(145455000, pll2,  2, 11),
+	F_GFX3D(160000000, pll2,  1,  5),
+	F_GFX3D(177778000, pll2,  2,  9),
+	F_GFX3D(192000000, pll8,  1,  2),
+	F_GFX3D(200000000, pll2,  1,  4),
+	F_GFX3D(228571000, pll2,  2,  7),
+	F_GFX3D(266667000, pll2,  1,  3),
+	F_GFX3D(320000000, pll2,  2,  5),
+	F_GFX3D(400000000, pll2,  1,  2),
+	F_GFX3D(450000000, pll15, 1,  2),
 	F_END
 };
 
@@ -3552,49 +3554,6 @@
 	F_END
 };
 
-static struct clk_freq_tbl clk_tbl_gfx3d_8064[] = {
-	F_GFX3D(        0, gnd,   0,  0),
-	F_GFX3D( 27000000, pxo,   0,  0),
-	F_GFX3D( 48000000, pll8,  1,  8),
-	F_GFX3D( 54857000, pll8,  1,  7),
-	F_GFX3D( 64000000, pll8,  1,  6),
-	F_GFX3D( 76800000, pll8,  1,  5),
-	F_GFX3D( 96000000, pll8,  1,  4),
-	F_GFX3D(128000000, pll8,  1,  3),
-	F_GFX3D(145455000, pll2,  2, 11),
-	F_GFX3D(160000000, pll2,  1,  5),
-	F_GFX3D(177778000, pll2,  2,  9),
-	F_GFX3D(192000000, pll8,  1,  2),
-	F_GFX3D(200000000, pll2,  1,  4),
-	F_GFX3D(228571000, pll2,  2,  7),
-	F_GFX3D(266667000, pll2,  1,  3),
-	F_GFX3D(400000000, pll2,  1,  2),
-	F_GFX3D(450000000, pll15, 1,  2),
-	F_END
-};
-
-static struct clk_freq_tbl clk_tbl_gfx3d_8930[] = {
-	F_GFX3D(        0, gnd,   0,  0),
-	F_GFX3D( 27000000, pxo,   0,  0),
-	F_GFX3D( 48000000, pll8,  1,  8),
-	F_GFX3D( 54857000, pll8,  1,  7),
-	F_GFX3D( 64000000, pll8,  1,  6),
-	F_GFX3D( 76800000, pll8,  1,  5),
-	F_GFX3D( 96000000, pll8,  1,  4),
-	F_GFX3D(128000000, pll8,  1,  3),
-	F_GFX3D(145455000, pll2,  2, 11),
-	F_GFX3D(160000000, pll2,  1,  5),
-	F_GFX3D(177778000, pll2,  2,  9),
-	F_GFX3D(192000000, pll8,  1,  2),
-	F_GFX3D(200000000, pll2,  1,  4),
-	F_GFX3D(228571000, pll2,  2,  7),
-	F_GFX3D(266667000, pll2,  1,  3),
-	F_GFX3D(320000000, pll2,  2,  5),
-	F_GFX3D(400000000, pll2,  1,  2),
-	F_GFX3D(450000000, pll15, 1,  2),
-	F_END
-};
-
 static unsigned long fmax_gfx3d_8064ab[VDD_DIG_NUM] = {
 	[VDD_DIG_LOW]     = 128000000,
 	[VDD_DIG_NOMINAL] = 325000000,
@@ -3651,7 +3610,7 @@
 	.ns_reg = GFX3D_NS_REG,
 	.root_en_mask = BIT(2),
 	.set_rate = set_rate_mnd_banked,
-	.freq_tbl = clk_tbl_gfx3d_8960,
+	.freq_tbl = clk_tbl_gfx3d,
 	.bank_info = &bmnd_info_gfx3d,
 	.current_freq = &rcg_dummy_freq,
 	.c = {
@@ -6558,7 +6517,6 @@
 			sizeof(msm_clocks_8960_common));
 	if (cpu_is_msm8960ab()) {
 		pll3_clk.c.rate = 650000000;
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960ab;
 		gfx3d_clk.c.fmax[VDD_DIG_LOW] = 192000000;
 		gfx3d_clk.c.fmax[VDD_DIG_NOMINAL] = 325000000;
 		gfx3d_clk.c.fmax[VDD_DIG_HIGH] = 400000000;
@@ -6573,6 +6531,7 @@
 
 		gmem_axi_clk.c.depends = &gfx3d_axi_clk.c;
 	} else if (cpu_is_msm8960()) {
+		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960;
 		memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_common),
 			 msm_clocks_8960_only, sizeof(msm_clocks_8960_only));
 		msm8960_clock_init_data.size -=
@@ -6583,11 +6542,9 @@
 	 * clocks which differ between chips.
 	 */
 	if (cpu_is_apq8064()) {
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
 		gfx3d_clk.c.fmax = fmax_gfx3d_8064;
 	}
 	if (cpu_is_apq8064ab()) {
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
 		gfx3d_clk.c.fmax = fmax_gfx3d_8064ab;
 	}
 	if ((cpu_is_apq8064() &&
@@ -6616,7 +6573,6 @@
 		gfx3d_clk.c.fmax = fmax_gfx3d_8930aa;
 	}
 	if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627()) {
-		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8930;
 		pll15_clk.c.rate = 900000000;
 		gmem_axi_clk.c.depends = &gfx3d_axi_clk_8930.c;
 	}
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 6c9b413..e0d98b7 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -52,8 +52,11 @@
 static int set_cpu_freq(struct cpufreq_policy *policy, unsigned int new_freq)
 {
 	int ret = 0;
+	int saved_sched_policy = -EINVAL;
+	int saved_sched_rt_prio = -EINVAL;
 	struct cpufreq_freqs freqs;
 	struct cpu_freq *limit = &per_cpu(cpu_freq_info, policy->cpu);
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
 	if (limit->limits_init) {
 		if (new_freq > limit->allowed_max) {
@@ -70,11 +73,29 @@
 	freqs.old = policy->cur;
 	freqs.new = new_freq;
 	freqs.cpu = policy->cpu;
+
+	/*
+	 * Put the caller into SCHED_FIFO priority to avoid cpu starvation
+	 * in the acpuclk_set_rate path while increasing frequencies
+	 */
+
+	if (freqs.new > freqs.old && current->policy != SCHED_FIFO) {
+		saved_sched_policy = current->policy;
+		saved_sched_rt_prio = current->rt_priority;
+		sched_setscheduler_nocheck(current, SCHED_FIFO, &param);
+	}
+
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
 	ret = acpuclk_set_rate(policy->cpu, new_freq, SETRATE_CPUFREQ);
 	if (!ret)
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
+	/* Restore priority after clock ramp-up */
+	if (freqs.new > freqs.old && saved_sched_policy >= 0) {
+		param.sched_priority = saved_sched_rt_prio;
+		sched_setscheduler_nocheck(current, saved_sched_policy, &param);
+	}
 	return ret;
 }
 
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 3b3425f..abc0e6a 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1103,10 +1103,10 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
-		.start	= 47,
-		.end	= 47,
+		.start	= MSM_GPIO_TO_INT(47),
+		.end	= MSM_GPIO_TO_INT(47),
 		.name	= "wakeup",
-		.flags	= IORESOURCE_IO,
+		.flags	= IORESOURCE_IRQ,
 	},
 };
 
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index af8687e..1ba408f 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -584,6 +584,10 @@
 	.name	= "msm-voip-dsp",
 	.id	= -1,
 };
+struct platform_device msm_dtmf = {
+	.name	= "msm-pcm-dtmf",
+	.id	= -1,
+};
 
 struct platform_device msm_compr_dsp = {
 	.name	= "msm-compr-dsp",
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index bcc9c94..cd99628 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -234,6 +234,7 @@
 extern struct platform_device msm_stub_codec;
 extern struct platform_device msm_voice;
 extern struct platform_device msm_voip;
+extern struct platform_device msm_dtmf;
 extern struct platform_device msm_lpa_pcm;
 extern struct platform_device msm_pcm_hostless;
 extern struct platform_device msm_cpudai_afe_01_rx;
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index 0a53b46..84a7dc0 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -92,6 +92,11 @@
 extern struct msm_bus_fabric_registration msm_bus_8974_config_noc_pdata;
 extern struct msm_bus_fabric_registration msm_bus_8974_ocmem_vnoc_pdata;
 
+extern struct msm_bus_fabric_registration msm_bus_9625_sys_noc_pdata;
+extern struct msm_bus_fabric_registration msm_bus_9625_bimc_pdata;
+extern struct msm_bus_fabric_registration msm_bus_9625_periph_noc_pdata;
+extern struct msm_bus_fabric_registration msm_bus_9625_config_noc_pdata;
+
 void msm_bus_rpm_set_mt_mask(void);
 int msm_bus_board_rpm_get_il_ids(uint16_t *id);
 int msm_bus_board_get_iid(int id);
@@ -291,8 +296,10 @@
 	MSM_BUS_MASTER_USB_HS,
 	MSM_BUS_MASTER_PNOC_CFG,
 	MSM_BUS_MASTER_V_OCMEM_GFX3D,
+	MSM_BUS_MASTER_IPA,
+	MSM_BUS_MASTER_QPIC,
 
-	MSM_BUS_MASTER_LAST = MSM_BUS_MASTER_V_OCMEM_GFX3D,
+	MSM_BUS_MASTER_LAST = MSM_BUS_MASTER_QPIC,
 
 	MSM_BUS_SYSTEM_FPB_MASTER_SYSTEM =
 		MSM_BUS_SYSTEM_MASTER_SYSTEM_FPB,
@@ -446,8 +453,10 @@
 	MSM_BUS_SLAVE_PHY_APU_CFG,
 	MSM_BUS_SLAVE_EBI1_PHY_CFG,
 	MSM_BUS_SLAVE_SERVICE_CNOC,
+	MSM_BUS_SLAVE_IPS_CFG,
+	MSM_BUS_SLAVE_QPIC,
 
-	MSM_BUS_SLAVE_LAST = MSM_BUS_SLAVE_SERVICE_CNOC,
+	MSM_BUS_SLAVE_LAST = MSM_BUS_SLAVE_QPIC,
 
 	MSM_BUS_SYSTEM_FPB_SLAVE_SYSTEM =
 		MSM_BUS_SYSTEM_SLAVE_SYSTEM_FPB,
diff --git a/arch/arm/mach-msm/include/mach/msm_qmi_interface.h b/arch/arm/mach-msm/include/mach/msm_qmi_interface.h
new file mode 100644
index 0000000..11867f3
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_qmi_interface.h
@@ -0,0 +1,280 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_QMI_INTERFACE_H_
+#define _MSM_QMI_INTERFACE_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/qmi_encdec.h>
+
+#define QMI_COMMON_TLV_TYPE 0
+
+enum qmi_event_type {
+	QMI_RECV_MSG = 1,
+	QMI_SERVER_ARRIVE,
+	QMI_SERVER_EXIT,
+};
+
+struct qmi_handle {
+	void *src_port;
+	void *dest_info;
+	uint16_t next_txn_id;
+	struct list_head txn_list;
+	struct mutex handle_lock;
+	spinlock_t notify_lock;
+	void (*notify)(struct qmi_handle *handle, enum qmi_event_type event,
+			void *notify_priv);
+	void *notify_priv;
+	void (*ind_cb)(struct qmi_handle *handle,
+			unsigned int msg_id, void *msg,
+			unsigned int msg_len, void *ind_cb_priv);
+	void *ind_cb_priv;
+	int handle_reset;
+	wait_queue_head_t reset_waitq;
+};
+
+enum qmi_result_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	QMI_RESULT_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
+	QMI_RESULT_SUCCESS_V01 = 0,
+	QMI_RESULT_FAILURE_V01 = 1,
+	QMI_RESULT_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
+};
+
+enum qmi_error_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	QMI_ERROR_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
+	QMI_ERR_NONE_V01 = 0x0000,
+	QMI_ERROR_MALFORMED_MSG_V01 = 0x0001,
+	QMI_ERR_NO_MEMORY_V01 = 0x0002,
+	QMI_ERR_INTERNAL_V01 = 0x0003,
+	QMI_ERR_INVALID_ID_V01 = 0x0029,
+	QMI_ERR_INCOMPATIBLE_STATE_V01 = 0x005A,
+	QMI_ERROR_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
+};
+
+struct qmi_response_type_v01 {
+	enum qmi_result_type_v01 result;
+	enum qmi_error_type_v01 error;
+};
+
+#ifdef CONFIG_MSM_QMI_INTERFACE
+
+/* Element info array describing common qmi response structure */
+extern struct elem_info qmi_response_type_v01_ei[];
+#define get_qmi_response_type_v01_ei() qmi_response_type_v01_ei
+
+/**
+ * qmi_handle_create() - Create a QMI handle
+ * @notify: Callback to notify events on the handle created.
+ * @notify_priv: Private information to be passed along with the notification.
+ *
+ * @return: Valid QMI handle on success, NULL on error.
+ */
+struct qmi_handle *qmi_handle_create(
+	void (*notify)(struct qmi_handle *handle,
+		       enum qmi_event_type event, void *notify_priv),
+	void *notify_priv);
+
+/**
+ * qmi_handle_destroy() - Destroy the QMI handle
+ * @handle: QMI handle to be destroyed.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_handle_destroy(struct qmi_handle *handle);
+
+/**
+ * qmi_register_ind_cb() - Register the indication callback function
+ * @handle: QMI handle with which the function is registered.
+ * @ind_cb: Callback function to be registered.
+ * @ind_cb_priv: Private data to be passed with the indication callback.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_register_ind_cb(struct qmi_handle *handle,
+	void (*ind_cb)(struct qmi_handle *handle,
+		       unsigned int msg_id, void *msg,
+		       unsigned int msg_len, void *ind_cb_priv),
+	void *ind_cb_priv);
+
+/**
+ * qmi_send_req_wait() - Send a synchronous QMI request
+ * @handle: QMI handle through which the QMI request is sent.
+ * @request_desc: Structure describing the request data structure.
+ * @req: Buffer containing the request data structure.
+ * @req_len: Length of the request data structure.
+ * @resp_desc: Structure describing the response data structure.
+ * @resp: Buffer to hold the response data structure.
+ * @resp_len: Length of the response data structure.
+ * @timeout_ms: Timeout before a response is received.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_send_req_wait(struct qmi_handle *handle,
+		      struct msg_desc *req_desc,
+		      void *req, unsigned int req_len,
+		      struct msg_desc *resp_desc,
+		      void *resp, unsigned int resp_len,
+		      unsigned long timeout_ms);
+
+/**
+ * qmi_send_req_nowait() - Send an asynchronous QMI request
+ * @handle: QMI handle through which the QMI request is sent.
+ * @request_desc: Structure describing the request data structure.
+ * @req: Buffer containing the request data structure.
+ * @req_len: Length of the request data structure.
+ * @resp_desc: Structure describing the response data structure.
+ * @resp: Buffer to hold the response data structure.
+ * @resp_len: Length of the response data structure.
+ * @resp_cb: Callback function to be invoked when the response arrives.
+ * @resp_cb_data: Private information to be passed along with the callback.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_send_req_nowait(struct qmi_handle *handle,
+			struct msg_desc *req_desc,
+			void *req, unsigned int req_len,
+			struct msg_desc *resp_desc,
+			void *resp, unsigned int resp_len,
+			void (*resp_cb)(struct qmi_handle *handle,
+					unsigned int msg_id, void *msg,
+					void *resp_cb_data),
+			void *resp_cb_data);
+
+/**
+ * qmi_recv_msg() - Receive the QMI message
+ * @handle: Handle for which the QMI message has to be received.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_recv_msg(struct qmi_handle *handle);
+
+/**
+ * qmi_connect_to_service() - Connect the QMI handle with a QMI service
+ * @handle: QMI handle to be connected with the QMI service.
+ * @service_id: Service id to identify the QMI service.
+ * @instance_id: Instance id to identify the instance of the QMI service.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_connect_to_service(struct qmi_handle *handle,
+			   uint32_t service_id, uint32_t instance_id);
+
+/**
+ * qmi_svc_event_notifier_register() - Register a notifier block to receive
+ *                                     events regarding a QMI service
+ * @service_id: Service ID to identify the QMI service.
+ * @instance_id: Instance ID to identify the instance of the QMI service.
+ * @nb: Notifier block used to receive the event.
+ *
+ * @return: 0 if successfully registered, < 0 on error.
+ */
+int qmi_svc_event_notifier_register(uint32_t service_id,
+				    uint32_t instance_id,
+				    struct notifier_block *nb);
+
+/**
+ * qmi_svc_event_notifier_unregister() - Unregister service event
+ *                                       notifier block
+ * @service_id: Service ID to identify the QMI service.
+ * @instance_id: Instance ID to identify the instance of the QMI service.
+ * @nb: Notifier block registered to receive the events.
+ *
+ * @return: 0 if successfully registered, < 0 on error.
+ */
+int qmi_svc_event_notifier_unregister(uint32_t service_id,
+				      uint32_t instance_id,
+				      struct notifier_block *nb);
+#else
+
+#define get_qmi_response_type_v01_ei() NULL
+
+static inline struct qmi_handle *qmi_handle_create(
+	void (*notify)(struct qmi_handle *handle,
+		       enum qmi_event_type event, void *notify_priv),
+	void *notify_priv)
+{
+	return NULL;
+}
+
+static inline int qmi_handle_destroy(struct qmi_handle *handle)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_register_ind_cb(struct qmi_handle *handle,
+	void (*ind_cb)(struct qmi_handle *handle,
+		       unsigned int msg_id, void *msg,
+		       unsigned int msg_len, void *ind_cb_priv),
+	void *ind_cb_priv)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_send_req_wait(struct qmi_handle *handle,
+				    struct msg_desc *req_desc,
+				    void *req, unsigned int req_len,
+				    struct msg_desc *resp_desc,
+				    void *resp, unsigned int resp_len,
+				    unsigned long timeout_ms)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_send_req_nowait(struct qmi_handle *handle,
+				struct msg_desc *req_desc,
+				void *req, unsigned int req_len,
+				struct msg_desc *resp_desc,
+				void *resp, unsigned int resp_len,
+				void (*resp_cb)(struct qmi_handle *handle,
+						unsigned int msg_id, void *msg,
+						void *resp_cb_data),
+				void *resp_cb_data)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_recv_msg(struct qmi_handle *handle)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_connect_to_service(struct qmi_handle *handle,
+					 uint32_t service_id,
+					 uint32_t instance_id)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_svc_event_notifier_register(uint32_t service_id,
+						  uint32_t instance_id,
+						  struct notifier_block *nb)
+{
+	return -ENODEV;
+}
+
+static inline int qmi_svc_event_notifier_unregister(uint32_t service_id,
+						    uint32_t instance_id,
+						    struct notifier_block *nb)
+{
+	return -ENODEV;
+}
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index 44b52b6..c77c181 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -83,7 +83,7 @@
 #define SMSM_WKUP_REASON_TIMER	0x00000008
 #define SMSM_WKUP_REASON_ALARM	0x00000010
 #define SMSM_WKUP_REASON_RESET	0x00000020
-#define SMSM_A2_FORCE_SHUTDOWN 0x00002000
+#define SMSM_USB_PLUG_UNPLUG    0x00002000
 #define SMSM_A2_RESET_BAM      0x00004000
 
 #define SMSM_VENDOR             0x00020000
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 4854fc48..61c2aa8 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -145,6 +145,11 @@
 		if (time_param->latency_us < level->latency_us)
 			continue;
 
+		if ((MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE == sleep_mode)
+			|| (MSM_PM_SLEEP_MODE_POWER_COLLAPSE == sleep_mode))
+			if (!cpu && msm_rpm_waiting_for_ack())
+					break;
+
 		if (time_param->sleep_us <= 1) {
 			pwr = level->energy_overhead;
 		} else if (time_param->sleep_us <= level->time_overhead_us) {
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 255cd46..c21ea33 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -27,6 +27,7 @@
 #include "lpm_resources.h"
 #include "rpm-notifier.h"
 #include "idle.h"
+#include "trace_msm_low_power.h"
 
 /*Debug Definitions*/
 enum {
@@ -417,6 +418,7 @@
 
 	if (rs->valid)
 		rs->sleep_value = limits->l2_cache;
+	trace_lpm_resources(rs->sleep_value, rs->name);
 }
 
 static void msm_lpm_flush_l2(int notify_rpm)
@@ -497,6 +499,7 @@
 		else
 			rs->sleep_value = vdd_buf;
 	}
+	trace_lpm_resources(rs->sleep_value, rs->name);
 }
 
 static void msm_lpm_flush_vdd_dig(int notify_rpm)
@@ -551,6 +554,7 @@
 		else
 			rs->sleep_value = vdd_buf;
 	}
+	trace_lpm_resources(rs->sleep_value, rs->name);
 }
 
 static void msm_lpm_flush_vdd_mem(int notify_rpm)
@@ -608,6 +612,7 @@
 			pr_info("%s: pxo buf %d sleep value %d\n",
 					__func__, pxo_buf, rs->sleep_value);
 	}
+	trace_lpm_resources(rs->sleep_value, rs->name);
 }
 
 static void msm_lpm_flush_pxo(int notify_rpm)
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index bdc6fac..dde25ab 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -11,4 +11,5 @@
 obj-$(CONFIG_ARCH_APQ8064) += msm_bus_board_8064.o
 obj-$(CONFIG_ARCH_MSM8930) += msm_bus_board_8930.o
 obj-$(CONFIG_ARCH_MSM8974) += msm_bus_board_8974.o
+obj-$(CONFIG_ARCH_MSM9625) += msm_bus_board_9625.o
 obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
new file mode 100644
index 0000000..92cd255
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9625.c
@@ -0,0 +1,1303 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/rpm.h>
+#include "msm_bus_core.h"
+#include "msm_bus_noc.h"
+#include "msm_bus_bimc.h"
+
+#define NMASTERS 120
+#define NSLAVES 150
+#define NFAB_9625 4
+
+enum msm_bus_9625_master_ports_type {
+	/* System NOC Masters */
+	MASTER_PORT_LPASS_AHB = 0,
+	MASTER_PORT_QDSS_BAM,
+	MASTER_PORT_SNOC_CFG,
+	MASTER_PORT_GW_BIMC_SNOC,
+	MASTER_PORT_GW_CNOC_SNOC,
+	MASTER_PORT_CRYPTO_CORE0,
+	MASTER_PORT_LPASS_PROC,
+	MASTER_PORT_MSS,
+	MASTER_PORT_MSS_NAV,
+	MASTER_PORT_IPA,
+	MASTER_PORT_GW_PNOC_SNOC,
+	MASTER_PORT_QDSS_ETR,
+
+	/* BIMC Masters */
+	MASTER_PORT_KMPSS_M0 = 0,
+	MASTER_PORT_MSS_PROC,
+	MASTER_PORT_GW_SNOC_BIMC_0,
+
+	/* Peripheral NOC Masters */
+	MASTER_PORT_QPIC = 0,
+	MASTER_PORT_SDCC_1,
+	MASTER_PORT_SDCC_3,
+	MASTER_PORT_SDCC_2,
+	MASTER_PORT_SDCC_4,
+	MASTER_PORT_TSIF,
+	MASTER_PORT_BAM_DMA,
+	MASTER_PORT_BLSP_2,
+	MASTER_PORT_USB_HSIC,
+	MASTER_PORT_BLSP_1,
+	MASTER_PORT_USB_HS1,
+	MASTER_PORT_USB_HS2,
+	MASTER_PORT_PNOC_CFG,
+	MASTER_PORT_GW_SNOC_PNOC,
+
+	/* Config NOC Masters */
+	MASTER_PORT_RPM_INST = 0,
+	MASTER_PORT_RPM_DATA,
+	MASTER_PORT_RPM_SYS,
+	MASTER_PORT_DEHR,
+	MASTER_PORT_QDSS_DAP,
+	MASTER_PORT_SPDM,
+	MASTER_PORT_TIC,
+	MASTER_PORT_GW_SNOC_CNOC,
+};
+
+enum msm_bus_9625_slave_ports_type {
+	/* System NOC Slaves */
+	SLAVE_PORT_KMPSS = 1,
+	SLAVE_PORT_LPASS,
+	SLAVE_PORT_GW_SNOC_BIMC_P0,
+	SLAVE_PORT_GW_SNOC_CNOC,
+	SLAVE_PORT_OCIMEM,
+	SLAVE_PORT_GW_SNOC_PNOC,
+	SLAVE_PORT_SERVICE_SNOC,
+	SLAVE_PORT_QDSS_STM,
+
+	/* BIMC Slaves */
+	SLAVE_PORT_EBI1_CH0 = 0,
+	SLAVE_PORT_GW_BIMC_SNOC,
+
+	/*Peripheral NOC Slaves */
+	SLAVE_PORT_QPIC = 0,
+	SLAVE_PORT_SDCC_1,
+	SLAVE_PORT_SDCC_3,
+	SLAVE_PORT_SDCC_2,
+	SLAVE_PORT_SDCC_4,
+	SLAVE_PORT_TSIF,
+	SLAVE_PORT_BAM_DMA,
+	SLAVE_PORT_BLSP_2,
+	SLAVE_PORT_USB_HSIC,
+	SLAVE_PORT_BLSP_1,
+	SLAVE_PORT_USB_HS1,
+	SLAVE_PORT_USB_HS2,
+	SLAVE_PORT_PDM,
+	SLAVE_PORT_PERIPH_APU_CFG,
+	SLAVE_PORT_PNOC_MPU_CFG,
+	SLAVE_PORT_PRNG,
+	SLAVE_PORT_GW_PNOC_SNOC,
+	SLAVE_PORT_SERVICE_PNOC,
+
+	/* Config NOC slaves */
+	SLAVE_PORT_CLK_CTL = 0,
+	SLAVE_PORT_CNOC_MSS,
+	SLAVE_PORT_SECURITY,
+	SLAVE_PORT_TCSR,
+	SLAVE_PORT_TLMM,
+	SLAVE_PORT_CRYPTO_0_CFG,
+	SLAVE_PORT_IMEM_CFG,
+	SLAVE_PORT_IPS_CFG,
+	SLAVE_PORT_MESSAGE_RAM,
+	SLAVE_PORT_BIMC_CFG,
+	SLAVE_PORT_BOOT_ROM,
+	SLAVE_PORT_PMIC_ARB,
+	SLAVE_PORT_SPDM_WRAPPER,
+	SLAVE_PORT_DEHR_CFG,
+	SLAVE_PORT_MPM,
+	SLAVE_PORT_QDSS_CFG,
+	SLAVE_PORT_RBCPR_CFG,
+	SLAVE_PORT_RBCPR_QDSS_APU_CFG,
+	SLAVE_PORT_SNOC_MPU_CFG,
+	SLAVE_PORT_PNOC_CFG,
+	SLAVE_PORT_SNOC_CFG,
+	SLAVE_PORT_PHY_APU_CFG,
+	SLAVE_PORT_EBI1_PHY_CFG,
+	SLAVE_PORT_RPM,
+	SLAVE_PORT_GW_CNOC_SNOC,
+	SLAVE_PORT_SERVICE_CNOC,
+};
+
+/* Hardware IDs for RPM */
+enum msm_bus_9625_mas_hw_id {
+	MAS_APPSS_PROC = 0,
+	MAS_AMSS_PROC,
+	MAS_MNOC_BIMC,
+	MAS_SNOC_BIMC,
+	MAS_CNOC_MNOC_MMSS_CFG,
+	MAS_CNOC_MNOC_CFG,
+	MAS_GFX3D,
+	MAS_JPEG,
+	MAS_MDP,
+	MAS_VIDEO_P0,
+	MAS_VIDEO_P1,
+	MAS_VFE,
+	MAS_CNOC_ONOC_CFG,
+	MAS_JPEG_OCMEM,
+	MAS_MDP_OCMEM,
+	MAS_VIDEO_P0_OCMEM,
+	MAS_VIDEO_P1_OCMEM,
+	MAS_VFE_OCMEM,
+	MAS_LPASS_AHB,
+	MAS_QDSS_BAM,
+	MAS_SNOC_CFG,
+	MAS_BIMC_SNOC,
+	MAS_CNOC_SNOC,
+	MAS_CRYPTO_CORE0,
+	MAS_CRYPTO_CORE1,
+	MAS_LPASS_PROC,
+	MAS_MSS,
+	MAS_MSS_NAV,
+	MAS_OCMEM_DMA,
+	MAS_PNOC_SNOC,
+	MAS_WCSS,
+	MAS_QDSS_ETR,
+	MAS_USB3,
+	MAS_SDCC_1,
+	MAS_SDCC_3,
+	MAS_SDCC_2,
+	MAS_SDCC_4,
+	MAS_TSIF,
+	MAS_BAM_DMA,
+	MAS_BLSP_2,
+	MAS_USB_HSIC,
+	MAS_BLSP_1,
+	MAS_USB_HS,
+	MAS_PNOC_CFG,
+	MAS_SNOC_PNOC,
+	MAS_RPM_INST,
+	MAS_RPM_DATA,
+	MAS_RPM_SYS,
+	MAS_DEHR,
+	MAS_QDSS_DAP,
+	MAS_SPDM,
+	MAS_TIC,
+	MAS_SNOC_CNOC,
+	MAS_OVNOC_SNOC,
+	MAS_OVNOC_ONOC,
+	MAS_V_OCMEM_GFX3D,
+	MAS_ONOC_OVNOC,
+	MAS_SNOC_OVNOC,
+	MAS_QPIC,
+	MAS_IPA,
+};
+
+enum msm_bus_9625_slv_hw_id {
+	SLV_EBI = 0,
+	SLV_APSS_L2,
+	SLV_BIMC_SNOC,
+	SLV_CAMERA_CFG,
+	SLV_DISPLAY_CFG,
+	SLV_OCMEM_CFG,
+	SLV_CPR_CFG,
+	SLV_CPR_XPU_CFG,
+	SLV_MISC_CFG,
+	SLV_MISC_XPU_CFG,
+	SLV_VENUS_CFG,
+	SLV_GFX3D_CFG,
+	SLV_MMSS_CLK_CFG,
+	SLV_MMSS_CLK_XPU_CFG,
+	SLV_MNOC_MPU_CFG,
+	SLV_ONOC_MPU_CFG,
+	SLV_MMSS_BIMC,
+	SLV_SERVICE_MNOC,
+	SLV_OCMEM,
+	SLV_SERVICE_ONOC,
+	SLV_APPSS,
+	SLV_LPASS,
+	SLV_USB3,
+	SLV_WCSS,
+	SLV_SNOC_BIMC,
+	SLV_SNOC_CNOC,
+	SLV_OCIMEM,
+	SLV_SNOC_OCMEM,
+	SLV_SNOC_PNOC,
+	SLV_SERVICE_SNOC,
+	SLV_QDSS_STM,
+	SLV_SDCC_1,
+	SLV_SDCC_3,
+	SLV_SDCC_2,
+	SLV_SDCC_4,
+	SLV_TSIF,
+	SLV_BAM_DMA,
+	SLV_BLSP_2,
+	SLV_USB_HSIC,
+	SLV_BLSP_1,
+	SLV_USB_HS,
+	SLV_PDM,
+	SLV_PERIPH_APU_CFG,
+	SLV_MPU_CFG,
+	SLV_PRNG,
+	SLV_PNOC_SNOC,
+	SLV_SERVICE_PNOC,
+	SLV_CLK_CTL,
+	SLV_CNOC_MSS,
+	SLV_SECURITY,
+	SLV_TCSR,
+	SLV_TLMM,
+	SLV_CRYPTO_0_CFG,
+	SLV_CRYPTO_1_CFG,
+	SLV_IMEM_CFG,
+	SLV_MESSAGE_RAM,
+	SLV_BIMC_CFG,
+	SLV_BOOT_ROM,
+	SLV_CNOC_MNOC_MMSS_CFG,
+	SLV_PMIC_ARB,
+	SLV_SPDM_WRAPPER,
+	SLV_DEHR_CFG,
+	SLV_MPM,
+	SLV_QDSS_CFG,
+	SLV_RBCPR_CFG,
+	SLV_RBCPR_QDSS_APU_CFG,
+	SLV_CNOC_MNOC_CFG,
+	SLV_SNOC_MPU_CFG,
+	SLV_CNOC_ONOC_CFG,
+	SLV_PNOC_CFG,
+	SLV_SNOC_CFG,
+	SLV_EBI1_DLL_CFG,
+	SLV_PHY_APU_CFG,
+	SLV_EBI1_PHY_CFG,
+	SLV_RPM,
+	SLV_CNOC_SNOC,
+	SLV_SERVICE_CNOC,
+	SLV_SNOC_OVNOC,
+	SLV_ONOC_OVNOC,
+	SLV_USB_HS2,
+	SLV_QPIC,
+	SLV_IPS_CFG,
+};
+
+static uint32_t master_iids[NMASTERS];
+static uint32_t slave_iids[NSLAVES];
+
+/* System NOC nodes */
+static int mport_lpass_ahb[] = {MASTER_PORT_LPASS_AHB,};
+static int mport_qdss_bam[] = {MASTER_PORT_QDSS_BAM,};
+static int mport_snoc_cfg[] = {MASTER_PORT_SNOC_CFG,};
+static int mport_gw_bimc_snoc[] = {MASTER_PORT_GW_BIMC_SNOC,};
+static int mport_gw_cnoc_snoc[] = {MASTER_PORT_GW_CNOC_SNOC,};
+static int mport_crypto_core0[] = {MASTER_PORT_CRYPTO_CORE0,};
+static int mport_lpass_proc[] = {MASTER_PORT_LPASS_PROC};
+static int mport_mss[] = {MASTER_PORT_MSS};
+static int mport_mss_nav[] = {MASTER_PORT_MSS_NAV};
+static int mport_ipa[] = {MASTER_PORT_IPA};
+static int mport_gw_pnoc_snoc[] = {MASTER_PORT_GW_PNOC_SNOC};
+static int mport_qdss_etr[] = {MASTER_PORT_QDSS_ETR};
+
+static int sport_kmpss[] = {SLAVE_PORT_KMPSS};
+static int sport_lpass[] = {SLAVE_PORT_LPASS};
+static int sport_gw_snoc_bimc[] = {SLAVE_PORT_GW_SNOC_BIMC_P0};
+static int sport_gw_snoc_cnoc[] = {SLAVE_PORT_GW_SNOC_CNOC};
+static int sport_ocimem[] = {SLAVE_PORT_OCIMEM};
+static int sport_gw_snoc_pnoc[] = {SLAVE_PORT_GW_SNOC_PNOC};
+static int sport_service_snoc[] = {SLAVE_PORT_SERVICE_SNOC};
+static int sport_qdss_stm[] = {SLAVE_PORT_QDSS_STM};
+
+/* BIMC Nodes */
+
+static int mport_kmpss_m0[] = {MASTER_PORT_KMPSS_M0,};
+static int mport_mss_proc[] = {MASTER_PORT_MSS_PROC};
+static int mport_gw_snoc_bimc[] = {MASTER_PORT_GW_SNOC_BIMC_0};
+
+static int sport_ebi1[] = {SLAVE_PORT_EBI1_CH0};
+static int sport_gw_bimc_snoc[] = {SLAVE_PORT_GW_BIMC_SNOC,};
+
+/* Peripheral NOC Nodes */
+static int mport_sdcc_1[] = {MASTER_PORT_SDCC_1,};
+static int mport_sdcc_3[] = {MASTER_PORT_SDCC_3,};
+static int mport_sdcc_2[] = {MASTER_PORT_SDCC_2,};
+static int mport_sdcc_4[] = {MASTER_PORT_SDCC_4,};
+static int mport_tsif[] = {MASTER_PORT_TSIF,};
+static int mport_bam_dma[] = {MASTER_PORT_BAM_DMA,};
+static int mport_blsp_2[] = {MASTER_PORT_BLSP_2,};
+static int mport_usb_hsic[] = {MASTER_PORT_USB_HSIC,};
+static int mport_blsp_1[] = {MASTER_PORT_BLSP_1,};
+static int mport_pnoc_cfg[] = {MASTER_PORT_PNOC_CFG,};
+static int mport_qpic[] = {MASTER_PORT_QPIC,};
+static int mport_gw_snoc_pnoc[] = {MASTER_PORT_GW_SNOC_PNOC,};
+
+static int sport_sdcc_1[] = {SLAVE_PORT_SDCC_1,};
+static int sport_sdcc_3[] = {SLAVE_PORT_SDCC_3,};
+static int sport_sdcc_2[] = {SLAVE_PORT_SDCC_2,};
+static int sport_sdcc_4[] = {SLAVE_PORT_SDCC_4,};
+static int sport_tsif[] = {SLAVE_PORT_TSIF,};
+static int sport_qpic[] = {SLAVE_PORT_QPIC,};
+static int sport_bam_dma[] = {SLAVE_PORT_BAM_DMA,};
+static int sport_blsp_2[] = {SLAVE_PORT_BLSP_2,};
+static int sport_usb_hsic[] = {SLAVE_PORT_USB_HSIC,};
+static int sport_blsp_1[] = {SLAVE_PORT_BLSP_1,};
+static int sport_pdm[] = {SLAVE_PORT_PDM,};
+static int sport_periph_apu_cfg[] = {
+	SLAVE_PORT_PERIPH_APU_CFG,
+};
+static int sport_pnoc_mpu_cfg[] = {SLAVE_PORT_PNOC_MPU_CFG,};
+static int sport_prng[] = {SLAVE_PORT_PRNG,};
+static int sport_gw_pnoc_snoc[] = {SLAVE_PORT_GW_PNOC_SNOC,};
+static int sport_service_pnoc[] = {SLAVE_PORT_SERVICE_PNOC,};
+
+/* Config NOC Nodes */
+static int mport_rpm_inst[] = {MASTER_PORT_RPM_INST,};
+static int mport_rpm_data[] = {MASTER_PORT_RPM_DATA,};
+static int mport_rpm_sys[] = {MASTER_PORT_RPM_SYS,};
+static int mport_dehr[] = {MASTER_PORT_DEHR,};
+static int mport_qdss_dap[] = {MASTER_PORT_QDSS_DAP,};
+static int mport_spdm[] = {MASTER_PORT_SPDM,};
+static int mport_tic[] = {MASTER_PORT_TIC,};
+static int mport_gw_snoc_cnoc[] = {MASTER_PORT_GW_SNOC_CNOC,};
+
+static int sport_clk_ctl[] = {SLAVE_PORT_CLK_CTL,};
+static int sport_cnoc_mss[] = {SLAVE_PORT_CNOC_MSS,};
+static int sport_security[] = {SLAVE_PORT_SECURITY,};
+static int sport_tcsr[] = {SLAVE_PORT_TCSR,};
+static int sport_tlmm[] = {SLAVE_PORT_TLMM,};
+static int sport_crypto_0_cfg[] = {SLAVE_PORT_CRYPTO_0_CFG,};
+static int sport_imem_cfg[] = {SLAVE_PORT_IMEM_CFG,};
+static int sport_ips_cfg[] = {SLAVE_PORT_IPS_CFG,};
+static int sport_message_ram[] = {SLAVE_PORT_MESSAGE_RAM,};
+static int sport_bimc_cfg[] = {SLAVE_PORT_BIMC_CFG,};
+static int sport_boot_rom[] = {SLAVE_PORT_BOOT_ROM,};
+static int sport_pmic_arb[] = {SLAVE_PORT_PMIC_ARB,};
+static int sport_spdm_wrapper[] = {SLAVE_PORT_SPDM_WRAPPER,};
+static int sport_dehr_cfg[] = {SLAVE_PORT_DEHR_CFG,};
+static int sport_mpm[] = {SLAVE_PORT_MPM,};
+static int sport_qdss_cfg[] = {SLAVE_PORT_QDSS_CFG,};
+static int sport_rbcpr_cfg[] = {SLAVE_PORT_RBCPR_CFG,};
+static int sport_rbcpr_qdss_apu_cfg[] = {SLAVE_PORT_RBCPR_QDSS_APU_CFG,};
+static int sport_snoc_mpu_cfg[] = {SLAVE_PORT_SNOC_MPU_CFG,};
+static int sport_pnoc_cfg[] = {SLAVE_PORT_PNOC_CFG,};
+static int sport_snoc_cfg[] = {SLAVE_PORT_SNOC_CFG,};
+static int sport_phy_apu_cfg[] = {SLAVE_PORT_PHY_APU_CFG,};
+static int sport_ebi1_phy_cfg[] = {SLAVE_PORT_EBI1_PHY_CFG,};
+static int sport_rpm[] = {SLAVE_PORT_RPM,};
+static int sport_gw_cnoc_snoc[] = {SLAVE_PORT_GW_CNOC_SNOC,};
+static int sport_service_cnoc[] = {SLAVE_PORT_SERVICE_CNOC,};
+
+static int tier2[] = {MSM_BUS_BW_TIER2,};
+
+/*
+ * QOS Ports defined only when qos ports are different than
+ * master ports
+ **/
+static int qports_crypto_c0[] = {2};
+static int qports_lpass_proc[] = {4};
+static int qports_gw_snoc_bimc[] = {2};
+static int qports_kmpss[] = {0};
+static int qports_lpass_ahb[] = {0};
+static int qports_qdss_bam[] = {1};
+static int qports_gw_pnoc_snoc[] = {8};
+static int qports_ipa[] = {7};
+static int qports_qdss_etr[] = {10};
+
+static struct msm_bus_node_info sys_noc_info[] = {
+	{
+		.id = MSM_BUS_MASTER_LPASS_AHB,
+		.masterp = mport_lpass_ahb,
+		.num_mports = ARRAY_SIZE(mport_lpass_ahb),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.qport = qports_lpass_ahb,
+		.mas_hw_id = MAS_LPASS_AHB,
+		.mode = NOC_QOS_MODE_FIXED,
+		.prio_rd = 2,
+		.prio_wr = 2,
+	},
+	{
+		.id = MSM_BUS_MASTER_QDSS_BAM,
+		.masterp = mport_qdss_bam,
+		.num_mports = ARRAY_SIZE(mport_qdss_bam),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.mode = NOC_QOS_MODE_FIXED,
+		.qport = qports_qdss_bam,
+		.mas_hw_id = MAS_QDSS_BAM,
+	},
+	{
+		.id = MSM_BUS_MASTER_SNOC_CFG,
+		.masterp = mport_snoc_cfg,
+		.num_mports = ARRAY_SIZE(mport_snoc_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.mas_hw_id = MAS_SNOC_CFG,
+	},
+	{
+		.id = MSM_BUS_FAB_BIMC,
+		.gateway = 1,
+		.slavep = sport_gw_snoc_bimc,
+		.num_sports = ARRAY_SIZE(sport_gw_snoc_bimc),
+		.masterp = mport_gw_bimc_snoc,
+		.num_mports = ARRAY_SIZE(mport_gw_bimc_snoc),
+		.buswidth = 8,
+		.mas_hw_id = MAS_BIMC_SNOC,
+		.slv_hw_id = SLV_SNOC_BIMC,
+	},
+	{
+		.id = MSM_BUS_FAB_CONFIG_NOC,
+		.gateway = 1,
+		.slavep = sport_gw_snoc_cnoc,
+		.num_sports = ARRAY_SIZE(sport_gw_snoc_cnoc),
+		.masterp = mport_gw_cnoc_snoc,
+		.num_mports = ARRAY_SIZE(mport_gw_cnoc_snoc),
+		.buswidth = 8,
+		.mas_hw_id = MAS_CNOC_SNOC,
+		.slv_hw_id = SLV_SNOC_CNOC,
+	},
+	{
+		.id = MSM_BUS_FAB_PERIPH_NOC,
+		.gateway = 1,
+		.slavep = sport_gw_snoc_pnoc,
+		.num_sports = ARRAY_SIZE(sport_gw_snoc_pnoc),
+		.masterp = mport_gw_pnoc_snoc,
+		.num_mports = ARRAY_SIZE(mport_gw_pnoc_snoc),
+		.buswidth = 8,
+		.qport = qports_gw_pnoc_snoc,
+		.mas_hw_id = MAS_PNOC_SNOC,
+		.slv_hw_id = SLV_SNOC_PNOC,
+		.mode = NOC_QOS_MODE_FIXED,
+		.prio_rd = 2,
+		.prio_wr = 2,
+	},
+	{
+		.id = MSM_BUS_MASTER_CRYPTO_CORE0,
+		.masterp = mport_crypto_core0,
+		.num_mports = ARRAY_SIZE(mport_crypto_core0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.mode = NOC_QOS_MODE_FIXED,
+		.qport = qports_crypto_c0,
+		.mas_hw_id = MAS_CRYPTO_CORE0,
+		.hw_sel = MSM_BUS_NOC,
+	},
+	{
+		.id = MSM_BUS_MASTER_LPASS_PROC,
+		.masterp = mport_lpass_proc,
+		.num_mports = ARRAY_SIZE(mport_lpass_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.qport = qports_lpass_proc,
+		.mas_hw_id = MAS_LPASS_PROC,
+		.mode = NOC_QOS_MODE_FIXED,
+		.prio_rd = 2,
+		.prio_wr = 2,
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS,
+		.masterp = mport_mss,
+		.num_mports = ARRAY_SIZE(mport_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.mas_hw_id = MAS_MSS,
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_NAV,
+		.masterp = mport_mss_nav,
+		.num_mports = ARRAY_SIZE(mport_mss_nav),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.mas_hw_id = MAS_MSS_NAV,
+	},
+	{
+		.id = MSM_BUS_MASTER_IPA,
+		.masterp = mport_ipa,
+		.num_mports = ARRAY_SIZE(mport_ipa),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.mode = NOC_QOS_MODE_FIXED,
+		.qport = qports_ipa,
+		.mas_hw_id = MAS_IPA,
+	},
+	{
+		.id = MSM_BUS_MASTER_QDSS_ETR,
+		.masterp = mport_qdss_etr,
+		.num_mports = ARRAY_SIZE(mport_qdss_etr),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.qport = qports_qdss_etr,
+		.mode = NOC_QOS_MODE_FIXED,
+		.mas_hw_id = MAS_QDSS_ETR,
+	},
+	{
+		.id = MSM_BUS_SLAVE_AMPSS,
+		.slavep = sport_kmpss,
+		.num_sports = ARRAY_SIZE(sport_kmpss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_APPSS,
+	},
+	{
+		.id = MSM_BUS_SLAVE_LPASS,
+		.slavep = sport_lpass,
+		.num_sports = ARRAY_SIZE(sport_lpass),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_LPASS,
+	},
+	{
+		.id = MSM_BUS_SLAVE_OCIMEM,
+		.slavep = sport_ocimem,
+		.num_sports = ARRAY_SIZE(sport_ocimem),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_OCIMEM,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SERVICE_SNOC,
+		.slavep = sport_service_snoc,
+		.num_sports = ARRAY_SIZE(sport_service_snoc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SERVICE_SNOC,
+	},
+	{
+		.id = MSM_BUS_SLAVE_QDSS_STM,
+		.slavep = sport_qdss_stm,
+		.num_sports = ARRAY_SIZE(sport_qdss_stm),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_QDSS_STM,
+	},
+};
+
+static struct msm_bus_node_info bimc_info[]  = {
+	{
+		.id = MSM_BUS_MASTER_AMPSS_M0,
+		.masterp = mport_kmpss_m0,
+		.num_mports = ARRAY_SIZE(mport_kmpss_m0),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.hw_sel = MSM_BUS_BIMC,
+		.mode = NOC_QOS_MODE_FIXED,
+		.qport = qports_kmpss,
+		.ws = 10000,
+		.mas_hw_id = MAS_APPSS_PROC,
+		.prio_lvl = 0,
+		.prio_rd = 2,
+		.prio_wr = 2,
+	},
+	{
+		.id = MSM_BUS_MASTER_MSS_PROC,
+		.masterp = mport_mss_proc,
+		.num_mports = ARRAY_SIZE(mport_mss_proc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.hw_sel = MSM_BUS_RPM,
+		.mas_hw_id = MAS_AMSS_PROC,
+	},
+	{
+		.id = MSM_BUS_FAB_SYS_NOC,
+		.gateway = 1,
+		.slavep = sport_gw_bimc_snoc,
+		.num_sports = ARRAY_SIZE(sport_gw_bimc_snoc),
+		.masterp = mport_gw_snoc_bimc,
+		.num_mports = ARRAY_SIZE(mport_gw_snoc_bimc),
+		.qport = qports_gw_snoc_bimc,
+		.buswidth = 8,
+		.ws = 10000,
+		.mas_hw_id = MAS_SNOC_BIMC,
+		.slv_hw_id = SLV_BIMC_SNOC,
+		.mode = NOC_QOS_MODE_BYPASS,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI_CH0,
+		.slavep = sport_ebi1,
+		.num_sports = ARRAY_SIZE(sport_ebi1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_EBI,
+		.mode = NOC_QOS_MODE_BYPASS,
+	},
+};
+
+static struct msm_bus_node_info periph_noc_info[] = {
+	{
+		.id = MSM_BUS_MASTER_PNOC_CFG,
+		.masterp = mport_pnoc_cfg,
+		.num_mports = ARRAY_SIZE(mport_pnoc_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_PNOC_CFG,
+	},
+	{
+		.id = MSM_BUS_MASTER_QPIC,
+		.masterp = mport_qpic,
+		.num_mports = ARRAY_SIZE(mport_qpic),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_QPIC,
+	},
+	{
+		.id = MSM_BUS_MASTER_SDCC_1,
+		.masterp = mport_sdcc_1,
+		.num_mports = ARRAY_SIZE(mport_sdcc_1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_SDCC_1,
+	},
+	{
+		.id = MSM_BUS_MASTER_SDCC_3,
+		.masterp = mport_sdcc_3,
+		.num_mports = ARRAY_SIZE(mport_sdcc_3),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_SDCC_3,
+	},
+	{
+		.id = MSM_BUS_MASTER_SDCC_4,
+		.masterp = mport_sdcc_4,
+		.num_mports = ARRAY_SIZE(mport_sdcc_4),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_SDCC_4,
+	},
+	{
+		.id = MSM_BUS_MASTER_SDCC_2,
+		.masterp = mport_sdcc_2,
+		.num_mports = ARRAY_SIZE(mport_sdcc_2),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_SDCC_2,
+	},
+	{
+		.id = MSM_BUS_MASTER_TSIF,
+		.masterp = mport_tsif,
+		.num_mports = ARRAY_SIZE(mport_tsif),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_TSIF,
+	},
+	{
+		.id = MSM_BUS_MASTER_BAM_DMA,
+		.masterp = mport_bam_dma,
+		.num_mports = ARRAY_SIZE(mport_bam_dma),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_BAM_DMA,
+	},
+	{
+		.id = MSM_BUS_MASTER_BLSP_2,
+		.masterp = mport_blsp_2,
+		.num_mports = ARRAY_SIZE(mport_blsp_2),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_BLSP_2,
+	},
+	{
+		.id = MSM_BUS_MASTER_USB_HSIC,
+		.masterp = mport_usb_hsic,
+		.num_mports = ARRAY_SIZE(mport_usb_hsic),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_USB_HSIC,
+	},
+	{
+		.id = MSM_BUS_MASTER_BLSP_1,
+		.masterp = mport_blsp_1,
+		.num_mports = ARRAY_SIZE(mport_blsp_1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_BLSP_1,
+	},
+	{
+		.id = MSM_BUS_FAB_SYS_NOC,
+		.gateway = 1,
+		.slavep = sport_gw_pnoc_snoc,
+		.num_sports = ARRAY_SIZE(sport_gw_pnoc_snoc),
+		.masterp = mport_gw_snoc_pnoc,
+		.num_mports = ARRAY_SIZE(mport_gw_snoc_pnoc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_PNOC_SNOC,
+		.mas_hw_id = MAS_SNOC_PNOC,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SDCC_1,
+		.slavep = sport_sdcc_1,
+		.num_sports = ARRAY_SIZE(sport_sdcc_1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SDCC_1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SDCC_3,
+		.slavep = sport_sdcc_3,
+		.num_sports = ARRAY_SIZE(sport_sdcc_3),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SDCC_3,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SDCC_2,
+		.slavep = sport_sdcc_2,
+		.num_sports = ARRAY_SIZE(sport_sdcc_2),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SDCC_2,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SDCC_4,
+		.slavep = sport_sdcc_4,
+		.num_sports = ARRAY_SIZE(sport_sdcc_4),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SDCC_4,
+	},
+	{
+		.id = MSM_BUS_SLAVE_TSIF,
+		.slavep = sport_tsif,
+		.num_sports = ARRAY_SIZE(sport_tsif),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_TSIF,
+	},
+	{
+		.id = MSM_BUS_SLAVE_BAM_DMA,
+		.slavep = sport_bam_dma,
+		.num_sports = ARRAY_SIZE(sport_bam_dma),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_BAM_DMA,
+	},
+	{
+		.id = MSM_BUS_SLAVE_QPIC,
+		.masterp = sport_qpic,
+		.num_mports = ARRAY_SIZE(sport_qpic),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = SLV_QPIC,
+	},
+	{
+		.id = MSM_BUS_SLAVE_BLSP_2,
+		.slavep = sport_blsp_2,
+		.num_sports = ARRAY_SIZE(sport_blsp_2),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_BLSP_2,
+	},
+	{
+		.id = MSM_BUS_SLAVE_USB_HSIC,
+		.slavep = sport_usb_hsic,
+		.num_sports = ARRAY_SIZE(sport_usb_hsic),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_USB_HSIC,
+	},
+	{
+		.id = MSM_BUS_SLAVE_BLSP_1,
+		.slavep = sport_blsp_1,
+		.num_sports = ARRAY_SIZE(sport_blsp_1),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_BLSP_1,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PDM,
+		.slavep = sport_pdm,
+		.num_sports = ARRAY_SIZE(sport_pdm),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_PDM,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PERIPH_APU_CFG,
+		.slavep = sport_periph_apu_cfg,
+		.num_sports = ARRAY_SIZE(sport_periph_apu_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_PERIPH_APU_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PNOC_MPU_CFG,
+		.slavep = sport_pnoc_mpu_cfg,
+		.num_sports = ARRAY_SIZE(sport_pnoc_mpu_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_MPU_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PRNG,
+		.slavep = sport_prng,
+		.num_sports = ARRAY_SIZE(sport_prng),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_PRNG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SERVICE_PNOC,
+		.slavep = sport_service_pnoc,
+		.num_sports = ARRAY_SIZE(sport_service_pnoc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SERVICE_PNOC,
+	},
+};
+
+static struct msm_bus_node_info config_noc_info[] = {
+	{
+		.id = MSM_BUS_MASTER_RPM_INST,
+		.masterp = mport_rpm_inst,
+		.num_mports = ARRAY_SIZE(mport_rpm_inst),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_RPM_INST,
+	},
+	{
+		.id = MSM_BUS_MASTER_RPM_DATA,
+		.masterp = mport_rpm_data,
+		.num_mports = ARRAY_SIZE(mport_rpm_data),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_RPM_DATA,
+	},
+	{
+		.id = MSM_BUS_MASTER_RPM_SYS,
+		.masterp = mport_rpm_sys,
+		.num_mports = ARRAY_SIZE(mport_rpm_sys),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_RPM_SYS,
+	},
+	{
+		.id = MSM_BUS_MASTER_DEHR,
+		.masterp = mport_dehr,
+		.num_mports = ARRAY_SIZE(mport_dehr),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_DEHR,
+	},
+	{
+		.id = MSM_BUS_MASTER_QDSS_DAP,
+		.masterp = mport_qdss_dap,
+		.num_mports = ARRAY_SIZE(mport_qdss_dap),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_QDSS_DAP,
+	},
+	{
+		.id = MSM_BUS_MASTER_SPDM,
+		.masterp = mport_spdm,
+		.num_mports = ARRAY_SIZE(mport_spdm),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_SPDM,
+	},
+	{
+		.id = MSM_BUS_MASTER_TIC,
+		.masterp = mport_tic,
+		.num_mports = ARRAY_SIZE(mport_tic),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_TIC,
+	},
+	{
+		.id = MSM_BUS_SLAVE_CLK_CTL,
+		.slavep = sport_clk_ctl,
+		.num_sports = ARRAY_SIZE(sport_clk_ctl),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_CLK_CTL,
+	},
+	{
+		.id = MSM_BUS_SLAVE_CNOC_MSS,
+		.slavep = sport_cnoc_mss,
+		.num_sports = ARRAY_SIZE(sport_cnoc_mss),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_CNOC_MSS,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SECURITY,
+		.slavep = sport_security,
+		.num_sports = ARRAY_SIZE(sport_security),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SECURITY,
+	},
+	{
+		.id = MSM_BUS_SLAVE_TCSR,
+		.slavep = sport_tcsr,
+		.num_sports = ARRAY_SIZE(sport_tcsr),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_TCSR,
+	},
+	{
+		.id = MSM_BUS_SLAVE_TLMM,
+		.slavep = sport_tlmm,
+		.num_sports = ARRAY_SIZE(sport_tlmm),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_TLMM,
+	},
+	{
+		.id = MSM_BUS_SLAVE_CRYPTO_0_CFG,
+		.slavep = sport_crypto_0_cfg,
+		.num_sports = ARRAY_SIZE(sport_crypto_0_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_CRYPTO_0_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_IMEM_CFG,
+		.slavep = sport_imem_cfg,
+		.num_sports = ARRAY_SIZE(sport_imem_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_IMEM_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_IPS_CFG,
+		.slavep = sport_ips_cfg,
+		.num_sports = ARRAY_SIZE(sport_ips_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_IPS_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MESSAGE_RAM,
+		.slavep = sport_message_ram,
+		.num_sports = ARRAY_SIZE(sport_message_ram),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_MESSAGE_RAM,
+	},
+	{
+		.id = MSM_BUS_SLAVE_BIMC_CFG,
+		.slavep = sport_bimc_cfg,
+		.num_sports = ARRAY_SIZE(sport_bimc_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_BIMC_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_BOOT_ROM,
+		.slavep = sport_boot_rom,
+		.num_sports = ARRAY_SIZE(sport_boot_rom),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_BOOT_ROM,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PMIC_ARB,
+		.slavep = sport_pmic_arb,
+		.num_sports = ARRAY_SIZE(sport_pmic_arb),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_PMIC_ARB,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SPDM_WRAPPER,
+		.slavep = sport_spdm_wrapper,
+		.num_sports = ARRAY_SIZE(sport_spdm_wrapper),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SPDM_WRAPPER,
+	},
+	{
+		.id = MSM_BUS_SLAVE_DEHR_CFG,
+		.slavep = sport_dehr_cfg,
+		.num_sports = ARRAY_SIZE(sport_dehr_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_DEHR_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_MPM,
+		.slavep = sport_mpm,
+		.num_sports = ARRAY_SIZE(sport_mpm),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_MPM,
+	},
+	{
+		.id = MSM_BUS_SLAVE_QDSS_CFG,
+		.slavep = sport_qdss_cfg,
+		.num_sports = ARRAY_SIZE(sport_qdss_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_QDSS_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RBCPR_CFG,
+		.slavep = sport_rbcpr_cfg,
+		.num_sports = ARRAY_SIZE(sport_rbcpr_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_RBCPR_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RBCPR_QDSS_APU_CFG,
+		.slavep = sport_rbcpr_qdss_apu_cfg,
+		.num_sports = ARRAY_SIZE(sport_rbcpr_qdss_apu_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_RBCPR_QDSS_APU_CFG,
+	},
+	{
+		.id = MSM_BUS_FAB_SYS_NOC,
+		.gateway = 1,
+		.slavep = sport_gw_cnoc_snoc,
+		.num_sports = ARRAY_SIZE(sport_gw_cnoc_snoc),
+		.masterp = mport_gw_snoc_cnoc,
+		.num_mports = ARRAY_SIZE(mport_gw_snoc_cnoc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.mas_hw_id = MAS_SNOC_CNOC,
+		.slv_hw_id = SLV_CNOC_SNOC,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PNOC_CFG,
+		.slavep = sport_pnoc_cfg,
+		.num_sports = ARRAY_SIZE(sport_pnoc_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_PNOC_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SNOC_MPU_CFG,
+		.slavep = sport_snoc_mpu_cfg,
+		.num_sports = ARRAY_SIZE(sport_snoc_mpu_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SNOC_MPU_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SNOC_CFG,
+		.slavep = sport_snoc_cfg,
+		.num_sports = ARRAY_SIZE(sport_snoc_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SNOC_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_PHY_APU_CFG,
+		.slavep = sport_phy_apu_cfg,
+		.num_sports = ARRAY_SIZE(sport_phy_apu_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_PHY_APU_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_EBI1_PHY_CFG,
+		.slavep = sport_ebi1_phy_cfg,
+		.num_sports = ARRAY_SIZE(sport_ebi1_phy_cfg),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_EBI1_PHY_CFG,
+	},
+	{
+		.id = MSM_BUS_SLAVE_RPM,
+		.slavep = sport_rpm,
+		.num_sports = ARRAY_SIZE(sport_rpm),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_RPM,
+	},
+	{
+		.id = MSM_BUS_SLAVE_SERVICE_CNOC,
+		.slavep = sport_service_cnoc,
+		.num_sports = ARRAY_SIZE(sport_service_cnoc),
+		.tier = tier2,
+		.num_tiers = ARRAY_SIZE(tier2),
+		.buswidth = 8,
+		.slv_hw_id = SLV_SERVICE_CNOC,
+	},
+};
+
+static void msm_bus_board_assign_iids(struct msm_bus_fabric_registration
+	*fabreg, int fabid)
+{
+	int i;
+	for (i = 0; i < fabreg->len; i++) {
+		if (!fabreg->info[i].gateway) {
+			fabreg->info[i].priv_id = fabid + fabreg->info[i].id;
+			if (fabreg->info[i].id < SLAVE_ID_KEY) {
+				WARN(fabreg->info[i].id >= NMASTERS,
+					"id %d exceeds array size!\n",
+					fabreg->info[i].id);
+				master_iids[fabreg->info[i].id] =
+					fabreg->info[i].priv_id;
+			} else {
+				WARN((fabreg->info[i].id - SLAVE_ID_KEY) >=
+					NSLAVES, "id %d exceeds array size!\n",
+					fabreg->info[i].id);
+				slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)]
+					= fabreg->info[i].priv_id;
+			}
+		} else {
+			fabreg->info[i].priv_id = fabreg->info[i].id;
+		}
+	}
+}
+
+static int msm_bus_board_9625_get_iid(int id)
+{
+	if ((id < SLAVE_ID_KEY && id >= NMASTERS) ||
+		id >= (SLAVE_ID_KEY + NSLAVES)) {
+		MSM_BUS_ERR("Cannot get iid. Invalid id %d passed\n", id);
+		return -EINVAL;
+	}
+
+	return CHECK_ID(((id < SLAVE_ID_KEY) ? master_iids[id] :
+		slave_iids[id - SLAVE_ID_KEY]), id);
+}
+
+int msm_bus_board_rpm_get_il_ids(uint16_t *id)
+{
+	return -ENXIO;
+}
+
+static struct msm_bus_board_algorithm msm_bus_board_algo = {
+	.board_nfab = NFAB_9625,
+	.get_iid = msm_bus_board_9625_get_iid,
+	.assign_iids = msm_bus_board_assign_iids,
+};
+
+struct msm_bus_fabric_registration msm_bus_9625_sys_noc_pdata = {
+	.id = MSM_BUS_FAB_SYS_NOC,
+	.name = "msm_sys_noc",
+	.info = sys_noc_info,
+	.len = ARRAY_SIZE(sys_noc_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.nmasters = 15,
+	.nslaves = 12,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+	.qos_freq = 4800,
+	.hw_sel = MSM_BUS_NOC,
+	.rpm_enabled = 1,
+};
+
+struct msm_bus_fabric_registration msm_bus_9625_bimc_pdata = {
+	.id = MSM_BUS_FAB_BIMC,
+	.name = "msm_bimc",
+	.info = bimc_info,
+	.len = ARRAY_SIZE(bimc_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "mem_clk",
+	.fabclk[ACTIVE_CTX] = "mem_a_clk",
+	.nmasters = 7,
+	.nslaves = 4,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+	.qos_freq = 4800,
+	.hw_sel = MSM_BUS_BIMC,
+	.rpm_enabled = 1,
+};
+
+struct msm_bus_fabric_registration msm_bus_9625_periph_noc_pdata = {
+	.id = MSM_BUS_FAB_PERIPH_NOC,
+	.name = "msm_periph_noc",
+	.info = periph_noc_info,
+	.len = ARRAY_SIZE(periph_noc_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.nmasters = 14,
+	.nslaves = 15,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+	.hw_sel = MSM_BUS_NOC,
+	.rpm_enabled = 1,
+};
+
+struct msm_bus_fabric_registration msm_bus_9625_config_noc_pdata = {
+	.id = MSM_BUS_FAB_CONFIG_NOC,
+	.name = "msm_config_noc",
+	.info = config_noc_info,
+	.len = ARRAY_SIZE(config_noc_info),
+	.ahb = 0,
+	.fabclk[DUAL_CTX] = "bus_clk",
+	.fabclk[ACTIVE_CTX] = "bus_a_clk",
+	.nmasters = 8,
+	.nslaves = 30,
+	.ntieredslaves = 0,
+	.board_algo = &msm_bus_board_algo,
+	.hw_sel = MSM_BUS_NOC,
+	.rpm_enabled = 1,
+};
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index b2160c5..c1c05af 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -384,9 +384,6 @@
 static int msm_dcvs_do_freq(void *data)
 {
 	struct dcvs_core *core = (struct dcvs_core *)data;
-	static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
-
-	sched_setscheduler(current, SCHED_FIFO, &param);
 
 	while (!kthread_should_stop()) {
 		wait_event(core->wait_q, !(core->pending_freq == 0 ||
diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c
index 9f6cc11..a65b3ee 100644
--- a/arch/arm/mach-msm/msm_mpdecision.c
+++ b/arch/arm/mach-msm/msm_mpdecision.c
@@ -356,11 +356,8 @@
 static int __cpuinit msm_mpd_do_hotplug(void *data)
 {
 	int *event = (int *)data;
-	static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
 	int cpu;
 
-	sched_setscheduler(current, SCHED_FIFO, &param);
-
 	while (1) {
 		wait_event(msm_mpd.wait_hpq, *event || kthread_should_stop());
 		if (kthread_should_stop())
@@ -400,13 +397,10 @@
 static int msm_mpd_do_update_scm(void *data)
 {
 	struct msm_mpd_scm_data *scm_data = (struct msm_mpd_scm_data *)data;
-	static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
 	unsigned long flags;
 	enum msm_dcvs_scm_event event;
 	int nr;
 
-	sched_setscheduler(current, SCHED_FIFO, &param);
-
 	while (1) {
 		wait_event(msm_mpd.wait_q,
 			msm_mpd.data.event == MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED
diff --git a/arch/arm/mach-msm/msm_qmi_interface.c b/arch/arm/mach-msm/msm_qmi_interface.c
new file mode 100644
index 0000000..4c4635a
--- /dev/null
+++ b/arch/arm/mach-msm/msm_qmi_interface.c
@@ -0,0 +1,694 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/qmi_encdec.h>
+
+#include <mach/msm_qmi_interface.h>
+#include <mach/msm_ipc_router.h>
+
+#include "msm_qmi_interface_priv.h"
+
+static LIST_HEAD(svc_event_nb_list);
+static DEFINE_MUTEX(svc_event_nb_list_lock);
+
+struct elem_info qmi_response_type_v01_ei[] = {
+	{
+		.data_type	= QMI_SIGNED_2_BYTE_ENUM,
+		.elem_len	= 1,
+		.elem_size	= sizeof(uint16_t),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= offsetof(struct qmi_response_type_v01,
+					   result),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type      = QMI_SIGNED_2_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint16_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+		.offset         = offsetof(struct qmi_response_type_v01,
+					   error),
+		.ei_array       = NULL,
+	},
+	{
+		.data_type	= QMI_EOTI,
+		.elem_len	= 0,
+		.elem_size	= 0,
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= 0,
+		.ei_array	= NULL,
+	},
+};
+
+static void qmi_event_notify(unsigned event, void *priv)
+{
+	struct qmi_handle *handle = (struct qmi_handle *)priv;
+	unsigned long flags;
+
+	if (!handle)
+		return;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return;
+	}
+
+	switch (event) {
+	case MSM_IPC_ROUTER_READ_CB:
+		spin_lock_irqsave(&handle->notify_lock, flags);
+		handle->notify(handle, QMI_RECV_MSG, handle->notify_priv);
+		spin_unlock_irqrestore(&handle->notify_lock, flags);
+		break;
+
+	default:
+		break;
+	}
+	mutex_unlock(&handle->handle_lock);
+}
+
+struct qmi_handle *qmi_handle_create(
+	void (*notify)(struct qmi_handle *handle,
+		       enum qmi_event_type event, void *notify_priv),
+	void *notify_priv)
+{
+	struct qmi_handle *temp_handle;
+	struct msm_ipc_port *port_ptr;
+
+	temp_handle = kzalloc(sizeof(struct qmi_handle), GFP_KERNEL);
+	if (!temp_handle) {
+		pr_err("%s: Failure allocating client handle\n", __func__);
+		return NULL;
+	}
+
+	port_ptr = msm_ipc_router_create_port(qmi_event_notify,
+					      (void *)temp_handle);
+	if (!port_ptr) {
+		pr_err("%s: IPC router port creation failed\n", __func__);
+		kfree(temp_handle);
+		return NULL;
+	}
+
+	temp_handle->src_port = port_ptr;
+	temp_handle->next_txn_id = 1;
+	INIT_LIST_HEAD(&temp_handle->txn_list);
+	mutex_init(&temp_handle->handle_lock);
+	spin_lock_init(&temp_handle->notify_lock);
+	temp_handle->notify = notify;
+	temp_handle->notify_priv = notify_priv;
+	temp_handle->handle_reset = 0;
+	init_waitqueue_head(&temp_handle->reset_waitq);
+	return temp_handle;
+}
+EXPORT_SYMBOL(qmi_handle_create);
+
+static void clean_txn_info(struct qmi_handle *handle)
+{
+	struct qmi_txn *txn_handle, *temp_txn_handle;
+
+	list_for_each_entry_safe(txn_handle, temp_txn_handle,
+				 &handle->txn_list, list) {
+		if (txn_handle->type == QMI_ASYNC_TXN) {
+			list_del(&txn_handle->list);
+			kfree(txn_handle);
+		} else if (txn_handle->type == QMI_SYNC_TXN) {
+			wake_up(&txn_handle->wait_q);
+		}
+	}
+}
+
+int qmi_handle_destroy(struct qmi_handle *handle)
+{
+	int rc;
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	handle->handle_reset = 1;
+	clean_txn_info(handle);
+	mutex_unlock(&handle->handle_lock);
+
+	rc = wait_event_interruptible(handle->reset_waitq,
+				      list_empty(&handle->txn_list));
+
+	/* TODO: Destroy client owned transaction */
+	msm_ipc_router_close_port((struct msm_ipc_port *)(handle->src_port));
+	kfree(handle->dest_info);
+	kfree(handle);
+	return 0;
+}
+EXPORT_SYMBOL(qmi_handle_destroy);
+
+int qmi_register_ind_cb(struct qmi_handle *handle,
+	void (*ind_cb)(struct qmi_handle *handle,
+		       unsigned int msg_id, void *msg,
+		       unsigned int msg_len, void *ind_cb_priv),
+	void *ind_cb_priv)
+{
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+
+	handle->ind_cb = ind_cb;
+	handle->ind_cb_priv = ind_cb_priv;
+	mutex_unlock(&handle->handle_lock);
+	return 0;
+}
+EXPORT_SYMBOL(qmi_register_ind_cb);
+
+static int qmi_encode_and_send_req(struct qmi_txn **ret_txn_handle,
+	struct qmi_handle *handle, enum txn_type type,
+	struct msg_desc *req_desc, void *req, unsigned int req_len,
+	struct msg_desc *resp_desc, void *resp, unsigned int resp_len,
+	void (*resp_cb)(struct qmi_handle *handle,
+			unsigned int msg_id, void *msg,
+			void *resp_cb_data),
+	void *resp_cb_data)
+{
+	struct qmi_txn *txn_handle;
+	int rc, encoded_req_len;
+	void *encoded_req;
+
+	if (!handle || !handle->dest_info ||
+	    !req_desc || !req || !resp_desc || !resp)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+
+	/* Allocate Transaction Info */
+	txn_handle = kzalloc(sizeof(struct qmi_txn), GFP_KERNEL);
+	if (!txn_handle) {
+		pr_err("%s: Failed to allocate txn handle\n", __func__);
+		mutex_unlock(&handle->handle_lock);
+		return -ENOMEM;
+	}
+	txn_handle->type = type;
+	INIT_LIST_HEAD(&txn_handle->list);
+	init_waitqueue_head(&txn_handle->wait_q);
+
+	/* Cache the parameters passed & mark it as sync*/
+	txn_handle->handle = handle;
+	txn_handle->resp_desc = resp_desc;
+	txn_handle->resp = resp;
+	txn_handle->resp_len = resp_len;
+	txn_handle->resp_received = 0;
+	txn_handle->resp_cb = resp_cb;
+	txn_handle->resp_cb_data = resp_cb_data;
+
+	/* Encode the request msg */
+	encoded_req_len = req_desc->max_msg_len + QMI_HEADER_SIZE;
+	encoded_req = kmalloc(encoded_req_len, GFP_KERNEL);
+	if (!encoded_req) {
+		pr_err("%s: Failed to allocate req_msg_buf\n", __func__);
+		rc = -ENOMEM;
+		goto encode_and_send_req_err1;
+	}
+	rc = qmi_kernel_encode(req_desc,
+		(void *)(encoded_req + QMI_HEADER_SIZE),
+		req_desc->max_msg_len, req);
+	if (rc < 0) {
+		pr_err("%s: Encode Failure %d\n", __func__, rc);
+		goto encode_and_send_req_err2;
+	}
+	encoded_req_len = rc;
+
+	/* Encode the header & Add to the txn_list */
+	if (!handle->next_txn_id)
+		handle->next_txn_id++;
+	txn_handle->txn_id = handle->next_txn_id++;
+	encode_qmi_header(encoded_req, QMI_REQUEST_CONTROL_FLAG,
+			  txn_handle->txn_id, req_desc->msg_id,
+			  encoded_req_len);
+	encoded_req_len += QMI_HEADER_SIZE;
+	list_add_tail(&txn_handle->list, &handle->txn_list);
+
+	/* Send the request */
+	rc = msm_ipc_router_send_msg((struct msm_ipc_port *)(handle->src_port),
+		(struct msm_ipc_addr *)handle->dest_info,
+		encoded_req, encoded_req_len);
+	if (rc < 0) {
+		pr_err("%s: send_msg failed %d\n", __func__, rc);
+		goto encode_and_send_req_err3;
+	}
+	mutex_unlock(&handle->handle_lock);
+
+	kfree(encoded_req);
+	if (ret_txn_handle)
+		*ret_txn_handle = txn_handle;
+	return 0;
+
+encode_and_send_req_err3:
+	list_del(&txn_handle->list);
+encode_and_send_req_err2:
+	kfree(encoded_req);
+encode_and_send_req_err1:
+	kfree(txn_handle);
+	mutex_unlock(&handle->handle_lock);
+	return rc;
+}
+
+int qmi_send_req_wait(struct qmi_handle *handle,
+		      struct msg_desc *req_desc,
+		      void *req, unsigned int req_len,
+		      struct msg_desc *resp_desc,
+		      void *resp, unsigned int resp_len,
+		      unsigned long timeout_ms)
+{
+	struct qmi_txn *txn_handle = NULL;
+	int rc;
+
+	/* Encode and send the request */
+	rc = qmi_encode_and_send_req(&txn_handle, handle, QMI_SYNC_TXN,
+				     req_desc, req, req_len,
+				     resp_desc, resp, resp_len,
+				     NULL, NULL);
+	if (rc < 0) {
+		pr_err("%s: Error encode & send req: %d\n", __func__, rc);
+		return rc;
+	}
+
+	/* Wait for the response */
+	if (!timeout_ms) {
+		rc = wait_event_interruptible(txn_handle->wait_q,
+					(txn_handle->resp_received ||
+					 handle->handle_reset));
+	} else {
+		rc = wait_event_interruptible_timeout(txn_handle->wait_q,
+					(txn_handle->resp_received ||
+					 handle->handle_reset),
+					msecs_to_jiffies(timeout_ms));
+		if (rc == 0)
+			rc = -ETIMEDOUT;
+	}
+
+	mutex_lock(&handle->handle_lock);
+	if (!txn_handle->resp_received) {
+		pr_err("%s: Response Wait Error %d\n", __func__, rc);
+		if (handle->handle_reset)
+			rc = -ENETRESET;
+		if (rc >= 0)
+			rc = -EFAULT;
+		goto send_req_wait_err;
+	}
+	rc = 0;
+
+send_req_wait_err:
+	list_del(&txn_handle->list);
+	kfree(txn_handle);
+	mutex_unlock(&handle->handle_lock);
+	wake_up(&handle->reset_waitq);
+	return rc;
+}
+EXPORT_SYMBOL(qmi_send_req_wait);
+
+int qmi_send_req_nowait(struct qmi_handle *handle,
+			struct msg_desc *req_desc,
+			void *req, unsigned int req_len,
+			struct msg_desc *resp_desc,
+			void *resp, unsigned int resp_len,
+			void (*resp_cb)(struct qmi_handle *handle,
+					unsigned int msg_id, void *msg,
+					void *resp_cb_data),
+			void *resp_cb_data)
+{
+	return qmi_encode_and_send_req(NULL, handle, QMI_ASYNC_TXN,
+				       req_desc, req, req_len,
+				       resp_desc, resp, resp_len,
+				       resp_cb, resp_cb_data);
+}
+EXPORT_SYMBOL(qmi_send_req_nowait);
+
+static struct qmi_txn *find_txn_handle(struct qmi_handle *handle,
+				       uint16_t txn_id)
+{
+	struct qmi_txn *txn_handle;
+
+	list_for_each_entry(txn_handle, &handle->txn_list, list) {
+		if (txn_handle->txn_id == txn_id)
+			return txn_handle;
+	}
+	return NULL;
+}
+
+static int handle_qmi_response(struct qmi_handle *handle,
+			       unsigned char *resp_msg, uint16_t txn_id,
+			       uint16_t msg_id, uint16_t msg_len)
+{
+	struct qmi_txn *txn_handle;
+	int rc;
+
+	/* Find the transaction handle */
+	txn_handle = find_txn_handle(handle, txn_id);
+	if (!txn_handle) {
+		pr_err("%s Response received for non-existent txn_id %d\n",
+			__func__, txn_id);
+		return -EINVAL;
+	}
+
+	/* Decode the message */
+	rc = qmi_kernel_decode(txn_handle->resp_desc, txn_handle->resp,
+			       (void *)(resp_msg + QMI_HEADER_SIZE), msg_len);
+	if (rc < 0) {
+		pr_err("%s: Response Decode Failure <%d: %d: %d> rc: %d\n",
+			__func__, txn_id, msg_id, msg_len, rc);
+		wake_up(&txn_handle->wait_q);
+		if (txn_handle->type == QMI_ASYNC_TXN) {
+			list_del(&txn_handle->list);
+			kfree(txn_handle);
+		}
+		return rc;
+	}
+
+	/* Handle async or sync resp */
+	switch (txn_handle->type) {
+	case QMI_SYNC_TXN:
+		txn_handle->resp_received = 1;
+		wake_up(&txn_handle->wait_q);
+		rc = 0;
+		break;
+
+	case QMI_ASYNC_TXN:
+		if (txn_handle->resp_cb)
+			txn_handle->resp_cb(txn_handle->handle, msg_id,
+					    txn_handle->resp,
+					    txn_handle->resp_cb_data);
+		list_del(&txn_handle->list);
+		kfree(txn_handle);
+		rc = 0;
+		break;
+
+	default:
+		pr_err("%s: Unrecognized transaction type\n", __func__);
+		return -EFAULT;
+	}
+	return rc;
+}
+
+static int handle_qmi_indication(struct qmi_handle *handle, void *msg,
+				 unsigned int msg_id, unsigned int msg_len)
+{
+	if (handle->ind_cb)
+		handle->ind_cb(handle, msg_id, msg,
+				msg_len, handle->ind_cb_priv);
+	return 0;
+}
+
+int qmi_recv_msg(struct qmi_handle *handle)
+{
+	unsigned int recv_msg_len;
+	unsigned char *recv_msg = NULL;
+	struct msm_ipc_addr src_addr;
+	unsigned char cntl_flag;
+	uint16_t txn_id, msg_id, msg_len;
+	int rc;
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+
+	/* Read the messages */
+	rc = msm_ipc_router_read_msg((struct msm_ipc_port *)(handle->src_port),
+				     &src_addr, &recv_msg, &recv_msg_len);
+	if (rc < 0) {
+		pr_err("%s: Read failed %d\n", __func__, rc);
+		mutex_unlock(&handle->handle_lock);
+		return rc;
+	}
+
+	/* Decode the header & Handle the req, resp, indication message */
+	decode_qmi_header(recv_msg, &cntl_flag, &txn_id, &msg_id, &msg_len);
+
+	switch (cntl_flag) {
+	case QMI_RESPONSE_CONTROL_FLAG:
+		rc = handle_qmi_response(handle, recv_msg,
+					 txn_id, msg_id, msg_len);
+		break;
+
+	case QMI_INDICATION_CONTROL_FLAG:
+		rc = handle_qmi_indication(handle, recv_msg, msg_id, msg_len);
+		break;
+
+	default:
+		rc = -EFAULT;
+		pr_err("%s: Unsupported message type %d\n",
+			__func__, cntl_flag);
+		break;
+	}
+	kfree(recv_msg);
+	mutex_unlock(&handle->handle_lock);
+	return rc;
+}
+EXPORT_SYMBOL(qmi_recv_msg);
+
+int qmi_connect_to_service(struct qmi_handle *handle,
+			   uint32_t service_id, uint32_t instance_id)
+{
+	struct msm_ipc_port_name svc_name;
+	struct msm_ipc_server_info svc_info;
+	struct msm_ipc_addr *svc_dest_addr;
+	int rc;
+
+	if (!handle)
+		return -EINVAL;
+
+	svc_dest_addr = kzalloc(sizeof(struct msm_ipc_addr),
+				GFP_KERNEL);
+	if (!svc_dest_addr) {
+		pr_err("%s: Failure allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	svc_name.service = service_id;
+	svc_name.instance = instance_id;
+
+	rc = msm_ipc_router_lookup_server_name(&svc_name, &svc_info, 1, 0xFF);
+	if (rc <= 0) {
+		pr_err("%s: Server not found\n", __func__);
+		return -ENODEV;
+	}
+	svc_dest_addr->addrtype = MSM_IPC_ADDR_ID;
+	svc_dest_addr->addr.port_addr.node_id = svc_info.node_id;
+	svc_dest_addr->addr.port_addr.port_id = svc_info.port_id;
+	mutex_lock(&handle->handle_lock);
+	if (handle->handle_reset) {
+		mutex_unlock(&handle->handle_lock);
+		return -ENETRESET;
+	}
+	handle->dest_info = svc_dest_addr;
+	mutex_unlock(&handle->handle_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(qmi_connect_to_service);
+
+static struct svc_event_nb *find_svc_event_nb_by_name(const char *name)
+{
+	struct svc_event_nb *temp;
+
+	list_for_each_entry(temp, &svc_event_nb_list, list) {
+		if (!strncmp(name, temp->pdriver_name,
+			     sizeof(temp->pdriver_name)))
+			return temp;
+	}
+	return NULL;
+}
+
+static int qmi_svc_event_probe(struct platform_device *pdev)
+{
+	struct svc_event_nb *temp;
+	unsigned long flags;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb_by_name(pdev->name);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	temp->svc_avail = 1;
+	raw_notifier_call_chain(&temp->svc_event_rcvr_list,
+				QMI_SERVER_ARRIVE, NULL);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+	return 0;
+}
+
+static int qmi_svc_event_remove(struct platform_device *pdev)
+{
+	struct svc_event_nb *temp;
+	unsigned long flags;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb_by_name(pdev->name);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	temp->svc_avail = 0;
+	raw_notifier_call_chain(&temp->svc_event_rcvr_list,
+				QMI_SERVER_EXIT, NULL);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+	return 0;
+}
+
+static struct svc_event_nb *find_svc_event_nb(uint32_t service_id,
+					      uint32_t instance_id)
+{
+	struct svc_event_nb *temp;
+
+	list_for_each_entry(temp, &svc_event_nb_list, list) {
+		if (temp->service_id == service_id &&
+		    temp->instance_id == instance_id)
+			return temp;
+	}
+	return NULL;
+}
+
+static struct svc_event_nb *find_and_add_svc_event_nb(uint32_t service_id,
+						      uint32_t instance_id)
+{
+	struct svc_event_nb *temp;
+	int ret;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb(service_id, instance_id);
+	if (temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return temp;
+	}
+
+	temp = kzalloc(sizeof(struct svc_event_nb), GFP_KERNEL);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		pr_err("%s: Failed to alloc notifier block\n", __func__);
+		return temp;
+	}
+
+	spin_lock_init(&temp->nb_lock);
+	temp->service_id = service_id;
+	temp->instance_id = instance_id;
+	INIT_LIST_HEAD(&temp->list);
+	temp->svc_driver.probe = qmi_svc_event_probe;
+	temp->svc_driver.remove = qmi_svc_event_remove;
+	scnprintf(temp->pdriver_name, sizeof(temp->pdriver_name),
+		  "QMI%08x:%08x", service_id, instance_id);
+	temp->svc_driver.driver.name = temp->pdriver_name;
+	RAW_INIT_NOTIFIER_HEAD(&temp->svc_event_rcvr_list);
+
+	list_add_tail(&temp->list, &svc_event_nb_list);
+	mutex_unlock(&svc_event_nb_list_lock);
+
+	ret = platform_driver_register(&temp->svc_driver);
+	if (ret < 0) {
+		pr_err("%s: Failed pdriver register\n", __func__);
+		mutex_lock(&svc_event_nb_list_lock);
+		list_del(&temp->list);
+		mutex_unlock(&svc_event_nb_list_lock);
+		kfree(temp);
+		temp = NULL;
+	}
+
+	return temp;
+}
+
+int qmi_svc_event_notifier_register(uint32_t service_id,
+				    uint32_t instance_id,
+				    struct notifier_block *nb)
+{
+	struct svc_event_nb *temp;
+	unsigned long flags;
+	int ret;
+
+	temp = find_and_add_svc_event_nb(service_id, instance_id);
+	if (!temp)
+		return -EFAULT;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb(service_id, instance_id);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EFAULT;
+	}
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	if (temp->svc_avail)
+		nb->notifier_call(nb, QMI_SERVER_ARRIVE, NULL);
+
+	ret = raw_notifier_chain_register(&temp->svc_event_rcvr_list, nb);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(qmi_svc_event_notifier_register);
+
+int qmi_svc_event_notifier_unregister(uint32_t service_id,
+				      uint32_t instance_id,
+				      struct notifier_block *nb)
+{
+	int ret;
+	struct svc_event_nb *temp;
+	unsigned long flags;
+
+	mutex_lock(&svc_event_nb_list_lock);
+	temp = find_svc_event_nb(service_id, instance_id);
+	if (!temp) {
+		mutex_unlock(&svc_event_nb_list_lock);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&temp->nb_lock, flags);
+	ret = raw_notifier_chain_unregister(&temp->svc_event_rcvr_list, nb);
+	spin_unlock_irqrestore(&temp->nb_lock, flags);
+	mutex_unlock(&svc_event_nb_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(qmi_svc_event_notifier_unregister);
+
+MODULE_DESCRIPTION("MSM QMI Interface");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/msm_qmi_interface_priv.h b/arch/arm/mach-msm/msm_qmi_interface_priv.h
new file mode 100644
index 0000000..58f1ce3
--- /dev/null
+++ b/arch/arm/mach-msm/msm_qmi_interface_priv.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_QMI_INTERFACE_PRIV_H_
+#define _MSM_QMI_INTERFACE_PRIV_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/platform_device.h>
+#include <linux/qmi_encdec.h>
+
+#include <mach/msm_qmi_interface.h>
+
+enum txn_type {
+	QMI_SYNC_TXN = 1,
+	QMI_ASYNC_TXN,
+};
+
+struct qmi_txn {
+	struct list_head list;
+	uint16_t txn_id;
+	enum txn_type type;
+	struct qmi_handle *handle;
+	struct msg_desc *resp_desc;
+	void *resp;
+	unsigned int resp_len;
+	int resp_received;
+	void (*resp_cb)(struct qmi_handle *handle, unsigned int msg_id,
+			void *msg, void *resp_cb_data);
+	void *resp_cb_data;
+	wait_queue_head_t wait_q;
+};
+
+struct svc_event_nb {
+	spinlock_t nb_lock;
+	uint32_t service_id;
+	uint32_t instance_id;
+	char pdriver_name[32];
+	int svc_avail;
+	struct platform_driver svc_driver;
+	struct raw_notifier_head svc_event_rcvr_list;
+	struct list_head list;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 2eac6b7..550bb56 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -51,7 +51,8 @@
 #include "timer.h"
 #include "pm-boot.h"
 #include <mach/event_timer.h>
-
+#define CREATE_TRACE_POINTS
+#include "trace_msm_low_power.h"
 /******************************************************************************
  * Debug Definitions
  *****************************************************************************/
@@ -724,6 +725,51 @@
 	return;
 }
 
+static inline void msm_pm_ftrace_lpm_enter(unsigned int cpu,
+		uint32_t latency, uint32_t sleep_us,
+		uint32_t wake_up,
+		enum msm_pm_sleep_mode mode)
+{
+	switch (mode) {
+	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+		trace_msm_pm_enter_wfi(cpu, latency, sleep_us, wake_up);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+		trace_msm_pm_enter_spc(cpu, latency, sleep_us, wake_up);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+		trace_msm_pm_enter_pc(cpu, latency, sleep_us, wake_up);
+		break;
+	case MSM_PM_SLEEP_MODE_RETENTION:
+		trace_msm_pm_enter_ret(cpu, latency, sleep_us, wake_up);
+		break;
+	default:
+		break;
+	}
+}
+
+static inline void msm_pm_ftrace_lpm_exit(unsigned int cpu,
+		enum msm_pm_sleep_mode mode,
+		bool success)
+{
+	switch (mode) {
+	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+		trace_msm_pm_exit_wfi(cpu, success);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+		trace_msm_pm_exit_spc(cpu, success);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+		trace_msm_pm_exit_pc(cpu, success);
+		break;
+	case MSM_PM_SLEEP_MODE_RETENTION:
+		trace_msm_pm_exit_ret(cpu, success);
+		break;
+	default:
+		break;
+	}
+}
+
 int msm_pm_idle_prepare(struct cpuidle_device *dev,
 		struct cpuidle_driver *drv, int index)
 {
@@ -828,6 +874,11 @@
 
 	if (modified_time_us && !dev->cpu)
 		msm_pm_set_timer(modified_time_us);
+
+	msm_pm_ftrace_lpm_enter(dev->cpu, time_param.latency_us,
+			time_param.sleep_us, time_param.next_event_us,
+			ret);
+
 	return ret;
 }
 
@@ -835,6 +886,7 @@
 {
 	int64_t time;
 	int exit_stat;
+	bool collapsed = 1;
 
 	if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: mode %d\n",
@@ -854,7 +906,7 @@
 		break;
 
 	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
-		msm_pm_power_collapse_standalone(true);
+		collapsed = msm_pm_power_collapse_standalone(true);
 		exit_stat = MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
 		break;
 
@@ -865,8 +917,6 @@
 		int ret = -ENODEV;
 		int notify_rpm =
 			(sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE);
-		int collapsed;
-
 		timer_expiration = msm_pm_timer_enter_idle();
 
 		sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
@@ -901,6 +951,8 @@
 
 	time = ktime_to_ns(ktime_get()) - time;
 	msm_pm_add_stat(exit_stat, time);
+	msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode,
+				collapsed);
 
 	do_div(time, 1000);
 	return (int) time;
diff --git a/arch/arm/mach-msm/rpm-notifier.h b/arch/arm/mach-msm/rpm-notifier.h
index 33086c6..b9815a5 100644
--- a/arch/arm/mach-msm/rpm-notifier.h
+++ b/arch/arm/mach-msm/rpm-notifier.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -47,4 +47,12 @@
  * msm_rpm_exit_sleep - Notify RPM driver about resuming from power collapse
  */
 void msm_rpm_exit_sleep(void);
+
+/**
+ * msm_rpm_waiting_for_ack - Indicate if there is RPM message
+ *				pending acknowledgement.
+ * returns true for pending messages and false otherwise
+ */
+bool msm_rpm_waiting_for_ack(void);
+
 #endif /*__ARCH_ARM_MACH_MSM_RPM_NOTIF_H */
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index f97eb9a..6d1d038 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -354,6 +354,18 @@
 	}
 }
 
+bool msm_rpm_waiting_for_ack(void)
+{
+	bool ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msm_rpm_list_lock, flags);
+	ret = list_empty(&msm_rpm_wait_list);
+	spin_unlock_irqrestore(&msm_rpm_list_lock, flags);
+
+	return !ret;
+}
+
 static struct msm_rpm_wait_data *msm_rpm_get_entry_from_msg_id(uint32_t msg_id)
 {
 	struct list_head *ptr;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 3c0cbf7..b1dd1db 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -1016,6 +1016,7 @@
 	notify_dsp_smd();
 	notify_dsps_smd();
 	notify_wcnss_smd();
+	notify_rpm_smd();
 
 	/* change all remote states to CLOSED */
 	mutex_lock(&smd_probe_lock);
@@ -1031,6 +1032,7 @@
 	notify_dsp_smd();
 	notify_dsps_smd();
 	notify_wcnss_smd();
+	notify_rpm_smd();
 
 	SMD_DBG("%s: finished reset\n", __func__);
 }
diff --git a/arch/arm/mach-msm/trace_msm_low_power.h b/arch/arm/mach-msm/trace_msm_low_power.h
new file mode 100644
index 0000000..4e9da85
--- /dev/null
+++ b/arch/arm/mach-msm/trace_msm_low_power.h
@@ -0,0 +1,154 @@
+/* Copyright (c) 2012, 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM msm_low_power
+
+#if !defined(_TRACE_MSM_LOW_POWER_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MSM_LOW_POWER_H_
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(msm_pm_enter,
+
+	TP_PROTO(unsigned int cpu, uint32_t latency,
+		uint32_t sleep_us, uint32_t wake_up),
+
+	TP_ARGS(cpu, latency, sleep_us, wake_up),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, cpu)
+		__field(uint32_t, latency)
+		__field(uint32_t, sleep_us)
+		__field(uint32_t, wake_up)
+	),
+
+	TP_fast_assign(
+		__entry->cpu = cpu;
+		__entry->latency = latency;
+		__entry->sleep_us = sleep_us;
+		__entry->wake_up = wake_up;
+	),
+
+	TP_printk("cpu: %u latency: %uus sleep: %uus wake_up: %u",
+		__entry->cpu,
+		__entry->latency,
+		__entry->sleep_us,
+		__entry->wake_up)
+);
+
+DEFINE_EVENT(msm_pm_enter, msm_pm_enter_pc,
+
+	TP_PROTO(unsigned int cpu, uint32_t latency,
+		uint32_t sleep_us, uint32_t wake_up),
+
+	TP_ARGS(cpu, latency, sleep_us, wake_up)
+);
+
+DEFINE_EVENT(msm_pm_enter, msm_pm_enter_ret,
+
+	TP_PROTO(unsigned int cpu, uint32_t latency,
+		uint32_t sleep_us, uint32_t wake_up),
+
+	TP_ARGS(cpu, latency, sleep_us, wake_up)
+);
+
+DEFINE_EVENT(msm_pm_enter, msm_pm_enter_spc,
+
+	TP_PROTO(unsigned int cpu, uint32_t latency,
+		uint32_t sleep_us, uint32_t wake_up),
+
+	TP_ARGS(cpu, latency, sleep_us, wake_up)
+);
+
+DEFINE_EVENT(msm_pm_enter, msm_pm_enter_wfi,
+
+	TP_PROTO(unsigned int cpu, uint32_t latency,
+		uint32_t sleep_us, uint32_t wake_up),
+
+	TP_ARGS(cpu, latency, sleep_us, wake_up)
+);
+
+DECLARE_EVENT_CLASS(msm_pm_exit,
+
+	TP_PROTO(unsigned int cpu, bool success),
+
+	TP_ARGS(cpu, success),
+
+	TP_STRUCT__entry(
+		__field(unsigned int , cpu)
+		__field(int, success)
+	),
+
+	TP_fast_assign(
+		__entry->cpu = cpu;
+		__entry->success = success;
+	),
+
+	TP_printk("cpu:%u success:%d",
+			__entry->cpu,
+			__entry->success)
+);
+
+DEFINE_EVENT(msm_pm_exit, msm_pm_exit_pc,
+
+	TP_PROTO(unsigned int cpu, bool success),
+
+	TP_ARGS(cpu, success)
+);
+
+DEFINE_EVENT(msm_pm_exit, msm_pm_exit_ret,
+
+	TP_PROTO(unsigned int cpu, bool success),
+
+	TP_ARGS(cpu, success)
+);
+
+DEFINE_EVENT(msm_pm_exit, msm_pm_exit_spc,
+
+	TP_PROTO(unsigned int cpu, bool success),
+
+	TP_ARGS(cpu, success)
+);
+
+DEFINE_EVENT(msm_pm_exit, msm_pm_exit_wfi,
+
+	TP_PROTO(unsigned int cpu, bool success),
+
+	TP_ARGS(cpu, success)
+);
+
+TRACE_EVENT(lpm_resources,
+
+	TP_PROTO(uint32_t sleep_value , char *name),
+
+	TP_ARGS(sleep_value, name),
+
+	TP_STRUCT__entry(
+		__field(uint32_t , sleep_value)
+		__string(name, name)
+	),
+
+	TP_fast_assign(
+		__entry->sleep_value = sleep_value;
+		__assign_str(name, name);
+	),
+
+	TP_printk("name:%s sleep_value:%d",
+			 __get_str(name),
+			__entry->sleep_value)
+);
+#endif
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_msm_low_power
+#include <trace/define_trace.h>
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ab1bd68..afaa39d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -314,7 +314,8 @@
 core_initcall(consistent_init);
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
-				     pgprot_t prot, struct page **ret_page);
+				     pgprot_t prot, struct page **ret_page,
+				     bool no_kernel_mapping);
 
 static struct arm_vmregion_head coherent_head = {
 	.vm_lock	= __SPIN_LOCK_UNLOCKED(&coherent_head.vm_lock),
@@ -343,7 +344,7 @@
 	if (!IS_ENABLED(CONFIG_CMA))
 		return 0;
 
-	ptr = __alloc_from_contiguous(NULL, size, prot, &page);
+	ptr = __alloc_from_contiguous(NULL, size, prot, &page, false);
 	if (ptr) {
 		coherent_head.vm_start = (unsigned long) ptr;
 		coherent_head.vm_end = (unsigned long) ptr + size;
@@ -522,12 +523,27 @@
 	return 0;
 }
 
-static void __dma_remap(struct page *page, size_t size, pgprot_t prot)
+static int __dma_clear_pte(pte_t *pte, pgtable_t token, unsigned long addr,
+			    void *data)
+{
+	pte_clear(&init_mm, addr, pte);
+	return 0;
+}
+
+static void __dma_remap(struct page *page, size_t size, pgprot_t prot,
+			bool no_kernel_map)
 {
 	unsigned long start = (unsigned long) page_address(page);
 	unsigned end = start + size;
+	int (*func)(pte_t *pte, pgtable_t token, unsigned long addr,
+			    void *data);
 
-	apply_to_page_range(&init_mm, start, size, __dma_update_pte, &prot);
+	if (no_kernel_map)
+		func = __dma_clear_pte;
+	else
+		func = __dma_update_pte;
+
+	apply_to_page_range(&init_mm, start, size, func, &prot);
 	dsb();
 	flush_tlb_kernel_range(start, end);
 }
@@ -604,7 +620,8 @@
 }
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
-				     pgprot_t prot, struct page **ret_page)
+				     pgprot_t prot, struct page **ret_page,
+				     bool no_kernel_mapping)
 {
 	unsigned long order = get_order(size);
 	size_t count = size >> PAGE_SHIFT;
@@ -615,7 +632,7 @@
 		return NULL;
 
 	__dma_clear_buffer(page, size);
-	__dma_remap(page, size, prot);
+	__dma_remap(page, size, prot, no_kernel_mapping);
 
 	*ret_page = page;
 	return page_address(page);
@@ -624,7 +641,7 @@
 static void __free_from_contiguous(struct device *dev, struct page *page,
 				   size_t size)
 {
-	__dma_remap(page, size, pgprot_kernel);
+	__dma_remap(page, size, pgprot_kernel, false);
 	dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
 }
 
@@ -649,7 +666,7 @@
 
 #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c)	NULL
 #define __alloc_from_pool(dev, size, ret_page, c)		NULL
-#define __alloc_from_contiguous(dev, size, prot, ret)		NULL
+#define __alloc_from_contiguous(dev, size, prot, ret, w)	NULL
 #define __free_from_pool(cpu_addr, size)			0
 #define __free_from_contiguous(dev, page, size)			do { } while (0)
 #define __dma_free_remap(cpu_addr, size)			do { } while (0)
@@ -672,7 +689,8 @@
 
 
 static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-			 gfp_t gfp, pgprot_t prot, const void *caller)
+			 gfp_t gfp, pgprot_t prot, const void *caller,
+			 bool no_kernel_mapping)
 {
 	u64 mask = get_coherent_dma_mask(dev);
 	struct page *page;
@@ -712,7 +730,8 @@
 	else if (gfp & GFP_ATOMIC)
 		addr = __alloc_from_pool(dev, size, &page, caller);
 	else
-		addr = __alloc_from_contiguous(dev, size, prot, &page);
+		addr = __alloc_from_contiguous(dev, size, prot, &page,
+						no_kernel_mapping);
 
 	if (addr)
 		*handle = pfn_to_dma(dev, page_to_pfn(page));
@@ -729,12 +748,14 @@
 {
 	pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel);
 	void *memory;
+	bool no_kernel_mapping = dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING,
+					attrs);
 
 	if (dma_alloc_from_coherent(dev, size, handle, &memory))
 		return memory;
 
 	return __dma_alloc(dev, size, handle, gfp, prot,
-			   __builtin_return_address(0));
+			   __builtin_return_address(0), no_kernel_mapping);
 }
 
 /*
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 92efd94..fe61d2d 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1037,8 +1037,8 @@
 static int diagchar_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	int err, ret = 0, pkt_type;
-	bool mdm_mask = false;
+	int err, ret = 0, pkt_type, token_offset = 0;
+	bool remote_data = false;
 #ifdef DIAG_DEBUG
 	int length = 0, i;
 #endif
@@ -1072,14 +1072,16 @@
 	if (pkt_type == USER_SPACE_DATA_TYPE) {
 		err = copy_from_user(driver->user_space_data, buf + 4,
 							 payload_size);
+		/* Check for proc_type */
+		if (*(int *)driver->user_space_data == MDM_TOKEN) {
+			remote_data = true;
+			token_offset = 4;
+			payload_size -= 4;
+			buf += 4;
+		}
+
 		/* Check masks for On-Device logging */
 		if (driver->mask_check) {
-			/* Check if mask is for MDM or MSM */
-			if (*(int *)driver->user_space_data == MDM_TOKEN) {
-				mdm_mask = true;
-				driver->user_space_data += 4;
-				buf += 4;
-			}
 			if (!mask_request_validate(driver->user_space_data)) {
 				pr_alert("diag: mask request Invalid\n");
 				return -EFAULT;
@@ -1089,31 +1091,34 @@
 #ifdef DIAG_DEBUG
 		pr_debug("diag: user space data %d\n", payload_size);
 		for (i = 0; i < payload_size; i++)
-			pr_debug("\t %x", *((driver->user_space_data)+i));
+			pr_debug("\t %x", *((driver->user_space_data
+						+ token_offset)+i));
 #endif
 #ifdef CONFIG_DIAG_SDIO_PIPE
 		/* send masks to 9k too */
-		if (driver->sdio_ch && mdm_mask) {
+		if (driver->sdio_ch && remote_data) {
 			wait_event_interruptible(driver->wait_q,
 				 (sdio_write_avail(driver->sdio_ch) >=
 					 payload_size));
 			if (driver->sdio_ch && (payload_size > 0)) {
 				sdio_write(driver->sdio_ch, (void *)
-				   (driver->user_space_data), payload_size);
+				   (driver->user_space_data + token_offset),
+				   payload_size);
 			}
 		}
 #endif
 #ifdef CONFIG_DIAG_BRIDGE_CODE
 		/* send masks to 9k too */
-		if (driver->hsic_ch && (payload_size > 0) && mdm_mask) {
+		if (driver->hsic_ch && (payload_size > 0) && remote_data) {
 			/* wait sending mask updates if HSIC ch not ready */
 			if (driver->in_busy_hsic_write)
 				wait_event_interruptible(driver->wait_q,
 					(driver->in_busy_hsic_write != 1));
 			driver->in_busy_hsic_write = 1;
 			driver->in_busy_hsic_read_on_device = 0;
-			err = diag_bridge_write(driver->user_space_data,
-							 payload_size);
+			err = diag_bridge_write(
+					driver->user_space_data + token_offset,
+					payload_size);
 			if (err) {
 				pr_err("diag: err sending mask to MDM: %d\n",
 									 err);
@@ -1127,11 +1132,12 @@
 					driver->in_busy_hsic_write = 0;
 			}
 		}
-		if (driver->diag_smux_enabled && mdm_mask && driver->lcid) {
+		if (driver->diag_smux_enabled && remote_data
+						&& driver->lcid) {
 			if (payload_size > 0) {
 				err = msm_smux_write(driver->lcid, NULL,
-						driver->user_space_data,
-						payload_size);
+					driver->user_space_data + token_offset,
+					payload_size);
 				if (err) {
 					pr_err("diag:send mask to MDM err %d",
 							err);
@@ -1141,9 +1147,10 @@
 		}
 #endif
 		/* send masks to 8k now */
-		if (!mdm_mask)
-			diag_process_hdlc((void *)(driver->user_space_data),
-							 payload_size);
+		if (!remote_data)
+			diag_process_hdlc((void *)
+				(driver->user_space_data + token_offset),
+				 payload_size);
 		return 0;
 	}
 
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 8de2c70..4e4843b 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1718,9 +1718,15 @@
 					eoptimestamp));
 
 		if (context_id < KGSL_MEMSTORE_MAX) {
-			kgsl_sharedmem_writel(&rb->device->memstore,
+			/* reset per context ts_cmp_enable */
+			kgsl_sharedmem_writel(&device->memstore,
 					KGSL_MEMSTORE_OFFSET(context_id,
 						ts_cmp_enable), 0);
+			/* Always reset global timestamp ts_cmp_enable */
+			kgsl_sharedmem_writel(&device->memstore,
+					KGSL_MEMSTORE_OFFSET(
+						KGSL_MEMSTORE_GLOBAL,
+						ts_cmp_enable), 0);
 			wmb();
 		}
 
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 4c7534c..9e71199 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2586,9 +2586,15 @@
 					eoptimestamp));
 
 		if (context_id < KGSL_MEMSTORE_MAX) {
+			/* reset per context ts_cmp_enable */
 			kgsl_sharedmem_writel(&device->memstore,
 					KGSL_MEMSTORE_OFFSET(context_id,
 						ts_cmp_enable), 0);
+			/* Always reset global timestamp ts_cmp_enable */
+			kgsl_sharedmem_writel(&device->memstore,
+					KGSL_MEMSTORE_OFFSET(
+						KGSL_MEMSTORE_GLOBAL,
+						ts_cmp_enable), 0);
 			wmb();
 		}
 
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 0d5e409..9648f27 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -535,12 +535,8 @@
 	/* internal ib command identifier for the ringbuffer */
 	total_sizedwords += (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) ? 2 : 0;
 
-	/*
-	 * Add CP_COND_EXEC commands to generate CP_INTERRUPT only
-	 * for submissions from userspace.
-	 */
-	total_sizedwords += (context &&
-			!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) ? 7 : 0;
+	/* Add CP_COND_EXEC commands to generate CP_INTERRUPT */
+	total_sizedwords += context ? 7 : 0;
 
 	if (adreno_is_a3xx(adreno_dev))
 		total_sizedwords += 7;
@@ -676,7 +672,7 @@
 				rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
 	}
 
-	if (context && !(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
+	if (context) {
 		/* Conditional execution based on memory values */
 		GSL_RB_WRITE(ringcmds, rcmd_gpu,
 			cp_type3_packet(CP_COND_EXEC, 4));
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 119e25d..98c7434 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -28,7 +28,7 @@
 #define DRIVER_AUTHOR           "Qualcomm"
 #define DRIVER_NAME             "kgsl"
 #define DRIVER_DESC             "KGSL DRM"
-#define DRIVER_DATE             "20100127"
+#define DRIVER_DATE             "20121107"
 
 #define DRIVER_MAJOR            2
 #define DRIVER_MINOR            1
@@ -635,6 +635,43 @@
 }
 
 int
+kgsl_gem_get_ion_fd_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_kgsl_gem_get_ion_fd *args = data;
+	struct drm_gem_object *obj;
+	struct drm_kgsl_gem_object *priv;
+	int ret = 0;
+
+	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+
+	if (obj == NULL) {
+		DRM_ERROR("Invalid GEM handle %x\n", args->handle);
+		return -EBADF;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+	priv = obj->driver_private;
+
+	if (TYPE_IS_FD(priv->type))
+		ret = -EINVAL;
+	else {
+		if (priv->ion_handle) {
+			args->ion_fd = ion_share_dma_buf(
+			kgsl_drm_ion_phys_client, priv->ion_handle);
+		} else {
+			DRM_ERROR("GEM object has no ion memory allocated.\n");
+			ret = -EINVAL;
+		}
+	}
+
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+int
 kgsl_gem_setmemtype_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
@@ -1482,6 +1519,7 @@
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_ALLOC, kgsl_gem_alloc_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_MMAP, kgsl_gem_mmap_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFINFO, kgsl_gem_get_bufinfo_ioctl, 0),
+	DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_ION_FD, kgsl_gem_get_ion_fd_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_BUFCOUNT,
 		      kgsl_gem_set_bufcount_ioctl, 0),
 	DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_ACTIVE, kgsl_gem_set_active_ioctl, 0),
@@ -1547,7 +1585,7 @@
 
 	/* Create ION Client */
 	kgsl_drm_ion_phys_client = msm_ion_client_create(
-			ION_HEAP_CARVEOUT_MASK, ION_SF_HEAP_NAME);
+			ION_HEAP_CARVEOUT_MASK, "kgsl_drm");
 	if (!kgsl_drm_ion_phys_client) {
 		DRM_ERROR("Unable to create ION client\n");
 		return -ENOMEM;
@@ -1559,5 +1597,10 @@
 void kgsl_drm_exit(void)
 {
 	kgsl_drm_inited = DRM_KGSL_NOT_INITED;
+
+	if (kgsl_drm_ion_phys_client)
+		ion_client_destroy(kgsl_drm_ion_phys_client);
+	kgsl_drm_ion_phys_client = NULL;
+
 	drm_platform_exit(&driver, driver.kdriver.platform_device);
 }
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 10c5a17..0e82cf7 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -54,28 +54,6 @@
 #define QPNP_STATUS2_CONV_SEQ_TIMEOUT_STS		BIT(0)
 #define QPNP_CONV_TIMEOUT_ERR				2
 
-#define QPNP_INT_RT_ST					0x10
-#define QPNP_INT_SET_TYPE				0x11
-#define QPNP_INT_SET_TYPE_LOW_THR_INT_SET		BIT(4)
-#define QPNP_INT_SET_TYPE_HIGH_THR_INT_SET		BIT(3)
-#define QPNP_INT_SET_TYPE_CONV_SEQ_TIMEOUT_INT_SET	BIT(2)
-#define QPNP_INT_SET_TYPE_FIFO_NOT_EMPTY_INT_SET	BIT(1)
-#define QPNP_INT_SET_TYPE_EOC_SET_INT_TYPE		BIT(0)
-#define QPNP_INT_POLARITY_HIGH				0x12
-#define QPNP_INT_POLARITY_LOW				0x13
-#define QPNP_INT_EN_SET					0x15
-#define QPNP_INT_EN_SET_LOW_THR_INT_EN_SET		BIT(4)
-#define QPNP_INT_EN_SET_HIGH_THR_INT_EN_SET		BIT(3)
-#define QPNP_INT_EN_SET_CONV_SEQ_TIMEOUT_INT_EN		BIT(2)
-#define QPNP_INT_EN_SET_FIFO_NOT_EMPTY_INT_EN		BIT(1)
-#define QPNP_INT_EN_SET_EOC_INT_EN_SET			BIT(0)
-#define QPNP_INT_CLR					0x16
-#define QPNP_INT_CLR_LOW_THR_INT_EN_CLR			BIT(4)
-#define QPNP_INT_CLR_HIGH_THR_INT_EN_CLKR		BIT(3)
-#define QPNP_INT_CLR_CONV_SEQ_TIMEOUT_INT_EN		BIT(2)
-#define QPNP_INT_CLR_FIFO_NOT_EMPTY_INT_EN		BIT(1)
-#define QPNP_INT_CLR_EOC_INT_EN_CLR			BIT(0)
-#define QPNP_INT_CLR_MASK				0x1f
 #define QPNP_IADC_MODE_CTL				0x40
 #define QPNP_OP_MODE_SHIFT				4
 #define QPNP_USE_BMS_DATA				BIT(4)
@@ -146,6 +124,7 @@
 #define QPNP_RAW_CODE_16_BIT_LSB_MASK			0xff
 #define QPNP_BIT_SHIFT_8				8
 #define QPNP_RSENSE_MSB_SIGN_CHECK			0x80
+#define QPNP_ADC_COMPLETION_TIMEOUT			HZ
 
 struct qpnp_iadc_drv {
 	struct qpnp_adc_drv			*adc;
@@ -192,47 +171,9 @@
 	return 0;
 }
 
-static int32_t qpnp_iadc_configure_interrupt(void)
-{
-	int rc = 0;
-	u8 data = 0;
-
-	/* Configure interrupt as an Edge trigger */
-	rc = qpnp_iadc_write_reg(QPNP_INT_SET_TYPE,
-					QPNP_INT_CLR_MASK);
-	if (rc < 0) {
-		pr_err("%s Interrupt configure failed\n", __func__);
-		return rc;
-	}
-
-	/* Configure interrupt for rising edge trigger */
-	rc = qpnp_iadc_write_reg(QPNP_INT_POLARITY_HIGH,
-					QPNP_INT_CLR_MASK);
-	if (rc < 0) {
-		pr_err("%s Rising edge trigger configure failed\n", __func__);
-		return rc;
-	}
-
-	/* Disable low level interrupt triggering */
-	data = QPNP_INT_CLR_MASK;
-	rc = qpnp_iadc_write_reg(QPNP_INT_POLARITY_LOW,
-					(~data & QPNP_INT_CLR_MASK));
-	if (rc < 0) {
-		pr_err("%s Setting level low to disable failed\n", __func__);
-		return rc;
-	}
-
-	return 0;
-}
-
 static void trigger_iadc_completion(struct work_struct *work)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
-	int rc;
-
-	rc = qpnp_iadc_write_reg(QPNP_INT_CLR, QPNP_INT_CLR_MASK);
-	if (rc < 0)
-		pr_err("qpnp iadc interrupt mask failed with %d\n", rc);
 
 	complete(&iadc->adc->adc_rslt_completion);
 
@@ -315,13 +256,6 @@
 
 	qpnp_iadc_conv_req = QPNP_IADC_CONV_REQ;
 
-	rc = qpnp_iadc_write_reg(QPNP_INT_EN_SET,
-					QPNP_INT_EN_SET_EOC_INT_EN_SET);
-	if (rc < 0) {
-		pr_err("qpnp adc configure error for interrupt setup\n");
-		return rc;
-	}
-
 	rc = qpnp_iadc_write_reg(QPNP_IADC_MODE_CTL, qpnp_iadc_mode_reg);
 	if (rc) {
 		pr_err("qpnp adc read adc failed with %d\n", rc);
@@ -366,7 +300,22 @@
 		return rc;
 	}
 
-	wait_for_completion(&iadc->adc->adc_rslt_completion);
+	rc = wait_for_completion_timeout(&iadc->adc->adc_rslt_completion,
+				QPNP_ADC_COMPLETION_TIMEOUT);
+	if (!rc) {
+		u8 status1 = 0;
+		rc = qpnp_iadc_read_reg(QPNP_STATUS1, &status1);
+		if (rc < 0)
+			return rc;
+		status1 &= (QPNP_STATUS1_REQ_STS | QPNP_STATUS1_EOC);
+		if (status1 == QPNP_STATUS1_EOC)
+			pr_debug("End of conversion status set\n");
+		else {
+			pr_err("EOC interrupt not received\n");
+			return -EINVAL;
+		}
+	}
+
 
 	rc = qpnp_iadc_read_conversion_result(raw_code);
 	if (rc) {
@@ -766,12 +715,6 @@
 	}
 	iadc->iadc_hwmon = hwmon_device_register(&iadc->adc->spmi->dev);
 
-	rc = qpnp_iadc_configure_interrupt();
-	if (rc) {
-		dev_err(&spmi->dev, "failed to configure interrupt\n");
-		return rc;
-	}
-
 	rc = qpnp_iadc_version_check();
 	if (rc) {
 		dev_err(&spmi->dev, "IADC version not supported\n");
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 5eef34f..c59aa5b 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -54,18 +54,6 @@
 #define QPNP_VADC_STATUS2_CONV_SEQ_STATE_SHIFT			4
 #define QPNP_VADC_CONV_TIMEOUT_ERR				2
 
-#define QPNP_VADC_INT_SET_TYPE					0x11
-#define QPNP_VADC_INT_POLARITY_HIGH				0x12
-#define QPNP_VADC_INT_POLARITY_LOW				0x13
-#define QPNP_VADC_INT_LATCHED_CLR				0x14
-#define QPNP_VADC_INT_EN_SET					0x15
-#define QPNP_VADC_INT_CLR					0x16
-#define QPNP_VADC_INT_LOW_THR_BIT				BIT(4)
-#define QPNP_VADC_INT_HIGH_THR_BIT				BIT(3)
-#define QPNP_VADC_INT_CONV_SEQ_TIMEOUT_BIT			BIT(2)
-#define QPNP_VADC_INT_FIFO_NOT_EMPTY_BIT			BIT(1)
-#define QPNP_VADC_INT_EOC_BIT					BIT(0)
-#define QPNP_VADC_INT_CLR_MASK					0x1f
 #define QPNP_VADC_MODE_CTL					0x40
 #define QPNP_VADC_OP_MODE_SHIFT					4
 #define QPNP_VADC_VREF_XO_THM_FORCE				BIT(2)
@@ -101,6 +89,7 @@
 #define QPNP_VADC_CONV_TIMEOUT_ERR				2
 #define QPNP_VADC_CONV_TIME_MIN					2000
 #define QPNP_VADC_CONV_TIME_MAX					2100
+#define QPNP_ADC_COMPLETION_TIMEOUT				HZ
 
 struct qpnp_vadc_drv {
 	struct qpnp_adc_drv		*adc;
@@ -156,39 +145,6 @@
 	return 0;
 }
 
-static int32_t qpnp_vadc_configure_interrupt(void)
-{
-	int rc = 0;
-	u8 data = 0;
-
-	/* Configure interrupt as an Edge trigger */
-	rc = qpnp_vadc_write_reg(QPNP_VADC_INT_SET_TYPE,
-					QPNP_VADC_INT_CLR_MASK);
-	if (rc < 0) {
-		pr_err("%s Interrupt configure failed\n", __func__);
-		return rc;
-	}
-
-	/* Configure interrupt for rising edge trigger */
-	rc = qpnp_vadc_write_reg(QPNP_VADC_INT_POLARITY_HIGH,
-					QPNP_VADC_INT_CLR_MASK);
-	if (rc < 0) {
-		pr_err("%s Rising edge trigger configure failed\n", __func__);
-		return rc;
-	}
-
-	/* Disable low level interrupt triggering */
-	data = QPNP_VADC_INT_CLR_MASK;
-	rc = qpnp_vadc_write_reg(QPNP_VADC_INT_POLARITY_LOW,
-					(~data & QPNP_VADC_INT_CLR_MASK));
-	if (rc < 0) {
-		pr_err("%s Setting level low to disable failed\n", __func__);
-		return rc;
-	}
-
-	return 0;
-}
-
 static int32_t qpnp_vadc_enable(bool state)
 {
 	int rc = 0;
@@ -222,13 +178,6 @@
 	u8 mode_ctrl = 0;
 	int rc = 0;
 
-	rc = qpnp_vadc_write_reg(QPNP_VADC_INT_EN_SET,
-			QPNP_VADC_INT_EOC_BIT);
-	if (rc < 0) {
-		pr_err("Configure error for interrupt setup\n");
-		return rc;
-	}
-
 	/* Mode selection */
 	mode_ctrl = chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT;
 	rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, mode_ctrl);
@@ -389,11 +338,6 @@
 static void qpnp_vadc_work(struct work_struct *work)
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
-	int rc;
-
-	rc = qpnp_vadc_write_reg(QPNP_VADC_INT_CLR, QPNP_VADC_INT_EOC_BIT);
-	if (rc)
-		pr_err("qpnp_vadc clear mask interrupt failed with %d\n", rc);
 
 	complete(&vadc->adc->adc_rslt_completion);
 
@@ -606,8 +550,11 @@
 			!= channel || dt_index > vadc->max_channels_available)
 		dt_index++;
 
-	if (dt_index > vadc->max_channels_available)
+	if (dt_index > vadc->max_channels_available) {
+		pr_err("not a valid VADC channel\n");
+		rc = -EINVAL;
 		goto fail_unlock;
+	}
 
 	vadc->adc->amux_prop->decimation =
 			vadc->adc->adc_channels[dt_index].adc_decimation;
@@ -635,7 +582,22 @@
 		goto fail_unlock;
 	}
 
-	wait_for_completion(&vadc->adc->adc_rslt_completion);
+	rc = wait_for_completion_timeout(&vadc->adc->adc_rslt_completion,
+					QPNP_ADC_COMPLETION_TIMEOUT);
+	if (!rc) {
+		u8 status1 = 0;
+		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+		if (rc < 0)
+			goto fail_unlock;
+		status1 &= (QPNP_VADC_STATUS1_REQ_STS | QPNP_VADC_STATUS1_EOC);
+		if (status1 == QPNP_VADC_STATUS1_EOC)
+			pr_debug("End of conversion status set\n");
+		else {
+			pr_err("EOC interrupt not received\n");
+			rc = -EINVAL;
+			goto fail_unlock;
+		}
+	}
 
 	if (trigger_channel < ADC_SEQ_NONE) {
 		rc = qpnp_vadc_read_status(vadc->adc->amux_prop->mode_sel);
@@ -797,25 +759,14 @@
 	rc = qpnp_vadc_init_hwmon(spmi);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
-		goto fail_free_irq;
+		return rc;
 	}
 	vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
 	vadc->vadc_init_calib = false;
-	vadc->vadc_initialized = true;
 	vadc->max_channels_available = count_adc_channel_list;
-
-	rc = qpnp_vadc_configure_interrupt();
-	if (rc) {
-		dev_err(&spmi->dev, "failed to configure interrupt");
-		goto fail_free_irq;
-	}
+	vadc->vadc_initialized = true;
 
 	return 0;
-
-fail_free_irq:
-	free_irq(vadc->adc->adc_irq, vadc);
-
-	return rc;
 }
 
 static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
@@ -830,7 +781,6 @@
 			&vadc->sens_attr[i].dev_attr);
 		i++;
 	}
-	free_irq(vadc->adc->adc_irq, vadc);
 	vadc->vadc_initialized = false;
 	dev_set_drvdata(&spmi->dev, NULL);
 
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 80fdac5..912fad4 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -29,7 +29,6 @@
 #include "msm_vidc_debug.h"
 #include "vidc_hal_api.h"
 #include "msm_smem.h"
-#include "msm_vidc_ssr.h"
 
 #define BASE_DEVICE_NUMBER 32
 #define SHARED_QSIZE 0x1000000
@@ -1383,9 +1382,6 @@
 	core->debugfs_root = msm_vidc_debugfs_init_core(
 		core, vidc_driver->debugfs_root);
 	pdev->dev.platform_data = core;
-	rc = msm_vidc_ssr_init(core);
-	if (rc < 0)
-		dprintk(VIDC_ERR, "msm_vidc : Sub Systrem Restart failed\n");
 	return rc;
 
 err_cores_exceeded:
@@ -1414,7 +1410,6 @@
 	vidc_hal_delete_device(core->device);
 	video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
-	rc = msm_vidc_ssr_uninit(core);
 	v4l2_device_unregister(&core->v4l2_dev);
 	if (core->resources.ocmem.handle)
 		ocmem_notifier_unregister(core->resources.ocmem.handle,
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index fdadb36..d53da9e 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -23,6 +23,7 @@
 #define DEFAULT_WIDTH 1280
 #define MIN_NUM_OUTPUT_BUFFERS 4
 #define MAX_NUM_OUTPUT_BUFFERS 8
+#define MAX_INPUT_BUFFERS 32
 #define MIN_BIT_RATE 64000
 #define MAX_BIT_RATE 160000000
 #define DEFAULT_BIT_RATE 64000
@@ -136,11 +137,11 @@
 	{
 		.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME,
 		.name = "Request I Frame",
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.type = V4L2_CTRL_TYPE_BUTTON,
 		.minimum = 0,
-		.maximum = 1,
+		.maximum = 0,
 		.default_value = 0,
-		.step = 1,
+		.step = 0,
 		.menu_skip_mask = 0,
 		.qmenu = NULL,
 	},
@@ -558,6 +559,8 @@
 {
 	int i, rc = 0;
 	struct msm_vidc_inst *inst;
+	struct hal_buffer_count_actual new_buf_count;
+	enum hal_property property_id;
 	unsigned long flags;
 	if (!q || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
@@ -593,6 +596,11 @@
 			max(*num_buffers, inst->buff_req.buffer[0].
 			buffer_count_actual);
 		spin_unlock_irqrestore(&inst->lock, flags);
+		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+		new_buf_count.buffer_type = HAL_BUFFER_INPUT;
+		new_buf_count.buffer_count_actual = MAX_INPUT_BUFFERS;
+		rc = vidc_hal_session_set_property(inst->session,
+					property_id, &new_buf_count);
 		dprintk(VIDC_DBG, "size = %d, alignment = %d, count = %d\n",
 				inst->buff_req.buffer[0].buffer_size,
 				inst->buff_req.buffer[0].buffer_alignment,
@@ -808,7 +816,7 @@
 	case V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME:
 		property_id =
 			HAL_CONFIG_VENC_REQUEST_IFRAME;
-		request_iframe.enable = control.value;
+		request_iframe.enable = true;
 		pdata = &request_iframe;
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL:
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 772f0de..02773ff 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -587,7 +587,6 @@
 
 static void handle_sys_watchdog_timeout(enum command_response cmd, void *data)
 {
-	subsystem_restart("msm_vidc");
 	dprintk(VIDC_ERR,
 		"msm_vidc: Sub System Restart initiated\n");
 }
diff --git a/drivers/media/video/msm_wfd/enc-venus-subdev.c b/drivers/media/video/msm_wfd/enc-venus-subdev.c
index 89ad6c7..150c667 100644
--- a/drivers/media/video/msm_wfd/enc-venus-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-venus-subdev.c
@@ -178,7 +178,7 @@
 			rc = msm_vidc_dqbuf(inst->vidc_context, &buffer);
 
 			if (rc) {
-				WFD_MSG_ERR("Error dequeuing buffer" \
+				WFD_MSG_ERR("Error dequeuing buffer " \
 						"from vidc: %d", rc);
 				goto abort_dequeue;
 			}
@@ -1010,7 +1010,8 @@
 	inst = (struct venc_inst *)sd->dev_priv;
 
 	enc_cmd.cmd = V4L2_ENC_QCOM_CMD_FLUSH;
-	enc_cmd.flags = BUF_TYPE_INPUT | BUF_TYPE_OUTPUT;
+	enc_cmd.flags = V4L2_QCOM_CMD_FLUSH_OUTPUT |
+		V4L2_QCOM_CMD_FLUSH_CAPTURE;
 	msm_vidc_encoder_cmd(inst->vidc_context, &enc_cmd);
 
 	wait_for_completion(&inst->cmd_complete);
diff --git a/drivers/media/video/msm_wfd/wfd-ioctl.c b/drivers/media/video/msm_wfd/wfd-ioctl.c
index 371ae3c..5f67a96 100644
--- a/drivers/media/video/msm_wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm_wfd/wfd-ioctl.c
@@ -271,8 +271,9 @@
 			goto alloc_fail;
 		}
 
-		WFD_MSG_ERR("NOTE: enc paddr = %p, kvaddr = %p\n",
-				enc_mregion->paddr,
+		WFD_MSG_DBG("NOTE: enc paddr = [%p->%p], kvaddr = %p\n",
+				enc_mregion->paddr, (int8_t *)
+				enc_mregion->paddr + enc_mregion->size,
 				enc_mregion->kvaddr);
 
 		rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 9afc3df..f009e06 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -922,10 +922,15 @@
 	case VC_TYPE:
 		vc_format = (struct v4l2_format_vc_ext *) &priv_fmt->u.timing;
 		c_data->vc_format = *vc_format;
+		c_data->stride = priv_fmt->stride;
 
 		size = (c_data->vc_format.hactive_end -
 			c_data->vc_format.hactive_start);
-		size = VCAP_STRIDE_CALC(size);
+		if (c_data->stride == VC_STRIDE_32)
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_32);
+		else
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_16);
+
 
 		if (c_data->vc_format.color_space)
 			size *= 3;
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 08dcdf3..642074f 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -37,7 +37,10 @@
 	} else {
 		int size = (c_data->vc_format.hactive_end -
 				c_data->vc_format.hactive_start);
-		size = VCAP_STRIDE_CALC(size);
+		if (c_data->stride == VC_STRIDE_32)
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_32);
+		else
+			size = VCAP_STRIDE_CALC(size, VCAP_STRIDE_ALIGN_16);
 		size *= (c_data->vc_format.vactive_end -
 				c_data->vc_format.vactive_start);
 		writel_relaxed(buf->paddr, y_addr);
@@ -527,7 +530,10 @@
 	writel_iowmb(0x000033FF, VCAP_VC_BUF_CTRL);
 
 	rc = vc_format->hactive_end - vc_format->hactive_start;
-	rc = VCAP_STRIDE_CALC(rc);
+	if (c_data->stride == VC_STRIDE_32)
+		rc = VCAP_STRIDE_CALC(rc, VCAP_STRIDE_ALIGN_32);
+	else
+		rc = VCAP_STRIDE_CALC(rc, VCAP_STRIDE_ALIGN_16);
 	if (vc_format->color_space)
 		rc *= 3;
 
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index 48bc92d..4996279 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -373,6 +373,11 @@
 	.num_resources	= ARRAY_SIZE(ccadc_cell_resources),
 };
 
+static struct mfd_cell vibrator_cell __devinitdata = {
+	.name           = PM8XXX_VIBRATOR_DEV_NAME,
+	.id             = -1,
+};
+
 static struct pm8xxx_vreg regulator_data[] = {
 	/*   name	     pc_name	    ctrl   test   hpm_min */
 	NLDO1200("8038_l1",		    0x0AE, 0x0AF, LDO_1200),
@@ -609,6 +614,17 @@
 		}
 	}
 
+	if (pdata->vibrator_pdata) {
+		vibrator_cell.platform_data = pdata->vibrator_pdata;
+		vibrator_cell.pdata_size =
+			sizeof(struct pm8xxx_vibrator_platform_data);
+		ret = mfd_add_devices(pmic->dev, 0, &vibrator_cell, 1, NULL, 0);
+		if (ret) {
+			pr_err("Failed to add vibrator ret=%d\n", ret);
+			goto bail;
+		}
+	}
+
 	if (pdata->spk_pdata) {
 		spk_cell.platform_data = pdata->spk_pdata;
 		spk_cell.pdata_size = sizeof(struct pm8xxx_spk_platform_data);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 27123bc..1972845 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1339,6 +1339,15 @@
 	/* Populate the remaining parameters */
 	load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
 	memcpy(load_req.app_name, appname, MAX_APP_NAME_SIZE);
+	mutex_lock(&app_access_lock);
+	ret = qsee_vote_for_clock(CLK_SFPB);
+	if (ret) {
+		kzfree(img_data);
+		pr_warning("Unable to vote for SFPB clock");
+		mutex_unlock(&app_access_lock);
+		return -EIO;
+	}
+
 	/* SCM_CALL to load the image */
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,	&load_req,
 			sizeof(struct qseecom_load_app_ireq),
@@ -1346,6 +1355,8 @@
 	kzfree(img_data);
 	if (ret) {
 		pr_err("scm_call to load failed : ret %d\n", ret);
+		qsee_disable_clock_vote(CLK_SFPB);
+		mutex_unlock(&app_access_lock);
 		return -EIO;
 	}
 
@@ -1368,6 +1379,9 @@
 		ret = -EINVAL;
 		break;
 	}
+	qsee_disable_clock_vote(CLK_SFPB);
+	mutex_unlock(&app_access_lock);
+
 	return ret;
 }
 
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 85d2737..de87e82 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -25,6 +25,7 @@
 	int (*power_save)(struct mmc_host *);
 	int (*power_restore)(struct mmc_host *);
 	int (*alive)(struct mmc_host *);
+	int (*change_bus_speed)(struct mmc_host *, unsigned long *);
 };
 
 void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 5183f2a..a98ed3d 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -821,6 +821,69 @@
 	return err;
 }
 
+/**
+ * mmc_change_bus_speed() - Change MMC card bus frequency at runtime
+ * @host: pointer to mmc host structure
+ * @freq: pointer to desired frequency to be set
+ *
+ * Change the MMC card bus frequency at runtime after the card is
+ * initialized. Callers are expected to make sure of the card's
+ * state (DATA/RCV/TRANSFER) beforing changing the frequency at runtime.
+ *
+ * If the frequency to change is greater than max. supported by card,
+ * *freq is changed to max. supported by card and if it is less than min.
+ * supported by host, *freq is changed to min. supported by host.
+ */
+static int mmc_change_bus_speed(struct mmc_host *host, unsigned long *freq)
+{
+	int err = 0;
+	struct mmc_card *card;
+
+	mmc_claim_host(host);
+	/*
+	 * Assign card pointer after claiming host to avoid race
+	 * conditions that may arise during removal of the card.
+	 */
+	card = host->card;
+
+	if (!card || !freq) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (mmc_card_highspeed(card) || mmc_card_hs200(card)
+			|| mmc_card_ddr_mode(card)) {
+		if (*freq > card->ext_csd.hs_max_dtr)
+			*freq = card->ext_csd.hs_max_dtr;
+	} else if (*freq > card->csd.max_dtr) {
+		*freq = card->csd.max_dtr;
+	}
+
+	if (*freq < host->f_min)
+		*freq = host->f_min;
+
+	mmc_set_clock(host, (unsigned int) (*freq));
+
+	if (mmc_card_hs200(card) && card->host->ops->execute_tuning) {
+		/*
+		 * We try to probe host driver for tuning for any
+		 * frequency, it is host driver responsibility to
+		 * perform actual tuning only when required.
+		 */
+		mmc_host_clk_hold(card->host);
+		err = card->host->ops->execute_tuning(card->host,
+				MMC_SEND_TUNING_BLOCK_HS200);
+		mmc_host_clk_release(card->host);
+
+		if (err)
+			pr_warn("%s: %s: tuning execution failed %d\n",
+				   mmc_hostname(card->host), __func__, err);
+	}
+out:
+	mmc_release_host(host);
+	return err;
+}
+
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -1531,6 +1594,7 @@
 	.resume = NULL,
 	.power_restore = mmc_power_restore,
 	.alive = mmc_alive,
+	.change_bus_speed = mmc_change_bus_speed,
 };
 
 static const struct mmc_bus_ops mmc_ops_unsafe = {
@@ -1542,6 +1606,7 @@
 	.resume = mmc_resume,
 	.power_restore = mmc_power_restore,
 	.alive = mmc_alive,
+	.change_bus_speed = mmc_change_bus_speed,
 };
 
 static void mmc_attach_bus_ops(struct mmc_host *host)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ff5821b..8661929 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -609,6 +609,72 @@
 	return 0;
 }
 
+/**
+ * mmc_sd_change_bus_speed() - Change SD card bus frequency at runtime
+ * @host: pointer to mmc host structure
+ * @freq: pointer to desired frequency to be set
+ *
+ * Change the SD card bus frequency at runtime after the card is
+ * initialized. Callers are expected to make sure of the card's
+ * state (DATA/RCV/TRANSFER) beforing changing the frequency at runtime.
+ *
+ * If the frequency to change is greater than max. supported by card,
+ * *freq is changed to max. supported by card and if it is less than min.
+ * supported by host, *freq is changed to min. supported by host.
+ */
+static int mmc_sd_change_bus_speed(struct mmc_host *host, unsigned long *freq)
+{
+	int err = 0;
+	struct mmc_card *card;
+
+	mmc_claim_host(host);
+	/*
+	 * Assign card pointer after claiming host to avoid race
+	 * conditions that may arise during removal of the card.
+	 */
+	card = host->card;
+
+	/* sanity checks */
+	if (!card || !freq) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (mmc_card_uhs(card)) {
+		if (*freq > card->sw_caps.uhs_max_dtr)
+			*freq = card->sw_caps.uhs_max_dtr;
+	} else {
+		if (*freq > mmc_sd_get_max_clock(card))
+			*freq = mmc_sd_get_max_clock(card);
+	}
+
+	if (*freq < host->f_min)
+		*freq = host->f_min;
+
+	mmc_set_clock(host, (unsigned int) (*freq));
+
+	if (!mmc_host_is_spi(card->host) && mmc_sd_card_uhs(card)
+			&& card->host->ops->execute_tuning) {
+		/*
+		 * We try to probe host driver for tuning for any
+		 * frequency, it is host driver responsibility to
+		 * perform actual tuning only when required.
+		 */
+		mmc_host_clk_hold(card->host);
+		err = card->host->ops->execute_tuning(card->host,
+				MMC_SEND_TUNING_BLOCK);
+		mmc_host_clk_release(card->host);
+
+		if (err)
+			pr_warn("%s: %s: tuning execution failed %d\n",
+				   mmc_hostname(card->host), __func__, err);
+	}
+
+out:
+	mmc_release_host(host);
+	return err;
+}
+
 /*
  * UHS-I specific initialization procedure
  */
@@ -1191,6 +1257,7 @@
 	.resume = NULL,
 	.power_restore = mmc_sd_power_restore,
 	.alive = mmc_sd_alive,
+	.change_bus_speed = mmc_sd_change_bus_speed,
 };
 
 static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
@@ -1200,6 +1267,7 @@
 	.resume = mmc_sd_resume,
 	.power_restore = mmc_sd_power_restore,
 	.alive = mmc_sd_alive,
+	.change_bus_speed = mmc_sd_change_bus_speed,
 };
 
 static void mmc_sd_attach_bus_ops(struct mmc_host *host)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index a752357..de7e5bc 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -5271,7 +5271,7 @@
 	pull_data->on = pull;
 	pull_data->off = pull + pull_data->size;
 
-	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-pull-on",
+	ret = msmsdcc_dt_get_array(dev, "qcom,pad-pull-on",
 			&tmp, &len, pull_data->size);
 	if (!ret) {
 		for (i = 0; i < len; i++) {
@@ -5284,7 +5284,7 @@
 		goto err;
 	}
 
-	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-pull-off",
+	ret = msmsdcc_dt_get_array(dev, "qcom,pad-pull-off",
 			&tmp, &len, pull_data->size);
 	if (!ret) {
 		for (i = 0; i < len; i++) {
@@ -5349,7 +5349,7 @@
 	drv_data->on = drv;
 	drv_data->off = drv + drv_data->size;
 
-	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-drv-on",
+	ret = msmsdcc_dt_get_array(dev, "qcom,pad-drv-on",
 			&tmp, &len, drv_data->size);
 	if (!ret) {
 		for (i = 0; i < len; i++) {
@@ -5362,7 +5362,7 @@
 		goto err;
 	}
 
-	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-drv-off",
+	ret = msmsdcc_dt_get_array(dev, "qcom,pad-drv-off",
 			&tmp, &len, drv_data->size);
 	if (!ret) {
 		for (i = 0; i < len; i++) {
@@ -5442,7 +5442,7 @@
 			char result[32];
 			pin_data->gpio_data->gpio[i].no = of_get_gpio(np, i);
 			of_property_read_string_index(np,
-					"qcom,sdcc-gpio-names", i, &name);
+					"qcom,gpio-names", i, &name);
 
 			snprintf(result, 32, "%s-%s",
 					dev_name(dev), name ? name : "?");
@@ -5501,17 +5501,17 @@
 		vreg->name = vreg_name;
 
 		snprintf(prop_name, MAX_PROP_SIZE,
-				"qcom,sdcc-%s-always_on", vreg_name);
+				"qcom,%s-always-on", vreg_name);
 		if (of_get_property(np, prop_name, NULL))
 			vreg->always_on = true;
 
 		snprintf(prop_name, MAX_PROP_SIZE,
-				"qcom,sdcc-%s-lpm_sup", vreg_name);
+				"qcom,%s-lpm-sup", vreg_name);
 		if (of_get_property(np, prop_name, NULL))
 			vreg->lpm_sup = true;
 
 		snprintf(prop_name, MAX_PROP_SIZE,
-				"qcom,sdcc-%s-voltage_level", vreg_name);
+				"qcom,%s-voltage-level", vreg_name);
 		prop = of_get_property(np, prop_name, &len);
 		if (!prop || (len != (2 * sizeof(__be32)))) {
 			dev_warn(dev, "%s %s property\n",
@@ -5522,7 +5522,7 @@
 		}
 
 		snprintf(prop_name, MAX_PROP_SIZE,
-				"qcom,sdcc-%s-current_level", vreg_name);
+				"qcom,%s-current-level", vreg_name);
 		prop = of_get_property(np, prop_name, &len);
 		if (!prop || (len != (2 * sizeof(__be32)))) {
 			dev_warn(dev, "%s %s property\n",
@@ -5558,7 +5558,7 @@
 		goto err;
 	}
 
-	of_property_read_u32(np, "qcom,sdcc-bus-width", &bus_width);
+	of_property_read_u32(np, "qcom,bus-width", &bus_width);
 	if (bus_width == 8) {
 		pdata->mmc_bus_width = MMC_CAP_8_BIT_DATA;
 	} else if (bus_width == 4) {
@@ -5568,7 +5568,7 @@
 		pdata->mmc_bus_width = 0;
 	}
 
-	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-sup-voltages",
+	ret = msmsdcc_dt_get_array(dev, "qcom,sup-voltages",
 			&sup_voltages, &sup_volt_len, 0);
 	if (!ret) {
 		for (i = 0; i < sup_volt_len; i += 2) {
@@ -5583,7 +5583,7 @@
 		dev_dbg(dev, "OCR mask=0x%x\n", pdata->ocr_mask);
 	}
 
-	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-clk-rates",
+	ret = msmsdcc_dt_get_array(dev, "qcom,clk-rates",
 			&clk_table, &clk_table_len, 0);
 	if (!ret) {
 		pdata->sup_clk_table = clk_table;
@@ -5608,13 +5608,13 @@
 	if (msmsdcc_dt_parse_gpio_info(dev, pdata))
 		goto err;
 
-	len = of_property_count_strings(np, "qcom,sdcc-bus-speed-mode");
+	len = of_property_count_strings(np, "qcom,bus-speed-mode");
 
 	for (i = 0; i < len; i++) {
 		const char *name = NULL;
 
 		of_property_read_string_index(np,
-			"qcom,sdcc-bus-speed-mode", i, &name);
+			"qcom,bus-speed-mode", i, &name);
 		if (!name)
 			continue;
 
@@ -5640,7 +5640,7 @@
 						| MMC_CAP_UHS_DDR50;
 	}
 
-	of_property_read_u32(np, "qcom,sdcc-current-limit", &current_limit);
+	of_property_read_u32(np, "qcom,current-limit", &current_limit);
 	if (current_limit == 800)
 		pdata->uhs_caps |= MMC_CAP_MAX_CURRENT_800;
 	else if (current_limit == 600)
@@ -5650,11 +5650,11 @@
 	else if (current_limit == 200)
 		pdata->uhs_caps |= MMC_CAP_MAX_CURRENT_200;
 
-	if (of_get_property(np, "qcom,sdcc-xpc", NULL))
+	if (of_get_property(np, "qcom,xpc", NULL))
 		pdata->xpc_cap = true;
-	if (of_get_property(np, "qcom,sdcc-nonremovable", NULL))
+	if (of_get_property(np, "qcom,nonremovable", NULL))
 		pdata->nonremovable = true;
-	if (of_get_property(np, "qcom,sdcc-disable_cmd23", NULL))
+	if (of_get_property(np, "qcom,disable-cmd23", NULL))
 		pdata->disable_cmd23 = true;
 	of_property_read_u32(np, "qcom,dat1-mpm-int",
 					&pdata->mpm_sdiowakeup_int);
@@ -6241,7 +6241,7 @@
  vreg_deinit:
 	msmsdcc_vreg_init(host, false);
  clk_disable:
-	clk_disable(host->clk);
+	clk_disable_unprepare(host->clk);
 	msmsdcc_msm_bus_unregister(host);
  pm_qos_remove:
 	if (host->cpu_dma_latency)
diff --git a/drivers/platform/msm/sps/sps_dma.c b/drivers/platform/msm/sps/sps_dma.c
index f8b4f51d..335de9a 100644
--- a/drivers/platform/msm/sps/sps_dma.c
+++ b/drivers/platform/msm/sps/sps_dma.c
@@ -274,7 +274,6 @@
 {
 	struct bamdma_device *dev;
 	struct sps_bam_props *props;
-	u32 chan;
 	int result = SPS_ERROR;
 
 	mutex_lock(&bam_dma_lock);
@@ -343,14 +342,6 @@
 
 	dev->num_pipes = dev->bam->props.num_pipes;
 
-	/* Disable all channels */
-	if (dev->local)
-		for (chan = 0; chan < (dev->num_pipes / 2); chan++) {
-			dma_write_reg_field(dev->virt_addr,
-					    DMA_CHNL_CONFIG(chan),
-					    DMA_CHNL_ENABLE, 0);
-		}
-
 	result = 0;
 exit_err:
 	if (result) {
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 7b7e05e..bc2e2ae 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -333,6 +333,16 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called smb137b.
 
+config SMB137C_CHARGER
+	tristate "Summit SMB137C Battery Charger"
+	depends on I2C
+	depends on OF
+	help
+	  The SMB137C charger chip from Summit is a switching mode based
+	  charging solution.  This driver supports enabling and disabling
+	  charging, setting the input current limit, and enabling USB OTG mode
+	  in order to supply 5 V on the VBUS line.
+
 config SMB349_CHARGER
 	tristate "smb349 charger"
 	depends on I2C
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 3e74f35..990bd03 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -55,6 +55,7 @@
 obj-$(CONFIG_BATTERY_BQ27541)	+= bq27541_fuelgauger.o
 obj-$(CONFIG_BATTERY_BQ28400)	+= bq28400_battery.o
 obj-$(CONFIG_SMB137B_CHARGER)   += smb137b.o
+obj-$(CONFIG_SMB137C_CHARGER)	+= smb137c-charger.o
 obj-$(CONFIG_PM8XXX_CCADC)	+= pm8xxx-ccadc.o
 obj-$(CONFIG_PM8921_BMS)	+= pm8921-bms.o
 obj-$(CONFIG_QPNP_BMS)		+= qpnp-bms.o
diff --git a/drivers/power/bq28400_battery.c b/drivers/power/bq28400_battery.c
index 39eac60..61d5835 100644
--- a/drivers/power/bq28400_battery.c
+++ b/drivers/power/bq28400_battery.c
@@ -486,6 +486,8 @@
 	u16 battery_status;
 
 	battery_status = bq28400_read_reg(client, SBS_BATTERY_STATUS);
+	rsoc = bq28400_read_rsoc(client);
+	current_ma = bq28400_read_current(client);
 
 	if (battery_status & BAT_STATUS_EMPTY)
 		pr_debug("Battery report Empty.\n");
@@ -493,16 +495,16 @@
 	/* Battery may report FULL before rsoc is 100%
 	 * for protection and cell-balancing.
 	 * The FULL report may remain when rsoc drops from 100%.
+	 * If battery is full but DC-Jack is removed then report discahrging.
 	 */
 	if (battery_status & BAT_STATUS_FULL) {
 		pr_debug("Battery report Full.\n");
 		bq28400_enable_charging(bq28400_dev, false);
+		if (current_ma < 0)
+			return POWER_SUPPLY_STATUS_DISCHARGING;
 		return POWER_SUPPLY_STATUS_FULL;
 	}
 
-	rsoc = bq28400_read_rsoc(client);
-	current_ma = bq28400_read_current(client);
-
 	if (rsoc == 100) {
 		bq28400_enable_charging(bq28400_dev, false);
 		pr_debug("Full.\n");
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index bc012ca..b5559db 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -702,7 +702,7 @@
 }
 
 static int
-qpnp_chg_charge_dis(struct qpnp_chg_chip *chip, int disable)
+qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
 {
 	/* This bit forces the charger to run off of the battery rather
 	 * than a connected charger */
@@ -784,11 +784,9 @@
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
-		if (val->intval)
-			qpnp_chg_charge_en(chip, val->intval);
-		else
-			qpnp_chg_charge_dis(chip, val->intval);
 		chip->charging_disabled = !(val->intval);
+		qpnp_chg_charge_en(chip, !chip->charging_disabled);
+		qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
 		break;
 	default:
 		return -EINVAL;
@@ -1275,7 +1273,7 @@
 			qpnp_chg_is_usb_chg_plugged_in(chip));
 
 	qpnp_chg_charge_en(chip, !chip->charging_disabled);
-	qpnp_chg_charge_dis(chip, chip->charging_disabled);
+	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
 
 	pr_info("Probe success !\n");
 	return 0;
diff --git a/drivers/power/smb137c-charger.c b/drivers/power/smb137c-charger.c
new file mode 100644
index 0000000..b865bd7
--- /dev/null
+++ b/drivers/power/smb137c-charger.c
@@ -0,0 +1,1352 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+
+struct smb137c_chip {
+	struct i2c_client	*client;
+	struct power_supply	psy;
+	struct power_supply	*usb_psy;
+	struct mutex		lock;
+	int			charge_current_limit_ua;
+	int			input_current_limit_ua;
+	int			term_current_ua;
+	bool			charging_enabled;
+	bool			otg_mode_enabled;
+	bool			charging_allowed;
+};
+
+struct input_current_config {
+	int			current_limit_ua;
+	u8			cmd_b_reg;
+	u8			var_func_reg;
+	u8			input_cur_reg;
+};
+
+struct term_current_config {
+	int			term_current_ua;
+	u8			charge_cur_reg;
+};
+
+#define INPUT_CURRENT(_current_limit_ua, _cmd_b_reg, _var_func_reg, \
+			_input_cur_reg) \
+	{ \
+		.current_limit_ua	= _current_limit_ua, \
+		.cmd_b_reg		= _cmd_b_reg, \
+		.var_func_reg		= _var_func_reg, \
+		.input_cur_reg		= _input_cur_reg, \
+	}
+
+#define CHARGE_CURRENT_REG		0x00
+#define CHARGE_CURRENT_FAST_CHG_MASK	0xE0
+#define CHARGE_CURRENT_FAST_CHG_SHIFT	5
+#define CHARGE_CURRENT_PRE_CHG_MASK	0x18
+#define CHARGE_CURRENT_PRE_CHG_SHIFT	3
+#define CHARGE_CURRENT_TERM_CUR_MASK	0x06
+
+#define INPUT_CURRENT_REG		0x01
+#define INPUT_CURRENT_LIMIT_MASK	0xE0
+
+#define FLOAT_VOLTAGE_REG		0x02
+#define FLOAT_VOLTAGE_MASK		0x7F
+#define FLOAT_VOLTAGE_SHIFT		0
+
+#define CTRL_A_REG			0x03
+#define CTRL_A_AUTO_RECHARGE_MASK	0x80
+#define CTRL_A_AUTO_RECHARGE_ENABLED	0x00
+#define CTRL_A_AUTO_RECHARGE_DISABLED	0x80
+#define CTRL_A_TERM_CUR_MASK		0x40
+#define CTRL_A_TERM_CUR_ENABLED		0x00
+#define CTRL_A_TERM_CUR_DISABLED	0x40
+#define CTRL_A_THRESH_VOLTAGE_MASK	0x38
+#define CTRL_A_THRESH_VOLTAGE_SHIFT	3
+#define CTRL_A_VOUTL_MASK		0x02
+#define CTRL_A_VOUTL_4250MV		0x00
+#define CTRL_A_VOUTL_4460MV		0x02
+#define CTRL_A_THERM_MONITOR_MASK	0x01
+#define CTRL_A_THERM_MONITOR_ENABLED	0x01
+#define CTRL_A_THERM_MONITOR_DISABLED	0x00
+
+#define PIN_CTRL_REG			0x05
+#define PIN_CTRL_DEAD_BATT_CHG_MASK	0x80
+#define PIN_CTRL_DEAD_BATT_CHG_ENABLED	0x80
+#define PIN_CTRL_DEAD_BATT_CHG_DISABLED	0x00
+#define PIN_CTRL_OTG_LBR_MASK		0x20
+#define PIN_CTRL_OTG			0x00
+#define PIN_CTRL_LBR			0x20
+#define PIN_CTRL_USB_CUR_LIMIT_MASK	0x10
+#define PIN_CTRL_USB_CUR_LIMIT_REG	0x00
+#define PIN_CTRL_USB_CUR_LIMIT_PIN	0x10
+#define PIN_CTRL_CHG_EN_MASK		0x0C
+#define PIN_CTRL_CHG_EN_REG_LOW		0x00
+#define PIN_CTRL_CHG_EN_REG_HIGH	0x04
+#define PIN_CTRL_CHG_EN_PIN_LOW		0x08
+#define PIN_CTRL_CHG_EN_PIN_HIGH	0x0C
+#define PIN_CTRL_OTG_CTRL_MASK		0x02
+#define PIN_CTRL_OTG_CTRL_REG		0x00
+#define PIN_CTRL_OTG_CTRL_PIN		0x02
+
+#define OTG_CTRL_REG			0x06
+#define OTG_CTRL_BMD_MASK		0x80
+#define OTG_CTRL_BMD_ENABLED		0x80
+#define OTG_CTRL_BMD_DISABLED		0x00
+#define OTG_CTRL_AUTO_RECHARGE_MASK	0x40
+#define OTG_CTRL_AUTO_RECHARGE_75MV	0x00
+#define OTG_CTRL_AUTO_RECHARGE_120MV	0x40
+
+#define TEMP_MON_REG			0x08
+#define TEMP_MON_THERM_CURRENT_MASK	0xC0
+#define TEMP_MON_THERM_CURRENT_SHIFT	6
+#define TEMP_MON_TEMP_LOW_MASK		0x38
+#define TEMP_MON_TEMP_LOW_SHIFT		3
+#define TEMP_MON_TEMP_HIGH_MASK		0x07
+#define TEMP_MON_TEMP_HIGH_SHIFT	0
+
+#define SAFETY_TIMER_REG		0x09
+#define SAFETY_TIMER_RELOAD_MASK	0x40
+#define SAFETY_TIMER_RELOAD_ENABLED	0x40
+#define SAFETY_TIMER_RELOAD_DISABLED	0x00
+#define SAFETY_TIMER_CHG_TIMEOUT_MASK	0x0C
+#define SAFETY_TIMER_CHG_TIMEOUT_SHIFT	2
+#define SAFETY_TIMER_PRE_CHG_TIME_MASK	0x03
+#define SAFETY_TIMER_PRE_CHG_TIME_SHIFT	0
+
+#define VAR_FUNC_REG			0x0C
+#define VAR_FUNC_USB_MODE_MASK		0x80
+#define VAR_FUNC_BMD_MASK		0x0C
+#define VAR_FUNC_BMD_DISABLED		0x00
+#define VAR_FUNC_BMD_ALGO_PERIODIC	0x04
+#define VAR_FUNC_BMD_ALGO		0x08
+#define VAR_FUNC_BMD_THERM		0x0C
+
+#define CMD_A_REG			0x30
+#define CMD_A_VOLATILE_WRITE_MASK	0x80
+#define CMD_A_VOLATILE_WRITE_ALLOW	0x80
+#define CMD_A_VOLATILE_WRITE_DISALLOW	0x00
+#define CMD_A_FAST_CHG_MASK		0x40
+#define CMD_A_FAST_CHG_ALLOW		0x40
+#define CMD_A_FAST_CHG_DISALLOW		0x00
+#define CMD_A_OTG_MASK			0x10
+#define CMD_A_OTG_ENABLED		0x10
+#define CMD_A_OTG_DISABLED		0x00
+#define CMD_A_CHARGING_MASK		0x02
+#define CMD_A_CHARGING_ENABLED		0x00
+#define CMD_A_CHARGING_DISABLED		0x02
+
+#define CMD_B_REG			0x31
+#define CMD_B_USB_MODE_MASK		0x03
+
+#define DEV_ID_REG			0x33
+#define DEV_ID_PART_MASK		0x80
+#define DEV_ID_PART_SMB137C		0x00
+#define DEV_ID_GUI_REV_MASK		0x70
+#define DEV_ID_GUI_REV_SHIFT		4
+#define DEV_ID_SILICON_REV_MASK		0x0F
+#define DEV_ID_SILICON_REV_SHIFT	0
+
+#define IRQ_STAT_A_REG			0x35
+#define IRQ_STAT_A_BATT_HOT		0x40
+#define IRQ_STAT_A_BATT_COLD		0x10
+
+#define IRQ_STAT_B_REG			0x36
+#define IRQ_STAT_B_BATT_OVERVOLT	0x40
+#define IRQ_STAT_B_BATT_MISSING		0x10
+#define IRQ_STAT_B_BATT_UNDERVOLT	0x04
+
+#define STAT_C_REG			0x3D
+#define STAT_C_CHG_ERROR		0x40
+#define STAT_C_VBATT_LEVEL_BELOW_2P1V	0x10
+#define STAT_C_CHG_STAT_MASK		0x06
+#define STAT_C_CHG_STAT_SHIFT		1
+#define STAT_C_CHG_ENABLED		0x01
+
+/* Charge status register values */
+enum smb137c_charge_status {
+	CHARGE_STAT_NO_CHG	= 0,
+	CHARGE_STAT_PRE_CHG	= 1,
+	CHARGE_STAT_FAST_CHG	= 2,
+	CHARGE_STAT_TAPER_CHG	= 3,
+};
+
+#define PRE_CHARGE_CURRENT_MIN_UA	50000
+#define PRE_CHARGE_CURRENT_MAX_UA	200000
+#define PRE_CHARGE_CURRENT_STEP_UA	50000
+
+#define FLOAT_VOLTAGE_MIN_UV		3460000
+#define FLOAT_VOLTAGE_MAX_UV		4730000
+#define FLOAT_VOLTAGE_STEP_UV		10000
+
+#define PRE_CHG_THRESH_VOLTAGE_MIN_UV	2400000
+#define PRE_CHG_THRESH_VOLTAGE_MAX_UV	3100000
+#define PRE_CHG_THRESH_VOLTAGE_STEP_UV	100000
+
+#define USB_MIN_CURRENT_UA		100000
+
+static int smb137c_read_reg(struct smb137c_chip *chip, u8 reg, u8 *val)
+{
+	int rc;
+
+	rc = i2c_smbus_read_byte_data(chip->client, reg);
+	if (rc < 0) {
+		pr_err("i2c_smbus_read_byte_data failed. reg=0x%02X, rc=%d\n",
+			reg, rc);
+	} else {
+		*val = rc;
+		rc = 0;
+		pr_debug("read(0x%02X)=0x%02X\n", reg, *val);
+	}
+
+	return rc;
+}
+
+static int smb137c_write_reg(struct smb137c_chip *chip, u8 reg, u8 val)
+{
+	int rc;
+
+	rc = i2c_smbus_write_byte_data(chip->client, reg, val);
+	if (rc < 0)
+		pr_err("i2c_smbus_write_byte_data failed. reg=0x%02X, rc=%d\n",
+			reg, rc);
+	else
+		pr_debug("write(0x%02X)=0x%02X\n", reg, val);
+
+	return rc;
+}
+
+static int smb137c_masked_write_reg(struct smb137c_chip *chip, u8 reg, u8 mask,
+					u8 val)
+{
+	u8 reg_val;
+	int rc;
+
+	pr_debug("masked write(0x%02X), mask=0x%02X, value=0x%02X\n", reg, mask,
+		val);
+
+	rc = smb137c_read_reg(chip, reg, &reg_val);
+	if (rc < 0)
+		return rc;
+
+	val = (reg_val & ~mask) | (val & mask);
+
+	if (val != reg_val)
+		rc = smb137c_write_reg(chip, reg, val);
+
+	return rc;
+}
+
+static int smb137c_enable_charging(struct smb137c_chip *chip)
+{
+	int rc = 0;
+
+	chip->charging_allowed = true;
+
+	if (chip->input_current_limit_ua > 0
+	    && chip->charge_current_limit_ua > 0) {
+		if (!chip->charging_enabled)
+			rc = smb137c_masked_write_reg(chip, CMD_A_REG,
+				CMD_A_CHARGING_MASK, CMD_A_CHARGING_ENABLED);
+		chip->charging_enabled = true;
+
+		if (!rc)
+			dev_dbg(&chip->client->dev, "%s\n", __func__);
+	}
+
+	return rc;
+}
+
+static int smb137c_disable_charging(struct smb137c_chip *chip)
+{
+	int rc = 0;
+
+	chip->charging_allowed = false;
+
+	if (chip->charging_enabled) {
+		rc = smb137c_masked_write_reg(chip, CMD_A_REG,
+			CMD_A_CHARGING_MASK, CMD_A_CHARGING_DISABLED);
+	}
+
+	chip->charging_enabled = false;
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s\n", __func__);
+
+	return rc;
+}
+
+static int smb137c_enable_otg_mode(struct smb137c_chip *chip)
+{
+	int rc = 0;
+
+	if (!chip->otg_mode_enabled) {
+		rc = smb137c_masked_write_reg(chip, CMD_A_REG, CMD_A_OTG_MASK,
+					CMD_A_OTG_ENABLED);
+		chip->otg_mode_enabled = true;
+	}
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s\n", __func__);
+
+	return rc;
+}
+
+static int smb137c_disable_otg_mode(struct smb137c_chip *chip)
+{
+	int rc = 0;
+
+	if (chip->otg_mode_enabled) {
+		rc = smb137c_masked_write_reg(chip, CMD_A_REG, CMD_A_OTG_MASK,
+					CMD_A_OTG_DISABLED);
+		chip->otg_mode_enabled = false;
+	}
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s\n", __func__);
+
+	return rc;
+}
+
+static struct input_current_config supported_input_current[] = {
+	INPUT_CURRENT(100000,  0x00, 0x00, 0x00),
+	INPUT_CURRENT(150000,  0x00, 0x80, 0x00),
+	INPUT_CURRENT(500000,  0x02, 0x00, 0x00),
+	INPUT_CURRENT(700000,  0x01, 0x00, 0x00),
+	INPUT_CURRENT(800000,  0x01, 0x00, 0x20),
+	INPUT_CURRENT(900000,  0x01, 0x00, 0x40),
+	INPUT_CURRENT(1000000, 0x01, 0x00, 0x60),
+	INPUT_CURRENT(1100000, 0x01, 0x00, 0x80),
+	INPUT_CURRENT(1200000, 0x01, 0x00, 0xA0),
+	INPUT_CURRENT(1300000, 0x01, 0x00, 0xC0),
+	INPUT_CURRENT(1500000, 0x01, 0x00, 0xE0),
+};
+
+static int smb137c_set_usb_input_current_limit(struct smb137c_chip *chip,
+					int current_limit_ua)
+{
+	struct input_current_config *config = NULL;
+	int rc = 0;
+	int i;
+
+	for (i = ARRAY_SIZE(supported_input_current) - 1; i >= 0; i--) {
+		if (current_limit_ua
+		    >= supported_input_current[i].current_limit_ua) {
+			config = &supported_input_current[i];
+			break;
+		}
+	}
+
+	if (config) {
+		if (chip->input_current_limit_ua != config->current_limit_ua) {
+			rc = smb137c_masked_write_reg(chip, INPUT_CURRENT_REG,
+			       INPUT_CURRENT_LIMIT_MASK, config->input_cur_reg);
+			if (rc)
+				return rc;
+
+			rc = smb137c_masked_write_reg(chip, VAR_FUNC_REG,
+				VAR_FUNC_USB_MODE_MASK, config->var_func_reg);
+			if (rc)
+				return rc;
+
+			rc = smb137c_masked_write_reg(chip, CMD_B_REG,
+				CMD_B_USB_MODE_MASK, config->cmd_b_reg);
+			if (rc)
+				return rc;
+
+			chip->input_current_limit_ua = config->current_limit_ua;
+		}
+
+		if (chip->charging_allowed)
+			rc = smb137c_enable_charging(chip);
+	} else {
+		/* Current limit is below all set points so disable charging. */
+		chip->input_current_limit_ua = 0;
+
+		rc = smb137c_disable_charging(chip);
+	}
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
+			chip->input_current_limit_ua);
+
+	return rc;
+}
+
+static int fast_charge_current_ua[] = {
+	 500000,
+	 650000,
+	 750000,
+	 850000,
+	 950000,
+	1100000,
+	1300000,
+	1500000,
+};
+
+static int smb137c_set_charge_current_limit(struct smb137c_chip *chip,
+					int current_limit_ua)
+{
+	int fast_charge_limit_ua = 0;
+	int rc = 0;
+	u8 val = 0;
+	int i;
+
+	for (i = ARRAY_SIZE(fast_charge_current_ua) - 1; i >= 0; i--) {
+		if (current_limit_ua >= fast_charge_current_ua[i]) {
+			val = i << CHARGE_CURRENT_FAST_CHG_SHIFT;
+			fast_charge_limit_ua = fast_charge_current_ua[i];
+			break;
+		}
+	}
+
+	if (fast_charge_limit_ua
+	    && chip->charge_current_limit_ua != fast_charge_limit_ua)
+		rc = smb137c_masked_write_reg(chip, CHARGE_CURRENT_REG,
+					CHARGE_CURRENT_FAST_CHG_MASK, val);
+	else if (fast_charge_limit_ua == 0)
+		rc = smb137c_disable_charging(chip);
+
+	chip->charge_current_limit_ua = fast_charge_limit_ua;
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
+			fast_charge_limit_ua);
+
+	return rc;
+}
+
+static int smb137c_get_charge_current_limit(struct smb137c_chip *chip)
+{
+	int fast_charge_limit_ua = 0;
+	u8 val = 0;
+	int rc, i;
+
+	rc = smb137c_read_reg(chip, CHARGE_CURRENT_REG, &val);
+	if (rc)
+		return rc;
+
+	i = (val & CHARGE_CURRENT_FAST_CHG_MASK)
+		>> CHARGE_CURRENT_FAST_CHG_SHIFT;
+
+	if (i >= 0 && i < ARRAY_SIZE(fast_charge_current_ua))
+		fast_charge_limit_ua = fast_charge_current_ua[i];
+
+	dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
+		fast_charge_limit_ua);
+
+	return fast_charge_limit_ua;
+}
+
+static struct term_current_config term_current_ua[] = {
+	{ 35000, 0x06},
+	{ 50000, 0x00},
+	{100000, 0x02},
+	{150000, 0x04},
+};
+
+static int smb137c_set_term_current(struct smb137c_chip *chip,
+					int current_limit_ua)
+{
+	int term_current_limit_ua = 0;
+	int rc = 0;
+	u8 val = 0;
+	int i;
+
+	for (i = ARRAY_SIZE(term_current_ua) - 1; i >= 0; i--) {
+		if (current_limit_ua >= term_current_ua[i].term_current_ua) {
+			val = term_current_ua[i].charge_cur_reg;
+			term_current_limit_ua
+				= term_current_ua[i].term_current_ua;
+			break;
+		}
+	}
+
+	if (term_current_limit_ua) {
+		rc = smb137c_masked_write_reg(chip, CHARGE_CURRENT_REG,
+				CHARGE_CURRENT_TERM_CUR_MASK, val);
+		if (rc)
+			return rc;
+		rc = smb137c_masked_write_reg(chip, CTRL_A_REG,
+				CTRL_A_TERM_CUR_MASK, CTRL_A_TERM_CUR_ENABLED);
+	} else {
+		rc = smb137c_masked_write_reg(chip, CTRL_A_REG,
+				CTRL_A_TERM_CUR_MASK, CTRL_A_TERM_CUR_DISABLED);
+	}
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
+			term_current_limit_ua);
+
+	return rc;
+}
+
+static int smb137c_set_pre_charge_current_limit(struct smb137c_chip *chip,
+					int current_limit_ua)
+{
+	int setpoint, rc;
+	u8 val;
+
+	if (current_limit_ua < PRE_CHARGE_CURRENT_MIN_UA ||
+	    current_limit_ua > PRE_CHARGE_CURRENT_MAX_UA) {
+		dev_err(&chip->client->dev, "%s: current limit out of bounds: %d\n",
+			__func__, current_limit_ua);
+		return -EINVAL;
+	}
+
+	setpoint = (current_limit_ua - PRE_CHARGE_CURRENT_MIN_UA)
+			/ PRE_CHARGE_CURRENT_STEP_UA;
+	val = setpoint << CHARGE_CURRENT_PRE_CHG_SHIFT;
+
+	rc = smb137c_masked_write_reg(chip, CHARGE_CURRENT_REG,
+			CHARGE_CURRENT_PRE_CHG_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
+			setpoint * PRE_CHARGE_CURRENT_STEP_UA
+			+ PRE_CHARGE_CURRENT_MIN_UA);
+
+	return rc;
+}
+
+static int smb137c_set_float_voltage(struct smb137c_chip *chip, int voltage_uv)
+{
+	int setpoint, rc;
+	u8 val;
+
+	if (voltage_uv < FLOAT_VOLTAGE_MIN_UV ||
+	    voltage_uv > FLOAT_VOLTAGE_MAX_UV) {
+		dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
+			__func__, voltage_uv);
+		return -EINVAL;
+	}
+
+	setpoint = (voltage_uv - FLOAT_VOLTAGE_MIN_UV) / FLOAT_VOLTAGE_STEP_UV;
+	val = setpoint << FLOAT_VOLTAGE_SHIFT;
+
+	rc = smb137c_masked_write_reg(chip, FLOAT_VOLTAGE_REG,
+			FLOAT_VOLTAGE_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
+		       setpoint * FLOAT_VOLTAGE_STEP_UV + FLOAT_VOLTAGE_MIN_UV);
+
+	return rc;
+}
+
+static int smb137c_set_pre_charge_threshold_voltage(struct smb137c_chip *chip,
+							int voltage_uv)
+{
+	int setpoint, rc;
+	u8 val;
+
+	if (voltage_uv < PRE_CHG_THRESH_VOLTAGE_MIN_UV ||
+	    voltage_uv > PRE_CHG_THRESH_VOLTAGE_MAX_UV) {
+		dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
+			__func__, voltage_uv);
+		return -EINVAL;
+	}
+
+	setpoint = (voltage_uv - PRE_CHG_THRESH_VOLTAGE_MIN_UV)
+			/ PRE_CHG_THRESH_VOLTAGE_STEP_UV;
+	val = setpoint << CTRL_A_THRESH_VOLTAGE_SHIFT;
+
+	rc = smb137c_masked_write_reg(chip, CTRL_A_REG,
+			CTRL_A_THRESH_VOLTAGE_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
+		       setpoint * PRE_CHG_THRESH_VOLTAGE_STEP_UV
+		       + PRE_CHG_THRESH_VOLTAGE_MIN_UV);
+
+	return rc;
+}
+
+static int smb137c_set_recharge_threshold_voltage(struct smb137c_chip *chip,
+							int voltage_uv)
+{
+	int rc;
+	u8 val;
+
+	if (voltage_uv == 75000) {
+		val = OTG_CTRL_AUTO_RECHARGE_75MV;
+	} else if (voltage_uv == 120000) {
+		val = OTG_CTRL_AUTO_RECHARGE_120MV;
+	} else {
+		dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
+			__func__, voltage_uv);
+		return -EINVAL;
+	}
+
+	rc = smb137c_masked_write_reg(chip, OTG_CTRL_REG,
+			OTG_CTRL_AUTO_RECHARGE_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
+		       voltage_uv);
+
+	return rc;
+}
+
+static int smb137c_set_system_voltage(struct smb137c_chip *chip, int voltage_uv)
+{
+	int rc;
+	u8 val;
+
+	if (voltage_uv == 4250000) {
+		val = CTRL_A_VOUTL_4250MV;
+	} else if (voltage_uv == 4460000) {
+		val = CTRL_A_VOUTL_4460MV;
+	} else {
+		dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
+			__func__, voltage_uv);
+		return -EINVAL;
+	}
+
+	rc = smb137c_masked_write_reg(chip, CTRL_A_REG, CTRL_A_VOUTL_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
+		       voltage_uv);
+
+	return rc;
+}
+
+static int charging_timeout[] = {
+	 382,
+	 764,
+	 1527,
+};
+
+static int smb137c_set_charging_timeout(struct smb137c_chip *chip, int timeout)
+{
+	int timeout_chosen = 0;
+	u8 val = 3 << SAFETY_TIMER_CHG_TIMEOUT_SHIFT;
+	int rc, i;
+
+	for (i = ARRAY_SIZE(charging_timeout) - 1; i >= 0; i--) {
+		if (timeout >= charging_timeout[i]) {
+			val = i << SAFETY_TIMER_CHG_TIMEOUT_SHIFT;
+			timeout_chosen = charging_timeout[i];
+			break;
+		}
+	}
+
+	rc = smb137c_masked_write_reg(chip, SAFETY_TIMER_REG,
+			SAFETY_TIMER_CHG_TIMEOUT_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: timeout=%d min\n", __func__,
+			timeout_chosen);
+
+	return rc;
+}
+
+static int pre_charge_timeout[] = {
+	 48,
+	 95,
+	 191,
+};
+
+static int smb137c_set_pre_charge_timeout(struct smb137c_chip *chip,
+					int timeout)
+{
+	int timeout_chosen = 0;
+	u8 val = 3 << SAFETY_TIMER_PRE_CHG_TIME_SHIFT;
+	int rc, i;
+
+	for (i = ARRAY_SIZE(pre_charge_timeout) - 1; i >= 0; i--) {
+		if (timeout >= pre_charge_timeout[i]) {
+			val = i << SAFETY_TIMER_PRE_CHG_TIME_SHIFT;
+			timeout_chosen = pre_charge_timeout[i];
+			break;
+		}
+	}
+
+	rc = smb137c_masked_write_reg(chip, SAFETY_TIMER_REG,
+			SAFETY_TIMER_PRE_CHG_TIME_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: timeout=%d min\n", __func__,
+			timeout_chosen);
+
+	return rc;
+}
+
+static int thermistor_current[] = {
+	100,
+	40,
+	20,
+	10,
+};
+
+static int smb137c_set_thermistor_current(struct smb137c_chip *chip,
+					int current_ua)
+{
+	bool found = false;
+	u8 val = 0;
+	int rc, i;
+
+	for (i = 0; i < ARRAY_SIZE(thermistor_current); i++) {
+		if (current_ua == thermistor_current[i]) {
+			found = true;
+			val = i << TEMP_MON_THERM_CURRENT_SHIFT;
+		}
+	}
+
+	if (!found) {
+		dev_err(&chip->client->dev, "%s: current out of bounds: %d\n",
+			__func__, current_ua);
+		return -EINVAL;
+	}
+
+	rc = smb137c_masked_write_reg(chip, TEMP_MON_REG,
+			TEMP_MON_THERM_CURRENT_MASK, val);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
+			current_ua);
+
+	return 0;
+}
+
+static int smb137c_set_temperature_low_limit(struct smb137c_chip *chip,
+					int value)
+{
+	int rc;
+
+	if (value < 0 || value > 7) {
+		dev_err(&chip->client->dev, "%s: temperature value out of bounds: %d\n",
+			__func__, value);
+		return -EINVAL;
+	}
+
+	rc = smb137c_masked_write_reg(chip, TEMP_MON_REG,
+		TEMP_MON_TEMP_LOW_MASK, value << TEMP_MON_TEMP_LOW_SHIFT);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: temperature value=%d\n",
+			__func__, value);
+
+	return rc;
+}
+
+static int smb137c_set_temperature_high_limit(struct smb137c_chip *chip,
+					int value)
+{
+	int rc;
+
+	if (value < 0 || value > 7) {
+		dev_err(&chip->client->dev, "%s: temperature value out of bounds: %d\n",
+			__func__, value);
+		return -EINVAL;
+	}
+
+	rc = smb137c_masked_write_reg(chip, TEMP_MON_REG,
+		TEMP_MON_TEMP_HIGH_MASK, value << TEMP_MON_TEMP_HIGH_SHIFT);
+
+	if (!rc)
+		dev_dbg(&chip->client->dev, "%s: temperature value=%d\n",
+			__func__, value);
+
+	return rc;
+}
+
+static int charge_status_type_map[] = {
+	[CHARGE_STAT_NO_CHG]	= POWER_SUPPLY_CHARGE_TYPE_NONE,
+	[CHARGE_STAT_PRE_CHG]	= POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
+	[CHARGE_STAT_FAST_CHG]	= POWER_SUPPLY_CHARGE_TYPE_FAST,
+	[CHARGE_STAT_TAPER_CHG]	= POWER_SUPPLY_CHARGE_TYPE_FAST,
+};
+
+static const char * const charge_status_name[] = {
+	[CHARGE_STAT_NO_CHG]	= "none",
+	[CHARGE_STAT_PRE_CHG]	= "pre-charge",
+	[CHARGE_STAT_FAST_CHG]	= "fast-charge",
+	[CHARGE_STAT_TAPER_CHG]	= "taper-charge",
+};
+
+static int smb137c_get_property_status(struct smb137c_chip *chip)
+{
+	int status = POWER_SUPPLY_STATUS_DISCHARGING;
+	enum smb137c_charge_status charging_status;
+	bool charging_enabled;
+	bool charging_error;
+	int rc;
+	u8 val;
+
+	rc = smb137c_read_reg(chip, STAT_C_REG, &val);
+	if (rc)
+		return POWER_SUPPLY_STATUS_UNKNOWN;
+
+	charging_enabled = val & STAT_C_CHG_ENABLED;
+	charging_error = val & STAT_C_CHG_ERROR;
+	charging_status = (val & STAT_C_CHG_STAT_MASK) >> STAT_C_CHG_STAT_SHIFT;
+
+	if (charging_enabled && !charging_error
+	    && charging_status != CHARGE_STAT_NO_CHG)
+		status = POWER_SUPPLY_STATUS_CHARGING;
+
+	dev_dbg(&chip->client->dev, "%s: status=%s\n", __func__,
+		(status == POWER_SUPPLY_STATUS_CHARGING ? "charging"
+			: "discharging"));
+
+	return status;
+}
+
+static int smb137c_get_property_battery_present(struct smb137c_chip *chip)
+{
+	int rc;
+	u8 val;
+
+	rc = smb137c_read_reg(chip, IRQ_STAT_B_REG, &val);
+	if (rc || (val & IRQ_STAT_B_BATT_MISSING))
+		return 0;
+
+	/* Treat battery voltage less than 2.1 V as battery not present. */
+	rc = smb137c_read_reg(chip, STAT_C_REG, &val);
+	if (rc || (val & STAT_C_VBATT_LEVEL_BELOW_2P1V))
+		return 0;
+
+	return 1;
+}
+
+static int smb137c_get_property_battery_health(struct smb137c_chip *chip)
+{
+	int rc;
+	u8 val;
+
+	/* The health of a disconnected battery is unknown. */
+	if (!smb137c_get_property_battery_present(chip))
+		return POWER_SUPPLY_HEALTH_UNKNOWN;
+
+	rc = smb137c_read_reg(chip, IRQ_STAT_B_REG, &val);
+	if (rc)
+		return POWER_SUPPLY_HEALTH_UNKNOWN;
+
+	if (val & IRQ_STAT_B_BATT_OVERVOLT)
+		return POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+	else if (val & IRQ_STAT_B_BATT_UNDERVOLT)
+		return POWER_SUPPLY_HEALTH_DEAD;
+
+	rc = smb137c_read_reg(chip, IRQ_STAT_A_REG, &val);
+	if (rc)
+		return POWER_SUPPLY_HEALTH_UNKNOWN;
+
+	if (val & IRQ_STAT_A_BATT_HOT)
+		return POWER_SUPPLY_HEALTH_OVERHEAT;
+	else if (val & IRQ_STAT_A_BATT_COLD)
+		return POWER_SUPPLY_HEALTH_COLD;
+
+	return POWER_SUPPLY_HEALTH_GOOD;
+}
+
+static int smb137c_get_property_charge_type(struct smb137c_chip *chip)
+{
+	enum smb137c_charge_status status;
+	int charge_type = POWER_SUPPLY_CHARGE_TYPE_NONE;
+	bool charging_enabled;
+	bool charging_error;
+	int rc;
+	u8 val;
+
+	rc = smb137c_read_reg(chip, STAT_C_REG, &val);
+	if (rc)
+		return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+
+	charging_enabled = val & STAT_C_CHG_ENABLED;
+	charging_error = val & STAT_C_CHG_ERROR;
+	status = (val & STAT_C_CHG_STAT_MASK) >> STAT_C_CHG_STAT_SHIFT;
+
+	if (!charging_enabled) {
+		dev_dbg(&chip->client->dev, "%s: not charging\n", __func__);
+	} else if (charging_error) {
+		dev_warn(&chip->client->dev, "%s: charger error detected\n",
+			__func__);
+	} else {
+		charge_type = charge_status_type_map[status];
+	}
+
+	dev_dbg(&chip->client->dev, "%s: charging status=%s\n", __func__,
+		charge_status_name[status]);
+
+	return charge_type;
+}
+
+static enum power_supply_property smb137c_power_properties[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_CHARGING_ENABLED,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static int smb137c_property_is_writeable(struct power_supply *psy,
+						enum power_supply_property psp)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int smb137c_power_set_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  const union power_supply_propval *val)
+{
+	struct smb137c_chip *chip = container_of(psy, struct smb137c_chip, psy);
+
+	mutex_lock(&chip->lock);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+		if (val->intval)
+			smb137c_enable_charging(chip);
+		else
+			smb137c_disable_charging(chip);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		smb137c_set_charge_current_limit(chip, val->intval);
+		break;
+	default:
+		mutex_unlock(&chip->lock);
+		return -EINVAL;
+	}
+
+	mutex_unlock(&chip->lock);
+
+	power_supply_changed(&chip->psy);
+	return 0;
+}
+
+static int smb137c_power_get_property(struct power_supply *psy,
+				       enum power_supply_property psp,
+				       union power_supply_propval *val)
+{
+	struct smb137c_chip *chip = container_of(psy, struct smb137c_chip, psy);
+
+	mutex_lock(&chip->lock);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = smb137c_get_property_status(chip);
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		val->intval = smb137c_get_property_battery_health(chip);
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = smb137c_get_property_battery_present(chip);
+		break;
+	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+		val->intval = chip->charging_enabled;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_TYPE:
+		val->intval = smb137c_get_property_charge_type(chip);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		val->intval = chip->charge_current_limit_ua;
+		break;
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = "SMB137C";
+		break;
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		val->strval = "Summit Microelectronics";
+		break;
+	default:
+		mutex_unlock(&chip->lock);
+		return -EINVAL;
+	}
+
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+static void smb137c_external_power_changed(struct power_supply *psy)
+{
+	struct smb137c_chip *chip = container_of(psy, struct smb137c_chip, psy);
+	union power_supply_propval prop = {0,};
+
+	mutex_lock(&chip->lock);
+	dev_dbg(&chip->client->dev, "%s: start\n", __func__);
+
+	chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_ONLINE,
+					&prop);
+
+	if (prop.intval) {
+		/* USB online */
+		chip->usb_psy->get_property(chip->usb_psy,
+						POWER_SUPPLY_PROP_SCOPE, &prop);
+		if (prop.intval == POWER_SUPPLY_SCOPE_SYSTEM) {
+			/* USB host mode */
+			smb137c_enable_otg_mode(chip);
+			smb137c_disable_charging(chip);
+		} else {
+			/* USB device mode */
+			chip->usb_psy->get_property(chip->usb_psy,
+					POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
+			smb137c_set_usb_input_current_limit(chip, prop.intval);
+			smb137c_enable_charging(chip);
+			smb137c_disable_otg_mode(chip);
+		}
+	} else {
+		/* USB offline */
+		smb137c_disable_charging(chip);
+		smb137c_disable_otg_mode(chip);
+		smb137c_set_usb_input_current_limit(chip, USB_MIN_CURRENT_UA);
+	}
+
+	dev_dbg(&chip->client->dev, "%s: end\n", __func__);
+	mutex_unlock(&chip->lock);
+
+	power_supply_changed(&chip->psy);
+}
+
+static int __devinit smb137c_set_register_defaults(struct smb137c_chip *chip)
+{
+	int rc;
+	u8 val, mask;
+
+	/* Allow volatile register writes. */
+	rc = smb137c_masked_write_reg(chip, CMD_A_REG,
+			CMD_A_VOLATILE_WRITE_MASK, CMD_A_VOLATILE_WRITE_ALLOW);
+	if (rc)
+		return rc;
+
+	/* Do not reset register values on USB reinsertion. */
+	rc = smb137c_masked_write_reg(chip, SAFETY_TIMER_REG,
+			SAFETY_TIMER_RELOAD_MASK, SAFETY_TIMER_RELOAD_DISABLED);
+	if (rc)
+		return rc;
+
+	/* Set various default control parameters. */
+	val = PIN_CTRL_DEAD_BATT_CHG_ENABLED | PIN_CTRL_OTG
+		| PIN_CTRL_USB_CUR_LIMIT_REG | PIN_CTRL_CHG_EN_REG_LOW
+		| PIN_CTRL_OTG_CTRL_REG;
+	mask = PIN_CTRL_DEAD_BATT_CHG_MASK | PIN_CTRL_OTG_LBR_MASK
+		| PIN_CTRL_USB_CUR_LIMIT_MASK | PIN_CTRL_CHG_EN_MASK
+		| PIN_CTRL_OTG_CTRL_MASK;
+	rc = smb137c_masked_write_reg(chip, PIN_CTRL_REG, mask, val);
+	if (rc)
+		return rc;
+
+	/* Disable charging, disable OTG mode, and allow fast-charge current. */
+	val = CMD_A_CHARGING_DISABLED | CMD_A_OTG_DISABLED
+		| CMD_A_FAST_CHG_ALLOW;
+	mask = CMD_A_CHARGING_MASK | CMD_A_OTG_MASK | CMD_A_FAST_CHG_MASK;
+	rc = smb137c_masked_write_reg(chip, CMD_A_REG, mask, val);
+	if (rc)
+		return rc;
+
+	/* Enable auto recharging and full-time THERM monitor. */
+	val = CTRL_A_AUTO_RECHARGE_ENABLED | CTRL_A_THERM_MONITOR_ENABLED;
+	mask = CTRL_A_AUTO_RECHARGE_MASK | CTRL_A_THERM_MONITOR_MASK;
+	rc = smb137c_masked_write_reg(chip, CTRL_A_REG, mask, val);
+
+	return rc;
+}
+
+static int __devinit smb137c_apply_dt_configs(struct smb137c_chip *chip)
+{
+	struct device *dev = &chip->client->dev;
+	struct device_node *node = chip->client->dev.of_node;
+	int ret, current_ma, voltage_mv, timeout, value;
+	int rc = 0;
+
+	/*
+	 * All device tree parameters are optional so it is ok if read calls
+	 * fail.
+	 */
+	ret = of_property_read_u32(node, "summit,chg-current-ma", &current_ma);
+	if (ret == 0) {
+		rc = smb137c_set_charge_current_limit(chip, current_ma * 1000);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set charge current, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	} else {
+		chip->charge_current_limit_ua
+			= smb137c_get_charge_current_limit(chip);
+		rc = chip->charge_current_limit_ua;
+		if (rc < 0) {
+			dev_err(dev, "%s: Failed to get charge current, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,term-current-ma", &current_ma);
+	if (ret == 0) {
+		rc = smb137c_set_term_current(chip, current_ma * 1000);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set termination current, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,pre-chg-current-ma",
+					&current_ma);
+	if (ret == 0) {
+		rc = smb137c_set_pre_charge_current_limit(chip,
+				current_ma * 1000);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set pre-charge current limit, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,float-voltage-mv",
+					&voltage_mv);
+	if (ret == 0) {
+		rc = smb137c_set_float_voltage(chip, voltage_mv * 1000);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set float voltage, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,thresh-voltage-mv",
+					&voltage_mv);
+	if (ret == 0) {
+		rc = smb137c_set_pre_charge_threshold_voltage(chip,
+				voltage_mv * 1000);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set fast-charge threshold voltage, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,recharge-thresh-mv",
+					&voltage_mv);
+	if (ret == 0) {
+		rc = smb137c_set_recharge_threshold_voltage(chip,
+				voltage_mv * 1000);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set recharge threshold voltage, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,system-voltage-mv",
+					&voltage_mv);
+	if (ret == 0) {
+		rc = smb137c_set_system_voltage(chip, voltage_mv * 1000);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set system voltage, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,charging-timeout", &timeout);
+	if (ret == 0) {
+		rc = smb137c_set_charging_timeout(chip, timeout);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set charging timeout, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,pre-charge-timeout", &timeout);
+	if (ret == 0) {
+		rc = smb137c_set_pre_charge_timeout(chip, timeout);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set pre-charge timeout, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,therm-current-ua", &value);
+	if (ret == 0) {
+		rc = smb137c_set_thermistor_current(chip, value);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set thermistor current, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,temperature-min", &value);
+	if (ret == 0) {
+		rc = smb137c_set_temperature_low_limit(chip, value);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set low temperature limit, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	ret = of_property_read_u32(node, "summit,temperature-max", &value);
+	if (ret == 0) {
+		rc = smb137c_set_temperature_high_limit(chip, value);
+		if (rc) {
+			dev_err(dev, "%s: Failed to set high temperature limit, rc=%d\n",
+				__func__, rc);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
+static int __devinit smb137c_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct smb137c_chip *chip;
+	struct device *dev = &client->dev;
+	struct device_node *node = client->dev.of_node;
+	int rc = 0;
+	int gui_rev, silicon_rev;
+	u8 dev_id;
+
+	if (!node) {
+		dev_err(dev, "%s: device tree information missing\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(dev, "%s: SMBUS_BYTE_DATA unsupported\n", __func__);
+		return -EIO;
+	}
+
+	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip) {
+		dev_err(dev, "%s: devm_kzalloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	mutex_init(&chip->lock);
+	chip->client = client;
+	i2c_set_clientdata(client, chip);
+
+	chip->usb_psy = power_supply_get_by_name("usb");
+	if (!chip->usb_psy) {
+		dev_dbg(dev, "%s: USB supply not found; deferring charger probe\n",
+			__func__);
+		return -EPROBE_DEFER;
+	}
+
+	rc = smb137c_read_reg(chip, DEV_ID_REG, &dev_id);
+	if (rc)
+		return rc;
+
+	if ((dev_id & DEV_ID_PART_MASK) != DEV_ID_PART_SMB137C) {
+		dev_err(dev, "%s: invalid device ID=0x%02X\n", __func__,
+			dev_id);
+		return -ENODEV;
+	}
+
+	gui_rev = (dev_id & DEV_ID_GUI_REV_MASK) >> DEV_ID_GUI_REV_SHIFT;
+	silicon_rev = (dev_id & DEV_ID_SILICON_REV_MASK)
+			>> DEV_ID_SILICON_REV_SHIFT;
+
+	rc = smb137c_set_register_defaults(chip);
+	if (rc)
+		return rc;
+
+	rc = smb137c_apply_dt_configs(chip);
+	if (rc)
+		return rc;
+
+	chip->psy.name			 = "battery";
+	chip->psy.type			 = POWER_SUPPLY_TYPE_BATTERY;
+	chip->psy.properties		 = smb137c_power_properties;
+	chip->psy.num_properties	 = ARRAY_SIZE(smb137c_power_properties);
+	chip->psy.get_property		 = smb137c_power_get_property;
+	chip->psy.set_property		 = smb137c_power_set_property;
+	chip->psy.property_is_writeable  = smb137c_property_is_writeable;
+	chip->psy.external_power_changed = smb137c_external_power_changed;
+
+	rc = power_supply_register(dev, &chip->psy);
+	if (rc < 0) {
+		dev_err(dev, "%s: power_supply_register failed, rc=%d\n",
+						__func__, rc);
+		return rc;
+	}
+
+	smb137c_external_power_changed(&chip->psy);
+
+	dev_info(dev, "%s: SMB137C charger probed successfully, gui_rev=%d, silicon_rev=%d\n",
+		__func__, gui_rev, silicon_rev);
+
+	return rc;
+}
+
+static int __devexit smb137c_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static const struct i2c_device_id smb137c_id[] = {
+	{ .name = "smb137c", },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, smb137c_id);
+
+/* TODO: should this be "summit,smb137c-charger"? */
+static const struct of_device_id smb137c_match[] = {
+	{ .compatible = "summit,smb137c", },
+	{ },
+};
+
+static struct i2c_driver smb137c_driver = {
+	.driver	= {
+		.name		= "smb137c",
+		.owner		= THIS_MODULE,
+		.of_match_table	= smb137c_match,
+	},
+	.probe		= smb137c_probe,
+	.remove		= __devexit_p(smb137c_remove),
+	.id_table	= smb137c_id,
+};
+
+static int __init smb137c_init(void)
+{
+	return i2c_add_driver(&smb137c_driver);
+}
+module_init(smb137c_init);
+
+static void __exit smb137c_exit(void)
+{
+	return i2c_del_driver(&smb137c_driver);
+}
+module_exit(smb137c_exit);
+
+MODULE_DESCRIPTION("SMB137C Charger");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("i2c:smb137c");
diff --git a/drivers/power/smb350_charger.c b/drivers/power/smb350_charger.c
index 319caba..d07c100 100644
--- a/drivers/power/smb350_charger.c
+++ b/drivers/power/smb350_charger.c
@@ -212,21 +212,6 @@
 	return ret;
 }
 
-#define SMB350_FLOAT_VOLT_BASE_MV 6920
-#define SMB350_FLOAT_VOLT_STEP_MV   40
-#define SMB350_FLOAT_VOLT_MAX_MV  (6920 + 0x2F * 40)
-
-/* Fast-to-Taper charging volatge */
-static int smb350_get_float_voltage(struct i2c_client *client)
-{
-	u16 val = smb350_read_reg(client, STATUS_A_REG);
-
-	val = SMB350_FLOAT_VOLT_BASE_MV +
-		((val & 0x2F) * SMB350_FLOAT_VOLT_STEP_MV);
-
-	return val;
-}
-
 static bool smb350_is_dc_present(struct i2c_client *client)
 {
 	u16 irq_status_f = smb350_read_reg(client, IRQ_STATUS_F_REG);
@@ -398,7 +383,6 @@
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_CHARGE_TYPE,
-	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	/* fixed */
 	POWER_SUPPLY_PROP_MANUFACTURER,
 	POWER_SUPPLY_PROP_MODEL_NAME,
@@ -429,10 +413,6 @@
 	case POWER_SUPPLY_PROP_CHARGE_TYPE:
 		val->intval = smb350_get_prop_charge_type(dev);
 		break;
-	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-		val->intval = smb350_get_float_voltage(client);
-		val->intval *= 1000; /* mV to uV */
-		break;
 	case POWER_SUPPLY_PROP_MODEL_NAME:
 		val->strval = SMB350_NAME;
 		break;
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 1f2a95e..02e1952 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -144,6 +144,30 @@
 	return IRQ_HANDLED;
 }
 
+static int ngd_clk_pause_wakeup(struct slim_controller *ctrl)
+{
+	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+	return msm_slim_qmi_power_request(dev, true);
+}
+
+static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
+				void *_cmd)
+{
+	struct msm_slim_qmi *qmi = container_of(n, struct msm_slim_qmi, nb);
+	pr_info("Slimbus QMI NGD CB received event:%ld", code);
+	switch (code) {
+	case QMI_SERVER_ARRIVE:
+		complete(&qmi->qmi_comp);
+		break;
+	case QMI_SERVER_EXIT:
+		/* SSR implementation */
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
 static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn,
 				u8 *tid, struct completion *done)
 {
@@ -184,16 +208,21 @@
 	u32 *pbuf;
 	u8 *puc;
 	int ret = 0;
-	int msgv = -1;
 	u8 la = txn->la;
 	u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
 
+	if (txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
+			SLIM_MSG_MC_RECONFIGURE_NOW))
+		return msm_slim_qmi_power_request(dev, false);
+	else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
+		return 0;
+
 	if (txn->mt == SLIM_MSG_MT_CORE &&
 		(txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
 		 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
 		return 0;
 	}
-	msgv = msm_slim_get_ctrl(dev);
+	msm_slim_get_ctrl(dev);
 	mutex_lock(&dev->tx_lock);
 	if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE &&
 		(dev->state == MSM_CTRL_ASLEEP ||
@@ -206,8 +235,7 @@
 		if (timeout) {
 			mutex_lock(&dev->tx_lock);
 		} else {
-			if (msgv >= 0)
-				msm_slim_put_ctrl(dev);
+			msm_slim_put_ctrl(dev);
 			return -EBUSY;
 		}
 	}
@@ -293,8 +321,7 @@
 			 */
 			dev->pipes[wbuf[1]].connected = false;
 			mutex_unlock(&dev->tx_lock);
-			if (msgv >= 0)
-				msm_slim_put_ctrl(dev);
+			msm_slim_put_ctrl(dev);
 			return 0;
 		}
 		if (dev->err) {
@@ -336,8 +363,7 @@
 		 txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
 		int timeout;
 		mutex_unlock(&dev->tx_lock);
-		if (msgv >= 0)
-			msm_slim_put_ctrl(dev);
+		msm_slim_put_ctrl(dev);
 		timeout = wait_for_completion_timeout(txn->comp, HZ);
 		if (!timeout) {
 			pr_err("connect/disc :0x%x, tid:%d timed out", txn->mc,
@@ -353,8 +379,7 @@
 	}
 ngd_xfer_err:
 	mutex_unlock(&dev->tx_lock);
-	if (msgv >= 0)
-		msm_slim_put_ctrl(dev);
+	msm_slim_put_ctrl(dev);
 	return ret ? ret : dev->err;
 }
 
@@ -405,8 +430,9 @@
 			return -ENXIO;
 		}
 		if (txn.len == 0) {
+			/* Per protocol, only last 5 bits for client no. */
 			wbuf[txn.len++] = (u8) (slc->prop.dataf << 5) |
-					sb->laddr;
+					(sb->laddr & 0x1f);
 			wbuf[txn.len] = slc->seglen;
 			if (slc->coeff == SLIM_COEFF_3)
 				wbuf[txn.len] |= 1 << 5;
@@ -420,6 +446,7 @@
 			}
 		}
 		wbuf[txn.len++] = slc->chan;
+		pr_debug("slim define chan:%d, tid:0x%x", slc->chan, txn.tid);
 	}
 	if (txn.len) {
 		txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
@@ -448,8 +475,9 @@
 			return -ENXIO;
 		}
 		if (txn.len == 0) {
+			/* Per protocol, only last 5 bits for client no. */
 			wbuf[txn.len++] = (u8) (SLIM_CH_REMOVE << 6) |
-					sb->laddr;
+					(sb->laddr & 0x1f);
 			ret = ngd_get_tid(ctrl, &txn, &wbuf[txn.len++], &done);
 			if (ret) {
 				pr_err("no tid for channel define?");
@@ -457,6 +485,7 @@
 			}
 		}
 		wbuf[txn.len++] = slc->chan;
+		pr_debug("slim remove chan:%d, tid:0x%x", slc->chan, txn.tid);
 	}
 	if (txn.len) {
 		txn.mc = SLIM_USR_MC_CHAN_CTRL;
@@ -544,6 +573,7 @@
 		wbuf[3] = SAT_MSG_PROT;
 		txn.wbuf = wbuf;
 		txn.len = 4;
+		pr_info("SLIM SAT: Received master capability");
 		dev->use_rx_msgqs = 1;
 		msm_slim_sps_init(dev, dev->bam_mem,
 			NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_STATUS, true);
@@ -557,6 +587,12 @@
 		ret = ngd_xfer_msg(&dev->ctrl, &txn);
 		if (!ret) {
 			dev->state = MSM_CTRL_AWAKE;
+
+			pm_runtime_use_autosuspend(dev->dev);
+			pm_runtime_set_autosuspend_delay(dev->dev,
+							MSM_SLIM_AUTOSUSPEND);
+			pm_runtime_set_active(dev->dev);
+			pm_runtime_enable(dev->dev);
 			complete(&dev->reconf);
 		}
 	}
@@ -595,6 +631,41 @@
 		complete(txn->comp);
 	}
 }
+
+static int ngd_slim_enable(struct msm_slim_ctrl *dev, bool enable)
+{
+	u32 ngd_int = (NGD_INT_RECFG_DONE | NGD_INT_TX_NACKED_2 |
+			NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
+			NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
+			NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
+	if (enable) {
+		int ret = msm_slim_qmi_init(dev, false);
+		if (ret)
+			return ret;
+		ret = msm_slim_qmi_power_request(dev, true);
+		if (ret)
+			return ret;
+		writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
+					NGD_BASE(dev->ctrl.nr, dev->ver));
+		/*
+		 * Enable NGD. Configure NGD in register acc. mode until master
+		 * announcement is received
+		 */
+		writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
+		/* make sure NGD enabling goes through */
+		mb();
+	} else {
+		writel_relaxed(0, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
+		writel_relaxed(0, dev->base + NGD_INT_EN +
+				NGD_BASE(dev->ctrl.nr, dev->ver));
+		/* make sure NGD disabling goes through */
+		mb();
+		msm_slim_qmi_exit(dev);
+	}
+
+	return 0;
+}
+
 static int ngd_slim_rx_msgq_thread(void *data)
 {
 	struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
@@ -605,6 +676,14 @@
 	u32 buffer[10];
 	u8 msg_len = 0;
 
+	wait_for_completion_interruptible(&dev->qmi.qmi_comp);
+	ret = ngd_slim_enable(dev, true);
+	/* Exit the thread if component can't be enabled */
+	if (ret) {
+		pr_err("Enabling NGD failed:%d", ret);
+		return 0;
+	}
+
 	while (!kthread_should_stop()) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		ret = wait_for_completion_interruptible(notify);
@@ -648,7 +727,6 @@
 	struct resource		*slim_mem;
 	struct resource		*irq, *bam_irq;
 	enum apr_subsys_state q6_state;
-	u32 ngd_int;
 
 	q6_state = apr_get_q6_state();
 	if (q6_state == APR_SUBSYS_DOWN) {
@@ -725,7 +803,7 @@
 	dev->ctrl.get_laddr = ngd_get_laddr;
 	dev->ctrl.allocbw = ngd_allocbw;
 	dev->ctrl.xfer_msg = ngd_xfer_msg;
-	dev->ctrl.wakeup =  NULL;
+	dev->ctrl.wakeup =  ngd_clk_pause_wakeup;
 	dev->ctrl.config_port = msm_config_port;
 	dev->ctrl.port_xfer = msm_slim_port_xfer;
 	dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
@@ -743,10 +821,6 @@
 	dev->ver = readl_relaxed(dev->base);
 	/* Version info in 16 MSbits */
 	dev->ver >>= 16;
-	ngd_int = (NGD_INT_RECFG_DONE | NGD_INT_TX_NACKED_2 |
-			NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
-			NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
-			NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
 	init_completion(&dev->rx_msgq_notify);
 
 	/* Register with framework */
@@ -768,6 +842,15 @@
 		goto err_request_irq_failed;
 	}
 
+	init_completion(&dev->qmi.qmi_comp);
+	dev->qmi.nb.notifier_call = ngd_qmi_available;
+	ret = qmi_svc_event_notifier_register(SLIMBUS_QMI_SVC_ID,
+				SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
+	if (ret) {
+		pr_err("Slimbus QMI service registration failed:%d", ret);
+		goto qmi_register_failed;
+	}
+
 	/* Fire up the Rx message queue thread */
 	dev->rx_msgq_thread = kthread_run(ngd_slim_rx_msgq_thread, dev,
 					NGD_SLIM_NAME "_ngd_msgq_thread");
@@ -777,30 +860,19 @@
 		goto err_thread_create_failed;
 	}
 
-	writel_relaxed(ngd_int, dev->base + NGD_INT_EN +
-				NGD_BASE(dev->ctrl.nr, dev->ver));
-	/*
-	 * Enable NGD. Configure NGD in register access mode until master
-	 * announcement is received
-	 */
-	writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
-	/* make sure NGD enabling goes through */
-	mb();
-
 	if (pdev->dev.of_node)
 		of_register_slim_devices(&dev->ctrl);
 
 	/* Add devices registered with board-info now that controller is up */
 	slim_ctrl_add_boarddevs(&dev->ctrl);
 
-	pm_runtime_use_autosuspend(&pdev->dev);
-	pm_runtime_set_autosuspend_delay(&pdev->dev, MSM_SLIM_AUTOSUSPEND);
-	pm_runtime_set_active(&pdev->dev);
-
 	dev_dbg(dev->dev, "NGD SB controller is up!\n");
 	return 0;
 
 err_thread_create_failed:
+	qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
+				SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
+qmi_register_failed:
 	free_irq(dev->irq, dev);
 err_request_irq_failed:
 	slim_del_controller(&dev->ctrl);
@@ -816,6 +888,9 @@
 static int __devexit ngd_slim_remove(struct platform_device *pdev)
 {
 	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
+	ngd_slim_enable(dev, false);
+	qmi_svc_event_notifier_unregister(SLIMBUS_QMI_SVC_ID,
+				SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	free_irq(dev->irq, dev);
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 7cd34d3..c62ac27 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -582,3 +582,351 @@
 		sps_deregister_bam_device(dev->bam.hdl);
 	}
 }
+
+/* Slimbus QMI Messaging */
+#define SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01 0x0020
+#define SLIMBUS_QMI_SELECT_INSTANCE_RESP_V01 0x0020
+#define SLIMBUS_QMI_POWER_REQ_V01 0x0021
+#define SLIMBUS_QMI_POWER_RESP_V01 0x0021
+
+enum slimbus_mode_enum_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	SLIMBUS_MODE_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
+	SLIMBUS_MODE_SATELLITE_V01 = 1,
+	SLIMBUS_MODE_MASTER_V01 = 2,
+	SLIMBUS_MODE_ENUM_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
+};
+
+enum slimbus_pm_enum_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	SLIMBUS_PM_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
+	SLIMBUS_PM_INACTIVE_V01 = 1,
+	SLIMBUS_PM_ACTIVE_V01 = 2,
+	SLIMBUS_PM_ENUM_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
+};
+
+struct slimbus_select_inst_req_msg_v01 {
+	/* Mandatory */
+	/* Hardware Instance Selection */
+	uint32_t instance;
+
+	/* Optional */
+	/* Optional Mode Request Operation */
+	/* Must be set to true if mode is being passed */
+	uint8_t mode_valid;
+	enum slimbus_mode_enum_type_v01 mode;
+};
+
+struct slimbus_select_inst_resp_msg_v01 {
+	/* Mandatory */
+	/* Result Code */
+	struct qmi_response_type_v01 resp;
+};
+
+struct slimbus_power_req_msg_v01 {
+	/* Mandatory */
+	/* Power Request Operation */
+	enum slimbus_pm_enum_type_v01 pm_req;
+};
+
+struct slimbus_power_resp_msg_v01 {
+	/* Mandatory */
+	/* Result Code */
+	struct qmi_response_type_v01 resp;
+};
+
+static struct elem_info slimbus_select_inst_req_msg_v01_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len  = 1,
+		.elem_size = sizeof(uint32_t),
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x01,
+		.offset    = offsetof(struct slimbus_select_inst_req_msg_v01,
+				      instance),
+		.ei_array  = NULL,
+	},
+	{
+		.data_type = QMI_OPT_FLAG,
+		.elem_len  = 1,
+		.elem_size = sizeof(uint8_t),
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x10,
+		.offset    = offsetof(struct slimbus_select_inst_req_msg_v01,
+				      mode_valid),
+		.ei_array  = NULL,
+	},
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len  = 1,
+		.elem_size = sizeof(enum slimbus_mode_enum_type_v01),
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x10,
+		.offset    = offsetof(struct slimbus_select_inst_req_msg_v01,
+				      mode),
+		.ei_array  = NULL,
+	},
+	{
+		.data_type = QMI_EOTI,
+		.elem_len  = 0,
+		.elem_size = 0,
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x00,
+		.offset    = 0,
+		.ei_array  = NULL,
+	},
+};
+
+static struct elem_info slimbus_select_inst_resp_msg_v01_ei[] = {
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len  = 1,
+		.elem_size = sizeof(struct qmi_response_type_v01),
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x02,
+		.offset    = offsetof(struct slimbus_select_inst_resp_msg_v01,
+				      resp),
+		.ei_array  = get_qmi_response_type_v01_ei(),
+	},
+	{
+		.data_type = QMI_EOTI,
+		.elem_len  = 0,
+		.elem_size = 0,
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x00,
+		.offset    = 0,
+		.ei_array  = NULL,
+	},
+};
+
+static struct elem_info slimbus_power_req_msg_v01_ei[] = {
+	{
+		.data_type = QMI_UNSIGNED_4_BYTE,
+		.elem_len  = 1,
+		.elem_size = sizeof(enum slimbus_pm_enum_type_v01),
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x01,
+		.offset    = offsetof(struct slimbus_power_req_msg_v01, pm_req),
+		.ei_array  = NULL,
+	},
+	{
+		.data_type = QMI_EOTI,
+		.elem_len  = 0,
+		.elem_size = 0,
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x00,
+		.offset    = 0,
+		.ei_array  = NULL,
+	},
+};
+
+static struct elem_info slimbus_power_resp_msg_v01_ei[] = {
+	{
+		.data_type = QMI_STRUCT,
+		.elem_len  = 1,
+		.elem_size = sizeof(struct qmi_response_type_v01),
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x02,
+		.offset    = offsetof(struct slimbus_power_resp_msg_v01, resp),
+		.ei_array  = get_qmi_response_type_v01_ei(),
+	},
+	{
+		.data_type = QMI_EOTI,
+		.elem_len  = 0,
+		.elem_size = 0,
+		.is_array  = NO_ARRAY,
+		.tlv_type  = 0x00,
+		.offset    = 0,
+		.ei_array  = NULL,
+	},
+};
+
+static void msm_slim_qmi_recv_msg(struct kthread_work *work)
+{
+	int rc;
+	struct msm_slim_qmi *qmi =
+			container_of(work, struct msm_slim_qmi, kwork);
+
+	rc = qmi_recv_msg(qmi->handle);
+	if (rc < 0)
+		pr_err("%s: Error receiving QMI message\n", __func__);
+}
+
+static void msm_slim_qmi_notify(struct qmi_handle *handle,
+				enum qmi_event_type event, void *notify_priv)
+{
+	struct msm_slim_ctrl *dev = notify_priv;
+	struct msm_slim_qmi *qmi = &dev->qmi;
+
+	switch (event) {
+	case QMI_RECV_MSG:
+		queue_kthread_work(&qmi->kworker, &qmi->kwork);
+		break;
+	default:
+		break;
+	}
+}
+
+static const char *get_qmi_error(struct qmi_response_type_v01 *r)
+{
+	if (r->result == QMI_RESULT_SUCCESS_V01 || r->error == QMI_ERR_NONE_V01)
+		return "No Error";
+	else if (r->error == QMI_ERR_NO_MEMORY_V01)
+		return "Out of Memory";
+	else if (r->error == QMI_ERR_INTERNAL_V01)
+		return "Unexpected error occurred";
+	else if (r->error == QMI_ERR_INCOMPATIBLE_STATE_V01)
+		return "Slimbus s/w already configured to a different mode";
+	else if (r->error == QMI_ERR_INVALID_ID_V01)
+		return "Slimbus hardware instance is not valid";
+	else
+		return "Unknown error";
+}
+
+static int msm_slim_qmi_send_select_inst_req(struct msm_slim_ctrl *dev,
+				struct slimbus_select_inst_req_msg_v01 *req)
+{
+	struct slimbus_select_inst_resp_msg_v01 resp = { { 0, 0 } };
+	struct msg_desc req_desc, resp_desc;
+	int rc;
+
+	req_desc.msg_id = SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01;
+	req_desc.max_msg_len = sizeof(*req);
+	req_desc.ei_array = slimbus_select_inst_req_msg_v01_ei;
+
+	resp_desc.msg_id = SLIMBUS_QMI_SELECT_INSTANCE_RESP_V01;
+	resp_desc.max_msg_len = sizeof(resp);
+	resp_desc.ei_array = slimbus_select_inst_resp_msg_v01_ei;
+
+	rc = qmi_send_req_wait(dev->qmi.handle, &req_desc, req, sizeof(*req),
+					&resp_desc, &resp, sizeof(resp), 5000);
+	if (rc < 0) {
+		pr_err("%s: QMI send req failed %d\n", __func__, rc);
+		return rc;
+	}
+
+	/* Check the response */
+	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+		pr_err("%s: QMI request failed 0x%x (%s)\n", __func__,
+				resp.resp.result, get_qmi_error(&resp.resp));
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int msm_slim_qmi_send_power_request(struct msm_slim_ctrl *dev,
+				struct slimbus_power_req_msg_v01 *req)
+{
+	struct slimbus_power_resp_msg_v01 resp = { { 0, 0 } };
+	struct msg_desc req_desc, resp_desc;
+	int rc;
+
+	req_desc.msg_id = SLIMBUS_QMI_POWER_REQ_V01;
+	req_desc.max_msg_len = sizeof(*req);
+	req_desc.ei_array = slimbus_power_req_msg_v01_ei;
+
+	resp_desc.msg_id = SLIMBUS_QMI_POWER_RESP_V01;
+	resp_desc.max_msg_len = sizeof(resp);
+	resp_desc.ei_array = slimbus_power_resp_msg_v01_ei;
+
+	rc = qmi_send_req_wait(dev->qmi.handle, &req_desc, req, sizeof(*req),
+					&resp_desc, &resp, sizeof(resp), 5000);
+	if (rc < 0) {
+		pr_err("%s: QMI send req failed %d\n", __func__, rc);
+		return rc;
+	}
+
+	/* Check the response */
+	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+		pr_err("%s: QMI request failed 0x%x (%s)\n", __func__,
+				resp.resp.result, get_qmi_error(&resp.resp));
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+int msm_slim_qmi_init(struct msm_slim_ctrl *dev, bool apps_is_master)
+{
+	int rc = 0;
+	struct qmi_handle *handle;
+	struct slimbus_select_inst_req_msg_v01 req;
+
+	init_kthread_worker(&dev->qmi.kworker);
+
+	dev->qmi.task = kthread_run(kthread_worker_fn,
+			&dev->qmi.kworker, "msm_slim_qmi_clnt%d", dev->ctrl.nr);
+
+	if (IS_ERR(dev->qmi.task)) {
+		pr_err("%s: Failed to create QMI client kthread\n", __func__);
+		return -ENOMEM;
+	}
+
+	init_kthread_work(&dev->qmi.kwork, msm_slim_qmi_recv_msg);
+
+	handle = qmi_handle_create(msm_slim_qmi_notify, dev);
+	if (!handle) {
+		rc = -ENOMEM;
+		pr_err("%s: QMI client handle alloc failed\n", __func__);
+		goto qmi_handle_create_failed;
+	}
+
+	rc = qmi_connect_to_service(handle, SLIMBUS_QMI_SVC_ID,
+						SLIMBUS_QMI_INS_ID);
+	if (rc < 0) {
+		pr_err("%s: QMI server not found\n", __func__);
+		goto qmi_connect_to_service_failed;
+	}
+
+	/* Instance is 0 based */
+	req.instance = dev->ctrl.nr - 1;
+	req.mode_valid = 1;
+
+	/* Mode indicates the role of the ADSP */
+	if (apps_is_master)
+		req.mode = SLIMBUS_MODE_SATELLITE_V01;
+	else
+		req.mode = SLIMBUS_MODE_MASTER_V01;
+
+	dev->qmi.handle = handle;
+
+	rc = msm_slim_qmi_send_select_inst_req(dev, &req);
+	if (rc) {
+		pr_err("%s: failed to select h/w instance\n", __func__);
+		goto qmi_select_instance_failed;
+	}
+
+	return 0;
+
+qmi_select_instance_failed:
+	dev->qmi.handle = NULL;
+qmi_connect_to_service_failed:
+	qmi_handle_destroy(handle);
+qmi_handle_create_failed:
+	flush_kthread_worker(&dev->qmi.kworker);
+	kthread_stop(dev->qmi.task);
+	dev->qmi.task = NULL;
+	return rc;
+}
+
+void msm_slim_qmi_exit(struct msm_slim_ctrl *dev)
+{
+	qmi_handle_destroy(dev->qmi.handle);
+	flush_kthread_worker(&dev->qmi.kworker);
+	kthread_stop(dev->qmi.task);
+	dev->qmi.task = NULL;
+	dev->qmi.handle = NULL;
+}
+
+int msm_slim_qmi_power_request(struct msm_slim_ctrl *dev, bool active)
+{
+	struct slimbus_power_req_msg_v01 req;
+
+	if (active)
+		req.pm_req = SLIMBUS_PM_ACTIVE_V01;
+	else
+		req.pm_req = SLIMBUS_PM_INACTIVE_V01;
+
+	return msm_slim_qmi_send_power_request(dev, &req);
+}
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 7d50620..3daf7ee 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -12,6 +12,10 @@
 
 #ifndef _SLIM_MSM_H
 #define _SLIM_MSM_H
+
+#include <linux/kthread.h>
+#include <mach/msm_qmi_interface.h>
+
 /* Per spec.max 40 bytes per received message */
 #define SLIM_RX_MSGQ_BUF_LEN	40
 
@@ -64,6 +68,10 @@
 #define MSM_MAX_NSATS	2
 #define MSM_MAX_SATCH	32
 
+/* Slimbus QMI service */
+#define SLIMBUS_QMI_SVC_ID 0x0301
+#define SLIMBUS_QMI_INS_ID 1
+
 #define PGD_THIS_EE(r, v) ((v) ? PGD_THIS_EE_V2(r) : PGD_THIS_EE_V1(r))
 #define PGD_PORT(r, p, v) ((v) ? PGD_PORT_V2(r, p) : PGD_PORT_V1(r, p))
 #define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))
@@ -161,6 +169,15 @@
 	bool				connected;
 };
 
+struct msm_slim_qmi {
+	struct qmi_handle		*handle;
+	struct task_struct		*task;
+	struct kthread_work		kwork;
+	struct kthread_worker		kworker;
+	struct completion		qmi_comp;
+	struct notifier_block		nb;
+};
+
 struct msm_slim_ctrl {
 	struct slim_controller  ctrl;
 	struct slim_framer	framer;
@@ -197,6 +214,7 @@
 	enum msm_ctrl_state	state;
 	int			nsats;
 	u32			ver;
+	struct msm_slim_qmi	qmi;
 };
 
 struct msm_sat_chan {
@@ -249,4 +267,8 @@
 int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
 			u32 pipe_reg, bool remote);
 void msm_slim_sps_exit(struct msm_slim_ctrl *dev);
+
+void msm_slim_qmi_exit(struct msm_slim_ctrl *dev);
+int msm_slim_qmi_init(struct msm_slim_ctrl *dev, bool apps_is_master);
+int msm_slim_qmi_power_request(struct msm_slim_ctrl *dev, bool active);
 #endif
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 9a99238..43d17c2 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -67,6 +67,15 @@
 	---help---
 	  Register processes to be killed when memory is low
 
+config ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+	bool "Android Low Memory Killer: detect oom_adj values"
+	depends on ANDROID_LOW_MEMORY_KILLER
+	default y
+	---help---
+	  Detect oom_adj values written to
+	  /sys/module/lowmemorykiller/parameters/adj and convert them
+	  to oom_score_adj values.
+
 source "drivers/staging/android/switch/Kconfig"
 
 config ANDROID_INTF_ALARM_DEV
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 432abe5..c67b75b 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -259,9 +259,94 @@
 	unregister_shrinker(&lowmem_shrinker);
 }
 
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+static int lowmem_oom_adj_to_oom_score_adj(int oom_adj)
+{
+	if (oom_adj == OOM_ADJUST_MAX)
+		return OOM_SCORE_ADJ_MAX;
+	else
+		return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
+}
+
+static void lowmem_autodetect_oom_adj_values(void)
+{
+	int i;
+	int oom_adj;
+	int oom_score_adj;
+	int array_size = ARRAY_SIZE(lowmem_adj);
+
+	if (lowmem_adj_size < array_size)
+		array_size = lowmem_adj_size;
+
+	if (array_size <= 0)
+		return;
+
+	oom_adj = lowmem_adj[array_size - 1];
+	if (oom_adj > OOM_ADJUST_MAX)
+		return;
+
+	oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
+	if (oom_score_adj <= OOM_ADJUST_MAX)
+		return;
+
+	lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n");
+	for (i = 0; i < array_size; i++) {
+		oom_adj = lowmem_adj[i];
+		oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);
+		lowmem_adj[i] = oom_score_adj;
+		lowmem_print(1, "oom_adj %d => oom_score_adj %d\n",
+			     oom_adj, oom_score_adj);
+	}
+}
+
+static int lowmem_adj_array_set(const char *val, const struct kernel_param *kp)
+{
+	int ret;
+
+	ret = param_array_ops.set(val, kp);
+
+	/* HACK: Autodetect oom_adj values in lowmem_adj array */
+	lowmem_autodetect_oom_adj_values();
+
+	return ret;
+}
+
+static int lowmem_adj_array_get(char *buffer, const struct kernel_param *kp)
+{
+	return param_array_ops.get(buffer, kp);
+}
+
+static void lowmem_adj_array_free(void *arg)
+{
+	param_array_ops.free(arg);
+}
+
+static struct kernel_param_ops lowmem_adj_array_ops = {
+	.set = lowmem_adj_array_set,
+	.get = lowmem_adj_array_get,
+	.free = lowmem_adj_array_free,
+};
+
+static const struct kparam_array __param_arr_adj = {
+	.max = ARRAY_SIZE(lowmem_adj),
+	.num = &lowmem_adj_size,
+	.ops = &param_ops_int,
+	.elemsize = sizeof(lowmem_adj[0]),
+	.elem = lowmem_adj,
+};
+#endif
+
 module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
+__module_param_call(MODULE_PARAM_PREFIX, adj,
+		    &lowmem_adj_array_ops,
+		    .arr = &__param_arr_adj,
+		    S_IRUGO | S_IWUSR, -1);
+__MODULE_PARM_TYPE(adj, "array of int");
+#else
 module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size,
 			 S_IRUGO | S_IWUSR);
+#endif
 module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
 			 S_IRUGO | S_IWUSR);
 module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4a9c9a3..84cd3e7 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -168,6 +168,7 @@
 	struct work_struct clock_off_w; /* work for actual clock off */
 	struct workqueue_struct *hsuart_wq; /* hsuart workqueue */
 	struct mutex clk_mutex; /* mutex to guard against clock off/clock on */
+	bool tty_flush_receive;
 };
 
 #define MSM_UARTDM_BURST_SIZE 16   /* DM burst size (in bytes) */
@@ -1250,6 +1251,13 @@
 
 }
 
+static void msm_hs_flush_buffer(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	msm_uport->tty_flush_receive = true;
+}
+
 /*
  *  Standard API, Break Signal
  *
@@ -1465,7 +1473,14 @@
 		 */
 		mb();
 		/* Complete DMA TX transactions and submit new transactions */
-		tx_buf->tail = (tx_buf->tail + tx->tx_count) & ~UART_XMIT_SIZE;
+
+		/* Do not update tx_buf.tail if uart_flush_buffer already
+						called in serial core */
+		if (!msm_uport->tty_flush_receive)
+			tx_buf->tail = (tx_buf->tail +
+					tx->tx_count) & ~UART_XMIT_SIZE;
+		else
+			msm_uport->tty_flush_receive = false;
 
 		tx->dma_in_flight = 0;
 
@@ -2209,6 +2224,7 @@
 	.config_port = msm_hs_config_port,
 	.release_port = msm_hs_release_port,
 	.request_port = msm_hs_request_port,
+	.flush_buffer = msm_hs_flush_buffer,
 };
 
 module_init(msm_serial_hs_init);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index a292416..494ec49 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1405,7 +1405,6 @@
 	 * (This can't be done in usb_resume_interface()
 	 * above because it doesn't own the right set of locks.)
 	 */
-	pm_runtime_get_sync(dev->parent);
 	status = usb_resume_both(udev, msg);
 	if (status == 0) {
 		pm_runtime_disable(dev);
@@ -1413,7 +1412,6 @@
 		pm_runtime_enable(dev);
 		unbind_no_reset_resume_drivers_interfaces(udev);
 	}
-	pm_runtime_put_sync(dev->parent);
 
 	/* Avoid PM error messages for devices disconnected while suspended
 	 * as we'll display regular disconnect messages just a bit later.
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index cd02489..7b616e4 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -81,7 +81,6 @@
 	struct wake_lock	wlock;
 	int			peripheral_status_irq;
 	int			wakeup_irq;
-	int			wakeup_gpio;
 	bool			wakeup_irq_enabled;
 	atomic_t		pm_usage_cnt;
 	uint32_t		bus_perf_client;
@@ -525,22 +524,11 @@
 	if (rc < 0) {
 		dev_err(mehci->dev, "gpio request failed for HSIC DATA\n");
 		goto free_strobe;
-		}
-
-	if (mehci->wakeup_gpio) {
-		rc = gpio_request(mehci->wakeup_gpio, "HSIC_WAKEUP_GPIO");
-		if (rc < 0) {
-			dev_err(mehci->dev, "gpio request failed for HSIC WAKEUP\n");
-			goto free_data;
-		}
 	}
 
 	return 0;
 
 free_gpio:
-	if (mehci->wakeup_gpio)
-		gpio_free(mehci->wakeup_gpio);
-free_data:
 	gpio_free(pdata->data);
 free_strobe:
 	gpio_free(pdata->strobe);
@@ -1596,10 +1584,9 @@
 	if (res)
 		mehci->peripheral_status_irq = res->start;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup");
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "wakeup");
 	if (res) {
-		mehci->wakeup_gpio = res->start;
-		mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start);
+		mehci->wakeup_irq = res->start;
 		dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq);
 	}
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index d10c692..d04c234 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -82,6 +82,11 @@
 MODULE_PARM_DESC(override_phy_init,
 	"Override HSUSB PHY Init Settings");
 
+unsigned int lpm_disconnect_thresh = 1000;
+module_param(lpm_disconnect_thresh , uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(lpm_disconnect_thresh,
+	"Delay before entering LPM on USB disconnect");
+
 static DECLARE_COMPLETION(pmic_vbus_init);
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
@@ -2440,7 +2445,12 @@
 			msm_otg_notify_charger(motg, 0);
 			msm_otg_reset(otg->phy);
 			pm_runtime_put_noidle(otg->phy->dev);
-			pm_runtime_suspend(otg->phy->dev);
+			/*
+			 * Only if autosuspend was enabled in probe, it will be
+			 * used here. Otherwise, no delay will be used.
+			 */
+			pm_runtime_mark_last_busy(otg->phy->dev);
+			pm_runtime_autosuspend(otg->phy->dev);
 		}
 		break;
 	case OTG_STATE_B_SRP_INIT:
@@ -3989,6 +3999,12 @@
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
+	if (motg->pdata->delay_lpm_on_disconnect) {
+		pm_runtime_set_autosuspend_delay(&pdev->dev,
+			lpm_disconnect_thresh);
+		pm_runtime_use_autosuspend(&pdev->dev);
+	}
+
 	if (motg->pdata->bus_scale_table) {
 		motg->bus_perf_client =
 		    msm_bus_scale_register_client(motg->pdata->bus_scale_table);
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 9f30041..7a92645 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -3022,8 +3022,6 @@
 	hdmi_msm_state->hdcp_activating = TRUE;
 	mutex_unlock(&hdmi_msm_state_mutex);
 
-	fill_black_screen();
-
 	mutex_lock(&hdcp_auth_state_mutex);
 	/*
 	 * Initialize this to zero here to make
@@ -3065,8 +3063,6 @@
 	if (ret)
 		goto error;
 
-	unfill_black_screen();
-
 	mutex_lock(&hdmi_msm_state_mutex);
 	hdmi_msm_state->hdcp_activating = FALSE;
 	mutex_unlock(&hdmi_msm_state_mutex);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 985d0b0..0c526fd 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -1452,6 +1452,11 @@
 					      vsync_period);
 	if (diff_to_next > vsync_period)
 		return;
+	pr_debug("%s cur_time %d, pre_vsync %d, to_next %d\n",
+		 __func__,
+		 (int)ktime_to_ms(cur_time),
+		 (int)ktime_to_ms(pre_vsync),
+		 diff_to_next);
 	wakeup_time = ktime_add_ns(cur_time, diff_to_next * NSEC_PER_MSEC);
 	activate_event_timer(mfd->cpu_pm_hdl, wakeup_time);
 }
@@ -3114,7 +3119,7 @@
 {
 	mdp_suspend_sub();
 #ifdef CONFIG_FB_MSM_DTV
-	mdp4_dtv_set_black_screen();
+	mdp4_dtv_set_black_screen(FALSE);
 #endif
 	mdp_footswitch_ctrl(FALSE);
 }
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 3ea196a..d9da6f9 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -531,7 +531,7 @@
 }
 #endif /* CONFIG_FB_MSM_DTV */
 
-void mdp4_dtv_set_black_screen(void);
+void mdp4_dtv_set_black_screen(bool commit);
 
 int mdp4_overlay_dtv_set(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index c76e32f..11952f3 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -416,53 +416,34 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
-#ifdef CONFIG_FB_MSM_HDMI_3D
-void unfill_black_screen(void) { return; }
-#else
-void unfill_black_screen(void)
+void fill_black_screen(bool on, uint8 pipe_num, uint8 mixer_num)
 {
-	uint32 temp_src_format;
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	/*
-	* VG2 Constant Color
-	*/
-	temp_src_format = inpdw(MDP_BASE + 0x30050);
-	MDP_OUTP(MDP_BASE + 0x30050, temp_src_format&(~BIT(22)));
-	/*
-	* MDP_OVERLAY_REG_FLUSH
-	*/
-	MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	return;
-}
-#endif
+	uint32 reg_base        = 0x010000;
+	uint32 const_color_reg = reg_base * (pipe_num + 2) + 0x1008;
+	uint32 src_fmt_reg     = reg_base * (pipe_num + 2) + 0x50;
+	uint32 color           = 0x00000000;
+	uint32 temp_src_format = 0x00000000;
+	uint8  bit             = pipe_num + 2;
 
-#ifdef CONFIG_FB_MSM_HDMI_3D
-void fill_black_screen(void) { return; }
-#else
-void fill_black_screen(void)
-{
-	/*Black color*/
-	uint32 color = 0x00000000;
-	uint32 temp_src_format;
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	/*
-	* VG2 Constant Color
-	*/
-	MDP_OUTP(MDP_BASE + 0x31008, color);
-	/*
-	* MDP_VG2_SRC_FORMAT
-	*/
-	temp_src_format = inpdw(MDP_BASE + 0x30050);
-	MDP_OUTP(MDP_BASE + 0x30050, temp_src_format | BIT(22));
-	/*
-	* MDP_OVERLAY_REG_FLUSH
-	*/
-	MDP_OUTP(MDP_BASE + 0x18000, BIT(3));
+
+	/* Fill constant color */
+	MDP_OUTP(MDP_BASE + const_color_reg, color);
+
+	/* Update source format for pipe */
+	temp_src_format = inpdw(MDP_BASE + src_fmt_reg);
+
+	if (on)
+		MDP_OUTP(MDP_BASE + src_fmt_reg, temp_src_format | BIT(22));
+	else
+		MDP_OUTP(MDP_BASE + src_fmt_reg, temp_src_format | (~BIT(22)));
+
+	/* MDP_OVERLAY_REG_FLUSH for pipe*/
+	MDP_OUTP(MDP_BASE + 0x18000, BIT(bit) | BIT(mixer_num));
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
 	return;
 }
-#endif
 
 void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe)
 {
@@ -3132,6 +3113,9 @@
 								__func__);
 	}
 
+	if (hdmi_prim_display)
+		fill_black_screen(FALSE, pipe->pipe_num, pipe->mixer_num);
+
 	mdp4_overlay_mdp_pipe_req(pipe, mfd);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
@@ -3204,8 +3188,12 @@
 	if (pipe->mixer_num == MDP4_MIXER0) {
 
 	} else {	/* mixer1, DTV, ATV */
-		if (ctrl->panel_mode & MDP4_PANEL_DTV)
+		if (ctrl->panel_mode & MDP4_PANEL_DTV) {
+			if (hdmi_prim_display)
+				fill_black_screen(TRUE, pipe->pipe_num,
+					pipe->mixer_num);
 			mdp4_overlay_dtv_unset(mfd, pipe);
+		}
 	}
 
 	mdp4_stat.overlay_unset[pipe->mixer_num]++;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 3ae05c1..0015403 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -70,6 +70,7 @@
 	struct vsync_update vlist[2];
 	int vsync_enabled;
 	int clk_enabled;
+	int new_update;
 	int clk_control;
 	ktime_t vsync_time;
 	struct work_struct clk_work;
@@ -272,6 +273,8 @@
 	pipe = vctrl->base_pipe;
 	mixer = pipe->mixer_num;
 
+	mdp_update_pm(vctrl->mfd, vctrl->vsync_time);
+
 	if (vp->update_cnt == 0) {
 		mutex_unlock(&vctrl->update_lock);
 		return cnt;
@@ -421,6 +424,7 @@
 			mipi_dsi_clk_cfg(1);
 			mdp_clk_ctrl(1);
 			vctrl->clk_enabled = 1;
+			vctrl->new_update = 1;
 			clk_set_on = 1;
 		}
 		if (clk_set_on) {
@@ -517,6 +521,12 @@
 	spin_lock(&vctrl->spin_lock);
 	vctrl->vsync_time = ktime_get();
 
+	if (vctrl->new_update) {
+		vctrl->new_update = 0;
+		spin_unlock(&vctrl->spin_lock);
+		return;
+	}
+
 	complete_all(&vctrl->vsync_comp);
 	vctrl->wait_vsync_cnt = 0;
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 5551c9d..501c4e6 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -56,6 +56,7 @@
 	int wait_vsync_cnt;
 	int blt_change;
 	int blt_free;
+	int blt_ctrl;
 	int sysfs_created;
 	struct mutex update_lock;
 	struct completion ov_comp;
@@ -498,9 +499,11 @@
 	int ret = 0;
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
+	struct msm_panel_info *pinfo;
 
 	vctrl = &vsync_ctrl_db[cndx];
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+	pinfo = &mfd->panel_info;
 
 	if (!mfd)
 		return -ENODEV;
@@ -510,6 +513,7 @@
 
 	vctrl->mfd = mfd;
 	vctrl->dev = mfd->fbi->dev;
+	vctrl->blt_ctrl = pinfo->lcd.blt_ctrl;
 
 	/* mdp clock on */
 	mdp_clk_ctrl(1);
@@ -1011,6 +1015,7 @@
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	long long vtime;
 
 	vctrl = &vsync_ctrl_db[cndx];
 	pipe = vctrl->base_pipe;
@@ -1047,8 +1052,32 @@
 		spin_unlock_irqrestore(&vctrl->spin_lock, flag);
 		return;
 	}
-
 	spin_unlock_irqrestore(&vctrl->spin_lock, flag);
+
+	if (vctrl->blt_ctrl == BLT_SWITCH_TG_OFF) {
+		int tg_enabled;
+
+		vctrl->blt_change = 0;
+		tg_enabled = inpdw(MDP_BASE + DSI_VIDEO_BASE) & 0x01;
+		if (tg_enabled) {
+			mdp4_dsi_video_wait4vsync(0, &vtime);
+			MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
+			mdp4_dsi_video_wait4dmap_done(0);
+		}
+		mdp4_overlayproc_cfg(pipe);
+		mdp4_overlay_dmap_xy(pipe);
+		if (tg_enabled) {
+			/*
+			* need wait for more than 1 ms to
+			* make sure dsi lanes' fifo is empty and
+			* lanes in stop state befroe reset
+			* controller
+			*/
+			usleep(2000);
+			mipi_dsi_sw_reset();
+			MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1);
+		}
+	}
 }
 
 void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index e71f49f..2d48781 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -1004,7 +1004,7 @@
 	spin_unlock(&vctrl->spin_lock);
 }
 
-void mdp4_dtv_set_black_screen(void)
+void mdp4_dtv_set_black_screen(bool commit)
 {
 	char *rgb_base;
 	/*Black color*/
@@ -1015,26 +1015,34 @@
 
 	vctrl = &vsync_ctrl_db[cndx];
 	if (vctrl->base_pipe == NULL || !hdmi_prim_display) {
-		pr_err("dtv_pipe is not configured yet\n");
+		pr_debug("dtv_pipe is not configured yet\n");
 		return;
 	}
-	rgb_base = MDP_BASE + MDP4_RGB_BASE;
-	rgb_base += (MDP4_RGB_OFF * vctrl->base_pipe->pipe_num);
+	rgb_base = MDP_BASE;
+	rgb_base += (MDP4_RGB_OFF * (vctrl->base_pipe->pipe_num + 2));
 
-	/*
-	* RGB Constant Color
-	*/
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	/* RGB Constant Color */
 	MDP_OUTP(rgb_base + 0x1008, color);
-	/*
-	* MDP_RGB_SRC_FORMAT
-	*/
+
+	/* MDP_RGB_SRC_FORMAT */
 	temp_src_format = inpdw(rgb_base + 0x0050);
 	MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
-	mdp4_overlay_reg_flush(vctrl->base_pipe, 1);
 
-	mdp4_mixer_stage_up(vctrl->base_pipe, 0);
-	mdp4_mixer_stage_commit(vctrl->base_pipe->mixer_num);
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	if (commit) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+		mdp4_overlay_reg_flush(vctrl->base_pipe, 1);
+
+		mdp4_mixer_stage_up(vctrl->base_pipe, 0);
+		mdp4_mixer_stage_commit(vctrl->base_pipe->mixer_num);
+	} else {
+		/* MDP_OVERLAY_REG_FLUSH for pipe*/
+		MDP_OUTP(MDP_BASE + 0x18000,
+			BIT(vctrl->base_pipe->pipe_num + 2) | BIT(MDP4_MIXER1));
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
 }
 
 static void mdp4_dtv_do_blt(struct msm_fb_data_type *mfd, int enable)
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index a8f853d..d932bc9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -58,6 +58,7 @@
 
 static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
+static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
 
 struct mdss_hw hdmi_tx_hw = {
 	.hw_ndx = MDSS_HW_HDMI,
@@ -1082,6 +1083,8 @@
 	} else {
 		msm_dss_enable_clk(power_data->clk_config,
 			power_data->num_clk, 0);
+		msm_dss_clk_set_rate(power_data->clk_config,
+			power_data->num_clk);
 		msm_dss_enable_gpio(power_data->gpio_config,
 			power_data->num_gpio, 0);
 		msm_dss_enable_vreg(power_data->vreg_config,
@@ -1616,6 +1619,7 @@
 	bool polarity)
 {
 	struct dss_io_data *io = NULL;
+	u32 cable_sense;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -1632,7 +1636,12 @@
 	else
 		DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(2));
 
-	if ((DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) == polarity) {
+	cable_sense = (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
+	DEV_DBG("%s: listen = %s, sense = %s\n", __func__,
+		polarity ? "connect" : "disconnect",
+		cable_sense ? "connect" : "disconnect");
+
+	if (cable_sense == polarity) {
 		u32 reg_val = DSS_REG_R(io, HDMI_HPD_CTRL);
 
 		/* Toggle HPD circuit to trigger HPD sense */
@@ -1667,13 +1676,25 @@
 	}
 
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
+
+	/*
+	 * this is needed to avoid pll lock failure due to
+	 * clk framework's rate caching.
+	 */
+	hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate = 0;
+
 	hdmi_tx_core_off(hdmi_ctrl);
 
 	mutex_lock(&hdmi_ctrl->mutex);
 	hdmi_ctrl->panel_power_on = false;
 	mutex_unlock(&hdmi_ctrl->mutex);
 
-	hdmi_tx_hpd_polarity_setup(hdmi_ctrl, HPD_CONNECT_POLARITY);
+	if (hdmi_ctrl->hpd_off_pending) {
+		hdmi_tx_hpd_off(hdmi_ctrl);
+		hdmi_ctrl->hpd_off_pending = false;
+	} else {
+		hdmi_tx_hpd_polarity_setup(hdmi_ctrl, HPD_CONNECT_POLARITY);
+	}
 
 	DEV_INFO("%s: HDMI Core: OFF\n", __func__);
 } /* hdmi_tx_power_off_work */
@@ -1860,10 +1881,20 @@
 	if (on) {
 		rc = hdmi_tx_hpd_on(hdmi_ctrl);
 	} else {
-		hdmi_tx_hpd_off(hdmi_ctrl);
-		switch_set_state(&hdmi_ctrl->sdev, 0);
-		DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
-			hdmi_ctrl->sdev.state);
+		/* If power down is already underway, wait for it to finish */
+		flush_work_sync(&hdmi_ctrl->power_off_work);
+
+		if (!hdmi_ctrl->panel_power_on) {
+			hdmi_tx_hpd_off(hdmi_ctrl);
+		} else {
+			hdmi_ctrl->hpd_off_pending = true;
+
+			switch_set_state(&hdmi_ctrl->sdev, 0);
+			DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
+				hdmi_ctrl->sdev.state);
+			DEV_DBG("HDMI HPD: sent fake OFFLINE event\n");
+			kobject_uevent(hdmi_ctrl->kobj, KOBJ_OFFLINE);
+		}
 	}
 
 	return rc;
@@ -1954,6 +1985,8 @@
 	init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
 
 	hdmi_ctrl->hpd_state = false;
+	hdmi_ctrl->hpd_initialized = false;
+	hdmi_ctrl->hpd_off_pending = false;
 	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
 
 	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 3e9fd3c..ce19355 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -54,6 +54,7 @@
 
 	u32 hpd_initialized;
 	u32 hpd_state;
+	u32 hpd_off_pending;
 	u32 hpd_feature_on;
 	struct work_struct hpd_int_work;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 3db13f5..b5f6ddf 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -474,15 +474,25 @@
 	if (ctl->intf_num == MDSS_MDP_NO_INTF) {
 		ctl->dst_format = mfd->panel_info.out_format;
 	} else {
+		struct mdp_dither_cfg_data dither = {
+			.block = mfd->index + MDP_LOGICAL_BLOCK_DISP_0,
+			.flags = MDP_PP_OPS_DISABLE,
+		};
+
 		switch (mfd->panel_info.bpp) {
 		case 18:
 			ctl->dst_format = MDSS_MDP_PANEL_FORMAT_RGB666;
+			dither.flags = MDP_PP_OPS_ENABLE | MDP_PP_OPS_WRITE;
+			dither.g_y_depth = 2;
+			dither.r_cr_depth = 2;
+			dither.b_cb_depth = 2;
 			break;
 		case 24:
 		default:
 			ctl->dst_format = MDSS_MDP_PANEL_FORMAT_RGB888;
 			break;
 		}
+		mdss_mdp_dither_config(&dither, NULL);
 	}
 
 	if (ctl->mixer_right) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 3e5df2c..e4621d4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -355,6 +355,9 @@
 {
 	int ret;
 
+	if (!mfd->panel_power_on)
+		return -EPERM;
+
 	if (req->flags & MDSS_MDP_ROT_ONLY) {
 		ret = mdss_mdp_overlay_rotator_setup(mfd, req);
 	} else {
@@ -482,6 +485,9 @@
 		return ret;
 	}
 
+	if (!mfd->ctl->power_on)
+		return 0;
+
 	for (i = 0; unset_ndx != ndx && i < MDSS_MDP_MAX_SSPP; i++) {
 		pipe_ndx = BIT(i);
 		if (pipe_ndx & ndx) {
@@ -631,6 +637,9 @@
 
 	pr_debug("play req id=%x\n", req->id);
 
+	if (!mfd->panel_power_on)
+		return -EPERM;
+
 	if (req->id & MDSS_MDP_ROT_SESSION_MASK)
 		ret = mdss_mdp_overlay_rotate(mfd, req);
 	else
@@ -974,7 +983,7 @@
 		}
 
 		if (ret) {
-			pr_err("OVERLAY_GET failed (%d)\n", ret);
+			pr_debug("OVERLAY_GET failed (%d)\n", ret);
 			ret = -EFAULT;
 		}
 		break;
@@ -988,7 +997,7 @@
 				ret = copy_to_user(argp, &req, sizeof(req));
 		}
 		if (ret) {
-			pr_err("OVERLAY_SET failed (%d)\n", ret);
+			pr_debug("OVERLAY_SET failed (%d)\n", ret);
 			ret = -EFAULT;
 		}
 		break;
@@ -1020,7 +1029,7 @@
 			}
 
 			if (ret) {
-				pr_err("OVERLAY_PLAY failed (%d)\n", ret);
+				pr_debug("OVERLAY_PLAY failed (%d)\n", ret);
 				ret = -EFAULT;
 			}
 		} else {
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 527b02f..5189b6d 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -653,12 +653,6 @@
 	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
-	if (hdmi_prim_display) {
-		MSM_FB_INFO("%s: hdmi primary handles early suspend only\n",
-			__func__);
-		return 0;
-	}
-
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
@@ -684,12 +678,6 @@
 	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
-	if (hdmi_prim_display) {
-		MSM_FB_INFO("%s: hdmi primary handles early resume only\n",
-			__func__);
-		return 0;
-	}
-
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
@@ -714,8 +702,7 @@
 	.runtime_suspend = msm_fb_runtime_suspend,
 	.runtime_resume = msm_fb_runtime_resume,
 	.runtime_idle = msm_fb_runtime_idle,
-#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL) && \
-	!defined(CONFIG_FB_MSM_HDMI_AS_PRIMARY))
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
 	.suspend = msm_fb_ext_suspend,
 	.resume = msm_fb_ext_resume,
 #endif
@@ -749,9 +736,7 @@
 static void msmfb_early_suspend(struct early_suspend *h)
 {
 	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						early_suspend);
-	struct msm_fb_panel_data *pdata = NULL;
-
+						    early_suspend);
 #if defined(CONFIG_FB_MSM_MDP303)
 	/*
 	* For MDP with overlay, set framebuffer with black pixels
@@ -769,37 +754,12 @@
 	}
 #endif
 	msm_fb_suspend_sub(mfd);
-
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-	if (hdmi_prim_display &&
-		(mfd->panel_info.type == HDMI_PANEL ||
-		 mfd->panel_info.type == DTV_PANEL)) {
-		/* Turn off the HPD circuitry */
-		if (pdata->power_ctrl) {
-			MSM_FB_INFO("%s: Turning off HPD circuitry\n",
-				__func__);
-			pdata->power_ctrl(FALSE);
-		}
-	}
 }
 
 static void msmfb_early_resume(struct early_suspend *h)
 {
 	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						early_suspend);
-	struct msm_fb_panel_data *pdata = NULL;
-
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-	if (hdmi_prim_display &&
-		(mfd->panel_info.type == HDMI_PANEL ||
-		 mfd->panel_info.type == DTV_PANEL)) {
-		/* Turn on the HPD circuitry */
-		if (pdata->power_ctrl) {
-			MSM_FB_INFO("%s: Turning on HPD circuitry\n", __func__);
-			pdata->power_ctrl(TRUE);
-		}
-	}
-
+						    early_suspend);
 	msm_fb_resume_sub(mfd);
 }
 #endif
@@ -1510,10 +1470,7 @@
 	ret = 0;
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
-
-	if (hdmi_prim_display ||
-	    (mfd->panel_info.type != DTV_PANEL &&
-	     mfd->panel_info.type != WRITEBACK_PANEL)) {
+	if (mfd->panel_info.type != DTV_PANEL) {
 		mfd->early_suspend.suspend = msmfb_early_suspend;
 		mfd->early_suspend.resume = msmfb_early_resume;
 		mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 1594825..7d8ad73 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -214,8 +214,7 @@
 void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
 #endif
 
-void fill_black_screen(void);
-void unfill_black_screen(void);
+void fill_black_screen(bool on, uint8 pipe_num, uint8 mixer_num);
 int msm_fb_check_frame_rate(struct msm_fb_data_type *mfd,
 				struct fb_info *info);
 
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
index 7fc7a2f..bdd4f3bb 100644
--- a/drivers/video/msm/msm_fb_panel.h
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -56,6 +56,11 @@
 	MAX_PHYS_TARGET_NUM,
 } DISP_TARGET_PHYS;
 
+enum {
+	BLT_SWITCH_TG_OFF,
+	BLT_SWITCH_TG_ON
+};
+
 /* panel info type */
 struct lcd_panel_info {
 	__u32 vsync_enable;
@@ -65,6 +70,7 @@
 	__u32 v_pulse_width;
 	__u32 hw_vsync_mode;
 	__u32 vsync_notifier_period;
+	__u32 blt_ctrl;
 	__u32 rev;
 };
 
diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h
index f1c7f4e..7ffae9d 100644
--- a/include/drm/kgsl_drm.h
+++ b/include/drm/kgsl_drm.h
@@ -19,6 +19,7 @@
 #define DRM_KGSL_GEM_UNLOCK_HANDLE 0x0C
 #define DRM_KGSL_GEM_UNLOCK_ON_TS 0x0D
 #define DRM_KGSL_GEM_CREATE_FD 0x0E
+#define DRM_KGSL_GEM_GET_ION_FD 0x0F
 
 #define DRM_IOCTL_KGSL_GEM_CREATE \
 DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE, struct drm_kgsl_gem_create)
@@ -75,6 +76,10 @@
 DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FD, \
 struct drm_kgsl_gem_create_fd)
 
+#define DRM_IOCTL_KGSL_GEM_GET_ION_FD \
+DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_ION_FD, \
+struct drm_kgsl_gem_get_ion_fd)
+
 /* Maximum number of sub buffers per GEM object */
 #define DRM_KGSL_GEM_MAX_BUFFERS 2
 
@@ -189,4 +194,9 @@
 	uint32_t handle;
 };
 
+struct drm_kgsl_gem_get_ion_fd {
+	uint32_t ion_fd;
+	uint32_t handle;
+};
+
 #endif
diff --git a/include/linux/mfd/pm8xxx/pm8038.h b/include/linux/mfd/pm8xxx/pm8038.h
index 574dab6..9e25b5c 100644
--- a/include/linux/mfd/pm8xxx/pm8038.h
+++ b/include/linux/mfd/pm8xxx/pm8038.h
@@ -83,6 +83,7 @@
 	struct pm8921_bms_platform_data		*bms_pdata;
 	struct pm8xxx_adc_platform_data		*adc_pdata;
 	struct pm8xxx_led_platform_data		*leds_pdata;
+	struct pm8xxx_vibrator_platform_data	*vibrator_pdata;
 	struct pm8xxx_ccadc_platform_data	*ccadc_pdata;
 	struct pm8xxx_spk_platform_data		*spk_pdata;
 };
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index d229ad3..1717cd9 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -11,7 +11,7 @@
 #include <linux/of.h>
 
 /*
- * irq_of_parse_and_map() is used ba all OF enabled platforms; but SPARC
+ * irq_of_parse_and_map() is used by all OF enabled platforms; but SPARC
  * implements it differently.  However, the prototype is the same for all,
  * so declare it here regardless of the CONFIG_OF_IRQ setting.
  */
@@ -76,5 +76,13 @@
 extern void of_irq_init(const struct of_device_id *matches);
 
 #endif /* CONFIG_OF_IRQ */
-#endif /* CONFIG_OF */
+
+#else /* !CONFIG_OF */
+static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
+						int index)
+{
+	return 0;
+}
+#endif /* !CONFIG_OF */
+
 #endif /* __OF_IRQ_H */
diff --git a/include/linux/qmi_encdec.h b/include/linux/qmi_encdec.h
new file mode 100644
index 0000000..4c5f6d3
--- /dev/null
+++ b/include/linux/qmi_encdec.h
@@ -0,0 +1,169 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _QMI_ENCDEC_H_
+#define _QMI_ENCDEC_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+
+#define QMI_REQUEST_CONTROL_FLAG 0x00
+#define QMI_RESPONSE_CONTROL_FLAG 0x02
+#define QMI_INDICATION_CONTROL_FLAG 0x04
+#define QMI_HEADER_SIZE 7
+
+/**
+ * elem_type - Enum to identify the data type of elements in a data
+ *             structure.
+ */
+enum elem_type {
+	QMI_OPT_FLAG = 1,
+	QMI_DATA_LEN,
+	QMI_UNSIGNED_1_BYTE,
+	QMI_UNSIGNED_2_BYTE,
+	QMI_UNSIGNED_4_BYTE,
+	QMI_UNSIGNED_8_BYTE,
+	QMI_SIGNED_2_BYTE_ENUM,
+	QMI_SIGNED_4_BYTE_ENUM,
+	QMI_STRUCT,
+	QMI_EOTI,
+};
+
+/**
+ * array_type - Enum to identify if an element in a data structure is
+ *              an array. If so, then is it a static length array or a
+ *              variable length array.
+ */
+enum array_type {
+	NO_ARRAY = 0,
+	STATIC_ARRAY = 1,
+	VAR_LEN_ARRAY = 2,
+};
+
+/**
+ * elem_info - Data structure to specify information about an element
+ *               in a data structure. An array of this data structure
+ *               can be used to specify info about a complex data
+ *               structure to be encoded/decoded.
+ *
+ * @data_type: Data type of this element.
+ * @elem_len: Array length of this element, if an array.
+ * @elem_size: Size of a single instance of this data type.
+ * @is_array: Array type of this element.
+ * @tlv_type: QMI message specific type to identify which element
+ *            is present in an incoming message.
+ * @offset: To identify the address of the first instance of this
+ *          element in the data structure.
+ * @ei_array: Array to provide information about the nested structure
+ *            within a data structure to be encoded/decoded.
+ */
+struct elem_info {
+	enum elem_type data_type;
+	uint32_t elem_len;
+	uint32_t elem_size;
+	enum array_type is_array;
+	uint8_t tlv_type;
+	uint32_t offset;
+	struct elem_info *ei_array;
+};
+
+/**
+ * @msg_desc - Describe about the main/outer structure to be
+ *		  encoded/decoded.
+ *
+ * @max_msg_len: Maximum possible length of the QMI message.
+ * @ei_array: Array to provide information about a data structure.
+ */
+struct msg_desc {
+	uint16_t msg_id;
+	int max_msg_len;
+	struct elem_info *ei_array;
+};
+
+struct qmi_header {
+	unsigned char cntl_flag;
+	uint16_t txn_id;
+	uint16_t msg_id;
+	uint16_t msg_len;
+} __attribute__((__packed__));
+
+static inline void encode_qmi_header(unsigned char *buf,
+			unsigned char cntl_flag, uint16_t txn_id,
+			uint16_t msg_id, uint16_t msg_len)
+{
+	struct qmi_header *hdr = (struct qmi_header *)buf;
+
+	hdr->cntl_flag = cntl_flag;
+	hdr->txn_id = txn_id;
+	hdr->msg_id = msg_id;
+	hdr->msg_len = msg_len;
+}
+
+static inline void decode_qmi_header(unsigned char *buf,
+			unsigned char *cntl_flag, uint16_t *txn_id,
+			uint16_t *msg_id, uint16_t *msg_len)
+{
+	struct qmi_header *hdr = (struct qmi_header *)buf;
+
+	*cntl_flag = hdr->cntl_flag;
+	*txn_id = hdr->txn_id;
+	*msg_id = hdr->msg_id;
+	*msg_len = hdr->msg_len;
+}
+
+#ifdef CONFIG_QMI_ENCDEC
+/**
+ * qmi_kernel_encode() - Encode to QMI message wire format
+ * @desc: Pointer to structure descriptor.
+ * @out_buf: Buffer to hold the encoded QMI message.
+ * @out_buf_len: Length of the out buffer.
+ * @in_c_struct: C Structure to be encoded.
+ *
+ * @return: size of encoded message on success, < 0 on error.
+ */
+int qmi_kernel_encode(struct msg_desc *desc,
+		      void *out_buf, uint32_t out_buf_len,
+		      void *in_c_struct);
+
+/**
+ * qmi_kernel_decode() - Decode to C Structure format
+ * @desc: Pointer to structure descriptor.
+ * @out_c_struct: Buffer to hold the decoded C structure.
+ * @in_buf: Buffer containg the QMI message to be decoded.
+ * @in_buf_len: Length of the incoming QMI message.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_kernel_decode(struct msg_desc *desc, void *out_c_struct,
+		      void *in_buf, uint32_t in_buf_len);
+
+#else
+static inline int qmi_kernel_encode(struct msg_desc *desc,
+				    void *out_buf, uint32_t out_buf_len,
+				    void *in_c_struct)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int qmi_kernel_decode(struct msg_desc *desc,
+				    void *out_c_struct,
+				    void *in_buf, uint32_t in_buf_len)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
+#endif
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index e5516ab..9d5de90 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -137,7 +137,7 @@
 };
 
 #define QPNP_ADC_625_UV	625000
-#define QPNP_ADC_HWMON_NAME_LENGTH				16
+#define QPNP_ADC_HWMON_NAME_LENGTH				64
 
 /**
  * enum qpnp_adc_decimation_type - Sampling rate supported.
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1f13da3..0a1428e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2041,6 +2041,7 @@
 extern unsigned int sysctl_sched_min_granularity;
 extern unsigned int sysctl_sched_wakeup_granularity;
 extern unsigned int sysctl_sched_child_runs_first;
+extern unsigned int sysctl_sched_wake_to_idle;
 
 enum sched_tunable_scaling {
 	SCHED_TUNABLESCALING_NONE,
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index a998ac2..578b9f9 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -199,6 +199,8 @@
  *              is connected.
  * @core_clk_always_on_workaround: Don't disable core_clk when
  *              USB enters LPM.
+ * @delay_lpm_on_disconnect: Use a delay before entering LPM
+ *              upon USB cable disconnection.
  * @bus_scale_table: parameters for bus bandwidth requirements
  * @mhl_dev_name: MHL device name used to register with MHL driver.
  */
@@ -218,6 +220,7 @@
 	bool pnoc_errata_fix;
 	bool enable_lpm_on_dev_suspend;
 	bool core_clk_always_on_workaround;
+	bool delay_lpm_on_disconnect;
 	struct msm_bus_scale_pdata *bus_scale_table;
 	const char *mhl_dev_name;
 };
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 13b3f05..84d9b42 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -120,8 +120,14 @@
 	VP_OUT_TYPE,
 };
 
+enum vcap_stride {
+	VC_STRIDE_16,
+	VC_STRIDE_32,
+};
+
 struct vcap_priv_fmt {
 	enum vcap_type type;
+	enum vcap_stride stride;
 	union {
 		struct v4l2_format_vc_ext timing;
 		struct v4l2_pix_format pix;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 2d3b5c5..39aa1b9 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -39,10 +39,10 @@
 
 #define VCAP_USEC (1000000)
 
-#define VCAP_STRIDE_ALIGN 0x10
-#define VCAP_STRIDE_CALC(x) (((x / VCAP_STRIDE_ALIGN) + \
-			(!(!(x % VCAP_STRIDE_ALIGN)))) * \
-			VCAP_STRIDE_ALIGN)
+#define VCAP_STRIDE_ALIGN_16 0x10
+#define VCAP_STRIDE_ALIGN_32 0x20
+#define VCAP_STRIDE_CALC(x, align) (((x / align) + \
+			(!(!(x % align)))) * align)
 
 #define VCAP_BASE (dev->vcapbase)
 #define VCAP_OFFSET(off) (VCAP_BASE + off)
@@ -241,6 +241,7 @@
 	enum vcap_op_mode		op_mode;
 
 	struct v4l2_format_vc_ext vc_format;
+	enum vcap_stride		stride;
 
 	enum v4l2_buf_type		vp_buf_type_field;
 	struct vp_format_data	vp_in_fmt;
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 23c1d51..bfd7208 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -157,6 +157,55 @@
 	u16 reserved;
 } __attribute__ ((packed));
 
+/*
+ * Opcode for AFE to start DTMF.
+ */
+#define AFE_PORTS_CMD_DTMF_CTL	0x00010102
+
+/** DTMF payload.*/
+struct afe_dtmf_generation_command {
+	struct apr_hdr hdr;
+
+	/*
+	 * Duration of the DTMF tone in ms.
+	 * -1      -> continuous,
+	 *  0      -> disable
+	 */
+	int64_t                   duration_in_ms;
+
+	/*
+	 * The DTMF high tone frequency.
+	 */
+	uint16_t                  high_freq;
+
+	/*
+	 * The DTMF low tone frequency.
+	 */
+	uint16_t                  low_freq;
+
+	/*
+	 * The DTMF volume setting
+	 */
+	uint16_t                  gain;
+
+	/*
+	 * The number of ports to enable/disable on.
+	 */
+	uint16_t                  num_ports;
+
+	/*
+	 * The Destination ports - array  .
+	 * For DTMF on multiple ports, portIds needs to
+	 * be populated numPorts times.
+	 */
+	uint16_t                  port_ids;
+
+	/*
+	 * variable for 32 bit alignment of APR packet.
+	 */
+	uint16_t                  reserved;
+} __packed;
+
 #define AFE_PCM_CFG_MODE_PCM			0x0
 #define AFE_PCM_CFG_MODE_AUX			0x1
 #define AFE_PCM_CFG_SYNC_EXT			0x0
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index 8451ac6..1e12d48 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -88,7 +88,10 @@
 int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_unmap(u32 dma_addr_p);
 int afe_cmd_memory_unmap_nowait(u32 dma_addr_p);
-
+void afe_set_dtmf_gen_rx_portid(u16 rx_port_id, int set);
+int afe_dtmf_generate_rx(int64_t duration_in_ms,
+			 uint16_t high_freq,
+			 uint16_t low_freq, uint16_t gain);
 int afe_register_get_events(u16 port_id,
 		void (*cb) (uint32_t opcode,
 		uint32_t token, uint32_t *payload, void *priv),
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 9885a9e..b175073 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -77,6 +77,14 @@
 unsigned int sysctl_sched_child_runs_first __read_mostly;
 
 /*
+ * Controls whether, when SD_SHARE_PKG_RESOURCES is on, if all
+ * tasks go to idle CPUs when woken. If this is off, note that the
+ * per-task flag PF_WAKE_ON_IDLE can still cause a task to go to an
+ * idle CPU upon being woken.
+ */
+unsigned int __read_mostly sysctl_sched_wake_to_idle;
+
+/*
  * SCHED_OTHER wake-up granularity.
  * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
  *
@@ -2654,7 +2662,8 @@
 	if (target == prev_cpu && idle_cpu(prev_cpu))
 		return prev_cpu;
 
-	if (!(current->flags & PF_WAKE_UP_IDLE) &&
+	if (!sysctl_sched_wake_to_idle &&
+	    !(current->flags & PF_WAKE_UP_IDLE) &&
 	    !(p->flags & PF_WAKE_UP_IDLE))
 		return target;
 
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b693142..b390dad 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -264,6 +264,13 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
+	{
+		.procname	= "sched_wake_to_idle",
+		.data		= &sysctl_sched_wake_to_idle,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
 #ifdef CONFIG_SCHED_DEBUG
 	{
 		.procname	= "sched_min_granularity_ns",
diff --git a/lib/Kconfig b/lib/Kconfig
index 4a8aba2..f1621d5 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -378,4 +378,13 @@
 	  Digital signature verification. Currently only RSA is supported.
 	  Implementation is done using GnuPG MPI library
 
+config QMI_ENCDEC
+	bool
+	help
+	  Library to encode & decode QMI messages from within
+	  the kernel. The kernel drivers encode the C structure into
+	  QMI message wire format and then send it over a transport.
+	  The kernel drivers receive the QMI message over a transport
+	  and then decode it into a C structure.
+
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index acd6869..0fbcb04 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -123,6 +123,8 @@
 
 obj-$(CONFIG_CLZ_TAB) += clz_tab.o
 
+obj-$(CONFIG_QMI_ENCDEC) += qmi_encdec.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/qmi_encdec.c b/lib/qmi_encdec.c
new file mode 100644
index 0000000..d759885
--- /dev/null
+++ b/lib/qmi_encdec.c
@@ -0,0 +1,492 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/qmi_encdec.h>
+
+#include "qmi_encdec_priv.h"
+
+#define TLV_LEN_SIZE sizeof(uint16_t)
+#define TLV_TYPE_SIZE sizeof(uint8_t)
+
+static int _qmi_kernel_encode(struct elem_info *ei_array,
+			      void *out_buf, void *in_c_struct,
+			      int enc_level);
+
+static int _qmi_kernel_decode(struct elem_info *ei_array,
+			      void *out_c_struct,
+			      void *in_buf, uint32_t in_buf_len,
+			      int dec_level);
+
+/**
+ * qmi_kernel_encode() - Encode to QMI message wire format
+ * @desc: Pointer to structure descriptor.
+ * @out_buf: Buffer to hold the encoded QMI message.
+ * @out_buf_len: Length of the out buffer.
+ * @in_c_struct: C Structure to be encoded.
+ *
+ * @return: size of encoded message on success, < 0 for error.
+ */
+int qmi_kernel_encode(struct msg_desc *desc,
+		      void *out_buf, uint32_t out_buf_len,
+		      void *in_c_struct)
+{
+	int enc_level = 1;
+
+	if (!desc || !desc->ei_array)
+		return -EINVAL;
+
+	if (!out_buf || !in_c_struct)
+		return -EINVAL;
+
+	if (desc->max_msg_len < out_buf_len)
+		return -ETOOSMALL;
+
+	return _qmi_kernel_encode(desc->ei_array, out_buf,
+				  in_c_struct, enc_level);
+}
+EXPORT_SYMBOL(qmi_kernel_encode);
+
+/**
+ * qmi_encode_basic_elem() - Encodes elements of basic/primary data type
+ * @buf_dst: Buffer to store the encoded information.
+ * @buf_src: Buffer containing the elements to be encoded.
+ * @elem_len: Number of elements, in the buf_src, to be encoded.
+ * @elem_size: Size of a single instance of the element to be encoded.
+ *
+ * @return: number of bytes of encoded information.
+ *
+ * This function encodes the "elem_len" number of data elements, each of
+ * size "elem_size" bytes from the source buffer "buf_src" and stores the
+ * encoded information in the destination buffer "buf_dst". The elements are
+ * of primary data type which include uint8_t - uint64_t or similar. This
+ * function returns the number of bytes of encoded information.
+ */
+static int qmi_encode_basic_elem(void *buf_dst, void *buf_src,
+				 uint32_t elem_len, uint32_t elem_size)
+{
+	uint32_t i, rc = 0;
+
+	for (i = 0; i < elem_len; i++) {
+		QMI_ENCDEC_ENCODE_N_BYTES(buf_dst, buf_src, elem_size);
+		rc += elem_size;
+	}
+
+	return rc;
+}
+
+/**
+ * qmi_encode_struct_elem() - Encodes elements of struct data type
+ * @ei_array: Struct info array descibing the struct element.
+ * @buf_dst: Buffer to store the encoded information.
+ * @buf_src: Buffer containing the elements to be encoded.
+ * @elem_len: Number of elements, in the buf_src, to be encoded.
+ * @enc_level: Depth of the nested structure from the main structure.
+ *
+ * @return: Mumber of bytes of encoded information, on success.
+ *          < 0 on error.
+ *
+ * This function encodes the "elem_len" number of struct elements, each of
+ * size "ei_array->elem_size" bytes from the source buffer "buf_src" and
+ * stores the encoded information in the destination buffer "buf_dst". The
+ * elements are of struct data type which includes any C structure. This
+ * function returns the number of bytes of encoded information.
+ */
+static int qmi_encode_struct_elem(struct elem_info *ei_array,
+				  void *buf_dst, void *buf_src,
+				  uint32_t elem_len, int enc_level)
+{
+	int i, rc, encoded_bytes = 0;
+	struct elem_info *temp_ei = ei_array;
+
+	for (i = 0; i < elem_len; i++) {
+		rc = _qmi_kernel_encode(temp_ei->ei_array,
+					buf_dst, buf_src, enc_level);
+		if (rc < 0) {
+			pr_err("%s: STRUCT Encode failure\n", __func__);
+			return rc;
+		}
+		buf_dst = buf_dst + rc;
+		buf_src = buf_src + temp_ei->elem_size;
+		encoded_bytes += rc;
+	}
+
+	return encoded_bytes;
+}
+
+/**
+ * skip_to_next_elem() - Skip to next element in the structure to be encoded
+ * @ei_array: Struct info describing the element to be skipped.
+ *
+ * @return: Struct info of the next element that can be encoded.
+ *
+ * This function is used while encoding optional elements. If the flag
+ * corresponding to an optional element is not set, then encoding the
+ * optional element can be skipped. This function can be used to perform
+ * that operation.
+ */
+static struct elem_info *skip_to_next_elem(struct elem_info *ei_array)
+{
+	struct elem_info *temp_ei = ei_array;
+	uint8_t tlv_type;
+
+	do {
+		tlv_type = temp_ei->tlv_type;
+		temp_ei = temp_ei + 1;
+	} while (tlv_type == temp_ei->tlv_type);
+
+	return temp_ei;
+}
+
+/**
+ * _qmi_kernel_encode() - Core Encode Function
+ * @ei_array: Struct info array describing the structure to be encoded.
+ * @out_buf: Buffer to hold the encoded QMI message.
+ * @in_c_struct: Pointer to the C structure to be encoded.
+ * @enc_level: Encode level to indicate the depth of the nested structure,
+ *             within the main structure, being encoded.
+ *
+ * @return: Number of bytes of encoded information, on success.
+ *          < 0 on error.
+ */
+static int _qmi_kernel_encode(struct elem_info *ei_array,
+			      void *out_buf, void *in_c_struct,
+			      int enc_level)
+{
+	struct elem_info *temp_ei = ei_array;
+	uint8_t opt_flag_value = 0;
+	uint32_t data_len_value = 0, data_len_sz;
+	uint8_t *buf_dst = (uint8_t *)out_buf;
+	uint8_t *tlv_pointer;
+	uint32_t tlv_len;
+	uint8_t tlv_type;
+	uint32_t encoded_bytes = 0;
+	void *buf_src;
+	int encode_tlv = 0;
+	int rc;
+
+	tlv_pointer = buf_dst;
+	tlv_len = 0;
+	buf_dst = buf_dst + (TLV_LEN_SIZE + TLV_TYPE_SIZE);
+
+	while (temp_ei->data_type != QMI_EOTI) {
+		buf_src = in_c_struct + temp_ei->offset;
+		tlv_type = temp_ei->tlv_type;
+
+		if (temp_ei->is_array == NO_ARRAY) {
+			data_len_value = 1;
+		} else if (temp_ei->is_array == STATIC_ARRAY) {
+			data_len_value = temp_ei->elem_len;
+		} else if (data_len_value <= 0 ||
+			    temp_ei->elem_len < data_len_value) {
+			pr_err("%s: Invalid data length\n", __func__);
+			return -EINVAL;
+		}
+
+		switch (temp_ei->data_type) {
+		case QMI_OPT_FLAG:
+			rc = qmi_encode_basic_elem(&opt_flag_value, buf_src,
+						   1, sizeof(uint8_t));
+			if (opt_flag_value)
+				temp_ei = temp_ei + 1;
+			else
+				temp_ei = skip_to_next_elem(temp_ei);
+			break;
+
+		case QMI_DATA_LEN:
+			memcpy(&data_len_value, buf_src, temp_ei->elem_size);
+			data_len_sz = temp_ei->elem_size == sizeof(uint8_t) ?
+					sizeof(uint8_t) : sizeof(uint16_t);
+			rc = qmi_encode_basic_elem(buf_dst, &data_len_value,
+						   1, data_len_sz);
+			if (data_len_value) {
+				UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
+					encoded_bytes, tlv_len, encode_tlv, rc);
+				encode_tlv = 0;
+			} else {
+				temp_ei = skip_to_next_elem(temp_ei);
+			}
+			break;
+
+		case QMI_UNSIGNED_1_BYTE:
+		case QMI_UNSIGNED_2_BYTE:
+		case QMI_UNSIGNED_4_BYTE:
+		case QMI_UNSIGNED_8_BYTE:
+		case QMI_SIGNED_2_BYTE_ENUM:
+		case QMI_SIGNED_4_BYTE_ENUM:
+			rc = qmi_encode_basic_elem(buf_dst, buf_src,
+				data_len_value, temp_ei->elem_size);
+			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
+				encoded_bytes, tlv_len, encode_tlv, rc);
+			break;
+
+		case QMI_STRUCT:
+			rc = qmi_encode_struct_elem(temp_ei, buf_dst, buf_src,
+				data_len_value, (enc_level + 1));
+			if (rc < 0)
+				return rc;
+			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
+				encoded_bytes, tlv_len, encode_tlv, rc);
+			break;
+
+		default:
+			pr_err("%s: Unrecognized data type\n", __func__);
+			return -EINVAL;
+
+		}
+
+		if (encode_tlv && enc_level == 1) {
+			QMI_ENCDEC_ENCODE_TLV(tlv_type, tlv_len, tlv_pointer);
+			encoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
+			tlv_pointer = buf_dst;
+			tlv_len = 0;
+			buf_dst = buf_dst + TLV_LEN_SIZE + TLV_TYPE_SIZE;
+			encode_tlv = 0;
+		}
+	}
+	return encoded_bytes;
+}
+
+/**
+ * qmi_kernel_decode() - Decode to C Structure format
+ * @desc: Pointer to structure descriptor.
+ * @out_c_struct: Buffer to hold the decoded C structure.
+ * @in_buf: Buffer containg the QMI message to be decoded.
+ * @in_buf_len: Length of the incoming QMI message.
+ *
+ * @return: 0 on success, < 0 on error.
+ */
+int qmi_kernel_decode(struct msg_desc *desc, void *out_c_struct,
+		      void *in_buf, uint32_t in_buf_len)
+{
+	int dec_level = 1;
+	int rc = 0;
+
+	if (!desc || !desc->ei_array)
+		return -EINVAL;
+
+	if (!out_c_struct || !in_buf || !in_buf_len)
+		return -EINVAL;
+
+	if (desc->max_msg_len < in_buf_len)
+		return -EINVAL;
+
+	rc = _qmi_kernel_decode(desc->ei_array, out_c_struct,
+				in_buf, in_buf_len, dec_level);
+	if (rc < 0)
+		return rc;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(qmi_kernel_decode);
+
+/**
+ * qmi_decode_basic_elem() - Decodes elements of basic/primary data type
+ * @buf_dst: Buffer to store the decoded element.
+ * @buf_src: Buffer containing the elements in QMI wire format.
+ * @elem_len: Number of elements to be decoded.
+ * @elem_size: Size of a single instance of the element to be decoded.
+ *
+ * @return: Total size of the decoded data elements, in bytes.
+ *
+ * This function decodes the "elem_len" number of elements in QMI wire format,
+ * each of size "elem_size" bytes from the source buffer "buf_src" and stores
+ * the decoded elements in the destination buffer "buf_dst". The elements are
+ * of primary data type which include uint8_t - uint64_t or similar. This
+ * function returns the number of bytes of decoded information.
+ */
+static int qmi_decode_basic_elem(void *buf_dst, void *buf_src,
+				 uint32_t elem_len, uint32_t elem_size)
+{
+	uint32_t i, rc = 0;
+
+	for (i = 0; i < elem_len; i++) {
+		QMI_ENCDEC_DECODE_N_BYTES(buf_dst, buf_src, elem_size);
+		rc += elem_size;
+	}
+
+	return rc;
+}
+
+/**
+ * qmi_decode_struct_elem() - Decodes elements of struct data type
+ * @ei_array: Struct info array descibing the struct element.
+ * @buf_dst: Buffer to store the decoded element.
+ * @buf_src: Buffer containing the elements in QMI wire format.
+ * @elem_len: Number of elements to be decoded.
+ * @tlv_len: Total size of the encoded inforation corresponding to
+ *           this struct element.
+ * @dec_level: Depth of the nested structure from the main structure.
+ *
+ * @return: Total size of the decoded data elements, on success.
+ *          < 0 on error.
+ *
+ * This function decodes the "elem_len" number of elements in QMI wire format,
+ * each of size "(tlv_len/elem_len)" bytes from the source buffer "buf_src"
+ * and stores the decoded elements in the destination buffer "buf_dst". The
+ * elements are of struct data type which includes any C structure. This
+ * function returns the number of bytes of decoded information.
+ */
+static int qmi_decode_struct_elem(struct elem_info *ei_array, void *buf_dst,
+				  void *buf_src, uint32_t elem_len,
+				  uint32_t tlv_len, int dec_level)
+{
+	int i, rc, decoded_bytes = 0;
+	struct elem_info *temp_ei = ei_array;
+
+	for (i = 0; i < elem_len; i++) {
+		rc = _qmi_kernel_decode(temp_ei->ei_array, buf_dst, buf_src,
+					(tlv_len/elem_len), dec_level);
+		if (rc < 0)
+			return rc;
+		if (rc != (tlv_len/elem_len)) {
+			pr_err("%s: Fault in decoding\n", __func__);
+			return -EFAULT;
+		}
+		buf_src = buf_src + rc;
+		buf_dst = buf_dst + temp_ei->elem_size;
+		decoded_bytes += rc;
+	}
+
+	return decoded_bytes;
+}
+
+/**
+ * find_ei() - Find element info corresponding to TLV Type
+ * @ei_array: Struct info array of the message being decoded.
+ * @type: TLV Type of the element being searched.
+ *
+ * @return: Pointer to struct info, if found
+ *
+ * Every element that got encoded in the QMI message will have a type
+ * information associated with it. While decoding the QMI message,
+ * this function is used to find the struct info regarding the element
+ * that corresponds to the type being decoded.
+ */
+static struct elem_info *find_ei(struct elem_info *ei_array,
+				   uint32_t type)
+{
+	struct elem_info *temp_ei = ei_array;
+	while (temp_ei->data_type != QMI_EOTI) {
+		if (temp_ei->tlv_type == (uint8_t)type)
+			return temp_ei;
+		temp_ei = temp_ei + 1;
+	}
+	return NULL;
+}
+
+/**
+ * _qmi_kernel_decode() - Core Decode Function
+ * @ei_array: Struct info array describing the structure to be decoded.
+ * @out_c_struct: Buffer to hold the decoded C struct
+ * @in_buf: Buffer containing the QMI message to be decoded
+ * @in_buf_len: Length of the QMI message to be decoded
+ * @dec_level: Decode level to indicate the depth of the nested structure,
+ *             within the main structure, being decoded
+ *
+ * @return: Number of bytes of decoded information, on success
+ *          < 0 on error.
+ */
+static int _qmi_kernel_decode(struct elem_info *ei_array,
+			      void *out_c_struct,
+			      void *in_buf, uint32_t in_buf_len,
+			      int dec_level)
+{
+	struct elem_info *temp_ei = ei_array;
+	uint8_t opt_flag_value = 1;
+	uint32_t data_len_value = 0, data_len_sz = 0;
+	uint8_t *buf_dst = out_c_struct;
+	uint8_t *tlv_pointer;
+	uint32_t tlv_len = 0;
+	uint32_t tlv_type;
+	uint32_t decoded_bytes = 0;
+	void *buf_src = in_buf;
+	int rc;
+
+	while (decoded_bytes < in_buf_len) {
+		if (dec_level == 1) {
+			tlv_pointer = buf_src;
+			QMI_ENCDEC_DECODE_TLV(&tlv_type,
+					      &tlv_len, tlv_pointer);
+			buf_src += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
+			decoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
+			temp_ei = find_ei(ei_array, tlv_type);
+			if (!temp_ei) {
+				pr_err("%s: Inval element info\n", __func__);
+				return -EINVAL;
+			}
+		}
+
+		buf_dst = out_c_struct + temp_ei->offset;
+		if (temp_ei->data_type == QMI_OPT_FLAG) {
+			memcpy(buf_dst, &opt_flag_value, sizeof(uint8_t));
+			temp_ei = temp_ei + 1;
+			buf_dst = out_c_struct + temp_ei->offset;
+		}
+
+		if (temp_ei->data_type == QMI_DATA_LEN) {
+			data_len_sz = temp_ei->elem_size == sizeof(uint8_t) ?
+					sizeof(uint8_t) : sizeof(uint16_t);
+			rc = qmi_decode_basic_elem(&data_len_value, buf_src,
+						   1, data_len_sz);
+			memcpy(buf_dst, &data_len_value, sizeof(uint32_t));
+			temp_ei = temp_ei + 1;
+			buf_dst = out_c_struct + temp_ei->offset;
+			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
+		}
+
+		if (temp_ei->is_array == NO_ARRAY) {
+			data_len_value = 1;
+		} else if (temp_ei->is_array == STATIC_ARRAY) {
+			data_len_value = temp_ei->elem_len;
+		} else if (data_len_value > temp_ei->elem_len) {
+			pr_err("%s: Data len %d > max spec %d\n",
+				__func__, data_len_value, temp_ei->elem_len);
+			return -ETOOSMALL;
+		}
+
+		switch (temp_ei->data_type) {
+		case QMI_UNSIGNED_1_BYTE:
+		case QMI_UNSIGNED_2_BYTE:
+		case QMI_UNSIGNED_4_BYTE:
+		case QMI_UNSIGNED_8_BYTE:
+		case QMI_SIGNED_2_BYTE_ENUM:
+		case QMI_SIGNED_4_BYTE_ENUM:
+			rc = qmi_decode_basic_elem(buf_dst, buf_src,
+				data_len_value, temp_ei->elem_size);
+			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
+			break;
+
+		case QMI_STRUCT:
+			rc = qmi_decode_struct_elem(temp_ei, buf_dst, buf_src,
+				data_len_value, tlv_len, (dec_level + 1));
+			if (rc < 0)
+				return rc;
+			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
+			break;
+		default:
+			pr_err("%s: Unrecognized data type\n", __func__);
+			return -EINVAL;
+		}
+		temp_ei = temp_ei + 1;
+	}
+	return decoded_bytes;
+}
+MODULE_DESCRIPTION("QMI kernel enc/dec");
+MODULE_LICENSE("GPL v2");
diff --git a/lib/qmi_encdec_priv.h b/lib/qmi_encdec_priv.h
new file mode 100644
index 0000000..97fe45b
--- /dev/null
+++ b/lib/qmi_encdec_priv.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _QMI_ENCDEC_PRIV_H_
+#define _QMI_ENCDEC_PRIV_H_
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/socket.h>
+#include <linux/gfp.h>
+#include <linux/qmi_encdec.h>
+
+#define QMI_ENCDEC_ENCODE_TLV(type, length, p_dst) do { \
+	*p_dst++ = type; \
+	*p_dst++ = ((uint8_t)((length) & 0xFF)); \
+	*p_dst++ = ((uint8_t)(((length) >> 8) & 0xFF)); \
+} while (0)
+
+#define QMI_ENCDEC_DECODE_TLV(p_type, p_length, p_src) do { \
+	*p_type = (uint8_t)*p_src++; \
+	*p_length = (uint8_t)*p_src++; \
+	*p_length |= ((uint8_t)*p_src) << 8; \
+} while (0)
+
+#define QMI_ENCDEC_ENCODE_N_BYTES(p_dst, p_src, size) \
+do { \
+	memcpy(p_dst, p_src, size); \
+	p_dst = (uint8_t *)p_dst + size; \
+	p_src = (uint8_t *)p_src + size; \
+} while (0)
+
+#define QMI_ENCDEC_DECODE_N_BYTES(p_dst, p_src, size) \
+do { \
+	memcpy(p_dst, p_src, size); \
+	p_dst = (uint8_t *)p_dst + size; \
+	p_src = (uint8_t *)p_src + size; \
+} while (0)
+
+#define UPDATE_ENCODE_VARIABLES(temp_si, buf_dst, \
+				encoded_bytes, tlv_len, encode_tlv, rc) \
+do { \
+	buf_dst = (uint8_t *)buf_dst + rc; \
+	encoded_bytes += rc; \
+	tlv_len += rc; \
+	temp_si = temp_si + 1; \
+	encode_tlv = 1; \
+} while (0)
+
+#define UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc) \
+do { \
+	buf_src = (uint8_t *)buf_src + rc; \
+	decoded_bytes += rc; \
+} while (0)
+
+#endif
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 6b3287e..f28fd774 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -1889,6 +1889,8 @@
 pr_err:
 	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
 		__func__, port_id + 1);
+	mutex_unlock(&codec->mutex);
+	return 0;
 err:
 	mutex_unlock(&codec->mutex);
 	return -EINVAL;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 6f2885f..9f4babb 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -4504,6 +4504,8 @@
 
 	/* Disable TX7 internal biasing path which can cause leakage */
 	TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
+	/* Enable MICB 4 VDDIO switch to prevent leakage */
+	TAIKO_REG_VAL(TAIKO_A_MICB_4_MBHC, 0x81),
 };
 
 static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 99302eb..a261184 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -58,7 +58,7 @@
 
 snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-lowlatency-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o msm-dai-stub.o
 obj-$(CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO) += msm-dai-q6-hdmi.o
-obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
+obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o msm-pcm-dtmf.o
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
 obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
 
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index 5a47efe..0125c1a 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -2014,6 +2014,21 @@
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
 		.ignore_suspend = 1,
 	},
+	{
+		.name = "DTMF RX Hostless",
+		.stream_name = "DTMF RX Hostless",
+		.cpu_dai_name	= "DTMF_RX_HOSTLESS",
+		.platform_name  = "msm-pcm-dtmf",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.be_id = MSM_FRONTEND_DAI_DTMF_RX,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+	},
+
 	/* Backend BT DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index e91ed86..0926865 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -503,6 +503,20 @@
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "Pseudo",
 	},
+	{
+		.playback = {
+			.stream_name = "DTMF_RX Hostless Playback",
+			.aif_name = "DTMF_DL_HL",
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 2,
+			.rate_min =	8000,
+			.rate_max = 48000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "DTMF_RX_HOSTLESS",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-pcm-dtmf.c b/sound/soc/msm/msm-pcm-dtmf.c
new file mode 100644
index 0000000..04ab7a9
--- /dev/null
+++ b/sound/soc/msm/msm-pcm-dtmf.c
@@ -0,0 +1,100 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/q6afe.h>
+
+static int msm_dtmf_rx_generate_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	uint16_t low_freq = ucontrol->value.integer.value[0];
+	uint16_t high_freq = ucontrol->value.integer.value[1];
+	int64_t duration = ucontrol->value.integer.value[2];
+	uint16_t gain = ucontrol->value.integer.value[3];
+
+	pr_debug("%s: low_freq=%d high_freq=%d duration=%d gain=%d\n",
+		 __func__, low_freq, high_freq, (int)duration, gain);
+	afe_dtmf_generate_rx(duration, high_freq, low_freq, gain);
+	return 0;
+}
+
+static int msm_dtmf_rx_generate_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s:\n", __func__);
+	ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static struct snd_kcontrol_new msm_dtmf_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DTMF_Generate Rx Low High Duration Gain",
+			     SND_SOC_NOPM, 0, 5000, 0, 4,
+			     msm_dtmf_rx_generate_get,
+			     msm_dtmf_rx_generate_put),
+};
+
+static int msm_pcm_dtmf_probe(struct snd_soc_platform *platform)
+{
+	snd_soc_add_platform_controls(platform, msm_dtmf_controls,
+				      ARRAY_SIZE(msm_dtmf_controls));
+	return 0;
+}
+
+static struct snd_pcm_ops msm_pcm_ops = {};
+
+static struct snd_soc_platform_driver msm_soc_platform = {
+	.ops		= &msm_pcm_ops,
+	.probe		= msm_pcm_dtmf_probe,
+};
+
+static __devinit int msm_pcm_probe(struct platform_device *pdev)
+{
+	pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+	return snd_soc_register_platform(&pdev->dev,
+					 &msm_soc_platform);
+}
+
+static int msm_pcm_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_platform(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver msm_pcm_driver = {
+	.driver = {
+		.name = "msm-pcm-dtmf",
+		.owner = THIS_MODULE,
+	},
+	.probe = msm_pcm_probe,
+	.remove = __devexit_p(msm_pcm_remove),
+};
+
+static int __init msm_soc_platform_init(void)
+{
+	return platform_driver_register(&msm_pcm_driver);
+}
+module_init(msm_soc_platform_init);
+
+static void __exit msm_soc_platform_exit(void)
+{
+	platform_driver_unregister(&msm_pcm_driver);
+}
+module_exit(msm_soc_platform_exit);
+
+MODULE_DESCRIPTION("DTMF platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 378baf1..1ddb6c9 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -655,6 +655,14 @@
 	else
 		clear_bit(val, &msm_bedais[reg].fe_sessions);
 
+	if (val == MSM_FRONTEND_DAI_DTMF_RX &&
+	    afe_get_port_type(msm_bedais[reg].port_id) ==
+						MSM_AFE_PORT_TYPE_RX) {
+		pr_debug("%s(): set=%d port id=0x%x for dtmf generation\n",
+			 __func__, set, msm_bedais[reg].port_id);
+		afe_set_dtmf_gen_rx_portid(msm_bedais[reg].port_id, set);
+	}
+
 	mutex_unlock(&routing_lock);
 
 	if (afe_get_port_type(msm_bedais[reg].port_id) ==
@@ -1588,6 +1596,9 @@
 	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_voice_mixer_controls[] = {
@@ -1603,6 +1614,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -1618,6 +1632,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
@@ -1636,6 +1653,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_rx_voice_mixer_controls[] = {
@@ -1651,6 +1671,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
@@ -1669,6 +1692,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
@@ -1687,6 +1713,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
@@ -1702,6 +1731,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
@@ -1720,6 +1752,9 @@
 	SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -2288,6 +2323,8 @@
 		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MI2S_UL_HL", "MI2S_TX_HOSTLESS Capture",
 		0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DTMF_DL_HL", "DTMF_RX_HOSTLESS Playback",
+		0, 0, 0, 0),
 
 	/* Backend AIF */
 	/* Stream name equals to backend dai link stream name
@@ -2606,48 +2643,56 @@
 	{"PRI_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
 	{"PRI_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+	{"PRI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
 
 	{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SEC_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"SEC_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
 
 	{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SLIM_0_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"SLIM_0_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
 
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"INTERNAL_BT_SCO_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
 
 	{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"AFE_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
 
 	{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
 	{"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"SEC_AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"SEC_AUX_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"SEC_AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
 
 	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
 	{"HDMI_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
 	{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"HDMI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
 	{"HDMI", NULL, "HDMI_DL_HL"},
 
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 32ab063..0c0d3b4 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -70,6 +70,7 @@
 	MSM_FRONTEND_DAI_VOICE_STUB,
 	MSM_FRONTEND_DAI_VOLTE,
 	MSM_FRONTEND_DAI_SGLTE,
+	MSM_FRONTEND_DAI_DTMF_RX,
 	MSM_FRONTEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 359414b..4d2b253 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -43,6 +43,25 @@
 #define MODE_AMR		0x5
 #define MODE_AMR_WB		0xD
 #define MODE_PCM		0xC
+#define MODE_G711		0xA
+#define MODE_G711A		0xF
+
+enum msm_audio_g711a_frame_type {
+	MVS_G711A_SPEECH_GOOD,
+	MVS_G711A_SID,
+	MVS_G711A_NO_DATA,
+	MVS_G711A_ERASURE
+};
+
+enum msm_audio_g711a_mode {
+	MVS_G711A_MODE_MULAW,
+	MVS_G711A_MODE_ALAW
+};
+
+enum msm_audio_g711_mode {
+	MVS_G711_MODE_MULAW,
+	MVS_G711_MODE_ALAW
+};
 
 enum format {
 	FORMAT_S16_LE = 2,
@@ -135,7 +154,7 @@
 	unsigned int pcm_capture_buf_pos;       /* position in buffer */
 };
 
-static int voip_get_media_type(uint32_t mode,
+static int voip_get_media_type(uint32_t mode, uint32_t rate_type,
 				unsigned int samp_rate);
 static int voip_get_rate_type(uint32_t mode,
 				uint32_t rate,
@@ -309,6 +328,79 @@
 			list_add_tail(&buf_node->list, &prtd->out_queue);
 			break;
 		}
+		case MODE_G711:
+		case MODE_G711A:{
+			/* G711 frames are 10ms each, but the DSP works with
+			 * 20ms frames and sends two 10ms frames per buffer.
+			 * Extract the two frames and put them in separate
+			 * buffers.
+			 */
+			/* Remove the first DSP frame info header.
+			 * Header format: G711A
+			 * Bits 0-1: Frame type
+			 * Bits 2-3: Frame rate
+			 *
+			 * Header format: G711
+			 * Bits 2-3: Frame rate
+			 */
+			if (prtd->mode == MODE_G711A)
+				buf_node->frame.header.frame_type =
+							(*voc_pkt) & 0x03;
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+
+			/* There are two frames in the buffer. Length of the
+			 * first frame:
+			 */
+			buf_node->frame.len = (pkt_len -
+					       2 * DSP_FRAME_HDR_LEN) / 2;
+
+			memcpy(&buf_node->frame.voc_pkt[0],
+			       voc_pkt,
+			       buf_node->frame.len);
+			voc_pkt = voc_pkt + buf_node->frame.len;
+
+			list_add_tail(&buf_node->list, &prtd->out_queue);
+
+			/* Get another buffer from the free Q and fill in the
+			 * second frame.
+			 */
+			if (!list_empty(&prtd->free_out_queue)) {
+				buf_node =
+					list_first_entry(&prtd->free_out_queue,
+							 struct voip_buf_node,
+							 list);
+				list_del(&buf_node->list);
+
+				/* Remove the second DSP frame info header.
+				 * Header format:
+				 * Bits 0-1: Frame type
+				 * Bits 2-3: Frame rate
+				 */
+
+				if (prtd->mode == MODE_G711A)
+					buf_node->frame.header.frame_type =
+							(*voc_pkt) & 0x03;
+				voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+
+				/* There are two frames in the buffer. Length
+				 * of the second frame:
+				 */
+				buf_node->frame.len = (pkt_len -
+					2 * DSP_FRAME_HDR_LEN) / 2;
+
+				memcpy(&buf_node->frame.voc_pkt[0],
+				       voc_pkt,
+				       buf_node->frame.len);
+
+				list_add_tail(&buf_node->list,
+					      &prtd->out_queue);
+			} else {
+				/* Drop the second frame */
+				pr_err("%s: UL data dropped, read is slow\n",
+				       __func__);
+			}
+			break;
+		}
 		default: {
 			buf_node->frame.len = pkt_len;
 			memcpy(&buf_node->frame.voc_pkt[0],
@@ -383,6 +475,67 @@
 			list_add_tail(&buf_node->list, &prtd->free_in_queue);
 			break;
 		}
+		case MODE_G711:
+		case MODE_G711A:{
+			/* G711 frames are 10ms each but the DSP expects 20ms
+			 * worth of data, so send two 10ms frames per buffer.
+			 */
+			/* Add the first DSP frame info header. Header format:
+			 * Bits 0-1: Frame type
+			 * Bits 2-3: Frame rate
+			 */
+
+			*voc_pkt = ((prtd->rate_type  & 0x0F) << 2) |
+				    (buf_node->frame.header.frame_type & 0x03);
+			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+
+			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
+
+			memcpy(voc_pkt,
+			       &buf_node->frame.voc_pkt[0],
+			       buf_node->frame.len);
+			voc_pkt = voc_pkt + buf_node->frame.len;
+
+			list_add_tail(&buf_node->list, &prtd->free_in_queue);
+
+			if (!list_empty(&prtd->in_queue)) {
+				/* Get the second buffer. */
+				buf_node = list_first_entry(&prtd->in_queue,
+							struct voip_buf_node,
+							list);
+				list_del(&buf_node->list);
+
+				/* Add the second DSP frame info header.
+				 * Header format:
+				 * Bits 0-1: Frame type
+				 * Bits 2-3: Frame rate
+				 */
+				*voc_pkt = ((prtd->rate_type & 0x0F) << 2) |
+				(buf_node->frame.header.frame_type & 0x03);
+				voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+
+				*pkt_len = *pkt_len +
+					buf_node->frame.len + DSP_FRAME_HDR_LEN;
+
+				memcpy(voc_pkt,
+				       &buf_node->frame.voc_pkt[0],
+				       buf_node->frame.len);
+
+				list_add_tail(&buf_node->list,
+					      &prtd->free_in_queue);
+			} else {
+				/* Only 10ms worth of data is available, signal
+				 * erasure frame.
+				 */
+				*voc_pkt = ((prtd->rate_type & 0x0F) << 2) |
+					    (MVS_G711A_ERASURE & 0x03);
+
+				*pkt_len = *pkt_len + DSP_FRAME_HDR_LEN;
+				pr_debug("%s, Only 10ms read, erase 2nd frame\n",
+					 __func__);
+			}
+			break;
+		}
 		default: {
 			*pkt_len = buf_node->frame.len;
 
@@ -753,7 +906,8 @@
 	if ((runtime->format != FORMAT_SPECIAL) &&
 		 ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
 		 (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
-		 (prtd->mode == MODE_4GV_WB))) {
+		 (prtd->mode == MODE_4GV_WB) || (prtd->mode == MODE_G711) ||
+		 (prtd->mode == MODE_G711A))) {
 		pr_err("mode:%d and format:%u are not mached\n",
 			prtd->mode, (uint32_t)runtime->format);
 		ret =  -EINVAL;
@@ -781,6 +935,7 @@
 		}
 		prtd->rate_type = rate_type;
 		media_type = voip_get_media_type(prtd->mode,
+						prtd->rate_type,
 						prtd->play_samp_rate);
 		if (media_type < 0) {
 			pr_err("fail at getting media_type\n");
@@ -1041,6 +1196,10 @@
 		}
 		break;
 	}
+	case MODE_G711:
+	case MODE_G711A:
+		*rate_type = rate;
+		break;
 	default:
 		pr_err("wrong mode type.\n");
 		ret = -EINVAL;
@@ -1050,7 +1209,7 @@
 	return ret;
 }
 
-static int voip_get_media_type(uint32_t mode,
+static int voip_get_media_type(uint32_t mode, uint32_t rate_type,
 				unsigned int samp_rate)
 {
 	uint32_t media_type;
@@ -1079,6 +1238,13 @@
 	case MODE_4GV_WB: /* EVRC-WB */
 		media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
 		break;
+	case MODE_G711:
+	case MODE_G711A:
+		if (rate_type == MVS_G711A_MODE_MULAW)
+			media_type = VSS_MEDIA_ID_G711_MULAW;
+		else
+			media_type = VSS_MEDIA_ID_G711_ALAW;
+		break;
 	default:
 		pr_debug(" input mode is not supported\n");
 		media_type = -EINVAL;
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 9c62a2e..6cabc97 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -33,6 +33,7 @@
 		uint32_t token, uint32_t *payload, void *priv);
 	void *tx_private_data;
 	void *rx_private_data;
+	u16 dtmf_gen_rx_portid;
 };
 
 static struct afe_ctl this_afe;
@@ -91,6 +92,7 @@
 			case AFE_SERVICE_CMD_MEMORY_MAP:
 			case AFE_SERVICE_CMD_MEMORY_UNMAP:
 			case AFE_SERVICE_CMD_UNREG_RTPORT:
+			case AFE_PORTS_CMD_DTMF_CTL:
 				atomic_set(&this_afe.state, 0);
 				wake_up(&this_afe.wait);
 				break;
@@ -1621,6 +1623,83 @@
 	.write = afe_debug_write
 };
 #endif
+
+void afe_set_dtmf_gen_rx_portid(u16 port_id, int set)
+{
+	if (set)
+		this_afe.dtmf_gen_rx_portid = port_id;
+	else if (this_afe.dtmf_gen_rx_portid == port_id)
+		this_afe.dtmf_gen_rx_portid = -1;
+}
+
+int afe_dtmf_generate_rx(int64_t duration_in_ms,
+			 uint16_t high_freq,
+			 uint16_t low_freq, uint16_t gain)
+{
+	int ret = 0;
+	struct afe_dtmf_generation_command cmd_dtmf;
+
+	pr_debug("%s: DTMF AFE Gen\n", __func__);
+
+	if (afe_validate_port(this_afe.dtmf_gen_rx_portid) < 0) {
+		pr_err("%s: Failed : Invalid Port id = %d\n",
+		       __func__, this_afe.dtmf_gen_rx_portid);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+
+	if (this_afe.apr == NULL) {
+		this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
+					    0xFFFFFFFF, &this_afe);
+		pr_debug("%s: Register AFE\n", __func__);
+		if (this_afe.apr == NULL) {
+			pr_err("%s: Unable to register AFE\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+	}
+
+	pr_debug("dur=%lld: hfreq=%d lfreq=%d gain=%d portid=%x\n",
+		duration_in_ms, high_freq, low_freq, gain,
+		this_afe.dtmf_gen_rx_portid);
+
+	cmd_dtmf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	cmd_dtmf.hdr.pkt_size = sizeof(cmd_dtmf);
+	cmd_dtmf.hdr.src_port = 0;
+	cmd_dtmf.hdr.dest_port = 0;
+	cmd_dtmf.hdr.token = 0;
+	cmd_dtmf.hdr.opcode = AFE_PORTS_CMD_DTMF_CTL;
+	cmd_dtmf.duration_in_ms = duration_in_ms;
+	cmd_dtmf.high_freq = high_freq;
+	cmd_dtmf.low_freq = low_freq;
+	cmd_dtmf.gain = gain;
+	cmd_dtmf.num_ports = 1;
+	cmd_dtmf.port_ids = this_afe.dtmf_gen_rx_portid;
+
+	atomic_set(&this_afe.state, 1);
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_dtmf);
+	if (ret < 0) {
+		pr_err("%s: AFE DTMF failed for num_ports:%d ids:%x\n",
+		       __func__, cmd_dtmf.num_ports, cmd_dtmf.port_ids);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+
+	ret = wait_event_timeout(this_afe.wait,
+		(atomic_read(&this_afe.state) == 0),
+			msecs_to_jiffies(TIMEOUT_MS));
+	if (ret < 0) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	return 0;
+
+fail_cmd:
+	return ret;
+}
+
 int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
 {
 	struct afe_port_sidetone_command cmd_sidetone;
@@ -1755,6 +1834,7 @@
 	atomic_set(&this_afe.state, 0);
 	atomic_set(&this_afe.status, 0);
 	this_afe.apr = NULL;
+	this_afe.dtmf_gen_rx_portid = -1;
 #ifdef CONFIG_DEBUG_FS
 	debugfs_afelb = debugfs_create_file("afe_loopback",
 	S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",