Merge "msm_fb: mdss: Add eDP controller driver support"
diff --git a/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt
new file mode 100644
index 0000000..19fbd3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt
@@ -0,0 +1,66 @@
+Qualcomm QPNP Temperature Alarm
+
+QPNP temperature alarm peripherals are found inside of Qualcomm PMIC chips that
+utilize the MSM SPMI implementation.  These peripherals provide an interrupt
+signal and status register to identify high PMIC die temperature.
+
+Required properties:
+- compatible:      Must be "qcom,qpnp-temp-alarm".
+- reg:             Specifies the SPMI address and size for this temperature
+		    alarm device.
+- interrupts:      PMIC temperature alarm interrupt
+- label:           A string used as a descriptive name for this thermal device.
+		    This name should be 19 characters or less.
+
+Required structure:
+- A qcom,qpnp-temp-alarm node must be a child of an SPMI node that has specified
+   the spmi-slave-container property
+
+Optional properties:
+- qcom,channel-num:    VADC channel number associated PMIC DIE_TEMP thermistor.
+			If no channel is specified, then the die temperature
+			must be estimated based on the over temperature stage.
+- qcom,threshold-set:  Integer value which specifies which set of threshold
+			temperatures to use for the over temperature stages.
+			Possible values (x = {stage 1 threshold temperature,
+				stage 2 threshold temperature,
+				stage 3 threshold temperature}):
+			 0 = {105 C, 125 C, 145 C}
+			 1 = {110 C, 130 C, 150 C}
+			 2 = {115 C, 135 C, 155 C}
+			 3 = {120 C, 140 C, 160 C}
+- qcom,allow-override: Boolean which controls the ability of software to
+			override shutdowns.  If present, then software is
+			allowed to override automatic PMIC hardware stage 2 and
+			stage 3 over temperature shutdowns.  Otherwise, software
+			is not allowed to override automatic shutdown.
+- qcom,default-temp:   Specifies the default temperature in millicelcius to use
+			if no ADC channel is present to read the real time
+			temperature.
+
+Note, if a given optional qcom,* binding is not present, then the default
+hardware state for that feature will be maintained.
+
+Example:
+&spmi_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	interrupt-controller;
+	#interrupt-cells = <3>;
+
+	qcom,pm8941@0 {
+		spmi-slave-container;
+		reg = <0x0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		qcom,temp-alarm@2400 {
+			compatible = "qcom,qpnp-temp-alarm";
+			reg = <0x2400 0x100>;
+			interrupts = <0x0 0x24 0x0>;
+			label = "pm8941_tz";
+			qcom,channel-num = <8>;
+			qcom,threshold-set = <0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/mpq8092-regulator.dtsi b/arch/arm/boot/dts/mpq8092-regulator.dtsi
new file mode 100644
index 0000000..fbc9586
--- /dev/null
+++ b/arch/arm/boot/dts/mpq8092-regulator.dtsi
@@ -0,0 +1,290 @@
+/* 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.
+ */
+
+
+/* QPNP controlled regulators: */
+
+&spmi_bus {
+
+	qcom,pm8644@1 {
+
+		pm8644_s3: regulator@1a00 {
+			regulator-min-microvolt = <1350000>;
+			regulator-max-microvolt = <1350000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		pm8644_s4: regulator@1d00 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		pm8644_s5: regulator@2000 {
+			regulator-min-microvolt = <2150000>;
+			regulator-max-microvolt = <2150000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_s6: regulator@2300 {
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <900000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_s7: regulator@2600 {
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <900000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_s8: regulator@2900 {
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <900000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l1: regulator@4000 {
+			parent-supply = <&pm8644_s3>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <10000>;
+			status = "okay";
+		};
+
+		pm8644_l2: regulator@4100 {
+			parent-supply = <&pm8644_s3>;
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <900000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l3: regulator@4200 {
+			parent-supply = <&pm8644_s3>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l4: regulator@4300 {
+			parent-supply = <&pm8644_s3>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l6: regulator@4500 {
+			parent-supply = <&pm8644_s5>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l8: regulator@4700 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l9: regulator@4800 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l10: regulator@4900 {
+			regulator-min-microvolt = <2000000>;
+			regulator-max-microvolt = <2000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l11: regulator@4a00 {
+			parent-supply = <&pm8644_s3>;
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l12: regulator@4b00 {
+			parent-supply = <&pm8644_s5>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l13: regulator@4c00 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l14: regulator@4d00 {
+			parent-supply = <&pm8644_s5>;
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l15: regulator@4e00 {
+			parent-supply = <&pm8644_s5>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l16: regulator@4f00 {
+			parent-supply = <&pm8644_s4>;
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <750000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l17: regulator@5000 {
+			regulator-min-microvolt = <3150000>;
+			regulator-max-microvolt = <3150000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		pm8644_l18: regulator@5100 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l19: regulator@5200 {
+			parent-supply = <&pm8644_s4>;
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l20: regulator@5300 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l21: regulator@5400 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l22: regulator@5500 {
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l23: regulator@5600 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_l24: regulator@5700 {
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_lvs1: regulator@8000 {
+			parent-supply = <&pm8644_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_lvs2: regulator@8100 {
+			parent-supply = <&pm8644_s4>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_mvs1: regulator@8200 {
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8644_mvs2: regulator@8300 {
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+	};
+};
+
diff --git a/arch/arm/boot/dts/mpq8092-sim.dts b/arch/arm/boot/dts/mpq8092-sim.dts
index ac984a1..0cbfa33 100644
--- a/arch/arm/boot/dts/mpq8092-sim.dts
+++ b/arch/arm/boot/dts/mpq8092-sim.dts
@@ -26,6 +26,155 @@
 	serial@f995e000 {
 		status = "ok";
 	};
-
 };
 
+&pm8644_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+
+	gpio@c400 { /* GPIO 5 */
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+
+	gpio@e400 { /* GPIO 37 */
+	};
+
+	gpio@e500 { /* GPIO 38 */
+	};
+
+	gpio@e600 { /* GPIO 39 */
+	};
+
+	gpio@e700 { /* GPIO 40 */
+	};
+
+	gpio@e800 { /* GPIO 41 */
+	};
+
+	gpio@e900 { /* GPIO 42 */
+	};
+
+	gpio@ea00 { /* GPIO 43 */
+	};
+};
+
+&pm8644_mpps {
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP5 */
+	};
+
+	mpp@a500 { /* MPP 6 */
+	};
+};
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index a88e987..252b9f5 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -56,4 +56,179 @@
 		interrupts = <0 114 0>;
 		status = "disabled";
 	};
+
+	spmi_bus: qcom,spmi@fc4c0000 {
+		cell-index = <0>;
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0xfc4cf000 0x1000>,
+		      <0Xfc4cb000 0x1000>;
+		/* 190,ee0_krait_hlos_spmi_periph_irq */
+		/* 187,channel_0_krait_hlos_trans_done_irq */
+		interrupts = <0 190 0 0 187 0>;
+		qcom,pmic-arb-ee = <0>;
+		qcom,pmic-arb-channel = <0>;
+		qcom,pmic-arb-ppid-map = <0x00100000>, /* PM8644_0 */
+				 <0x10100001>, /* PM8644_1 */
+				 <0x00500002>, /* INTERRUPT */
+				 <0x00800003>, /* PON0 */
+				 <0x03000004>, /* ADC_1 */
+				 <0x03100005>, /* ADC_2 */
+				 <0x03200006>, /* ADC_3 */
+				 <0x03300007>, /* ADC_4 */
+				 <0x03400008>, /* ADC_5 */
+				 <0x03500009>, /* ADC_6 */
+				 <0x0360000a>, /* ADC_7 */
+				 <0x0370000b>, /* ADC_8 */
+				 <0x0500000c>, /* SHARED_XO */
+				 <0x0510000d>, /* BB_CLK1 */
+				 <0x0520000e>, /* BB_CLK2 */
+				 <0x05a0000f>, /* SLEEP_CLK */
+				 <0x06000010>, /* RTC_RW */
+				 <0x06100011>, /* RTC_ALARM */
+				 <0x07000012>, /* PBS_CORE */
+				 <0x07100013>, /* PBS_CLIENT_1 */
+				 <0x07200014>, /* PBS_CLIENT_2 */
+				 <0x07300015>, /* PBS_CLIENT_3 */
+				 <0x07400016>, /* PBS_CLIENT_4 */
+				 <0x07500017>, /* PBS_CLIENT_5 */
+				 <0x07600018>, /* PBS_CLIENT_6 */
+				 <0x07700019>, /* PBS_CLIENT_7 */
+				 <0x0780001a>, /* PBS_CLIENT_8 */
+				 <0x0790001b>, /* PBS_CLIENT_9 */
+				 <0x07a0001c>, /* PBS_CLIENT_10 */
+				 <0x07b0001d>, /* PBS_CLIENT_11 */
+				 <0x07c0001e>, /* PBS_CLIENT_12 */
+				 <0x07d0001f>, /* PBS_CLIENT_13 */
+				 <0x07e00020>, /* PBS_CLIENT_14 */
+				 <0x07f00021>, /* PBS_CLIENT_15 */
+				 <0x08000022>, /* PBS_CLIENT_16 */
+				 <0x0a000023>, /* MPP_1 */
+				 <0x0a100024>, /* MPP_2 */
+				 <0x0a200025>, /* MPP_3 */
+				 <0x0a300026>, /* MPP_4 */
+				 <0x0a400027>, /* MPP_5 */
+				 <0x0a500028>, /* MPP_6 */
+				 <0x0c000029>, /* PM8644_GPIO_1 */
+				 <0x0c10002a>, /* PM8644_GPIO_2 */
+				 <0x0c20002b>, /* PM8644_GPIO_3 */
+				 <0x0c30002c>, /* PM8644_GPIO_4 */
+				 <0x0c40002d>, /* PM8644_GPIO_5 */
+				 <0x0c50002e>, /* PM8644_GPIO_6 */
+				 <0x0c60002f>, /* PM8644_GPIO_7 */
+				 <0x0c700030>, /* PM8644_GPIO_8 */
+				 <0x0c800031>, /* PM8644_GPIO_9 */
+				 <0x0c900032>, /* PM8644_GPIO_10 */
+				 <0x0ca00033>, /* PM8644_GPIO_11 */
+				 <0x0cb00034>, /* PM8644_GPIO_12 */
+				 <0x0cc00035>, /* PM8644_GPIO_13 */
+				 <0x0cd00036>, /* PM8644_GPIO_14 */
+				 <0x0ce00037>, /* PM8644_GPIO_15 */
+				 <0x0cf00038>, /* PM8644_GPIO_16 */
+				 <0x0d000039>, /* PM8644_GPIO_17 */
+				 <0x0d10003a>, /* PM8644_GPIO_18 */
+				 <0x0d20003b>, /* PM8644_GPIO_19 */
+				 <0x0d30003c>, /* PM8644_GPIO_20 */
+				 <0x0d40003d>, /* PM8644_GPIO_21 */
+				 <0x0d50003e>, /* PM8644_GPIO_22 */
+				 <0x0d60003f>, /* PM8644_GPIO_23 */
+				 <0x0d700040>, /* PM8644_GPIO_24 */
+				 <0x0d800041>, /* PM8644_GPIO_25 */
+				 <0x0d900042>, /* PM8644_GPIO_26 */
+				 <0x0da00043>, /* PM8644_GPIO_27 */
+				 <0x0db00044>, /* PM8644_GPIO_28 */
+				 <0x0dc00045>, /* PM8644_GPIO_29 */
+				 <0x0dd00046>, /* PM8644_GPIO_30 */
+				 <0x0de00047>, /* PM8644_GPIO_31 */
+				 <0x0df00048>, /* PM8644_GPIO_32 */
+				 <0x0e000049>, /* PM8644_GPIO_33 */
+				 <0x0e10004a>, /* PM8644_GPIO_34 */
+				 <0x0e20004b>, /* PM8644_GPIO_35 */
+				 <0x0e30004c>, /* PM8644_GPIO_36 */
+				 <0x0e40004d>, /* PM8644_GPIO_37 */
+				 <0x0e50004e>, /* PM8644_GPIO_38 */
+				 <0x0e60004f>, /* PM8644_GPIO_39 */
+				 <0x0e700050>, /* PM8644_GPIO_40 */
+				 <0x0e800051>, /* PM8644_GPIO_41 */
+				 <0x0e900052>, /* PM8644_GPIO_42 */
+				 <0x0ea00053>, /* PM8644_GPIO_43 */
+				 <0x11000054>, /* BUCK_CMN_1 */
+				 <0x11100055>, /* BUCK_CMN_2 */
+				 <0x11200056>, /* BUCK_CMN_3 */
+				 <0x11400057>, /* PM8644_SMPS1 */
+				 <0x11500058>, /* SMPS_1_PS1 */
+				 <0x11600059>, /* BUCK_FREQ_1 */
+				 <0x1170005a>, /* PM8644_SMPS2 */
+				 <0x1180005b>, /* SMPS_2_PS1 */
+				 <0x1190005c>, /* BUCK_FREQ_2 */
+				 <0x11a0005d>, /* PM8644_SMPS3 */
+				 <0x11b0005e>, /* SMPS_3_PS1 */
+				 <0x11c0005f>, /* BUCK_FREQ_3 */
+				 <0x11d00060>, /* PM8644_SMPS4 */
+				 <0x11e00061>, /* SMPS_4_PS1 */
+				 <0x11f00062>, /* PM8644_BUCK_FREQ_4 */
+				 <0x12000063>, /* PM8644_SMPS5 */
+				 <0x12100064>, /* FTPS1_5 */
+				 <0x12200065>, /* PM8644_BUCK_FREQ_5 */
+				 <0x12300066>, /* PM8644_SMPS6 */
+				 <0x12400067>, /* FTPS1_6 */
+				 <0x12500068>, /* PM8644_BUCK_FREQ_6 */
+				 <0x12600069>, /* PM8644_SMPS7 */
+				 <0x1270006a>, /* FTPS1_7 */
+				 <0x1280006b>, /* PM8644_BUCK_FREQ_7 */
+				 <0x1290006c>, /* PM8644_SMPS8 */
+				 <0x12a0006d>, /* FTPS1_8 */
+				 <0x12b0006e>, /* PM8644_BUCK_FREQ_8 */
+				 <0x12c0006f>, /* PM8644_SMPS9 */
+				 <0x12d00070>, /* FTPS1_9 */
+				 <0x12e00071>, /* PM8644_BUCK_FREQ_9 */
+				 <0x12f00072>, /* PM8644_SMPS10 */
+				 <0x13000073>, /* FTPS1_10 */
+				 <0x13100074>, /* PM8644_BUCK_FREQ_10 */
+				 <0x13200075>, /* PM8644_SMPS11 */
+				 <0x13300076>, /* FTPS1_11 */
+				 <0x13400077>, /* BUCK_FREQ_11 */
+				 <0x14000078>, /* PM8644_LDO_1 */
+				 <0x14100079>, /* PM8644_LDO_2 */
+				 <0x1420007a>, /* PM8644_LDO_3 */
+				 <0x1430007b>, /* PM8644_LDO_4 */
+				 <0x1440007c>, /* PM8644_LDO_5 */
+				 <0x1450007d>, /* PM8644_LDO_6 */
+				 <0x1460007e>, /* PM8644_LDO_7 */
+				 <0x1470007f>, /* PM8644_LDO_8 */
+				 <0x14800080>, /* PM8644_LDO_9 */
+				 <0x14900081>, /* PM8644_LDO_10 */
+				 <0x14a00082>, /* PM8644_LDO_11 */
+				 <0x14b00083>, /* PM8644_LDO_12 */
+				 <0x14c00084>, /* PM8644_LDO_13 */
+				 <0x14d00085>, /* PM8644_LDO_14 */
+				 <0x14e00086>, /* PM8644_LDO_15 */
+				 <0x14f00087>, /* PM8644_LDO_16 */
+				 <0x15000088>, /* PM8644_LDO_17 */
+				 <0x15100089>, /* PM8644_LDO_18 */
+				 <0x1520008a>, /* PM8644_LDO_19 */
+				 <0x1530008b>, /* PM8644_LDO_20 */
+				 <0x1540008c>, /* PM8644_LDO_21 */
+				 <0x1550008d>, /* PM8644_LDO_22 */
+				 <0x1560008e>, /* PM8644_LDO_23 */
+				 <0x1570008f>, /* PM8644_LDO_24 */
+				 <0x15800090>, /* PM8644_LDO_25 */
+				 <0x18000091>, /* PM8644_LVS_1 */
+				 <0x18100092>, /* PM8644_LVS_2 */
+				 <0x18200093>, /* PM8644_OTG */
+				 <0x18300094>, /* PM8644_HDMI */
+				 <0x1a800095>, /* KEYPAD */
+				 <0x1b000096>, /* LPG_LUT */
+				 <0x1b100097>, /* LPG_CHAN_1 */
+				 <0x1b200098>, /* LPG_CHAN_2 */
+				 <0x1b300099>, /* LPG_CHAN_3 */
+				 <0x1b40009a>, /* LPG_CHAN_4 */
+				 <0x1b50009b>, /* LPG_CHAN_5 */
+				 <0x1b60009c>, /* LPG_CHAN_6 */
+				 <0x1b70009d>, /* LPG_CHAN_7 */
+				 <0x1b80009e>, /* LPG_CHAN_8 */
+				 <0x1bc0009f>; /* LPG_PWM */
+	};
 };
+
+/include/ "msm-pm8644.dtsi"
+/include/ "mpq8092-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm-pm8644.dtsi b/arch/arm/boot/dts/msm-pm8644.dtsi
new file mode 100644
index 0000000..17a6b0b
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pm8644.dtsi
@@ -0,0 +1,722 @@
+/* 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.
+ */
+
+&spmi_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	interrupt-controller;
+	#interrupt-cells = <3>;
+
+	qcom,pm8644@0 {
+		spmi-slave-container;
+		reg = <0x0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		pm8644_gpios: gpios {
+			spmi-dev-container;
+			compatible = "qcom,qpnp-pin";
+			gpio-controller;
+			#gpio-cells = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			label = "pm8644-gpio";
+
+			gpio@c000 {
+				reg = <0xc000 0x100>;
+				qcom,pin-num = <1>;
+			};
+
+			gpio@c100 {
+				reg = <0xc100 0x100>;
+				qcom,pin-num = <2>;
+			};
+
+			gpio@c200 {
+				reg = <0xc200 0x100>;
+				qcom,pin-num = <3>;
+			};
+
+			gpio@c300 {
+				reg = <0xc300 0x100>;
+				qcom,pin-num = <4>;
+			};
+
+			gpio@c400 {
+				reg = <0xc400 0x100>;
+				qcom,pin-num = <5>;
+			};
+
+			gpio@c500 {
+				reg = <0xc500 0x100>;
+				qcom,pin-num = <6>;
+			};
+
+			gpio@c600 {
+				reg = <0xc600 0x100>;
+				qcom,pin-num = <7>;
+			};
+
+			gpio@c700 {
+				reg = <0xc700 0x100>;
+				qcom,pin-num = <8>;
+			};
+
+			gpio@c800 {
+				reg = <0xc800 0x100>;
+				qcom,pin-num = <9>;
+			};
+
+			gpio@c900 {
+				reg = <0xc900 0x100>;
+				qcom,pin-num = <10>;
+			};
+
+			gpio@ca00 {
+				reg = <0xca00 0x100>;
+				qcom,pin-num = <11>;
+			};
+
+			gpio@cb00 {
+				reg = <0xcb00 0x100>;
+				qcom,pin-num = <12>;
+			};
+
+			gpio@cc00 {
+				reg = <0xcc00 0x100>;
+				qcom,pin-num = <13>;
+			};
+
+			gpio@cd00 {
+				reg = <0xcd00 0x100>;
+				qcom,pin-num = <14>;
+			};
+
+			gpio@ce00 {
+				reg = <0xce00 0x100>;
+				qcom,pin-num = <15>;
+			};
+
+			gpio@cf00 {
+				reg = <0xcf00 0x100>;
+				qcom,pin-num = <16>;
+			};
+
+			gpio@d000 {
+				reg = <0xd000 0x100>;
+				qcom,pin-num = <17>;
+			};
+
+			gpio@d100 {
+				reg = <0xd100 0x100>;
+				qcom,pin-num = <18>;
+			};
+
+			gpio@d200 {
+				reg = <0xd200 0x100>;
+				qcom,pin-num = <19>;
+			};
+
+			gpio@d300 {
+				reg = <0xd300 0x100>;
+				qcom,pin-num = <20>;
+			};
+
+			gpio@d400 {
+				reg = <0xd400 0x100>;
+				qcom,pin-num = <21>;
+			};
+
+			gpio@d500 {
+				reg = <0xd500 0x100>;
+				qcom,pin-num = <22>;
+			};
+
+			gpio@d600 {
+				reg = <0xd600 0x100>;
+				qcom,pin-num = <23>;
+			};
+
+			gpio@d700 {
+				reg = <0xd700 0x100>;
+				qcom,pin-num = <24>;
+			};
+
+			gpio@d800 {
+				reg = <0xd800 0x100>;
+				qcom,pin-num = <25>;
+			};
+
+			gpio@d900 {
+				reg = <0xd900 0x100>;
+				qcom,pin-num = <26>;
+			};
+
+			gpio@da00 {
+				reg = <0xda00 0x100>;
+				qcom,pin-num = <27>;
+			};
+
+			gpio@db00 {
+				reg = <0xdb00 0x100>;
+				qcom,pin-num = <28>;
+			};
+
+			gpio@dc00 {
+				reg = <0xdc00 0x100>;
+				qcom,pin-num = <29>;
+			};
+
+			gpio@dd00 {
+				reg = <0xdd00 0x100>;
+				qcom,pin-num = <30>;
+			};
+
+			gpio@de00 {
+				reg = <0xde00 0x100>;
+				qcom,pin-num = <31>;
+			};
+
+			gpio@df00 {
+				reg = <0xdf00 0x100>;
+				qcom,pin-num = <32>;
+			};
+
+			gpio@e000 {
+				reg = <0xe000 0x100>;
+				qcom,pin-num = <33>;
+			};
+
+			gpio@e100 {
+				reg = <0xe100 0x100>;
+				qcom,pin-num = <34>;
+			};
+
+			gpio@e200 {
+				reg = <0xe200 0x100>;
+				qcom,pin-num = <35>;
+			};
+
+			gpio@e300 {
+				reg = <0xe300 0x100>;
+				qcom,pin-num = <36>;
+			};
+
+			gpio@e400 {
+				reg = <0xe400 0x100>;
+				qcom,pin-num = <37>;
+			};
+
+			gpio@e500 {
+				reg = <0xe500 0x100>;
+				qcom,pin-num = <38>;
+			};
+
+			gpio@e600 {
+				reg = <0xe600 0x100>;
+				qcom,pin-num = <39>;
+			};
+
+			gpio@e700 {
+				reg = <0xe700 0x100>;
+				qcom,pin-num = <40>;
+			};
+
+			gpio@e800 {
+				reg = <0xe800 0x100>;
+				qcom,pin-num = <41>;
+			};
+
+			gpio@e900 {
+				reg = <0xe900 0x100>;
+				qcom,pin-num = <42>;
+			};
+
+			gpio@ea00 {
+				reg = <0xea00 0x100>;
+				qcom,pin-num = <43>;
+			};
+		};
+
+		pm8644_mpps: mpps {
+			spmi-dev-container;
+			compatible = "qcom,qpnp-pin";
+			gpio-controller;
+			#gpio-cells = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			label = "pm8644-mpp";
+
+			mpp@a000 {
+				reg = <0xa000 0x100>;
+				qcom,pin-num = <1>;
+			};
+
+			mpp@a100 {
+				reg = <0xa100 0x100>;
+				qcom,pin-num = <2>;
+			};
+
+			mpp@a200 {
+				reg = <0xa200 0x100>;
+				qcom,pin-num = <3>;
+			};
+
+			mpp@a300 {
+				reg = <0xa300 0x100>;
+				qcom,pin-num = <4>;
+			};
+
+			mpp@a400 {
+				reg = <0xa400 0x100>;
+				qcom,pin-num = <5>;
+			};
+
+			mpp@a500 {
+				reg = <0xa500 0x100>;
+				qcom,pin-num = <6>;
+			};
+		};
+	};
+
+	qcom,pm8644@1 {
+		spmi-slave-container;
+		reg = <0x1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		regulator@1400 {
+			regulator-name = "8644_s1";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1400 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1400 {
+				reg = <0x1400 0x100>;
+			};
+			qcom,ps@1500 {
+				reg = <0x1500 0x100>;
+			};
+			qcom,freq@1600 {
+				reg = <0x1600 0x100>;
+			};
+		};
+
+		regulator@1700 {
+			regulator-name = "8644_s2";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1700 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1700 {
+				reg = <0x1700 0x100>;
+			};
+			qcom,ps@1800 {
+				reg = <0x1800 0x100>;
+			};
+			qcom,freq@1900 {
+				reg = <0x1900 0x100>;
+			};
+		};
+
+		regulator@1a00 {
+			regulator-name = "8644_s3";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1a00 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1a00 {
+				reg = <0x1a00 0x100>;
+			};
+			qcom,ps@1b00 {
+				reg = <0x1b00 0x100>;
+			};
+			qcom,freq@1c00 {
+				reg = <0x1c00 0x100>;
+			};
+		};
+
+		regulator@1d00 {
+			regulator-name = "8644_s4";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1d00 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1d00 {
+				reg = <0x1d00 0x100>;
+			};
+			qcom,ps@1e00 {
+				reg = <0x1e00 0x100>;
+			};
+			qcom,freq@1f00 {
+				reg = <0x1f00 0x100>;
+			};
+		};
+
+		regulator@2000 {
+			regulator-name = "8644_s5";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x2000 0x300>;
+			status = "disabled";
+
+			qcom,ctl@2000 {
+				reg = <0x2000 0x100>;
+			};
+			qcom,ps@2100 {
+				reg = <0x2100 0x100>;
+			};
+			qcom,freq@2200 {
+				reg = <0x2200 0x100>;
+			};
+		};
+
+		regulator@2300 {
+			regulator-name = "8644_s6";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x2300 0x300>;
+			status = "disabled";
+
+			qcom,ctl@2300 {
+				reg = <0x2300 0x100>;
+			};
+			qcom,ps@2400 {
+				reg = <0x2400 0x100>;
+			};
+			qcom,freq@2500 {
+				reg = <0x2500 0x100>;
+			};
+		};
+
+		regulator@2600 {
+			regulator-name = "8644_s7";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x2600 0x300>;
+			status = "disabled";
+
+			qcom,ctl@2600 {
+				reg = <0x2600 0x100>;
+			};
+			qcom,ps@2700 {
+				reg = <0x2700 0x100>;
+			};
+			qcom,freq@2800 {
+				reg = <0x2800 0x100>;
+			};
+		};
+
+		regulator@2900 {
+			regulator-name = "8644_s8";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x2900 0x300>;
+			status = "disabled";
+
+			qcom,ctl@2900 {
+				reg = <0x2900 0x100>;
+			};
+			qcom,ps@2a00 {
+				reg = <0x2a00 0x100>;
+			};
+			qcom,freq@2b00 {
+				reg = <0x2b00 0x100>;
+			};
+		};
+
+		regulator@2c00 {
+			regulator-name = "8644_s9";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x2c00 0x300>;
+			status = "disabled";
+
+			qcom,ctl@2c00 {
+				reg = <0x2c00 0x100>;
+			};
+			qcom,ps@2d00 {
+				reg = <0x2d00 0x100>;
+			};
+			qcom,freq@2e00 {
+				reg = <0x2e00 0x100>;
+			};
+		};
+
+		regulator@2f00 {
+			regulator-name = "8644_s10";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x2f00 0x300>;
+			status = "disabled";
+
+			qcom,ctl@2f00 {
+				reg = <0x2f00 0x100>;
+			};
+			qcom,ps@3000 {
+				reg = <0x3000 0x100>;
+			};
+			qcom,freq@3100 {
+				reg = <0x3100 0x100>;
+			};
+		};
+
+		regulator@3200 {
+			regulator-name = "8644_s11";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x3200 0x300>;
+			status = "disabled";
+
+			qcom,ctl@3200 {
+				reg = <0x3200 0x100>;
+			};
+			qcom,ps@3300 {
+				reg = <0x3300 0x100>;
+			};
+			qcom,freq@3400 {
+				reg = <0x3400 0x100>;
+			};
+		};
+
+		regulator@4000 {
+			regulator-name = "8644_l1";
+			reg = <0x4000 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4100 {
+			regulator-name = "8644_l2";
+			reg = <0x4100 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4200 {
+			regulator-name = "8644_l3";
+			reg = <0x4200 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4300 {
+			regulator-name = "8644_l4";
+			reg = <0x4300 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4400 {
+			regulator-name = "8644_l5";
+			reg = <0x4400 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			qcom,force-type = <0x04 0x10>;
+			status = "disabled";
+		};
+
+		regulator@4500 {
+			regulator-name = "8644_l6";
+			reg = <0x4500 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4600 {
+			regulator-name = "8644_l7";
+			reg = <0x4600 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			qcom,force-type = <0x04 0x10>;
+			status = "disabled";
+		};
+
+		regulator@4700 {
+			regulator-name = "8644_l8";
+			reg = <0x4700 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4800 {
+			regulator-name = "8644_l9";
+			reg = <0x4800 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4900 {
+			regulator-name = "8644_l10";
+			reg = <0x4900 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4a00 {
+			regulator-name = "8644_l11";
+			reg = <0x4a00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4b00 {
+			regulator-name = "8644_l12";
+			reg = <0x4b00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4c00 {
+			regulator-name = "8644_l13";
+			reg = <0x4c00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4d00 {
+			regulator-name = "8644_l14";
+			reg = <0x4d00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4e00 {
+			regulator-name = "8644_l15";
+			reg = <0x4e00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4f00 {
+			regulator-name = "8644_l16";
+			reg = <0x4f00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5000 {
+			regulator-name = "8644_l17";
+			reg = <0x5000 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5100 {
+			regulator-name = "8644_l18";
+			reg = <0x5100 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5200 {
+			regulator-name = "8644_l19";
+			reg = <0x5200 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5300 {
+			regulator-name = "8644_l20";
+			reg = <0x5300 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5400 {
+			regulator-name = "8644_l21";
+			reg = <0x5400 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5500 {
+			regulator-name = "8644_l22";
+			reg = <0x5500 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5600 {
+			regulator-name = "8644_l23";
+			reg = <0x5600 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5700 {
+			regulator-name = "8644_l24";
+			reg = <0x5700 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@5800 {
+			regulator-name = "8644_l25";
+			reg = <0x5800 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@8000 {
+			regulator-name = "8644_lvs1";
+			reg = <0x8000 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@8100 {
+			regulator-name = "8644_lvs2";
+			reg = <0x8100 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@8200 {
+			regulator-name = "8644_mvs1";
+			reg = <0x8200 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@8300 {
+			regulator-name = "8644_mvs2";
+			reg = <0x8300 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index ea83231..1e0e5dfa 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -22,6 +22,15 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		qcom,temp-alarm@2400 {
+			compatible = "qcom,qpnp-temp-alarm";
+			reg = <0x2400 0x100>;
+			interrupts = <0x4 0x24 0x0>;
+			label = "pm8841_tz";
+			qcom,threshold-set = <0>;
+			qcom,default-temp = <37000>;
+		};
+
 		pm8841_mpps: mpps {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 1b18d25..1d95407 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -22,6 +22,15 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		qcom,temp-alarm@2400 {
+			compatible = "qcom,qpnp-temp-alarm";
+			reg = <0x2400 0x100>;
+			interrupts = <0x0 0x24 0x0>;
+			label = "pm8941_tz";
+			qcom,channel-num = <8>;
+			qcom,threshold-set = <0>;
+		};
+
 		qcom,power-on@800 {
 			compatible = "qcom,qpnp-power-on";
 			reg = <0x800 0x100>;
@@ -180,8 +189,8 @@
 						<0 0x13 0x1>,
 						<0x0 0x13 0x2>;
 
-				interrupt-names =	"usbin-valid",
-							"coarse-det-usb",
+				interrupt-names =	"coarse-det-usb",
+							"usbin-valid",
 							"chg-gone";
 			};
 
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index aeda1d8..7c25680 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -11,7 +11,7 @@
  */
 
 /dts-v1/;
-/include/ "skeleton.dtsi"
+/include/ "msm8226.dtsi"
 /include/ "msm8226-ion.dtsi"
 /include/ "msm8226-camera.dtsi"
 
@@ -19,60 +19,8 @@
 	model = "Qualcomm MSM 8226 Simulator";
 	compatible = "qcom,msm8226-sim", "qcom,msm8226";
 	qcom,msm-id = <145 1 0>;
-	interrupt-parent = <&intc>;
-
-	chosen {
-		bootargs ="root=/dev/ram rw init=/init console=ttyHSL0,115200n8 initrd=0x00000000,0x00000000 mem=512M@0x00000000";
-	};
-
-	intc: interrupt-controller@f9000000 {
-		compatible = "qcom,msm-qgic2";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		reg = <0xF9000000 0x1000>,
-		      <0xF9002000 0x1000>;
-	};
-
-	msmgpio: gpio@fd510000 {
-		compatible = "qcom,msm-gpio";
-		interrupt-controller;
-		#interrupt-cells = <2>;
-		reg = <0xfd510000 0x4000>;
-		#gpio-cells = <2>;
-	};
-
-	timer {
-		compatible = "qcom,msm-qtimer", "arm,armv7-timer";
-		interrupts = <1 2 0 1 3 0>;
-		clock-frequency = <19200000>;
-	};
 
 	serial@f991f000 {
-		compatible = "qcom,msm-lsuart-v14";
-		reg = <0xf991f000 0x1000>;
-		interrupts = <0 109 0>;
+		status = "ok";
 	};
-
-	serial@f995e000 {
-		compatible = "qcom,msm-lsuart-v14";
-		reg = <0xf995e000 0x1000>;
-		interrupts = <0 114 0>;
-	};
-
-        usb@f9a55000 {
-                compatible = "qcom,hsusb-otg";
-                reg = <0xf9a55000 0x400>;
-                interrupts = <0 134 0>;
-                interrupt-names = "core_irq";
-
-                qcom,hsusb-otg-phy-type = <2>;
-                qcom,hsusb-otg-mode = <1>;
-                qcom,hsusb-otg-otg-control = <1>;
-                qcom,hsusb-otg-disable-reset;
-        };
-
-	android_usb {
-		compatible = "qcom,android-usb";
-	};
-
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
new file mode 100644
index 0000000..6d2ffec
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -0,0 +1,72 @@
+/* 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/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8226";
+	compatible = "qcom,msm8226";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xF9000000 0x1000>,
+		      <0xF9002000 0x1000>;
+	};
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+		#gpio-cells = <2>;
+	};
+
+	timer {
+		compatible = "qcom,msm-qtimer", "arm,armv7-timer";
+		interrupts = <1 2 0 1 3 0>;
+		clock-frequency = <19200000>;
+	};
+
+	serial@f991f000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991f000 0x1000>;
+		interrupts = <0 109 0>;
+		status = "disabled";
+	};
+
+	serial@f995e000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf995e000 0x1000>;
+		interrupts = <0 114 0>;
+		status = "disabled";
+	};
+
+        usb@f9a55000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0xf9a55000 0x400>;
+		interrupts = <0 134 0>;
+		interrupt-names = "core_irq";
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-disable-reset;
+	};
+
+	android_usb {
+		compatible = "qcom,android-usb";
+	};
+
+};
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index c8a0f9c..83dabfb 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -45,4 +45,21 @@
 		interrupts = <0 109 0>;
 		status = "disabled";
 	};
+
+	usb@f9a55000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0xf9a55000 0x400>;
+		interrupts = <0 134 0>;
+		interrupt-names = "core_irq";
+
+		qcom,hsusb-otg-phy-type = <2>;
+		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-otg-control = <1>;
+		qcom,hsusb-otg-disable-reset;
+	};
+
+	android_usb {
+		compatible = "qcom,android-usb";
+	};
+
 };
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index 6d00b01..4fe0eda 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -26,7 +26,7 @@
 		qcom,idle-timeout = <83>; //<HZ/12>
 		qcom,nap-allowed = <1>;
 		qcom,strtstp-sleepwake;
-		qcom,clk-map = <0x00000016>; //KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE
+		qcom,clk-map = <0x0000006>; //KGSL_CLK_CORE | KGSL_CLK_IFACE
 
 		/* Bus Scale Settings */
 		qcom,grp3d-vectors = <0 0 0 0>, <2 1 0 0>,
diff --git a/arch/arm/boot/dts/msm8974-liquid.dts b/arch/arm/boot/dts/msm8974-liquid.dts
index bc682ea..8b4a3a3 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-liquid.dts
@@ -58,6 +58,101 @@
 	qcom,hdmi_tx@fd922100 {
 		status = "ok";
 	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l22>;
+			vcc_i2c-supply = <&pm8941_s3>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0 0 1080 1920>;
+			atmel,display-coords = <0 0 1080 1920>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0xa2>;
+				atmel,variant-id = <0x00>;
+				atmel,version = <0x11>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					16 00 00 14 09 0C 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 0A 03
+					/* Object 8, Instance = 0 */
+					5F 00 14 14 00 00 00 01 00 00
+					/* Object 9, Instance = 0 */
+					8F 00 00 20 34 00 87 3C 08 03
+					00 05 03 80 0A 14 14 0A 80 07
+					38 04 00 00 00 00 00 00 00 00
+					0F 0F 2E 33 02 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					04 00
+					/* Object 24, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 54 6F F0 55 00 00 00 00
+					00 00 00 00 00
+					/* Object 27, Instance = 0 */
+					00 00 00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 14 14 14 14
+					/* Object 42, Instance = 0 */
+					20 14 00 00 00 14 11 00 03 00
+					/* Object 43, Instance = 0 */
+					09 00 01 01 91 00 80 00 00 00
+					00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 01 00 00 0F
+					0A
+					/* Object 47, Instance = 0 */
+					00 14 23 02 05 1E 01 78 03 10
+					00 00 0C 00 00 00 00 00 00 00
+					00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					02 00 01 30 13 14 14 14 15 15
+					15 15 15 15 15 16 16 16 16 16
+					16 16 16 16 16 15 14 14 14 14
+					15 14 14 14 14 13 00 00 01 02
+					05 05 00 00 00 00 00 00 00 00
+					00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					00 01 03 01 00 00 00 00 00 0A
+					0F 14 19 23 05 00 0A 05 05 69
+					23 23 34 11 64 06 06 04 40 00
+					00 00 00 00 69 4B 02 00 00 80
+					0A 14 14 18 18 10 10 80 00 80
+					00 00 0F 02 00 00 00 00 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00
+					/* Object 63, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					];
+			};
+		};
+	};
 };
 
 &pm8941_gpios {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 615a387..8d54585 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -659,7 +659,7 @@
 		reg = <0xfe200000 0x00100>,
 		      <0xfd485100 0x00010>;
 		reg-names = "qdsp6_base", "halt_base";
-		interrupts = <0 194 1>;
+		interrupts = <0 162 1>;
 
 		qcom,firmware-name = "adsp";
 	};
@@ -820,7 +820,7 @@
 		reg = <0xfc820000 0x0020>,
 		      <0x0d1fc000 0x4000>;
 		reg-names = "rmb_base", "metadata_base";
-		interrupts = <0 56 1>;
+		interrupts = <0 24 1>;
 
 		qcom,firmware-name = "modem";
 		qcom,depends-on    = "mba";
@@ -832,7 +832,7 @@
 		      <0xfc401700 0x4>,
 		      <0xfd485300 0xc>;
 		reg-names = "pmu_base", "clk_base", "halt_base";
-		interrupts = <0 181 1>;
+		interrupts = <0 149 1>;
 		vdd_pronto_pll-supply = <&pm8941_l12>;
 
 		qcom,firmware-name = "wcnss";
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 6b8a374..b4574aa 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -67,6 +67,7 @@
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
+	u32 saved_dist_isr[DIV_ROUND_UP(1020, 32)];
 	struct irq_domain *domain;
 	unsigned int gic_irqs;
 #ifdef CONFIG_GIC_NON_BANKED
@@ -640,6 +641,11 @@
 	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
 		gic_data[gic_nr].saved_spi_enable[i] =
 			readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+	if (is_cpu_secure()) {
+		for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+			gic_data[gic_nr].saved_dist_isr[i] =
+				readl_relaxed(dist_base + GIC_DIST_ISR + i * 4);
+	}
 }
 
 /*
@@ -682,6 +688,12 @@
 		writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
 			dist_base + GIC_DIST_ENABLE_SET + i * 4);
 
+	if (is_cpu_secure()) {
+		for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+			writel_relaxed(gic_data[gic_nr].saved_dist_isr[i],
+					dist_base + GIC_DIST_ISR + i * 4);
+	}
+
 	writel_relaxed(saved_dist_ctrl, dist_base + GIC_DIST_CTRL);
 }
 
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index f7fb77b..76650e0 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -253,6 +253,7 @@
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
 # CONFIG_I2C_MSM is not set
 CONFIG_I2C_QUP=y
 CONFIG_DEBUG_GPIO=y
@@ -262,6 +263,7 @@
 CONFIG_BATTERY_MSM=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_MARIMBA_CORE=y
+CONFIG_REGULATOR_ONSEMI_NCP6335D=y
 CONFIG_REGULATOR_MSM_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 1145c0b..8ab57de 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -255,6 +255,7 @@
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
 # CONFIG_I2C_MSM is not set
 CONFIG_I2C_QUP=y
 CONFIG_DEBUG_GPIO=y
@@ -264,6 +265,7 @@
 CONFIG_BATTERY_MSM=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_MARIMBA_CORE=y
+CONFIG_REGULATOR_ONSEMI_NCP6335D=y
 CONFIG_REGULATOR_MSM_GPIO=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index ebcc6f5..a9dadee 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -35,6 +35,7 @@
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -46,6 +47,9 @@
 CONFIG_USE_OF=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_NETFILTER=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_ANDROID_PMEM is not set
@@ -56,15 +60,21 @@
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
 CONFIG_SERIO_LIBPS2=y
-# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 1558e11..53e6260 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -244,6 +244,7 @@
 CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_TSPP=m
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_PMIC8XXX_VIBRATOR=y
 CONFIG_QSEECOM=y
@@ -340,6 +341,7 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_DVB_CORE=m
 CONFIG_USER_RC_INPUT=y
 CONFIG_IR_GPIO_CIR=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -367,6 +369,11 @@
 CONFIG_MSM_WFD=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_VIDEO=m
+CONFIG_DVB_MPQ_TSPP1=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 981cdce..5770859 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -249,6 +249,7 @@
 CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_TSPP=m
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_PMIC8XXX_VIBRATOR=y
 CONFIG_QSEECOM=y
@@ -345,6 +346,7 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_DVB_CORE=m
 CONFIG_USER_RC_INPUT=y
 CONFIG_IR_GPIO_CIR=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -371,6 +373,11 @@
 CONFIG_MSM_WFD=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_VIDEO=m
+CONFIG_DVB_MPQ_TSPP1=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 9d2b7f3..d8d2eae 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -279,6 +279,7 @@
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_QPNP=y
 CONFIG_WCD9320_CODEC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_STUB=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 6b13eaf..6a62f8c 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -6,6 +6,7 @@
 endif
 obj-y += clock.o clock-voter.o clock-dummy.o
 obj-y += modem_notifier.o subsystem_map.o
+obj-$(CONFIG_USE_OF) += board-dt.o
 obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
 obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
 obj-$(CONFIG_KEXEC) += msm_kexec.o
@@ -288,7 +289,7 @@
 obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
-obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-gpiomux.o
+obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-8974-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
 obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o clock-mdss-8974.o
 obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
diff --git a/arch/arm/mach-msm/acpuclock-7627.c b/arch/arm/mach-msm/acpuclock-7627.c
index 5c4a923..dd27123 100644
--- a/arch/arm/mach-msm/acpuclock-7627.c
+++ b/arch/arm/mach-msm/acpuclock-7627.c
@@ -85,10 +85,12 @@
 };
 
 static struct pll_config pll4_cfg_tbl[] = {
-	{  36, 1, 2 }, /*  700.8 MHz */
-	{  52, 1, 2 }, /* 1008 MHz */
-	{  63, 0, 1 }, /* 1209.6 MHz */
-	{  73, 0, 1 }, /* 1401.6 MHz */
+	[0] = {  36, 1, 2 }, /*  700.8 MHz */
+	[1] = {  52, 1, 2 }, /* 1008 MHz */
+	[2] = {  63, 0, 1 }, /* 1209.6 MHz */
+	[3] = {  73, 0, 1 }, /* 1401.6 MHz */
+	[4] = {  60, 0, 1 }, /* 1152 MHz */
+	[5] = {  57, 1, 2 }, /* 1104 MHz */
 };
 
 struct clock_state {
@@ -266,8 +268,8 @@
 static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_1209[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
 	{ 0, 65536, ACPU_PLL_1, 1, 3,  8192, 3, 1, 49152 },
-	{ 0, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 2, 49152 },
-	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
+	{ 0, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 1, 49152 },
+	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 1, 98304 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
 	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
@@ -298,8 +300,8 @@
 static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_1401[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
 	{ 0, 65536, ACPU_PLL_1, 1, 3,  8192, 3, 1, 49152 },
-	{ 0, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 2, 49152 },
-	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
+	{ 0, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 1, 49152 },
+	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 1, 98304 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
 	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
@@ -310,7 +312,7 @@
 	{ 0 }
 };
 
-/* 8625v2.0 PLL4 @ 1008MHz with GSM capable modem */
+/* 8625 PLL4 @ 1008MHz with GSM capable modem */
 static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_pll4_1008_2p0[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
 	{ 0, 61440, ACPU_PLL_1, 1, 3,  7680, 3, 0, 61440 },
@@ -325,12 +327,12 @@
 	{ 0 }
 };
 
-/* 8625v2.0 PLL4 @ 1008MHz with CDMA capable modem */
+/* 8625 PLL4 @ 1008MHz with CDMA capable modem */
 static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_1008_2p0[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
 	{ 0, 65536, ACPU_PLL_1, 1, 3,  8192, 3, 1, 49152 },
-	{ 0, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 2, 49152 },
-	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
+	{ 0, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 1, 49152 },
+	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 1, 98304 },
 	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
 	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
 	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
@@ -339,35 +341,58 @@
 	{ 0 }
 };
 
-/* 8625 PLL4 @ 1152MHz with GSM capable modem */
+/* 8625 PLL4 @ 1104MHz with GSM capable modem with v2.0 plan */
+static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_pll4_1104[] = {
+	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
+	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 1, 61440 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
+	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
+	{ 1, 700800, ACPU_PLL_4, 6, 0, 87500, 3, 4, 160000, &pll4_cfg_tbl[0]},
+	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 5, 200000, &pll4_cfg_tbl[1]},
+	{ 1, 1104000, ACPU_PLL_4, 6, 0, 151200, 3, 6, 200000, &pll4_cfg_tbl[5]},
+	{ 0 }
+};
+
+/* 8625 PLL4 @ 1104MHz with CDMA capable modem with v2.0 plan */
+static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_1104[] = {
+	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
+	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 1, 98304 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
+	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
+	{ 1, 700800, ACPU_PLL_4, 6, 0, 87500, 3, 4, 160000, &pll4_cfg_tbl[0]},
+	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 5, 200000, &pll4_cfg_tbl[1]},
+	{ 1, 1104000, ACPU_PLL_4, 6, 0, 151200, 3, 6, 200000, &pll4_cfg_tbl[5]},
+	{ 0 }
+};
+
+/* 8625 PLL4 @ 1152MHz with GSM capable modem with v2.0 plan */
 static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_pll4_1152[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
-	{ 0, 61440, ACPU_PLL_1, 1, 3,  7680, 3, 1, 61440 },
-	{ 1, 122880, ACPU_PLL_1, 1, 1,  15360, 3, 2, 61440 },
-	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 3, 61440 },
-	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
-	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
-	{ 0, 576000, ACPU_PLL_4, 6, 1, 72000, 3, 6, 160000 },
-	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
-	{ 1, 1152000, ACPU_PLL_4, 6, 0, 144000, 3, 7, 200000},
+	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, 1, 61440 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
+	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
+	{ 1, 700800, ACPU_PLL_4, 6, 0, 87500, 3, 4, 160000, &pll4_cfg_tbl[0]},
+	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 5, 200000, &pll4_cfg_tbl[1]},
+	{ 1, 1152000, ACPU_PLL_4, 6, 0, 151200, 3, 6, 200000, &pll4_cfg_tbl[4]},
 	{ 0 }
 };
 
-/* 8625 PLL4 @ 1115MHz with CDMA capable modem */
+/* 8625 PLL4 @ 1115MHz with CDMA capable modem with v2.0 plan */
 static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_1152[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
-	{ 0, 65536, ACPU_PLL_1, 1, 3,  8192, 3, 1, 49152 },
-	{ 1, 98304, ACPU_PLL_1, 1, 1,  12288, 3, 2, 49152 },
-	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 3, 98304 },
-	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
-	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
-	{ 0, 576000, ACPU_PLL_4, 6, 1, 72000, 3, 6, 160000 },
-	{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 160000 },
-	{ 1, 1152000, ACPU_PLL_4, 6, 0, 144000, 3, 7, 200000},
+	{ 1, 196608, ACPU_PLL_1, 1, 0, 24576, 3, 1, 98304 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 2, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 3, 122880 },
+	{ 0, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 4, 160000 },
+	{ 1, 700800, ACPU_PLL_4, 6, 0, 87500, 3, 4, 160000, &pll4_cfg_tbl[0]},
+	{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 5, 200000, &pll4_cfg_tbl[1]},
+	{ 1, 1152000, ACPU_PLL_4, 6, 0, 151200, 3, 6, 200000, &pll4_cfg_tbl[4]},
 	{ 0 }
 };
 
-
 /* 7625a PLL2 @ 1200MHz with GSM capable modem */
 static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_25a[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
@@ -486,6 +511,8 @@
 	PLL_CONFIG(960, 196, 1200, 1209),
 	PLL_CONFIG(960, 245, 1200, 1152),
 	PLL_CONFIG(960, 196, 1200, 1152),
+	PLL_CONFIG(960, 245, 1200, 1104),
+	PLL_CONFIG(960, 196, 1200, 1104),
 	PLL_CONFIG(960, 245, 1200, 1401),
 	PLL_CONFIG(960, 196, 1200, 1401),
 	{ 0, 0, 0, 0, 0 }
@@ -754,7 +781,7 @@
 		acpuclk_set_div(tgt_s);
 		drv_state.current_speed = tgt_s;
 		/* Re-adjust lpj for the new clock speed. */
-		update_jiffies(cpu, cur_s->lpj);
+		update_jiffies(cpu, tgt_s->lpj);
 
 		/* Disable the backup PLL */
 		if ((delta > drv_state.max_speed_delta_khz)
@@ -987,14 +1014,10 @@
 
 	/*
 	 * 1008Mhz table selection based on the Lvalue of the PLL
-	 * is conflicting with the 7627AA and 8625 v1.0 1GHz parts
-	 * since v2.0 8625 chips are using different clock plan based
-	 * reprogramming method.
+	 * is conflicting with the 7627AA 1GHz parts since 8625 chips
+	 * are using different clock plan based reprogramming method.
 	 */
-	if (cpu_is_msm8625() &&
-		(SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) &&
-		pll_mhz[ACPU_PLL_4] == 1008) {
-
+	if (cpu_is_msm8625() &&	pll_mhz[ACPU_PLL_4] == 1008) {
 		if (pll_mhz[ACPU_PLL_2] == 245)
 			acpu_freq_tbl =
 				pll0_960_pll1_245_pll2_1200_pll4_1008_2p0;
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 56c3241..265f7f0 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -246,7 +246,7 @@
 
 static struct msm_panel_common_pdata mdp_pdata = {
 	.gpio = MDP_VSYNC_GPIO,
-	.mdp_max_clk = 200000000,
+	.mdp_max_clk = 266667000,
 	.mdp_bus_scale_table = &mdp_bus_scale_pdata,
 	.mdp_rev = MDP_REV_44,
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f192bc8..9e5e4f5 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -450,59 +450,27 @@
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	unsigned int i;
-	unsigned int reusable_count = 0;
 	unsigned int fixed_size = 0;
 	unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
 	unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
 
-	apq8064_fmem_pdata.size = 0;
-	apq8064_fmem_pdata.reserved_size_low = 0;
-	apq8064_fmem_pdata.reserved_size_high = 0;
-	apq8064_fmem_pdata.align = PAGE_SIZE;
 	fixed_low_size = 0;
 	fixed_middle_size = 0;
 	fixed_high_size = 0;
 
-	/* We only support 1 reusable heap. Check if more than one heap
-	 * is specified as reusable and set as non-reusable if found.
-	 */
-	for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
-		const struct ion_platform_heap *heap =
-			&(apq8064_ion_pdata.heaps[i]);
-
-		if (heap->type == (enum ion_heap_type) ION_HEAP_TYPE_CP
-			&& heap->extra_data) {
-			struct ion_cp_heap_pdata *data = heap->extra_data;
-
-			reusable_count += (data->reusable) ? 1 : 0;
-
-			if (data->reusable && reusable_count > 1) {
-				pr_err("%s: Too many heaps specified as "
-					"reusable. Heap %s was not configured "
-					"as reusable.\n", __func__, heap->name);
-				data->reusable = 0;
-			}
-		}
-	}
-
 	for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
 		const struct ion_platform_heap *heap =
 			&(apq8064_ion_pdata.heaps[i]);
 
 		if (heap->extra_data) {
 			int fixed_position = NOT_FIXED;
-			int mem_is_fmem = 0;
 
 			switch ((int)heap->type) {
 			case ION_HEAP_TYPE_CP:
-				mem_is_fmem = ((struct ion_cp_heap_pdata *)
-					heap->extra_data)->mem_is_fmem;
 				fixed_position = ((struct ion_cp_heap_pdata *)
 					heap->extra_data)->fixed_position;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
-				mem_is_fmem = ((struct ion_co_heap_pdata *)
-					heap->extra_data)->mem_is_fmem;
 				fixed_position = ((struct ion_co_heap_pdata *)
 					heap->extra_data)->fixed_position;
 				break;
@@ -521,21 +489,12 @@
 				fixed_middle_size += heap->size;
 			else if (fixed_position == FIXED_HIGH)
 				fixed_high_size += heap->size;
-
-			if (mem_is_fmem)
-				apq8064_fmem_pdata.size += heap->size;
 		}
 	}
 
 	if (!fixed_size)
 		return;
 
-	if (apq8064_fmem_pdata.size) {
-		apq8064_fmem_pdata.reserved_size_low = fixed_low_size +
-								HOLE_SIZE;
-		apq8064_fmem_pdata.reserved_size_high = fixed_high_size;
-	}
-
 	/* Since the fixed area may be carved out of lowmem,
 	 * make sure the length is a multiple of 1M.
 	 */
@@ -709,19 +668,6 @@
 	apq8064_set_display_params(prim_panel_name, ext_panel_name,
 		ext_resolution);
 	msm_reserve();
-	if (apq8064_fmem_pdata.size) {
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-		if (reserve_info->fixed_area_size) {
-			apq8064_fmem_pdata.phys =
-				reserve_info->fixed_area_start + MSM_MM_FW_SIZE;
-			pr_info("mm fw at %lx (fixed) size %x\n",
-				reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
-			pr_info("fmem start %lx (fixed) size %lx\n",
-				apq8064_fmem_pdata.phys,
-				apq8064_fmem_pdata.size);
-		}
-#endif
-	}
 }
 
 static void __init place_movable_zone(void)
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index e2ef969..bd1762d 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -24,6 +24,7 @@
 #include <mach/socinfo.h>
 #include <mach/board.h>
 #include <mach/msm_memtypes.h>
+#include <mach/qpnp-int.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
@@ -34,6 +35,7 @@
 static struct of_device_id irq_match[] __initdata  = {
 	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
 	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+	{ .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
 	{}
 };
 
@@ -109,6 +111,8 @@
 static struct of_dev_auxdata mpq8092_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
 			"msm_serial_hsl.0", NULL),
+	OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
+			"spmi-pmic-arb.0", NULL),
 	{}
 };
 
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 767736f..b27382f 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -44,10 +44,10 @@
 #include "clock.h"
 
 static struct clk_lookup msm_clocks_dummy[] = {
-	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
-	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "msm_serial_hsl.0", OFF),
-	CLK_DUMMY("iface_clk",  HSUSB_IFACE_CLK, "msm_otg", OFF),
-	CLK_DUMMY("core_clk",	HSUSB_CORE_CLK, "msm_otg", OFF),
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk",  HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
+	CLK_DUMMY("core_clk",	HSUSB_CORE_CLK, "f9a55000.usb", OFF),
 };
 
 struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -61,14 +61,6 @@
 	{}
 };
 
-static struct of_dev_auxdata msm8226_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
-			"msm_serial_hsl.0", NULL),
-	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
-			"msm_otg", NULL),
-	{}
-};
-
 static void __init msm8226_dt_timer_init(void)
 {
 	arch_timer_of_register();
@@ -83,24 +75,21 @@
 	of_irq_init(irq_match);
 }
 
-void __init msm8226_init(struct of_dev_auxdata **adata)
+void __init msm8226_init(void)
 {
 	msm8226_init_gpiomux();
 
 	msm_clock_init(&msm_dummy_clock_init_data);
-
-	*adata = msm8226_auxdata_lookup;
 }
 
 void __init msm8226_dt_init(void)
 {
-	struct of_dev_auxdata *adata = NULL;
-	msm8226_init(&adata);
+	msm8226_init();
 
 	if (socinfo_init() < 0)
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
-	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 
diff --git a/arch/arm/mach-msm/board-8910.c b/arch/arm/mach-msm/board-8910.c
index 18463e3..1c92494f 100644
--- a/arch/arm/mach-msm/board-8910.c
+++ b/arch/arm/mach-msm/board-8910.c
@@ -42,6 +42,8 @@
 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),
+	CLK_DUMMY("iface_clk",  HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
+	CLK_DUMMY("core_clk",	HSUSB_CORE_CLK, "f9a55000.usb", OFF),
 };
 
 struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index f0f59ec..05d2fe1 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -498,59 +498,27 @@
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	unsigned int i;
-	unsigned int reusable_count = 0;
 	unsigned int fixed_size = 0;
 	unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
 	unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
 
-	msm8930_fmem_pdata.size = 0;
-	msm8930_fmem_pdata.reserved_size_low = 0;
-	msm8930_fmem_pdata.reserved_size_high = 0;
-	msm8930_fmem_pdata.align = PAGE_SIZE;
 	fixed_low_size = 0;
 	fixed_middle_size = 0;
 	fixed_high_size = 0;
 
-	/* We only support 1 reusable heap. Check if more than one heap
-	 * is specified as reusable and set as non-reusable if found.
-	 */
-	for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
-		const struct ion_platform_heap *heap =
-						&(msm8930_ion_pdata.heaps[i]);
-
-		if (heap->type == (enum ion_heap_type) ION_HEAP_TYPE_CP
-			&& heap->extra_data) {
-			struct ion_cp_heap_pdata *data = heap->extra_data;
-
-			reusable_count += (data->reusable) ? 1 : 0;
-
-			if (data->reusable && reusable_count > 1) {
-				pr_err("%s: Too many heaps specified as "
-					"reusable. Heap %s was not configured "
-					"as reusable.\n", __func__, heap->name);
-				data->reusable = 0;
-			}
-		}
-	}
-
 	for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
 		const struct ion_platform_heap *heap =
 						&(msm8930_ion_pdata.heaps[i]);
 
 		if (heap->extra_data) {
 			int fixed_position = NOT_FIXED;
-			int mem_is_fmem = 0;
 
 			switch ((int) heap->type) {
 			case ION_HEAP_TYPE_CP:
-				mem_is_fmem = ((struct ion_cp_heap_pdata *)
-					heap->extra_data)->mem_is_fmem;
 				fixed_position = ((struct ion_cp_heap_pdata *)
 					heap->extra_data)->fixed_position;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
-				mem_is_fmem = ((struct ion_co_heap_pdata *)
-					heap->extra_data)->mem_is_fmem;
 				fixed_position = ((struct ion_co_heap_pdata *)
 					heap->extra_data)->fixed_position;
 				break;
@@ -570,20 +538,12 @@
 			else if (fixed_position == FIXED_HIGH)
 				fixed_high_size += heap->size;
 
-			if (mem_is_fmem)
-				msm8930_fmem_pdata.size += heap->size;
 		}
 	}
 
 	if (!fixed_size)
 		return;
 
-	if (msm8930_fmem_pdata.size) {
-		msm8930_fmem_pdata.reserved_size_low = fixed_low_size +
-							HOLE_SIZE;
-		msm8930_fmem_pdata.reserved_size_high = fixed_high_size;
-	}
-
 	/* Since the fixed area may be carved out of lowmem,
 	 * make sure the length is a multiple of 1M.
 	 */
@@ -755,18 +715,6 @@
 {
 	msm8930_set_display_params(prim_panel_name, ext_panel_name);
 	msm_reserve();
-	if (msm8930_fmem_pdata.size) {
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-		if (reserve_info->fixed_area_size) {
-			msm8930_fmem_pdata.phys =
-				reserve_info->fixed_area_start + MSM_MM_FW_SIZE;
-		pr_info("mm fw at %lx (fixed) size %x\n",
-			reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
-		pr_info("fmem start %lx (fixed) size %lx\n",
-			msm8930_fmem_pdata.phys, msm8930_fmem_pdata.size);
-		}
-#endif
-	}
 }
 
 static int msm8930_change_memory_power(u64 start, u64 size,
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 1771bb9..fe37f2a 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -449,6 +449,13 @@
 		},
 	},
 	{
+		.gpio      = 26,	/* GSBI6 WLAN_PWD_L for AR6004 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi6_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi6_active_cfg,
+		},
+	},
+	{
 		.gpio      = 27,        /* GSBI6 BT_INT2AP_N for AR3002 */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gsbi6_suspended_cfg,
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index 67f44aa..ded5bad 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -327,9 +327,11 @@
 #endif
 	.vreg_data	= &mmc_slot_vreg_data[SDCC3],
 	.pin_data	= &mmc_slot_pin_data[SDCC3],
+#ifndef CONFIG_MMC_MSM_SDC3_POLLING
 	.status_gpio	= PM8921_GPIO_PM_TO_SYS(26),
 	.status_irq	= PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 26),
 	.irq_flags	= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+#endif
 	.is_status_gpio_active_low = true,
 	.xpc_cap	= 1,
 	.uhs_caps	= (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 7e96edf..4a78e31 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -103,6 +103,11 @@
 #include "pm-boot.h"
 #include "msm_watchdog.h"
 
+#if defined(CONFIG_BT) && defined(CONFIG_BT_HCIUART_ATH3K)
+#include <linux/wlan_plat.h>
+#include <linux/mutex.h>
+#endif
+
 static struct platform_device msm_fm_platform_init = {
 	.name = "iris_fm",
 	.id   = -1,
@@ -541,42 +546,15 @@
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	unsigned int i;
-	unsigned int reusable_count = 0;
 	unsigned int fixed_size = 0;
 	unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
 	unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
 
 	adjust_mem_for_liquid();
-	msm8960_fmem_pdata.size = 0;
-	msm8960_fmem_pdata.reserved_size_low = 0;
-	msm8960_fmem_pdata.reserved_size_high = 0;
-	msm8960_fmem_pdata.align = PAGE_SIZE;
 	fixed_low_size = 0;
 	fixed_middle_size = 0;
 	fixed_high_size = 0;
 
-	/* We only support 1 reusable heap. Check if more than one heap
-	 * is specified as reusable and set as non-reusable if found.
-	 */
-	for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
-		const struct ion_platform_heap *heap =
-						&(msm8960_ion_pdata.heaps[i]);
-
-		if (heap->type == (enum ion_heap_type) ION_HEAP_TYPE_CP
-			&& heap->extra_data) {
-			struct ion_cp_heap_pdata *data = heap->extra_data;
-
-			reusable_count += (data->reusable) ? 1 : 0;
-
-			if (data->reusable && reusable_count > 1) {
-				pr_err("%s: Too many heaps specified as "
-					"reusable. Heap %s was not configured "
-					"as reusable.\n", __func__, heap->name);
-				data->reusable = 0;
-			}
-		}
-	}
-
 	for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
 		struct ion_platform_heap *heap =
 						&(msm8960_ion_pdata.heaps[i]);
@@ -586,12 +564,9 @@
 
 		if (heap->extra_data) {
 			int fixed_position = NOT_FIXED;
-			int mem_is_fmem = 0;
 
 			switch ((int) heap->type) {
 			case ION_HEAP_TYPE_CP:
-				mem_is_fmem = ((struct ion_cp_heap_pdata *)
-					heap->extra_data)->mem_is_fmem;
 				fixed_position = ((struct ion_cp_heap_pdata *)
 					heap->extra_data)->fixed_position;
 				align = ((struct ion_cp_heap_pdata *)
@@ -601,8 +576,6 @@
 					heap->extra_data)->iommu_map_all;
 				break;
 			case ION_HEAP_TYPE_CARVEOUT:
-				mem_is_fmem = ((struct ion_co_heap_pdata *)
-					heap->extra_data)->mem_is_fmem;
 				fixed_position = ((struct ion_co_heap_pdata *)
 					heap->extra_data)->fixed_position;
 				adjacent_mem_id = ((struct ion_co_heap_pdata *)
@@ -620,9 +593,6 @@
 				}
 			}
 
-			if (mem_is_fmem && adjacent_mem_id != INVALID_HEAP_ID)
-				msm8960_fmem_pdata.align = align;
-
 			if (fixed_position != NOT_FIXED)
 				fixed_size += heap->size;
 			else
@@ -634,21 +604,12 @@
 				fixed_middle_size += heap->size;
 			else if (fixed_position == FIXED_HIGH)
 				fixed_high_size += heap->size;
-
-			if (mem_is_fmem)
-				msm8960_fmem_pdata.size += heap->size;
 		}
 	}
 
 	if (!fixed_size)
 		return;
 
-	if (msm8960_fmem_pdata.size) {
-		msm8960_fmem_pdata.reserved_size_low = fixed_low_size +
-							HOLE_SIZE;
-		msm8960_fmem_pdata.reserved_size_high = fixed_high_size;
-	}
-
 	/* Since the fixed area may be carved out of lowmem,
 	 * make sure the length is a multiple of 1M.
 	 */
@@ -818,19 +779,6 @@
 {
 	msm8960_set_display_params(prim_panel_name, ext_panel_name);
 	msm_reserve();
-	if (msm8960_fmem_pdata.size) {
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-		if (reserve_info->fixed_area_size) {
-			msm8960_fmem_pdata.phys =
-				reserve_info->fixed_area_start + MSM_MM_FW_SIZE;
-			pr_info("mm fw at %lx (fixed) size %x\n",
-				reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
-			pr_info("fmem start %lx (fixed) size %lx\n",
-				msm8960_fmem_pdata.phys,
-				msm8960_fmem_pdata.size);
-		}
-#endif
-	}
 }
 
 static int msm8960_change_memory_power(u64 start, u64 size,
@@ -2602,6 +2550,76 @@
 #endif
 
 #if defined(CONFIG_BT) && defined(CONFIG_BT_HCIUART_ATH3K)
+enum WLANBT_STATUS {
+	WLANOFF_BTOFF = 1,
+	WLANOFF_BTON,
+	WLANON_BTOFF,
+	WLANON_BTON
+};
+
+static DEFINE_MUTEX(ath_wlanbt_mutex);
+static int gpio_wlan_sys_rest_en = 26;
+static int ath_wlanbt_status = WLANOFF_BTOFF;
+
+static int ath6kl_power_control(int on)
+{
+	int rc;
+
+	if (on) {
+		rc = gpio_request(gpio_wlan_sys_rest_en, "wlan sys_rst_n");
+		if (rc) {
+			pr_err("%s: unable to request gpio %d (%d)\n",
+				__func__, gpio_wlan_sys_rest_en, rc);
+			return rc;
+		}
+		rc = gpio_direction_output(gpio_wlan_sys_rest_en, 0);
+		msleep(200);
+		rc = gpio_direction_output(gpio_wlan_sys_rest_en, 1);
+		msleep(100);
+	} else {
+		gpio_set_value(gpio_wlan_sys_rest_en, 0);
+		rc = gpio_direction_input(gpio_wlan_sys_rest_en);
+		msleep(100);
+		gpio_free(gpio_wlan_sys_rest_en);
+	}
+	return 0;
+};
+
+static int ath6kl_wlan_power(int on)
+{
+	int ret = 0;
+
+	mutex_lock(&ath_wlanbt_mutex);
+	if (on) {
+		if (ath_wlanbt_status == WLANOFF_BTOFF) {
+			ret = ath6kl_power_control(1);
+			ath_wlanbt_status = WLANON_BTOFF;
+		} else if (ath_wlanbt_status == WLANOFF_BTON)
+			ath_wlanbt_status = WLANON_BTON;
+	} else {
+		if (ath_wlanbt_status == WLANON_BTOFF) {
+			ret = ath6kl_power_control(0);
+			ath_wlanbt_status = WLANOFF_BTOFF;
+		} else if (ath_wlanbt_status == WLANON_BTON)
+			ath_wlanbt_status = WLANOFF_BTON;
+	}
+	mutex_unlock(&ath_wlanbt_mutex);
+	pr_debug("%s on= %d, wlan_status= %d\n",
+		__func__, on, ath_wlanbt_status);
+	return ret;
+};
+
+static struct wifi_platform_data ath6kl_wifi_control = {
+	.set_power      = ath6kl_wlan_power,
+};
+
+static struct platform_device msm_wlan_power_device = {
+	.name = "ath6kl_power",
+	.dev            = {
+		.platform_data = &ath6kl_wifi_control,
+	},
+};
+
 static struct resource bluesleep_resources[] = {
 	{
 		.name   = "gpio_host_wake",
@@ -2634,50 +2652,54 @@
 	.name = "bt_power",
 };
 
-int gpio_bt_sys_rest_en = 28;
+static int gpio_bt_sys_rest_en = 28;
 
 static int bluetooth_power(int on)
 {
 	int rc;
 
-	pr_debug("%s on= %d\n", __func__, on);
-
+	mutex_lock(&ath_wlanbt_mutex);
 	if (on) {
+		if (ath_wlanbt_status == WLANOFF_BTOFF) {
+			ath6kl_power_control(1);
+			ath_wlanbt_status = WLANOFF_BTON;
+		} else if (ath_wlanbt_status == WLANON_BTOFF)
+			ath_wlanbt_status = WLANON_BTON;
+
 		rc = gpio_request(gpio_bt_sys_rest_en, "bt sys_rst_n");
 		if (rc) {
 			pr_err("%s: unable to request gpio %d (%d)\n",
 				__func__, gpio_bt_sys_rest_en, rc);
-			goto out;
+			mutex_unlock(&ath_wlanbt_mutex);
+			return rc;
 		}
 		rc = gpio_direction_output(gpio_bt_sys_rest_en, 0);
-		if (rc) {
-			pr_err("%s: Unable to set gpio %d direction\n",
-				__func__, gpio_bt_sys_rest_en);
-			goto free_gpio;
-		}
+		msleep(20);
+		rc = gpio_direction_output(gpio_bt_sys_rest_en, 1);
 		msleep(100);
-		gpio_set_value(gpio_bt_sys_rest_en, 1);
-		msleep(100);
-		goto out;
 	} else {
 		gpio_set_value(gpio_bt_sys_rest_en, 0);
 		rc = gpio_direction_input(gpio_bt_sys_rest_en);
 		msleep(100);
-	}
+		gpio_free(gpio_bt_sys_rest_en);
 
-free_gpio:
-	gpio_free(gpio_bt_sys_rest_en);
-out:
-	return rc;
-}
+		if (ath_wlanbt_status == WLANOFF_BTON) {
+			ath6kl_power_control(0);
+			ath_wlanbt_status = WLANOFF_BTOFF;
+		} else if (ath_wlanbt_status == WLANON_BTON)
+			ath_wlanbt_status = WLANON_BTOFF;
+	}
+	mutex_unlock(&ath_wlanbt_mutex);
+	pr_debug("%s on= %d, wlan_status= %d\n",
+		__func__, on, ath_wlanbt_status);
+	return 0;
+};
 
 static void __init bt_power_init(void)
 {
-	pr_debug("%s enter\n", __func__);
 	msm_bt_power_device.dev.platform_data = &bluetooth_power;
-
 	return;
-}
+};
 #else
 #define bt_power_init(x) do {} while (0)
 #endif
@@ -2703,6 +2725,7 @@
 #if defined(CONFIG_BT) && defined(CONFIG_BT_HCIUART_ATH3K)
 	&msm_bluesleep_device,
 	&msm_bt_power_device,
+	&msm_wlan_power_device,
 #endif
 #if defined(CONFIG_QSEECOM)
 	&qseecom_device,
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 7fe45b8..7480437 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -13,13 +13,11 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
-#include <linux/of_irq.h>
 #include <linux/memory.h>
 #ifdef CONFIG_ANDROID_PMEM
 #include <linux/android_pmem.h>
@@ -27,9 +25,10 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/krait-regulator.h>
 #include <linux/msm_thermal.h>
-#include <linux/mfd/wcd9xxx/core.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
 #include <mach/board.h>
 #include <mach/gpiomux.h>
 #include <mach/msm_iomap.h>
@@ -38,12 +37,12 @@
 #endif
 #include <mach/msm_memtypes.h>
 #include <mach/msm_smd.h>
+#include <mach/restart.h>
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
-#include <mach/qpnp-int.h>
 #include <mach/socinfo.h>
 #include <mach/msm_bus_board.h>
-#include <mach/mpm.h>
+#include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
 #include "spm.h"
@@ -62,7 +61,7 @@
 early_param("kernel_ebi1_mem_size", kernel_ebi1_mem_size_setup);
 #endif
 
-static struct memtype_reserve msm_8974_reserve_table[] __initdata = {
+static struct memtype_reserve msm8974_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
 	},
 	[MEMTYPE_EBI0] = {
@@ -73,7 +72,7 @@
 	},
 };
 
-static int msm_8974_paddr_to_memtype(unsigned int paddr)
+static int msm8974_paddr_to_memtype(unsigned int paddr)
 {
 	return MEMTYPE_EBI1;
 }
@@ -81,7 +80,7 @@
 static void __init reserve_ebi_memory(void)
 {
 #ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-	msm_8974_reserve_table[MEMTYPE_EBI1].size += kernel_ebi1_mem_size;
+	msm8974_reserve_table[MEMTYPE_EBI1].size += kernel_ebi1_mem_size;
 #endif
 }
 
@@ -247,26 +246,21 @@
 	}
 };
 
-static void __init msm_8974_calculate_reserve_sizes(void)
+static void __init msm8974_calculate_reserve_sizes(void)
 {
 	reserve_ebi_memory();
 }
 
-static struct reserve_info msm_8974_reserve_info __initdata = {
-	.memtype_reserve_table = msm_8974_reserve_table,
-	.calculate_reserve_sizes = msm_8974_calculate_reserve_sizes,
-	.paddr_to_memtype = msm_8974_paddr_to_memtype,
+static struct reserve_info msm8974_reserve_info __initdata = {
+	.memtype_reserve_table = msm8974_reserve_table,
+	.calculate_reserve_sizes = msm8974_calculate_reserve_sizes,
+	.paddr_to_memtype = msm8974_paddr_to_memtype,
 };
 
-static void __init msm_8974_early_memory(void)
+static void __init msm8974_early_memory(void)
 {
-	reserve_info = &msm_8974_reserve_info;
-	of_scan_flat_dt(dt_scan_for_memory_reserve, msm_8974_reserve_table);
-}
-
-void __init msm_8974_reserve(void)
-{
-	msm_reserve();
+	reserve_info = &msm8974_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msm8974_reserve_table);
 }
 
 #define BIMC_BASE	0xfc380000
@@ -456,7 +450,7 @@
 				ARRAY_SIZE(msm_bus_8974_devices));
 };
 
-void __init msm_8974_add_devices(void)
+void __init msm8974_add_devices(void)
 {
 	platform_device_register(&msm_device_smd_8974);
 }
@@ -467,7 +461,7 @@
  * into this category, and thus the driver should not be added here. The
  * EPROBE_DEFER can satisfy most dependency problems.
  */
-void __init msm_8974_add_drivers(void)
+void __init msm8974_add_drivers(void)
 {
 	msm_init_modem_notifier_list();
 	msm_smd_init();
@@ -485,32 +479,7 @@
 	mxt_init_vkeys_8974();
 }
 
-static struct of_device_id irq_match[] __initdata  = {
-	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
-	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
-	{ .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
-	{ .compatible = "qcom,wcd9xxx-irq", .data = wcd9xxx_irq_of_init, },
-	{}
-};
-static struct of_device_id mpm_match[] __initdata = {
-	{.compatible = "qcom,mpm-v2", },
-	{},
-};
-
-void __init msm_8974_init_irq(void)
-{
-	struct device_node *node;
-
-	of_irq_init(irq_match);
-	node = of_find_matching_node(NULL, mpm_match);
-
-	WARN_ON(!node);
-
-	if (node)
-		of_mpm_init(node);
-}
-
-static struct of_dev_auxdata msm_8974_auxdata_lookup[] __initdata = {
+static struct of_dev_auxdata msm8974_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
 			"msm_otg", NULL),
 	OF_DEV_AUXDATA("qcom,dwc-usb3-msm", 0xF9200000, \
@@ -577,16 +546,43 @@
 	{}
 };
 
-void __init msm_8974_init(struct of_dev_auxdata **adata)
+static void __init msm8974_map_io(void)
 {
+	msm_map_8974_io();
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed\n", __func__);
+}
+
+void __init msm8974_init(void)
+{
+	struct of_dev_auxdata *adata = msm8974_auxdata_lookup;
+
 	msm_8974_init_gpiomux();
-
-	*adata = msm_8974_auxdata_lookup;
-
 	regulator_has_full_constraints();
+	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+
+	msm8974_add_devices();
+	msm8974_add_drivers();
 }
 
-void __init msm_8974_very_early(void)
+void __init msm8974_init_very_early(void)
 {
-	msm_8974_early_memory();
+	msm8974_early_memory();
 }
+
+static const char *msm8974_dt_match[] __initconst = {
+	"qcom,msm8974",
+	NULL
+};
+
+DT_MACHINE_START(MSM8974_DT, "Qualcomm MSM 8974 (Flattened Device Tree)")
+	.map_io = msm8974_map_io,
+	.init_irq = msm_dt_init_irq,
+	.init_machine = msm8974_init,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_dt_timer,
+	.dt_compat = msm8974_dt_match,
+	.reserve = msm_reserve,
+	.init_very_early = msm8974_init_very_early,
+	.restart = msm_restart,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 43f863b..27e91ae 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -37,6 +37,7 @@
 #include <mach/msm_smd.h>
 #include <mach/rpm-smd.h>
 #include <mach/rpm-regulator-smd.h>
+#include <mach/mpm.h>
 #include "clock.h"
 #include "modem_notifier.h"
 #include "lpm_resources.h"
@@ -124,10 +125,22 @@
 	{}
 };
 
+static struct of_device_id mpm_match[] __initdata = {
+	{.compatible = "qcom,mpm-v2", },
+	{},
+};
+
 void __init msm9625_init_irq(void)
 {
+	struct device_node *node;
 	l2x0_of_init(L2CC_AUX_CTRL, L2X0_AUX_CTRL_MASK);
 	of_irq_init(irq_match);
+	node = of_find_matching_node(NULL, mpm_match);
+
+	WARN_ON(!node);
+
+	if (node)
+		of_mpm_init(node);
 }
 
 static void __init msm_dt_timer_init(void)
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 8f9a0ef..15a544a 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -10,83 +10,50 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/gpio.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/of_fdt.h>
 #include <linux/of_irq.h>
-#include <asm/hardware/gic.h>
+#include <linux/mfd/wcd9xxx/core.h>
 #include <asm/arch_timer.h>
-#include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/socinfo.h>
-#include <mach/board.h>
-#include <mach/restart.h>
+#include <asm/hardware/gic.h>
+#include <mach/mpm.h>
+#include <mach/qpnp-int.h>
+
+#include "board-dt.h"
 
 static void __init msm_dt_timer_init(void)
 {
 	arch_timer_of_register();
 }
 
-static struct sys_timer msm_dt_timer = {
+struct sys_timer msm_dt_timer = {
 	.init = msm_dt_timer_init
 };
 
-static void __init msm_dt_init_irq(void)
-{
-	if (machine_is_msm8974())
-		msm_8974_init_irq();
-}
-
-static void __init msm_dt_map_io(void)
-{
-	if (early_machine_is_msm8974())
-		msm_map_8974_io();
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed\n", __func__);
-}
-
-static void __init msm_dt_init(void)
-{
-	struct of_dev_auxdata *adata = NULL;
-
-	if (machine_is_msm8974())
-		msm_8974_init(&adata);
-
-	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
-	if (machine_is_msm8974()) {
-		msm_8974_add_devices();
-		msm_8974_add_drivers();
-	}
-}
-
-static const char *msm_dt_match[] __initconst = {
-	"qcom,msm8974",
-	NULL
+static struct of_device_id irq_match[] __initdata  = {
+	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
+	{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+	{ .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
+	{ .compatible = "qcom,wcd9xxx-irq", .data = wcd9xxx_irq_of_init, },
+	{}
 };
 
-static void __init msm_dt_reserve(void)
-{
-	if (early_machine_is_msm8974())
-		msm_8974_reserve();
-}
+static struct of_device_id mpm_match[] __initdata = {
+	{.compatible = "qcom,mpm-v2", },
+	{}
+};
 
-static void __init msm_dt_init_very_early(void)
+void __init msm_dt_init_irq(void)
 {
-	if (early_machine_is_msm8974())
-		msm_8974_very_early();
-}
+	struct device_node *node;
 
-DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
-	.map_io = msm_dt_map_io,
-	.init_irq = msm_dt_init_irq,
-	.init_machine = msm_dt_init,
-	.handle_irq = gic_handle_irq,
-	.timer = &msm_dt_timer,
-	.dt_compat = msm_dt_match,
-	.reserve = msm_dt_reserve,
-	.init_very_early = msm_dt_init_very_early,
-	.restart = msm_restart,
-MACHINE_END
+	of_irq_init(irq_match);
+	node = of_find_matching_node(NULL, mpm_match);
+
+	WARN_ON(!node);
+
+	if (node)
+		of_mpm_init(node);
+}
diff --git a/arch/arm/mach-msm/board-dt.h b/arch/arm/mach-msm/board-dt.h
new file mode 100644
index 0000000..31143a5
--- /dev/null
+++ b/arch/arm/mach-msm/board-dt.h
@@ -0,0 +1,14 @@
+/* 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.
+ */
+
+extern struct sys_timer msm_dt_timer;
+void __init msm_dt_init_irq(void);
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 3045f07..fd322e9 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -32,6 +32,8 @@
 #include <linux/msm_adc.h>
 #include <linux/regulator/msm-gpio-regulator.h>
 #include <linux/msm_ion.h>
+#include <linux/i2c-gpio.h>
+#include <linux/regulator/onsemi-ncp6335d.h>
 #include <asm/mach/mmc.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -128,6 +130,27 @@
 	.msm_i2c_config_gpio	= gsbi_qup_i2c_gpio_config,
 };
 
+static struct msm_gpio i2c_gpio_config[] = {
+	{ GPIO_CFG(39, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
+		"qup_scl" },
+	{ GPIO_CFG(36, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
+		"qup_sda" },
+};
+
+static struct i2c_gpio_platform_data i2c_gpio_pdata = {
+	.scl_pin = 39,
+	.sda_pin = 36,
+	.udelay = 5, /* 100 Khz */
+};
+
+static struct platform_device msm_i2c_gpio = {
+	.name	= "i2c-gpio",
+	.id	= 2,
+	.dev	= {
+		.platform_data = &i2c_gpio_pdata,
+	}
+};
+
 #ifdef CONFIG_ARCH_MSM7X27A
 
 #define MSM_RESERVE_MDP_SIZE       0x1B00000
@@ -597,6 +620,41 @@
 	},
 };
 
+/* Regulator configuration for the NCP6335D buck */
+struct regulator_consumer_supply ncp6335d_consumer_supplies[] = {
+	REGULATOR_SUPPLY("ncp6335d", NULL),
+};
+
+static struct regulator_init_data ncp6335d_init_data = {
+	.constraints	= {
+		.name		= "ncp6335d_sw",
+		.min_uV		= 600000,
+		.max_uV		= 1400000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+				REGULATOR_CHANGE_STATUS |
+				REGULATOR_CHANGE_MODE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+				REGULATOR_MODE_FAST,
+		.initial_mode	= REGULATOR_MODE_NORMAL,
+		.always_on	= 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(ncp6335d_consumer_supplies),
+	.consumer_supplies = ncp6335d_consumer_supplies,
+};
+
+static struct ncp6335d_platform_data ncp6335d_pdata = {
+	.init_data = &ncp6335d_init_data,
+	.default_vsel = NCP6335D_VSEL0,
+	.slew_rate_ns = 166,
+};
+
+static struct i2c_board_info i2c2_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("ncp6335d", 0x38 >> 1),
+		.platform_data = &ncp6335d_pdata,
+	},
+};
+
 static struct platform_device *common_devices[] __initdata = {
 	&android_usb_device,
 	&msm_batt_device,
@@ -651,6 +709,7 @@
 	&msm8625_device_smd,
 	&msm8625_gsbi0_qup_i2c_device,
 	&msm8625_gsbi1_qup_i2c_device,
+	&msm_i2c_gpio,  /* TODO: Make this specific to 8625q */
 	&msm8625_device_uart1,
 	&msm8625_device_uart_dm1,
 	&msm8625_device_otg,
@@ -847,10 +906,20 @@
 
 static void __init msm8625_device_i2c_init(void)
 {
+	int i, rc;
+
 	msm8625_gsbi0_qup_i2c_device.dev.platform_data
 					= &msm_gsbi0_qup_i2c_pdata;
 	msm8625_gsbi1_qup_i2c_device.dev.platform_data
 					= &msm_gsbi1_qup_i2c_pdata;
+	if (machine_is_qrd_skud_prime()) {
+		for (i = 0 ; i < ARRAY_SIZE(i2c_gpio_config); i++) {
+			rc = gpio_tlmm_config(i2c_gpio_config[i].gpio_cfg,
+					GPIO_CFG_ENABLE);
+			if (rc)
+				pr_err("I2C-gpio tlmm config failed\n");
+		}
+	}
 }
 
 static struct platform_device msm_proccomm_regulator_dev = {
@@ -997,6 +1066,11 @@
 	msm_pm_register_irqs();
 	msm_fb_add_devices();
 
+	if (machine_is_qrd_skud_prime())
+		i2c_register_board_info(2, i2c2_info,
+				ARRAY_SIZE(i2c2_info));
+
+
 #if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
 	msm7627a_bt_power_init();
 #endif
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index 98adc0e..2854cad 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -305,6 +305,7 @@
 	{41, 800000000},
 	{50, 960000000},
 	{52, 1008000000},
+	{57, 1104000000},
 	{60, 1152000000},
 	{62, 1200000000},
 	{63, 1209600000},
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 1f12bc7..5100980 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -532,8 +532,6 @@
 	if (!data)
 		return -EINVAL;
 
-	clock_debug_init();
-
 	clk_init_data = data;
 	if (clk_init_data->pre_init)
 		clk_init_data->pre_init();
@@ -541,6 +539,8 @@
 	clock_tbl = data->table;
 	num_clocks = data->size;
 
+	init_sibling_lists(clock_tbl, num_clocks);
+
 	/*
 	 * Detect and preserve initial clock state until clock_late_init() or
 	 * a driver explicitly changes it, whichever is first.
@@ -548,11 +548,14 @@
 	for (n = 0; n < num_clocks; n++)
 		__handoff_clk(clock_tbl[n].clk);
 
-	msm_clock_register(clock_tbl, num_clocks);
+	clkdev_add_table(clock_tbl, num_clocks);
 
 	if (clk_init_data->post_init)
 		clk_init_data->post_init();
 
+	clock_debug_init();
+	clock_debug_register(clock_tbl, num_clocks);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 6434a63..63c1dbd 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -1017,13 +1017,13 @@
 				ARRAY_SIZE(msm_iommu_gfx2d_devs));
 	}
 
-	if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
+	if (soc_class_is_apq8064() || cpu_is_msm8960ab()) {
 		platform_add_devices(msm_iommu_jpegd_devs,
 				ARRAY_SIZE(msm_iommu_jpegd_devs));
 		platform_add_devices(msm_iommu_adreno3xx_gfx_devs,
 				ARRAY_SIZE(msm_iommu_adreno3xx_gfx_devs));
 	}
-	if (cpu_is_apq8064() || cpu_is_apq8064ab())
+	if (soc_class_is_apq8064())
 		platform_add_devices(msm_iommu_vcap_devs,
 				ARRAY_SIZE(msm_iommu_vcap_devs));
 
@@ -1039,14 +1039,14 @@
 				ARRAY_SIZE(msm_iommu_gfx2d_ctx_devs));
 	}
 
-	if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
+	if (soc_class_is_apq8064() || cpu_is_msm8960ab()) {
 		platform_add_devices(msm_iommu_jpegd_ctx_devs,
 				ARRAY_SIZE(msm_iommu_jpegd_ctx_devs));
 
 		platform_add_devices(msm_iommu_adreno3xx_ctx_devs,
 				ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs));
 	}
-	if (cpu_is_apq8064() || cpu_is_apq8064ab())
+	if (soc_class_is_apq8064())
 		platform_add_devices(msm_iommu_vcap_ctx_devs,
 			ARRAY_SIZE(msm_iommu_vcap_ctx_devs));
 
@@ -1081,12 +1081,12 @@
 		for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_devs); i++)
 			platform_device_unregister(msm_iommu_jpegd_devs[i]);
 	}
-	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
+	if (soc_class_is_apq8064()) {
 		for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_ctx_devs); i++)
 			platform_device_unregister(msm_iommu_vcap_ctx_devs[i]);
 	}
 
-	if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
+	if (soc_class_is_apq8064() || cpu_is_msm8960ab()) {
 		for (i = 0; i < ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs);
 			   i++)
 			platform_device_unregister(
@@ -1097,7 +1097,7 @@
 			platform_device_unregister(
 				msm_iommu_jpegd_ctx_devs[i]);
 
-		if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
+		if (soc_class_is_apq8064()) {
 			for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_devs);
 			   i++)
 				platform_device_unregister(
diff --git a/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
index f835e82..a35ff4d 100644
--- a/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
+++ b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
@@ -2,7 +2,7 @@
 #define __ASM_ARCH_MSM_MSM_KRAIT_L2_ACCESSORS_H
 
 /*
- * Copyright (c) 2011, Code Aurora Forum. 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
@@ -13,8 +13,21 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
+#ifdef CONFIG_ARCH_MSM_KRAIT
 extern void set_l2_indirect_reg(u32 reg_addr, u32 val);
 extern u32 get_l2_indirect_reg(u32 reg_addr);
 extern u32 set_get_l2_indirect_reg(u32 reg_addr, u32 val);
+#else
+static inline void set_l2_indirect_reg(u32 reg_addr, u32 val) {}
+static inline u32 get_l2_indirect_reg(u32 reg_addr)
+{
+	return 0;
+}
+static inline u32 set_get_l2_indirect_reg(u32 reg_addr, u32 val)
+{
+	return 0;
+}
+#endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
index 3d33350..d34536d 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
@@ -25,6 +25,13 @@
 	MAX_AUDPROC_TYPES
 };
 
+enum {
+	VOCPROC_CAL,
+	VOCSTRM_CAL,
+	VOCVOL_CAL,
+	MAX_VOCPROC_TYPES
+};
+
 struct acdb_cal_block {
 	uint32_t		cal_size;
 	uint32_t		cal_kvaddr;
@@ -47,16 +54,20 @@
 uint32_t get_adm_rx_topology(void);
 uint32_t get_adm_tx_topology(void);
 uint32_t get_asm_topology(void);
+void get_voice_cal_allocation(struct acdb_cal_block *cal_block);
 void get_all_voice_cal(struct acdb_cal_block *cal_block);
 void get_all_cvp_cal(struct acdb_cal_block *cal_block);
 void get_all_vocproc_cal(struct acdb_cal_block *cal_block);
 void get_all_vocstrm_cal(struct acdb_cal_block *cal_block);
 void get_all_vocvol_cal(struct acdb_cal_block *cal_block);
+void get_voice_col_data(uint32_t vocproc_type,
+	struct acdb_cal_block *cal_block);
 void get_anc_cal(struct acdb_cal_block *cal_block);
 void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
 void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
+void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block);
 void get_vocproc_cal(struct acdb_cal_data *cal_data);
 void get_vocstrm_cal(struct acdb_cal_data *cal_data);
 void get_vocvol_cal(struct acdb_cal_data *cal_data);
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 86045b9..5c88101 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -436,4 +436,20 @@
 	return 0;
 #endif
 }
+
+static inline int soc_class_is_msm8960(void)
+{
+	return cpu_is_msm8960() || cpu_is_msm8960ab();
+}
+
+static inline int soc_class_is_apq8064(void)
+{
+	return cpu_is_apq8064() || cpu_is_apq8064ab();
+}
+
+static inline int soc_class_is_msm8930(void)
+{
+	return cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627();
+}
+
 #endif
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index b56a291..75e56fe 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -267,6 +267,7 @@
 	else
 		return NULL;
 }
+EXPORT_SYMBOL(msm_get_iommu_domain);
 
 int msm_allocate_iova_address(unsigned int iommu_domain,
 					unsigned int partition_no,
diff --git a/arch/arm/mach-msm/msm7k_fiq.c b/arch/arm/mach-msm/msm7k_fiq.c
index 887218c..421b4f9 100644
--- a/arch/arm/mach-msm/msm7k_fiq.c
+++ b/arch/arm/mach-msm/msm7k_fiq.c
@@ -18,6 +18,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/cacheflush.h>
 #include <mach/irqs-8625.h>
+#include <mach/socinfo.h>
 
 #include "msm_watchdog.h"
 
@@ -74,6 +75,9 @@
 
 static int __init init7k_fiq(void)
 {
+	if (!cpu_is_msm8625())
+		return 0;
+
 	if (msm_setup_fiq_handler())
 		pr_err("MSM7K FIQ INIT FAILED\n");
 
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 404b350..46d4a12 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -233,10 +233,9 @@
 	int ret;
 	struct msm_xo *xo = xo_voter->xo;
 	int is_d0 = xo == &msm_xo_sources[MSM_XO_TCXO_D0];
-	int needs_workaround = cpu_is_msm8960() || cpu_is_apq8064() ||
-			       cpu_is_msm8930() || cpu_is_msm8930aa() ||
-			       cpu_is_msm9615() || cpu_is_msm8627() ||
-			       cpu_is_msm8960ab() || cpu_is_apq8064ab();
+	int needs_workaround = soc_class_is_msm8960() ||
+			       soc_class_is_apq8064() ||
+			       soc_class_is_msm8930() || cpu_is_msm9615();
 
 	if (xo_voter->mode == mode)
 		return 0;
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 89003cf..5f05f98 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -183,9 +183,8 @@
 	    machine_is_msm8226_sim())
 		return krait_release_secondary_sim(0xf9088000, cpu);
 
-	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
-						cpu_is_apq8064ab())
+	if (soc_class_is_msm8960() || soc_class_is_msm8930() ||
+	    soc_class_is_apq8064())
 		return krait_release_secondary(0x02088000, cpu);
 
 	if (cpu_is_msm8974())
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 7272f97..a24b9ec 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/miscdevice.h>
@@ -20,7 +21,14 @@
 #include <mach/qdsp6v2/audio_acdb.h>
 
 
-#define MAX_NETWORKS		15
+#define MAX_NETWORKS			15
+#define MAX_IOCTL_DATA			(MAX_NETWORKS * 2)
+#define MAX_COL_SIZE			324
+
+#define ACDB_BLOCK_SIZE			4096
+#define NUM_VOCPROC_BLOCKS		(6 * MAX_NETWORKS)
+#define ACDB_TOTAL_VOICE_ALLOCATION	(ACDB_BLOCK_SIZE * NUM_VOCPROC_BLOCKS)
+
 
 struct sidetone_atomic_cal {
 	atomic_t	enable;
@@ -56,6 +64,15 @@
 	atomic_t			vocstrm_total_cal_size;
 	atomic_t			vocvol_total_cal_size;
 
+	/* Voice Column data */
+	struct acdb_atomic_cal_block	vocproc_col_cal[MAX_VOCPROC_TYPES];
+	uint32_t			*col_data[MAX_VOCPROC_TYPES];
+
+	/* VocProc dev cfg cal*/
+	struct acdb_atomic_cal_block	vocproc_dev_cal[MAX_NETWORKS];
+	atomic_t			vocproc_dev_cal_size;
+	atomic_t			vocproc_dev_total_cal_size;
+
 	/* AFE cal */
 	struct acdb_atomic_cal_block	afe_cal[MAX_AUDPROC_TYPES];
 
@@ -124,6 +141,15 @@
 	atomic_set(&acdb_data.asm_topology, topology);
 }
 
+void get_voice_cal_allocation(struct acdb_cal_block *cal_block)
+{
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+	cal_block->cal_size = ACDB_TOTAL_VOICE_ALLOCATION;
+}
+
 void get_all_voice_cal(struct acdb_cal_block *cal_block)
 {
 	cal_block->cal_kvaddr =
@@ -177,6 +203,45 @@
 		atomic_read(&acdb_data.vocvol_total_cal_size);
 }
 
+void get_voice_col_data(uint32_t vocproc_type,
+			struct acdb_cal_block *cal_block)
+{
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		goto done;
+	}
+
+	cal_block->cal_kvaddr = atomic_read(&acdb_data.
+				vocproc_col_cal[vocproc_type].cal_kvaddr);
+	cal_block->cal_paddr = atomic_read(&acdb_data.
+				vocproc_col_cal[vocproc_type].cal_paddr);
+	cal_block->cal_size = atomic_read(&acdb_data.
+				vocproc_col_cal[vocproc_type].cal_size);
+done:
+	return;
+}
+
+void store_voice_col_data(uint32_t vocproc_type, uint32_t cal_size,
+			  uint32_t *cal_data)
+{
+	if (cal_size > MAX_COL_SIZE) {
+		pr_err("%s: col size is to big %d\n", __func__,
+				cal_size);
+		goto done;
+	}
+	if (copy_from_user(acdb_data.col_data[vocproc_type],
+			(void *)((uint8_t *)cal_data + sizeof(cal_size)),
+			cal_size)) {
+		pr_err("%s: fail to copy col size %d\n",
+			__func__, cal_size);
+		goto done;
+	}
+	atomic_set(&acdb_data.vocproc_col_cal[vocproc_type].cal_size,
+		cal_size);
+done:
+	return;
+}
+
 void get_anc_cal(struct acdb_cal_block *cal_block)
 {
 	pr_debug("%s\n", __func__);
@@ -417,6 +482,56 @@
 	return;
 }
 
+void store_vocproc_dev_cfg_cal(int32_t len, struct cal_block *cal_blocks)
+{
+	int i;
+	pr_debug("%s\n", __func__);
+
+	if (len > MAX_NETWORKS) {
+		pr_err("%s: Calibration sent for %d networks, only %d are supported!\n",
+			__func__, len, MAX_NETWORKS);
+		goto done;
+	}
+
+	atomic_set(&acdb_data.vocproc_dev_total_cal_size, 0);
+	for (i = 0; i < len; i++) {
+		if (cal_blocks[i].cal_offset >
+					atomic64_read(&acdb_data.mem_len)) {
+			pr_err("%s: offset %d is > mem_len %ld\n",
+				__func__, cal_blocks[i].cal_offset,
+				(long)atomic64_read(&acdb_data.mem_len));
+			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_size, 0);
+		} else {
+			atomic_add(cal_blocks[i].cal_size,
+				&acdb_data.vocproc_dev_total_cal_size);
+			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_size,
+				cal_blocks[i].cal_size);
+			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_paddr,
+				cal_blocks[i].cal_offset +
+				atomic64_read(&acdb_data.paddr));
+			atomic_set(&acdb_data.vocproc_dev_cal[i].cal_kvaddr,
+				cal_blocks[i].cal_offset +
+				atomic64_read(&acdb_data.kvaddr));
+		}
+	}
+	atomic_set(&acdb_data.vocproc_dev_cal_size, len);
+done:
+	return;
+}
+
+void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block)
+{
+	pr_debug("%s\n", __func__);
+
+	cal_block->cal_kvaddr =
+		atomic_read(&acdb_data.vocproc_dev_cal[0].cal_kvaddr);
+	cal_block->cal_paddr =
+		atomic_read(&acdb_data.vocproc_dev_cal[0].cal_paddr);
+	cal_block->cal_size =
+		atomic_read(&acdb_data.vocproc_dev_total_cal_size);
+}
+
+
 
 void store_vocproc_cal(int32_t len, struct cal_block *cal_blocks)
 {
@@ -698,7 +813,7 @@
 	int32_t			size;
 	int32_t			map_fd;
 	uint32_t		topology;
-	struct cal_block	data[MAX_NETWORKS];
+	uint32_t		data[MAX_IOCTL_DATA];
 	pr_debug("%s\n", __func__);
 
 	switch (cmd) {
@@ -777,6 +892,18 @@
 		goto done;
 	}
 
+	switch (cmd) {
+	case AUDIO_SET_VOCPROC_COL_CAL:
+		store_voice_col_data(VOCPROC_CAL, size, (uint32_t *)arg);
+		goto done;
+	case AUDIO_SET_VOCSTRM_COL_CAL:
+		store_voice_col_data(VOCSTRM_CAL, size, (uint32_t *)arg);
+		goto done;
+	case AUDIO_SET_VOCVOL_COL_CAL:
+		store_voice_col_data(VOCVOL_CAL, size, (uint32_t *)arg);
+		goto done;
+	}
+
 	if (copy_from_user(data, (void *)(arg + sizeof(size)), size)) {
 
 		pr_err("%s: fail to copy table size %d\n", __func__, size);
@@ -795,58 +922,65 @@
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audproc_cal(TX_CAL, data);
+		store_audproc_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_CAL:
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audproc_cal(RX_CAL, data);
+		store_audproc_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audstrm_cal(TX_CAL, data);
+		store_audstrm_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audstrm_cal(RX_CAL, data);
+		store_audstrm_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_TX_VOL_CAL:
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audvol_cal(TX_CAL, data);
+		store_audvol_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AUDPROC_RX_VOL_CAL:
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More Audproc Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_audvol_cal(RX_CAL, data);
+		store_audvol_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AFE_TX_CAL:
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More AFE Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_afe_cal(TX_CAL, data);
+		store_afe_cal(TX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_AFE_RX_CAL:
 		if (size > sizeof(struct cal_block))
 			pr_err("%s: More AFE Cal then expected, "
 				"size received: %d\n", __func__, size);
-		store_afe_cal(RX_CAL, data);
+		store_afe_cal(RX_CAL, (struct cal_block *)data);
 		break;
 	case AUDIO_SET_VOCPROC_CAL:
-		store_vocproc_cal(size / sizeof(struct cal_block), data);
+		store_vocproc_cal(size / sizeof(struct cal_block),
+						(struct cal_block *)data);
 		break;
 	case AUDIO_SET_VOCPROC_STREAM_CAL:
-		store_vocstrm_cal(size / sizeof(struct cal_block), data);
+		store_vocstrm_cal(size / sizeof(struct cal_block),
+						(struct cal_block *)data);
 		break;
 	case AUDIO_SET_VOCPROC_VOL_CAL:
-		store_vocvol_cal(size / sizeof(struct cal_block), data);
+		store_vocvol_cal(size / sizeof(struct cal_block),
+						(struct cal_block *)data);
+		break;
+	case AUDIO_SET_VOCPROC_DEV_CFG_CAL:
+		store_vocproc_dev_cfg_cal(size / sizeof(struct cal_block),
+						(struct cal_block *)data);
 		break;
 	case AUDIO_SET_SIDETONE_CAL:
 		if (size > sizeof(struct sidetone_cal))
@@ -855,7 +989,7 @@
 		store_sidetone_cal((struct sidetone_cal *)data);
 		break;
 	case AUDIO_SET_ANC_CAL:
-		store_anc_cal(data);
+		store_anc_cal((struct cal_block *)data);
 		break;
 	default:
 		pr_err("ACDB=> ACDB ioctl not found!\n");
@@ -895,6 +1029,7 @@
 
 static int acdb_release(struct inode *inode, struct file *f)
 {
+	int i;
 	s32 result = 0;
 
 	atomic_dec(&usage_count);
@@ -903,6 +1038,11 @@
 	pr_debug("%s: ref count %d!\n", __func__,
 		atomic_read(&usage_count));
 
+	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
+		kfree(acdb_data.col_data[i]);
+		acdb_data.col_data[i] = NULL;
+	}
+
 	if (atomic_read(&usage_count) >= 1)
 		result = -EBUSY;
 	else
@@ -927,9 +1067,16 @@
 
 static int __init acdb_init(void)
 {
+	int i;
 	memset(&acdb_data, 0, sizeof(acdb_data));
 	mutex_init(&acdb_data.acdb_mutex);
 	atomic_set(&usage_count, 0);
+
+	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
+		acdb_data.col_data[i] = kmalloc(MAX_COL_SIZE, GFP_KERNEL);
+		atomic_set(&acdb_data.vocproc_col_cal[i].cal_kvaddr,
+			(uint32_t)acdb_data.col_data[i]);
+	}
 	return misc_register(&acdb_misc);
 }
 
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index dfed3aa..43073d3 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1131,9 +1131,8 @@
 
 static int __init msm_rpmrs_l2_init(void)
 {
-	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
-						cpu_is_apq8064ab()) {
+	if (soc_class_is_msm8960() || soc_class_is_msm8930() ||
+	    soc_class_is_apq8064()) {
 
 		msm_pm_set_l2_flush_flag(0);
 
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 152e2e9..3fe3bd7 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -183,9 +183,8 @@
 
 	reg = saw_bases[cpu];
 
-	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
-						cpu_is_apq8064ab()) {
+	if (soc_class_is_msm8960() || soc_class_is_msm8930() ||
+	    soc_class_is_apq8064()) {
 		val = 0xA4;
 		reg += 0x14;
 		timeout = 512;
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index b361d9d..b61604a 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -964,9 +964,8 @@
 	if (!smp_processor_id())
 		return 0;
 
-	if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
-	    cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627() ||
-	    cpu_is_msm8960ab() || cpu_is_apq8064ab())
+	if (cpu_is_msm8x60() || soc_class_is_msm8960() ||
+	    soc_class_is_apq8064() || soc_class_is_msm8930())
 		__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 
 	if (__get_cpu_var(first_boot)) {
@@ -1062,9 +1061,8 @@
 		sclk_hz = 32765;
 		gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 		dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
-	} else if (cpu_is_msm8960() || cpu_is_apq8064() || cpu_is_msm8930() ||
-		   cpu_is_msm8930aa() || cpu_is_msm8627() ||
-		   cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
+	} else if (soc_class_is_msm8960() || soc_class_is_apq8064() ||
+		   soc_class_is_msm8930()) {
 		global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
 		dgt->freq = 6750000;
 		__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
@@ -1073,8 +1071,7 @@
 		gpt->freq = 32765;
 		gpt_hz = 32765;
 		sclk_hz = 32765;
-		if (!cpu_is_msm8930() && !cpu_is_msm8930aa() &&
-		    !cpu_is_msm8627() && !cpu_is_msm8960ab()) {
+		if (!soc_class_is_msm8930() && !cpu_is_msm8960ab()) {
 			gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 			dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 		}
@@ -1124,10 +1121,9 @@
 			       "failed for %s\n", cs->name);
 
 		ce->irq = clock->irq;
-		if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
-		    cpu_is_msm8930() || cpu_is_msm9615() || cpu_is_msm8625() ||
-		    cpu_is_msm8627() || cpu_is_msm8930aa() ||
-		    cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
+		if (cpu_is_msm8x60() || cpu_is_msm9615() || cpu_is_msm8625() ||
+		    soc_class_is_msm8960() || soc_class_is_apq8064() ||
+		    soc_class_is_msm8930()) {
 			clock->percpu_evt = alloc_percpu(struct clock_event_device *);
 			if (!clock->percpu_evt) {
 				pr_err("msm_timer_init: memory allocation "
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index a537bb3..e4501f4 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -160,9 +160,8 @@
 {
 	if (driver->use_device_tree)
 		return 1;
-	else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-		cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627() ||
-		cpu_is_msm8960ab() || cpu_is_apq8064ab())
+	else if (soc_class_is_msm8960() || soc_class_is_msm8930() ||
+		 soc_class_is_apq8064() || cpu_is_msm9615())
 		return 1;
 	else
 		return 0;
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index de5f10f..8a9567b 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -77,7 +77,8 @@
 	int dst_nents;
 
 	dma_addr_t phy_iv_in;
-
+	unsigned char dec_iv[16];
+	int dir;
 	void *areq;
 	enum qce_cipher_mode_enum mode;
 	struct ce_sps_data ce_sps;
@@ -713,16 +714,19 @@
 {
 	struct ahash_request *areq;
 	unsigned char digest[SHA256_DIGEST_SIZE];
+	uint32_t bytecount32[2];
 
 	areq = (struct ahash_request *) pce_dev->areq;
 	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 				DMA_TO_DEVICE);
 	memcpy(digest, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
 						SHA256_DIGEST_SIZE);
+	_byte_stream_to_net_words(bytecount32,
+		(unsigned char *)pce_dev->ce_sps.result->auth_byte_count,
+					2 * CRYPTO_REG_SIZE);
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
-	pce_dev->qce_cb(areq, digest,
-			(char *)pce_dev->ce_sps.result->auth_byte_count,
+	pce_dev->qce_cb(areq, digest, (char *)bytecount32,
 				pce_dev->ce_sps.consumer_status);
 	return 0;
 };
@@ -750,10 +754,16 @@
 					pce_dev->ce_sps.producer_status);
 	} else {
 		if (pce_dev->ce_sps.minor_version == 0) {
-			if (pce_dev->mode == QCE_MODE_CBC)
-				memcpy(iv, (char *)sg_virt(areq->src),
-							sizeof(iv));
-
+			if (pce_dev->mode == QCE_MODE_CBC) {
+				if  (pce_dev->dir == QCE_DECRYPT)
+					memcpy(iv, (char *)pce_dev->dec_iv,
+								sizeof(iv));
+				else
+					memcpy(iv, (unsigned char *)
+						(sg_virt(areq->src) +
+						areq->src->length - 16),
+						sizeof(iv));
+			}
 			if ((pce_dev->mode == QCE_MODE_CTR) ||
 				(pce_dev->mode == QCE_MODE_XTS)) {
 				uint32_t num_blk = 0;
@@ -2326,6 +2336,16 @@
 	} else {
 		pce_dev->dst_nents = pce_dev->src_nents;
 	}
+	pce_dev->dir = c_req->dir;
+	if  ((pce_dev->ce_sps.minor_version == 0) && (c_req->dir == QCE_DECRYPT)
+			&& (c_req->mode == QCE_MODE_CBC)) {
+		struct ablkcipher_request *areq =
+				(struct ablkcipher_request *)pce_dev->areq;
+		memcpy(pce_dev->dec_iv, (unsigned char *)sg_virt(areq->src) +
+					 areq->src->length - 16,
+			NUM_OF_CRYPTO_CNTR_IV_REG * CRYPTO_REG_SIZE);
+	}
+
 	/* set up crypto device */
 	rc = _ce_setup_cipher(pce_dev, c_req, areq->nbytes, 0, cmdlistinfo);
 	if (rc < 0)
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index c9eba82..8533636 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -36,7 +36,7 @@
 
 /* QCE max number of descriptor in a descriptor list */
 #define QCE_MAX_NUM_DESC    128
-#define SPS_MAX_PKT_SIZE  (64 * 1024  - 1)
+#define SPS_MAX_PKT_SIZE  (32 * 1024  - 64)
 
 /* State of consumer/producer Pipe */
 enum qce_pipe_st_enum {
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index d0b1ed2..f9a9212 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -85,8 +85,8 @@
 	unsigned int heap_protected;
 	unsigned long allocated_bytes;
 	unsigned long total_size;
-	int (*request_region)(void *);
-	int (*release_region)(void *);
+	int (*heap_request_region)(void *);
+	int (*heap_release_region)(void *);
 	void *bus_id;
 	unsigned long kmap_cached_count;
 	unsigned long kmap_uncached_count;
@@ -144,6 +144,31 @@
 	return cp_heap->kmap_cached_count + cp_heap->kmap_uncached_count;
 }
 
+static int ion_on_first_alloc(struct ion_heap *heap)
+{
+	struct ion_cp_heap *cp_heap =
+		container_of(heap, struct ion_cp_heap, heap);
+	int ret_value;
+
+	if (cp_heap->reusable) {
+		ret_value = fmem_set_state(FMEM_C_STATE);
+		if (ret_value)
+			return 1;
+	}
+	return 0;
+}
+
+static void ion_on_last_free(struct ion_heap *heap)
+{
+	struct ion_cp_heap *cp_heap =
+		container_of(heap, struct ion_cp_heap, heap);
+
+	if (cp_heap->reusable)
+		if (fmem_set_state(FMEM_T_STATE) != 0)
+			pr_err("%s: unable to transition heap to T-state\n",
+				__func__);
+}
+
 /* Must be protected by ion_cp_buffer lock */
 static int __ion_cp_protect_buffer(struct ion_buffer *buffer, int version,
 					void *data, int flags)
@@ -296,11 +321,9 @@
 
 	if (atomic_inc_return(&cp_heap->protect_cnt) == 1) {
 		/* Make sure we are in C state when the heap is protected. */
-		if (cp_heap->reusable && !cp_heap->allocated_bytes) {
-			ret_value = fmem_set_state(FMEM_C_STATE);
-			if (ret_value)
+		if (!cp_heap->allocated_bytes)
+			if (ion_on_first_alloc(heap))
 				goto out;
-		}
 
 		ret_value = ion_cp_protect_mem(cp_heap->secure_base,
 				cp_heap->secure_size, cp_heap->permission_type,
@@ -309,11 +332,9 @@
 			pr_err("Failed to protect memory for heap %s - "
 				"error code: %d\n", heap->name, ret_value);
 
-			if (cp_heap->reusable && !cp_heap->allocated_bytes) {
-				if (fmem_set_state(FMEM_T_STATE) != 0)
-					pr_err("%s: unable to transition heap to T-state\n",
-						__func__);
-			}
+			if (!cp_heap->allocated_bytes)
+				ion_on_last_free(heap);
+
 			atomic_dec(&cp_heap->protect_cnt);
 		} else {
 			cp_heap->heap_protected = HEAP_PROTECTED;
@@ -350,11 +371,8 @@
 			pr_debug("Un-protected heap %s @ 0x%x\n", heap->name,
 				(unsigned int) cp_heap->base);
 
-			if (cp_heap->reusable && !cp_heap->allocated_bytes) {
-				if (fmem_set_state(FMEM_T_STATE) != 0)
-					pr_err("%s: unable to transition heap to T-state",
-						__func__);
-			}
+			if (!cp_heap->allocated_bytes)
+				ion_on_last_free(heap);
 		}
 	}
 	pr_debug("%s: protect count is %d\n", __func__,
@@ -395,12 +413,11 @@
 	 * if this is the first reusable allocation, transition
 	 * the heap
 	 */
-	if (cp_heap->reusable && !cp_heap->allocated_bytes) {
-		if (fmem_set_state(FMEM_C_STATE) != 0) {
+	if (!cp_heap->allocated_bytes)
+		if (ion_on_first_alloc(heap)) {
 			mutex_unlock(&cp_heap->lock);
 			return ION_RESERVED_ALLOCATE_FAIL;
 		}
-	}
 
 	cp_heap->allocated_bytes += size;
 	mutex_unlock(&cp_heap->lock);
@@ -419,13 +436,9 @@
 				__func__, heap->name,
 				cp_heap->total_size -
 				cp_heap->allocated_bytes, size);
-
-		if (cp_heap->reusable && !cp_heap->allocated_bytes &&
-		    cp_heap->heap_protected == HEAP_NOT_PROTECTED) {
-			if (fmem_set_state(FMEM_T_STATE) != 0)
-				pr_err("%s: unable to transition heap to T-state\n",
-					__func__);
-		}
+		if (!cp_heap->allocated_bytes &&
+			cp_heap->heap_protected == HEAP_NOT_PROTECTED)
+			ion_on_last_free(heap);
 		mutex_unlock(&cp_heap->lock);
 
 		return ION_CP_ALLOCATE_FAIL;
@@ -470,12 +483,9 @@
 	mutex_lock(&cp_heap->lock);
 	cp_heap->allocated_bytes -= size;
 
-	if (cp_heap->reusable && !cp_heap->allocated_bytes &&
-	    cp_heap->heap_protected == HEAP_NOT_PROTECTED) {
-		if (fmem_set_state(FMEM_T_STATE) != 0)
-			pr_err("%s: unable to transition heap to T-state\n",
-				__func__);
-	}
+	if (!cp_heap->allocated_bytes &&
+		cp_heap->heap_protected == HEAP_NOT_PROTECTED)
+		ion_on_last_free(heap);
 
 	/* Unmap everything if we previously mapped the whole heap at once. */
 	if (!cp_heap->allocated_bytes) {
@@ -621,8 +631,9 @@
 {
 	int ret_value = 0;
 	if ((cp_heap->umap_count + ion_cp_get_total_kmap_count(cp_heap)) == 0)
-		if (cp_heap->request_region)
-			ret_value = cp_heap->request_region(cp_heap->bus_id);
+		if (cp_heap->heap_request_region)
+			ret_value = cp_heap->heap_request_region(
+					cp_heap->bus_id);
 	return ret_value;
 }
 
@@ -633,8 +644,9 @@
 {
 	int ret_value = 0;
 	if ((cp_heap->umap_count + ion_cp_get_total_kmap_count(cp_heap)) == 0)
-		if (cp_heap->release_region)
-			ret_value = cp_heap->release_region(cp_heap->bus_id);
+		if (cp_heap->heap_release_region)
+			ret_value = cp_heap->heap_release_region(
+					cp_heap->bus_id);
 	return ret_value;
 }
 
@@ -1175,9 +1187,11 @@
 		if (extra_data->setup_region)
 			cp_heap->bus_id = extra_data->setup_region();
 		if (extra_data->request_region)
-			cp_heap->request_region = extra_data->request_region;
+			cp_heap->heap_request_region =
+				extra_data->request_region;
 		if (extra_data->release_region)
-			cp_heap->release_region = extra_data->release_region;
+			cp_heap->heap_release_region =
+				extra_data->release_region;
 		cp_heap->iommu_map_all =
 				extra_data->iommu_map_all;
 		cp_heap->iommu_2x_map_domain =
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 2681836..90f14e6 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -533,9 +533,9 @@
 /* RBBM_CLOCK_CTL default value */
 #define A305_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
 #define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
-#define A330_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAE
+#define A330_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
 
-#define A330_RBBM_GPR0_CTL_DEFAULT  0x0AE2B8AE
+#define A330_RBBM_GPR0_CTL_DEFAULT  0x00000000
 
 /* COUNTABLE FOR SP PERFCOUNTER */
 #define SP_FS_FULL_ALU_INSTRUCTIONS    0x0E
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 41fd7aa..930d233 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1467,6 +1467,7 @@
 		ret = -ENOMEM;
 		goto done;
 	}
+	rec_data->fault = device->mmu.fault;
 
 done:
 	if (ret) {
@@ -1529,9 +1530,9 @@
 			goto done;
 	}
 
-	/* Do not try the bad caommands if recovery has failed bad commands
-	 * once already */
-	if (!try_bad_commands)
+	/* Do not try the bad commands if recovery has failed bad commands
+	 * once already or if hang is due to a fault */
+	if (!try_bad_commands || rec_data->fault)
 		rec_data->bad_rb_size = 0;
 
 	if (rec_data->bad_rb_size) {
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index fd9a0c3..bec19e2 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -138,6 +138,7 @@
  * bad_rb_size - Number of valid dwords in bad_rb_buffer
  * @last_valid_ctx_id - The last context from which commands were placed in
  * ringbuffer before the GPU hung
+ * @fault - Indicates whether the hang was caused due to a pagefault
  */
 struct adreno_recovery_data {
 	unsigned int ib1;
@@ -148,6 +149,7 @@
 	unsigned int *bad_rb_buffer;
 	unsigned int bad_rb_size;
 	unsigned int last_valid_ctx_id;
+	int fault;
 };
 
 extern struct adreno_gpudev adreno_a2xx_gpudev;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 97d88ff..62108f2 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -34,6 +34,7 @@
 	{ 0x14, 0x0003FFFF, 14 },		/* TTBR1 */
 	{ 0x20, 0, 0 },				/* FSR */
 	{ 0x800, 0, 0 },			/* TLBIALL */
+	{ 0x820, 0, 0 },			/* RESUME */
 };
 
 static struct kgsl_iommu_register_list kgsl_iommuv2_reg[KGSL_IOMMU_REG_MAX] = {
@@ -41,7 +42,8 @@
 	{ 0x20, 0x00FFFFFF, 14 },		/* TTBR0 */
 	{ 0x28, 0x00FFFFFF, 14 },		/* TTBR1 */
 	{ 0x58, 0, 0 },				/* FSR */
-	{ 0x618, 0, 0 }				/* TLBIALL */
+	{ 0x618, 0, 0 },			/* TLBIALL */
+	{ 0x008, 0, 0 }				/* RESUME */
 };
 
 static int get_iommu_unit(struct device *dev, struct kgsl_mmu **mmu_out,
@@ -124,9 +126,19 @@
 	KGSL_MEM_CRIT(iommu_dev->kgsldev, "context = %d FSR = %X\n",
 		iommu_dev->ctx_id, fsr);
 
+	mmu->fault = 1;
+	iommu_dev->fault = 1;
+
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
 			kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), 0);
 
+	/*
+	 * We do not want the h/w to resume fetching data from an iommu unit
+	 * that has faulted, this is better for debugging as it will stall
+	 * the GPU and trigger a snapshot. To stall the transaction return
+	 * EBUSY error.
+	 */
+	ret = -EBUSY;
 done:
 	return ret;
 }
@@ -859,12 +871,13 @@
 	 */
 	for (i = 0; i < iommu->unit_count; i++) {
 		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
-		for (j = 0; j < iommu_unit->dev_count; j++)
+		for (j = 0; j < iommu_unit->dev_count; j++) {
 			iommu_unit->dev[j].pt_lsb = KGSL_IOMMMU_PT_LSB(iommu,
 						KGSL_IOMMU_GET_CTX_REG(iommu,
 						iommu_unit,
 						iommu_unit->dev[j].ctx_id,
 						TTBR0));
+		}
 	}
 
 	kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
@@ -948,6 +961,7 @@
 static void kgsl_iommu_stop(struct kgsl_mmu *mmu)
 {
 	struct kgsl_iommu *iommu = mmu->priv;
+	int i, j;
 	/*
 	 *  stop device mmu
 	 *
@@ -960,8 +974,25 @@
 		mmu->hwpagetable = NULL;
 
 		mmu->flags &= ~KGSL_FLAGS_STARTED;
-	}
 
+		if (mmu->fault) {
+			for (i = 0; i < iommu->unit_count; i++) {
+				struct kgsl_iommu_unit *iommu_unit =
+					&iommu->iommu_units[i];
+				for (j = 0; j < iommu_unit->dev_count; j++) {
+					if (iommu_unit->dev[j].fault) {
+						kgsl_iommu_enable_clk(mmu, j);
+						KGSL_IOMMU_SET_CTX_REG(iommu,
+						iommu_unit,
+						iommu_unit->dev[j].ctx_id,
+						RESUME, 1);
+						iommu_unit->dev[j].fault = 0;
+					}
+				}
+			}
+			mmu->fault = 0;
+		}
+	}
 	/* switch off MMU clocks and cancel any events it has queued */
 	iommu->clk_event_queued = false;
 	kgsl_cancel_events(mmu->device, mmu);
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index eafba7b..661b4f0 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -25,6 +25,7 @@
 	KGSL_IOMMU_CTX_TTBR1,
 	KGSL_IOMMU_CTX_FSR,
 	KGSL_IOMMU_CTX_TLBIALL,
+	KGSL_IOMMU_CTX_RESUME,
 	KGSL_IOMMU_REG_MAX
 };
 
@@ -77,6 +78,8 @@
  * @ctx_id: This iommu units context id. It can be either 0 or 1
  * @clk_enabled: If set indicates that iommu clocks of this iommu context
  * are on, else the clocks are off
+ * fault: Flag when set indicates that this iommu device has caused a page
+ * fault
  */
 struct kgsl_iommu_device {
 	struct device *dev;
@@ -85,6 +88,7 @@
 	enum kgsl_iommu_context_id ctx_id;
 	bool clk_enabled;
 	struct kgsl_device *kgsldev;
+	int fault;
 };
 
 /*
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 234629b..b8b9149 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -175,6 +175,7 @@
 	struct kgsl_pagetable  *hwpagetable;
 	const struct kgsl_mmu_ops *mmu_ops;
 	void *priv;
+	int fault;
 };
 
 #include "kgsl_gpummu.h"
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 16e70b2..89f0273 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -592,7 +592,7 @@
 	u32 ctrl_status = 0, count = 0, rc = 0;
 	int max_tries = 100;
 	write_register(device->hal_data->register_base_addr,
-			VIDC_WRAPPER_INTR_MASK, 0, 0);
+			VIDC_WRAPPER_INTR_MASK, 0x8, 0);
 	write_register(device->hal_data->register_base_addr,
 			VIDC_CPU_CS_SCIACMDARG3, 1, 0);
 	while (!ctrl_status && count < max_tries) {
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index c552e2d..7757b5c 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -21,13 +21,21 @@
 #include <linux/memory_alloc.h>
 #include <linux/ctype.h>
 #include <linux/debugfs.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/iommu.h>
 
 #include <mach/board.h>
 #include <mach/gpio.h>
 #include <mach/irqs.h>
+#include <mach/clk.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
 
 #include <media/videobuf2-msm-mem.h>
-
 #include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -35,16 +43,9 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-event.h>
-#include <linux/regulator/consumer.h>
-#include <mach/clk.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
-#include <mach/iommu_domains.h>
-
 #include <media/vcap_v4l2.h>
 #include <media/vcap_fmt.h>
+
 #include "vcap_vc.h"
 #include "vcap_vp.h"
 
@@ -79,7 +80,7 @@
 };
 #endif
 
-int vcap_reg_powerup(struct vcap_dev *dev)
+static int vcap_reg_powerup(struct vcap_dev *dev)
 {
 	dev->fs_vcap = regulator_get(NULL, "fs_vcap");
 	if (IS_ERR(dev->fs_vcap)) {
@@ -95,7 +96,7 @@
 	return 0;
 }
 
-void vcap_reg_powerdown(struct vcap_dev *dev)
+static void vcap_reg_powerdown(struct vcap_dev *dev)
 {
 	if (dev->fs_vcap == NULL)
 		return;
@@ -105,7 +106,7 @@
 	return;
 }
 
-int config_gpios(int on, struct vcap_platform_data *pdata)
+static int vcap_config_gpios(int on, struct vcap_platform_data *pdata)
 {
 	int i, ret;
 	int num_gpios = pdata->num_gpios;
@@ -140,7 +141,7 @@
 	return -EINVAL;
 }
 
-int vcap_clk_powerup(struct vcap_dev *dev, struct device *ddev,
+static int vcap_clk_powerup(struct vcap_dev *dev, struct device *ddev,
 		unsigned long rate)
 {
 	int ret = 0;
@@ -228,7 +229,7 @@
 	return -EINVAL;
 }
 
-void vcap_clk_powerdown(struct vcap_dev *dev)
+static void vcap_clk_powerdown(struct vcap_dev *dev)
 {
 	if (dev->vcap_p_clk != NULL) {
 		clk_disable(dev->vcap_p_clk);
@@ -254,7 +255,7 @@
 	dev->dbg_p.clk_rate = 0;
 }
 
-int vcap_get_bus_client_handle(struct vcap_dev *dev)
+static int vcap_get_bus_client_handle(struct vcap_dev *dev)
 {
 	struct msm_bus_scale_pdata *vcap_axi_client_pdata =
 			dev->vcap_pdata->bus_client_pdata;
@@ -264,7 +265,7 @@
 	return 0;
 }
 
-int vcap_enable(struct vcap_dev *dev, struct device *ddev,
+static int vcap_enable(struct vcap_dev *dev, struct device *ddev,
 		unsigned long rate)
 {
 	int rc;
@@ -279,14 +280,24 @@
 	rc = vcap_get_bus_client_handle(dev);
 	if (rc < 0)
 		goto bus_r_failed;
-	rc = config_gpios(1, dev->vcap_pdata);
+	rc = vcap_config_gpios(1, dev->vcap_pdata);
 	if (rc < 0)
 		goto gpio_failed;
+	rc = iommu_attach_device(dev->iommu_vcap_domain, dev->vc_iommu_ctx);
+	if (rc < 0)
+		goto vc_iommu_attach_failed;
+	rc = iommu_attach_device(dev->iommu_vcap_domain, dev->vp_iommu_ctx);
+	if (rc < 0)
+		goto vp_iommu_attach_failed;
 	writel_relaxed(0x00030003, VCAP_OFFSET(0xD78));
 	writel_relaxed(0x00030003, VCAP_OFFSET(0xD7C));
 	pr_debug("Success Exit %s", __func__);
 	return 0;
 
+vp_iommu_attach_failed:
+	iommu_detach_device(dev->iommu_vcap_domain, dev->vc_iommu_ctx);
+vc_iommu_attach_failed:
+	vcap_config_gpios(0, dev->vcap_pdata);
 gpio_failed:
 	msm_bus_scale_unregister_client(dev->bus_client_handle);
 	dev->bus_client_handle = 0;
@@ -298,10 +309,13 @@
 	return rc;
 }
 
-int vcap_disable(struct vcap_dev *dev)
+static int vcap_disable(struct vcap_dev *dev)
 {
 	pr_debug("Enter %s", __func__);
-	config_gpios(0, dev->vcap_pdata);
+	iommu_detach_device(dev->iommu_vcap_domain, dev->vp_iommu_ctx);
+	iommu_detach_device(dev->iommu_vcap_domain, dev->vc_iommu_ctx);
+
+	vcap_config_gpios(0, dev->vcap_pdata);
 
 	msm_bus_scale_unregister_client(dev->bus_client_handle);
 	dev->bus_client_handle = 0;
@@ -311,6 +325,22 @@
 	return 0;
 }
 
+static int vcap_register_domain(void)
+{
+	struct msm_iova_partition vcap_partition = {
+		.start = 0,
+		.size = SZ_2G,
+	};
+	struct msm_iova_layout vcap_layout = {
+		.partitions = &vcap_partition,
+		.npartitions = 1,
+		.client_name = "vcap",
+		.domain_flags = 0,
+	};
+
+	return msm_register_domain(&vcap_layout);
+}
+
 enum vcap_op_mode determine_mode(struct vcap_client_data *cd)
 {
 	if (cd->set_cap == 1 && cd->set_vp_o == 0 &&
@@ -476,8 +506,9 @@
 		buf->ion_handle = NULL;
 		return -ENOMEM;
 	}
-	rc = ion_phys(dev->ion_client, buf->ion_handle,
-			&buf->paddr, (size_t *)&len);
+	rc = ion_map_iommu(dev->ion_client, buf->ion_handle,
+		dev->domain_num, 0, SZ_4K, 0, &buf->paddr, &len,
+		0, 0);
 	if (rc < 0) {
 		pr_err("%s: Could not get phys addr\n", __func__);
 		ion_free(dev->ion_client, buf->ion_handle);
@@ -500,6 +531,7 @@
 		return;
 	}
 	buf->paddr = 0;
+	ion_unmap_iommu(dev->ion_client, buf->ion_handle, dev->domain_num, 0);
 	ion_free(dev->ion_client, buf->ion_handle);
 	buf->ion_handle = NULL;
 	return;
@@ -681,6 +713,7 @@
 	struct vb2_buffer *vb;
 
 	pr_debug("VP IN stop streaming\n");
+	vp_stop_capture(c_data);
 
 	while (!list_empty(&c_data->vp_action.in_active)) {
 		struct vcap_buffer *buf;
@@ -2244,6 +2277,34 @@
 	if (ret)
 		goto free_resource;
 
+	dev->vc_iommu_ctx = msm_iommu_get_ctx("vcap_vc");
+	if (!dev->vc_iommu_ctx) {
+		pr_err("%s: No iommu vc context found\n", __func__);
+		ret = -ENODEV;
+		goto free_resource;
+	}
+
+	dev->vp_iommu_ctx = msm_iommu_get_ctx("vcap_vp");
+	if (!dev->vp_iommu_ctx) {
+		pr_err("%s: No iommu vp context found\n", __func__);
+		ret = -ENODEV;
+		goto free_resource;
+	}
+
+	dev->domain_num = vcap_register_domain();
+	if (dev->domain_num < 0) {
+		pr_err("%s: VCAP iommu domain register failed\n", __func__);
+		ret = -ENODEV;
+		goto free_resource;
+	}
+
+	dev->iommu_vcap_domain = msm_get_iommu_domain(dev->domain_num);
+	if (!dev->iommu_vcap_domain) {
+		pr_err("%s: No iommu vcap domain found\n", __func__);
+		ret = -ENODEV;
+		goto free_resource;
+	}
+
 	ret = vcap_enable(dev, &pdev->dev, 54860000);
 	if (ret)
 		goto unreg_dev;
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index c7de465..57813f5 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -15,14 +15,16 @@
 #include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <mach/camera.h>
-#include <linux/io.h>
-#include <mach/clk.h>
 #include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/camera.h>
+#include <mach/clk.h>
 
 #include <media/v4l2-event.h>
 #include <media/vcap_v4l2.h>
 #include <media/vcap_fmt.h>
+
 #include "vcap_vp.h"
 
 void config_nr_buffer(struct vcap_client_data *c_data,
@@ -393,6 +395,7 @@
 				msecs_to_jiffies(50));
 		if (rc == 0 && atomic_read(&dev->vp_enabled) == 1) {
 			/* This should not happen, if it does hw is stuck */
+			disable_irq_nosync(dev->vpirq->start);
 			pr_err("%s: VP Timeout and VP still running\n",
 				__func__);
 		}
@@ -463,9 +466,8 @@
 	int rc;
 	struct vcap_dev *dev = c_data->dev;
 	struct ion_handle *handle = NULL;
-	unsigned long paddr, ionflag = 0;
+	unsigned long paddr, len, ionflag = 0;
 	void *vaddr;
-	size_t len;
 	size_t size = ((c_data->vp_out_fmt.width + 63) >> 6) *
 		((c_data->vp_out_fmt.height + 7) >> 3) * 16;
 
@@ -480,12 +482,6 @@
 		pr_err("%s: ion_alloc failed\n", __func__);
 		return -ENOMEM;
 	}
-	rc = ion_phys(dev->ion_client, handle, &paddr, &len);
-	if (rc < 0) {
-		pr_err("%s: ion_phys failed\n", __func__);
-		ion_free(dev->ion_client, handle);
-		return rc;
-	}
 
 	rc = ion_handle_get_flags(dev->ion_client, handle, &ionflag);
 	if (rc) {
@@ -503,10 +499,20 @@
 	}
 
 	memset(vaddr, 0, size);
+	ion_unmap_kernel(dev->ion_client, handle);
+
+	rc = ion_map_iommu(dev->ion_client, handle,
+		dev->domain_num, 0, SZ_4K, 0, &paddr, &len,
+		0, 0);
+	if (rc < 0) {
+		pr_err("%s: map_iommu failed\n", __func__);
+		ion_free(dev->ion_client, handle);
+		return rc;
+	}
+
 	c_data->vp_action.motionHandle = handle;
 
 	vaddr = NULL;
-	ion_unmap_kernel(dev->ion_client, handle);
 
 	writel_iowmb(paddr, VCAP_VP_MOTION_EST_ADDR);
 	return 0;
@@ -521,6 +527,8 @@
 	}
 
 	writel_iowmb(0x00000000, VCAP_VP_MOTION_EST_ADDR);
+	ion_unmap_iommu(dev->ion_client, c_data->vp_action.motionHandle,
+			dev->domain_num, 0);
 	ion_free(dev->ion_client, c_data->vp_action.motionHandle);
 	c_data->vp_action.motionHandle = NULL;
 	return;
@@ -530,8 +538,8 @@
 {
 	struct vcap_dev *dev = c_data->dev;
 	struct ion_handle *handle = NULL;
-	size_t frame_size, tot_size, len;
-	unsigned long paddr;
+	size_t frame_size, tot_size;
+	unsigned long paddr, len;
 	int rc;
 
 	if (c_data->vp_action.bufNR.nr_handle) {
@@ -552,9 +560,11 @@
 		return -ENOMEM;
 	}
 
-	rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+	rc = ion_map_iommu(dev->ion_client, handle,
+		dev->domain_num, 0, SZ_4K, 0, &paddr, &len,
+		0, 0);
 	if (rc < 0) {
-		pr_err("%s: ion_phys failed\n", __func__);
+		pr_err("%s: map_iommu failed\n", __func__);
 		ion_free(dev->ion_client, handle);
 		return rc;
 	}
@@ -588,6 +598,7 @@
 	rc &= !(0x0FF00001);
 	writel_relaxed(rc, VCAP_VP_NR_CONFIG2);
 
+	ion_unmap_iommu(dev->ion_client, buf->nr_handle, dev->domain_num, 0);
 	ion_free(dev->ion_client, buf->nr_handle);
 	buf->nr_handle = NULL;
 	buf->paddr = 0;
@@ -669,8 +680,7 @@
 	struct vcap_dev *dev = c_data->dev;
 	unsigned int width, height;
 	struct ion_handle *handle = NULL;
-	unsigned long paddr;
-	size_t len;
+	unsigned long paddr, len;
 	uint32_t reg;
 	int rc = 0;
 
@@ -682,9 +692,11 @@
 		return -ENOMEM;
 	}
 
-	rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+	rc = ion_map_iommu(dev->ion_client, handle,
+		dev->domain_num, 0, SZ_4K, 0, &paddr, &len,
+		0, 0);
 	if (rc < 0) {
-		pr_err("%s: ion_phys failed\n", __func__);
+		pr_err("%s: map_iommu failed\n", __func__);
 		ion_free(dev->ion_client, handle);
 		return rc;
 	}
@@ -732,6 +744,7 @@
 
 	c_data->vp_out_fmt.width = width;
 	c_data->vp_out_fmt.height = height;
+	ion_unmap_iommu(dev->ion_client, handle, dev->domain_num, 0);
 	ion_free(dev->ion_client, handle);
 
 	pr_debug("%s: Exit VP dummy event\n", __func__);
diff --git a/drivers/misc/tsif.c b/drivers/misc/tsif.c
index 1ff4468..b7b1203 100644
--- a/drivers/misc/tsif.c
+++ b/drivers/misc/tsif.c
@@ -140,6 +140,10 @@
 	unsigned int irq;
 	int mode;
 	u32 time_limit;
+	int clock_inverse;
+	int data_inverse;
+	int sync_inverse;
+	int enable_inverse;
 	enum tsif_state state;
 	struct wake_lock wake_lock;
 	/* clocks */
@@ -358,6 +362,19 @@
 		  TSIF_STS_CTL_EN_TIME_LIM |
 		  TSIF_STS_CTL_EN_TCR |
 		  TSIF_STS_CTL_EN_DM;
+
+	if (tsif_device->clock_inverse)
+		ctl |= TSIF_STS_CTL_INV_CLOCK;
+
+	if (tsif_device->data_inverse)
+		ctl |= TSIF_STS_CTL_INV_DATA;
+
+	if (tsif_device->sync_inverse)
+		ctl |= TSIF_STS_CTL_INV_SYNC;
+
+	if (tsif_device->enable_inverse)
+		ctl |= TSIF_STS_CTL_INV_ENABLE;
+
 	dev_info(&tsif_device->pdev->dev, "%s\n", __func__);
 	switch (tsif_device->mode) {
 	case 1: /* mode 1 */
@@ -805,6 +822,10 @@
 			"Client     = %p\n"
 			"Pkt/Buf    = %d\n"
 			"Pkt/chunk  = %d\n"
+			"Clock inv  = %d\n"
+			"Data inv   = %d\n"
+			"Sync inv   = %d\n"
+			"Enable inv = %d\n"
 			"--statistics--\n"
 			"Rx chunks  = %d\n"
 			"Overflow   = %d\n"
@@ -827,6 +848,10 @@
 			tsif_device->client_data,
 			TSIF_PKTS_IN_BUF,
 			TSIF_PKTS_IN_CHUNK,
+			tsif_device->clock_inverse,
+			tsif_device->data_inverse,
+			tsif_device->sync_inverse,
+			tsif_device->enable_inverse,
 			tsif_device->stat_rx,
 			tsif_device->stat_overflow,
 			tsif_device->stat_lost_sync,
@@ -950,11 +975,120 @@
 static DEVICE_ATTR(buf_config, S_IRUGO | S_IWUSR,
 		   show_buf_config, set_buf_config);
 
+static ssize_t show_clk_inverse(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->clock_inverse);
+}
+
+static ssize_t set_clk_inverse(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	int value;
+	int rc;
+	if (1 != sscanf(buf, "%d", &value)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Failed to parse integer: <%s>\n", buf);
+		return -EINVAL;
+	}
+	rc = tsif_set_clk_inverse(tsif_device, value);
+	if (!rc)
+		rc = count;
+	return rc;
+}
+static DEVICE_ATTR(clk_inverse, S_IRUGO | S_IWUSR,
+	show_clk_inverse, set_clk_inverse);
+
+static ssize_t show_data_inverse(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->data_inverse);
+}
+
+static ssize_t set_data_inverse(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	int value;
+	int rc;
+	if (1 != sscanf(buf, "%d", &value)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Failed to parse integer: <%s>\n", buf);
+		return -EINVAL;
+	}
+	rc = tsif_set_data_inverse(tsif_device, value);
+	if (!rc)
+		rc = count;
+	return rc;
+}
+static DEVICE_ATTR(data_inverse, S_IRUGO | S_IWUSR,
+	show_data_inverse, set_data_inverse);
+
+static ssize_t show_sync_inverse(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->sync_inverse);
+}
+
+static ssize_t set_sync_inverse(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	int value;
+	int rc;
+	if (1 != sscanf(buf, "%d", &value)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Failed to parse integer: <%s>\n", buf);
+		return -EINVAL;
+	}
+	rc = tsif_set_sync_inverse(tsif_device, value);
+	if (!rc)
+		rc = count;
+	return rc;
+}
+static DEVICE_ATTR(sync_inverse, S_IRUGO | S_IWUSR,
+	show_sync_inverse, set_sync_inverse);
+
+static ssize_t show_enable_inverse(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tsif_device->enable_inverse);
+}
+
+static ssize_t set_enable_inverse(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct msm_tsif_device *tsif_device = dev_get_drvdata(dev);
+	int value;
+	int rc;
+	if (1 != sscanf(buf, "%d", &value)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Failed to parse integer: <%s>\n", buf);
+		return -EINVAL;
+	}
+	rc = tsif_set_enable_inverse(tsif_device, value);
+	if (!rc)
+		rc = count;
+	return rc;
+}
+static DEVICE_ATTR(enable_inverse, S_IRUGO | S_IWUSR,
+	show_enable_inverse, set_enable_inverse);
+
+
 static struct attribute *dev_attrs[] = {
 	&dev_attr_stats.attr,
 	&dev_attr_mode.attr,
 	&dev_attr_time_limit.attr,
 	&dev_attr_buf_config.attr,
+	&dev_attr_clk_inverse.attr,
+	&dev_attr_data_inverse.attr,
+	&dev_attr_sync_inverse.attr,
+	&dev_attr_enable_inverse.attr,
 	NULL,
 };
 static struct attribute_group dev_attr_grp = {
@@ -1287,6 +1421,10 @@
 	tsif_device->pdev = pdev;
 	platform_set_drvdata(pdev, tsif_device);
 	tsif_device->mode = 1;
+	tsif_device->clock_inverse = 0;
+	tsif_device->data_inverse = 0;
+	tsif_device->sync_inverse = 0;
+	tsif_device->enable_inverse = 0;
 	tsif_device->pkts_per_chunk = TSIF_PKTS_IN_CHUNK_DEFAULT;
 	tsif_device->chunks_per_buf = TSIF_CHUNKS_IN_BUF_DEFAULT;
 	tasklet_init(&tsif_device->dma_refill, tsif_dma_refill,
@@ -1534,6 +1672,78 @@
 }
 EXPORT_SYMBOL(tsif_set_buf_config);
 
+int tsif_set_clk_inverse(void *cookie, int value)
+{
+	struct msm_tsif_device *tsif_device = cookie;
+	if (tsif_device->state != tsif_state_stopped) {
+		dev_err(&tsif_device->pdev->dev,
+			"Can't change clock inverse while device is active\n");
+		return -EBUSY;
+	}
+	if ((value != 0) && (value != 1)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Invalid parameter, either 0 or 1: %#x\n", value);
+		return -EINVAL;
+	}
+	tsif_device->clock_inverse = value;
+	return 0;
+}
+EXPORT_SYMBOL(tsif_set_clk_inverse);
+
+int tsif_set_data_inverse(void *cookie, int value)
+{
+	struct msm_tsif_device *tsif_device = cookie;
+	if (tsif_device->state != tsif_state_stopped) {
+		dev_err(&tsif_device->pdev->dev,
+			"Can't change data inverse while device is active\n");
+		return -EBUSY;
+	}
+	if ((value != 0) && (value != 1)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Invalid parameter, either 0 or 1: %#x\n", value);
+		return -EINVAL;
+	}
+	tsif_device->data_inverse = value;
+	return 0;
+}
+EXPORT_SYMBOL(tsif_set_data_inverse);
+
+int tsif_set_sync_inverse(void *cookie, int value)
+{
+	struct msm_tsif_device *tsif_device = cookie;
+	if (tsif_device->state != tsif_state_stopped) {
+		dev_err(&tsif_device->pdev->dev,
+			"Can't change sync inverse while device is active\n");
+		return -EBUSY;
+	}
+	if ((value != 0) && (value != 1)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Invalid parameter, either 0 or 1: %#x\n", value);
+		return -EINVAL;
+	}
+	tsif_device->sync_inverse = value;
+	return 0;
+}
+EXPORT_SYMBOL(tsif_set_sync_inverse);
+
+int tsif_set_enable_inverse(void *cookie, int value)
+{
+	struct msm_tsif_device *tsif_device = cookie;
+	if (tsif_device->state != tsif_state_stopped) {
+		dev_err(&tsif_device->pdev->dev,
+			"Can't change enable inverse while device is active\n");
+		return -EBUSY;
+	}
+	if ((value != 0) && (value != 1)) {
+		dev_err(&tsif_device->pdev->dev,
+			"Invalid parameter, either 0 or 1: %#x\n", value);
+		return -EINVAL;
+	}
+	tsif_device->enable_inverse = value;
+	return 0;
+}
+EXPORT_SYMBOL(tsif_set_enable_inverse);
+
 void tsif_get_state(void *cookie, int *ri, int *wi, enum tsif_state *state)
 {
 	struct msm_tsif_device *tsif_device = cookie;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 7387d9a..254672f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1392,7 +1392,10 @@
 	}
 
 	mqrq->mmc_active.mrq = &brq->mrq;
-	mqrq->mmc_active.err_check = mmc_blk_err_check;
+	if (mq->err_check_fn)
+		mqrq->mmc_active.err_check = mq->err_check_fn;
+	else
+		mqrq->mmc_active.err_check = mmc_blk_err_check;
 
 	mmc_queue_bounce_pre(mqrq);
 }
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index bdda8d5..7d3ac83 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -21,6 +21,7 @@
 #include <linux/delay.h>
 #include <linux/test-iosched.h>
 #include "queue.h"
+#include <linux/mmc/mmc.h>
 
 #define MODULE_NAME "mmc_block_test"
 #define TEST_MAX_SECTOR_RANGE		(600*1024*1024) /* 600 MB */
@@ -32,11 +33,24 @@
 #define PACKED_HDR_RW_MASK 0x0000FF00
 #define PACKED_HDR_NUM_REQS_MASK 0x00FF0000
 #define PACKED_HDR_BITS_16_TO_29_SET 0x3FFF0000
+#define SECTOR_SIZE 512
+#define NUM_OF_SECTORS_PER_BIO		((BIO_U32_SIZE * 4) / SECTOR_SIZE)
+#define BIO_TO_SECTOR(x)		(x * NUM_OF_SECTORS_PER_BIO)
 
 #define test_pr_debug(fmt, args...) pr_debug("%s: "fmt"\n", MODULE_NAME, args)
 #define test_pr_info(fmt, args...) pr_info("%s: "fmt"\n", MODULE_NAME, args)
 #define test_pr_err(fmt, args...) pr_err("%s: "fmt"\n", MODULE_NAME, args)
 
+#define SANITIZE_TEST_TIMEOUT 240000
+#define TEST_REQUEST_NUM_OF_BIOS	3
+
+
+#define CHECK_BKOPS_STATS(stats, exp_bkops, exp_hpi, exp_suspend)	\
+				   ((stats.bkops != exp_bkops) ||	\
+				    (stats.hpi != exp_hpi) ||		\
+				    (stats.suspend != exp_suspend))
+#define BKOPS_TEST_TIMEOUT 60000
+
 enum is_random {
 	NON_RANDOM_TEST,
 	RANDOM_TEST,
@@ -101,6 +115,18 @@
 	TEST_PACK_MIX_PACKED_NO_PACKED_PACKED,
 	TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED,
 	PACKING_CONTROL_MAX_TESTCASE = TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED,
+
+	TEST_WRITE_DISCARD_SANITIZE_READ,
+
+	/* Start of bkops test group */
+	BKOPS_MIN_TESTCASE,
+	BKOPS_DELAYED_WORK_LEVEL_1 = BKOPS_MIN_TESTCASE,
+	BKOPS_DELAYED_WORK_LEVEL_1_HPI,
+	BKOPS_CANCEL_DELAYED_WORK,
+	BKOPS_URGENT_LEVEL_2,
+	BKOPS_URGENT_LEVEL_2_TWO_REQS,
+	BKOPS_URGENT_LEVEL_3,
+	BKOPS_MAX_TESTCASE = BKOPS_URGENT_LEVEL_3,
 };
 
 enum mmc_block_test_group {
@@ -110,6 +136,14 @@
 	TEST_ERR_CHECK_GROUP,
 	TEST_SEND_INVALID_GROUP,
 	TEST_PACKING_CONTROL_GROUP,
+	TEST_BKOPS_GROUP,
+};
+
+enum bkops_test_stages {
+	BKOPS_STAGE_1,
+	BKOPS_STAGE_2,
+	BKOPS_STAGE_3,
+	BKOPS_STAGE_4,
 };
 
 struct mmc_block_test_debug {
@@ -118,6 +152,8 @@
 	struct dentry *send_invalid_packed_test;
 	struct dentry *random_test_seed;
 	struct dentry *packing_control_test;
+	struct dentry *discard_sanitize_test;
+	struct dentry *bkops_test;
 };
 
 struct mmc_block_test_data {
@@ -149,6 +185,10 @@
 	struct test_info test_info;
 	/* mmc block device test */
 	struct blk_dev_test_type bdt;
+	/* Current BKOPs test stage */
+	enum bkops_test_stages	bkops_stage;
+	/* A wait queue for BKOPs tests */
+	wait_queue_head_t bkops_wait_q;
 };
 
 static struct mmc_block_test_data *mbtd;
@@ -308,6 +348,7 @@
 	struct mmc_queue *mq;
 	int max_packed_reqs;
 	int ret = 0;
+	struct mmc_blk_request *brq;
 
 	if (req_q)
 		mq = req_q->queuedata;
@@ -329,6 +370,7 @@
 			mmc_hostname(card->host));
 		return 0;
 	}
+	brq = &mq_rq->brq;
 
 	switch (mbtd->test_info.testcase) {
 	case TEST_RET_ABORT:
@@ -397,6 +439,16 @@
 		test_pr_info("%s: return data err", __func__);
 		ret = MMC_BLK_DATA_ERR;
 		break;
+	case BKOPS_URGENT_LEVEL_2:
+	case BKOPS_URGENT_LEVEL_3:
+	case BKOPS_URGENT_LEVEL_2_TWO_REQS:
+		if (mbtd->err_check_counter++ == 0) {
+			test_pr_info("%s: simulate an exception from the card",
+				     __func__);
+			brq->cmd.resp[0] |= R1_EXCEPTION_EVENT;
+		}
+		mq->err_check_fn = NULL;
+		break;
 	default:
 		test_pr_err("%s: unexpected testcase %d",
 			__func__, mbtd->test_info.testcase);
@@ -496,6 +548,20 @@
 		return "\nTest packing control - mix: pack -> no pack -> pack";
 	case TEST_PACK_MIX_NO_PACKED_PACKED_NO_PACKED:
 		return "\nTest packing control - mix: no pack->pack->no pack";
+	case TEST_WRITE_DISCARD_SANITIZE_READ:
+		return "\nTest write, discard, sanitize";
+	case BKOPS_DELAYED_WORK_LEVEL_1:
+		return "\nTest delayed work BKOPS level 1";
+	case BKOPS_DELAYED_WORK_LEVEL_1_HPI:
+		return "\nTest delayed work BKOPS level 1 with HPI";
+	case BKOPS_CANCEL_DELAYED_WORK:
+		return "\nTest cancel delayed BKOPS work";
+	case BKOPS_URGENT_LEVEL_2:
+		return "\nTest urgent BKOPS level 2";
+	case BKOPS_URGENT_LEVEL_2_TWO_REQS:
+		return "\nTest urgent BKOPS level 2, followed by a request";
+	case BKOPS_URGENT_LEVEL_3:
+		return "\nTest urgent BKOPS level 3";
 	default:
 		 return "Unknown testcase";
 	}
@@ -1382,6 +1448,446 @@
 	return 0;
 }
 
+static void pseudo_rnd_sector_and_size(unsigned int *seed,
+				       unsigned int min_start_sector,
+				       unsigned int *start_sector,
+				       unsigned int *num_of_bios)
+{
+	unsigned int max_sec = min_start_sector + TEST_MAX_SECTOR_RANGE;
+	do {
+		*start_sector = pseudo_random_seed(seed,
+						   1, max_sec);
+		*num_of_bios = pseudo_random_seed(seed,
+						  1, TEST_MAX_BIOS_PER_REQ);
+		if (!(*num_of_bios))
+			*num_of_bios = 1;
+	} while ((*start_sector < min_start_sector) ||
+		 (*start_sector + (*num_of_bios * BIO_U32_SIZE * 4)) > max_sec);
+}
+
+/* sanitize test functions */
+static int prepare_write_discard_sanitize_read(struct test_data *td)
+{
+	unsigned int start_sector;
+	unsigned int num_of_bios = 0;
+	static unsigned int total_bios;
+	unsigned int *num_bios_seed;
+	int i = 0;
+
+	if (mbtd->random_test_seed == 0) {
+		mbtd->random_test_seed =
+			(unsigned int)(get_jiffies_64() & 0xFFFF);
+		test_pr_info("%s: got seed from jiffies %d",
+			     __func__, mbtd->random_test_seed);
+	}
+	num_bios_seed = &mbtd->random_test_seed;
+
+	do {
+		pseudo_rnd_sector_and_size(num_bios_seed, td->start_sector,
+					   &start_sector, &num_of_bios);
+
+		/* DISCARD */
+		total_bios += num_of_bios;
+		test_pr_info("%s: discard req: id=%d, startSec=%d, NumBios=%d",
+		       __func__, td->unique_next_req_id, start_sector,
+			     num_of_bios);
+		test_iosched_add_unique_test_req(0, REQ_UNIQUE_DISCARD,
+				    start_sector, BIO_TO_SECTOR(num_of_bios),
+						 NULL);
+
+	} while (++i < (BLKDEV_MAX_RQ-10));
+
+	test_pr_info("%s: total discard bios = %d", __func__, total_bios);
+
+	test_pr_info("%s: add sanitize req", __func__);
+	test_iosched_add_unique_test_req(0, REQ_UNIQUE_SANITIZE, 0, 0, NULL);
+
+	return 0;
+}
+
+/*
+ * Post test operations for BKOPs test
+ * Disable the BKOPs statistics and clear the feature flags
+ */
+static int bkops_post_test(struct test_data *td)
+{
+	struct request_queue *q = td->req_q;
+	struct mmc_queue *mq = (struct mmc_queue *)q->queuedata;
+	struct mmc_card *card = mq->card;
+
+	mmc_card_clr_doing_bkops(mq->card);
+	card->ext_csd.raw_bkops_status = 0;
+
+	spin_lock(&card->bkops_info.bkops_stats.lock);
+	card->bkops_info.bkops_stats.enabled = false;
+	spin_unlock(&card->bkops_info.bkops_stats.lock);
+
+	return 0;
+}
+
+/*
+ * Verify the BKOPs statsistics
+ */
+static int check_bkops_result(struct test_data *td)
+{
+	struct request_queue *q = td->req_q;
+	struct mmc_queue *mq = (struct mmc_queue *)q->queuedata;
+	struct mmc_card *card = mq->card;
+	struct mmc_bkops_stats *bkops_stat;
+
+	if (!card)
+		goto fail;
+
+	bkops_stat = &card->bkops_info.bkops_stats;
+
+	test_pr_info("%s: Test results: bkops:(%d,%d,%d) hpi:%d, suspend:%d",
+			__func__,
+			bkops_stat->bkops_level[BKOPS_SEVERITY_1_INDEX],
+			bkops_stat->bkops_level[BKOPS_SEVERITY_2_INDEX],
+			bkops_stat->bkops_level[BKOPS_SEVERITY_3_INDEX],
+			bkops_stat->hpi,
+			bkops_stat->suspend);
+
+	switch (mbtd->test_info.testcase) {
+	case BKOPS_DELAYED_WORK_LEVEL_1:
+		if ((bkops_stat->bkops_level[BKOPS_SEVERITY_1_INDEX] == 1) &&
+		    (bkops_stat->suspend == 1) &&
+		    (bkops_stat->hpi == 0))
+			goto exit;
+		else
+			goto fail;
+		break;
+	case BKOPS_DELAYED_WORK_LEVEL_1_HPI:
+		if ((bkops_stat->bkops_level[BKOPS_SEVERITY_1_INDEX] == 1) &&
+		    (bkops_stat->suspend == 0) &&
+		    (bkops_stat->hpi == 1))
+			goto exit;
+		else
+			goto fail;
+		break;
+	case BKOPS_CANCEL_DELAYED_WORK:
+		if ((bkops_stat->bkops_level[BKOPS_SEVERITY_1_INDEX] == 0) &&
+		    (bkops_stat->bkops_level[BKOPS_SEVERITY_2_INDEX] == 0) &&
+		    (bkops_stat->bkops_level[BKOPS_SEVERITY_3_INDEX] == 0) &&
+			(bkops_stat->suspend == 0) &&
+			  (bkops_stat->hpi == 0))
+			goto exit;
+		else
+			goto fail;
+	case BKOPS_URGENT_LEVEL_2:
+	case BKOPS_URGENT_LEVEL_2_TWO_REQS:
+		if ((bkops_stat->bkops_level[BKOPS_SEVERITY_2_INDEX] == 1) &&
+		    (bkops_stat->suspend == 0) &&
+		    (bkops_stat->hpi == 0))
+			goto exit;
+		else
+			goto fail;
+	case BKOPS_URGENT_LEVEL_3:
+		if ((bkops_stat->bkops_level[BKOPS_SEVERITY_3_INDEX] == 1) &&
+		    (bkops_stat->suspend == 0) &&
+		    (bkops_stat->hpi == 0))
+			goto exit;
+		else
+			goto fail;
+	default:
+		return -EINVAL;
+	}
+
+exit:
+	return 0;
+fail:
+	if (td->fs_wr_reqs_during_test) {
+		test_pr_info("%s: wr reqs during test, cancel the round",
+		     __func__);
+		test_iosched_set_ignore_round(true);
+		return 0;
+	}
+
+	test_pr_info("%s: BKOPs statistics are not as expected, test failed",
+		     __func__);
+	return -EINVAL;
+}
+
+static void bkops_end_io_final_fn(struct request *rq, int err)
+{
+	struct test_request *test_rq =
+		(struct test_request *)rq->elv.priv[0];
+	BUG_ON(!test_rq);
+
+	test_rq->req_completed = 1;
+	test_rq->req_result = err;
+
+	test_pr_info("%s: request %d completed, err=%d",
+		     __func__, test_rq->req_id, err);
+
+	mbtd->bkops_stage = BKOPS_STAGE_4;
+	wake_up(&mbtd->bkops_wait_q);
+}
+
+static void bkops_end_io_fn(struct request *rq, int err)
+{
+	struct test_request *test_rq =
+		(struct test_request *)rq->elv.priv[0];
+	BUG_ON(!test_rq);
+
+	test_rq->req_completed = 1;
+	test_rq->req_result = err;
+
+	test_pr_info("%s: request %d completed, err=%d",
+		     __func__, test_rq->req_id, err);
+	mbtd->bkops_stage = BKOPS_STAGE_2;
+	wake_up(&mbtd->bkops_wait_q);
+
+}
+
+static int prepare_bkops(struct test_data *td)
+{
+	int ret = 0;
+	struct request_queue *q = td->req_q;
+	struct mmc_queue *mq = (struct mmc_queue *)q->queuedata;
+	struct mmc_card  *card = mq->card;
+	struct mmc_bkops_stats *bkops_stat;
+
+	if (!card)
+		return -EINVAL;
+
+	bkops_stat = &card->bkops_info.bkops_stats;
+
+	if (!card->ext_csd.bkops_en) {
+		test_pr_err("%s: BKOPS is not enabled by card or host)",
+				__func__);
+		return -ENOTSUPP;
+	}
+	if (mmc_card_doing_bkops(card)) {
+		test_pr_err("%s: BKOPS in progress, try later", __func__);
+		return -EAGAIN;
+	}
+
+	mmc_blk_init_bkops_statistics(card);
+
+	if ((mbtd->test_info.testcase == BKOPS_URGENT_LEVEL_2) ||
+	    (mbtd->test_info.testcase ==  BKOPS_URGENT_LEVEL_2_TWO_REQS) ||
+	    (mbtd->test_info.testcase == BKOPS_URGENT_LEVEL_3))
+		mq->err_check_fn = test_err_check;
+	mbtd->err_check_counter = 0;
+
+	return ret;
+}
+
+static int run_bkops(struct test_data *td)
+{
+	int ret = 0;
+	struct request_queue *q = td->req_q;
+	struct mmc_queue *mq = (struct mmc_queue *)q->queuedata;
+	struct mmc_card  *card = mq->card;
+	struct mmc_bkops_stats *bkops_stat;
+
+	if (!card)
+		return -EINVAL;
+
+	bkops_stat = &card->bkops_info.bkops_stats;
+
+	switch (mbtd->test_info.testcase) {
+	case BKOPS_DELAYED_WORK_LEVEL_1:
+		bkops_stat->ignore_card_bkops_status = true;
+		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
+		mbtd->bkops_stage = BKOPS_STAGE_1;
+
+		__blk_run_queue(q);
+		/* this long sleep makes sure the host starts bkops and
+		   also, gets into suspend */
+		msleep(10000);
+
+		bkops_stat->ignore_card_bkops_status = false;
+		card->ext_csd.raw_bkops_status = 0;
+
+		test_iosched_mark_test_completion();
+		break;
+
+	case BKOPS_DELAYED_WORK_LEVEL_1_HPI:
+		bkops_stat->ignore_card_bkops_status = true;
+		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
+		mbtd->bkops_stage = BKOPS_STAGE_1;
+
+		__blk_run_queue(q);
+		msleep(card->bkops_info.delay_ms);
+
+		ret = test_iosched_add_wr_rd_test_req(0, WRITE,
+				      td->start_sector,
+				      TEST_REQUEST_NUM_OF_BIOS,
+				      TEST_PATTERN_5A,
+				      bkops_end_io_final_fn);
+		if (ret) {
+			test_pr_err("%s: failed to add a write request",
+					__func__);
+			ret = -EINVAL;
+			break;
+		}
+
+		td->next_req = list_entry(td->test_queue.prev,
+				struct test_request, queuelist);
+		__blk_run_queue(q);
+		wait_event(mbtd->bkops_wait_q,
+			   mbtd->bkops_stage == BKOPS_STAGE_4);
+		bkops_stat->ignore_card_bkops_status = false;
+
+		test_iosched_mark_test_completion();
+		break;
+
+	case BKOPS_CANCEL_DELAYED_WORK:
+		bkops_stat->ignore_card_bkops_status = true;
+		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
+		mbtd->bkops_stage = BKOPS_STAGE_1;
+
+		__blk_run_queue(q);
+
+		ret = test_iosched_add_wr_rd_test_req(0, WRITE,
+				td->start_sector,
+				TEST_REQUEST_NUM_OF_BIOS,
+				TEST_PATTERN_5A,
+				bkops_end_io_final_fn);
+		if (ret) {
+			test_pr_err("%s: failed to add a write request",
+					__func__);
+			ret = -EINVAL;
+			break;
+		}
+
+		td->next_req = list_entry(td->test_queue.prev,
+				struct test_request, queuelist);
+		__blk_run_queue(q);
+		wait_event(mbtd->bkops_wait_q,
+			   mbtd->bkops_stage == BKOPS_STAGE_4);
+		bkops_stat->ignore_card_bkops_status = false;
+
+		test_iosched_mark_test_completion();
+		break;
+
+	case BKOPS_URGENT_LEVEL_2:
+	case BKOPS_URGENT_LEVEL_3:
+		bkops_stat->ignore_card_bkops_status = true;
+		if (mbtd->test_info.testcase == BKOPS_URGENT_LEVEL_2)
+			card->ext_csd.raw_bkops_status = 2;
+		else
+			card->ext_csd.raw_bkops_status = 3;
+		mbtd->bkops_stage = BKOPS_STAGE_1;
+
+		ret = test_iosched_add_wr_rd_test_req(0, WRITE,
+				td->start_sector,
+				TEST_REQUEST_NUM_OF_BIOS,
+				TEST_PATTERN_5A,
+				bkops_end_io_fn);
+		if (ret) {
+			test_pr_err("%s: failed to add a write request",
+					__func__);
+			ret = -EINVAL;
+			break;
+		}
+
+		td->next_req = list_entry(td->test_queue.prev,
+				struct test_request, queuelist);
+		__blk_run_queue(q);
+		wait_event(mbtd->bkops_wait_q,
+			   mbtd->bkops_stage == BKOPS_STAGE_2);
+		card->ext_csd.raw_bkops_status = 0;
+
+		ret = test_iosched_add_wr_rd_test_req(0, WRITE,
+				td->start_sector,
+				TEST_REQUEST_NUM_OF_BIOS,
+				TEST_PATTERN_5A,
+				bkops_end_io_final_fn);
+		if (ret) {
+			test_pr_err("%s: failed to add a write request",
+					__func__);
+			ret = -EINVAL;
+			break;
+		}
+
+		td->next_req = list_entry(td->test_queue.prev,
+				struct test_request, queuelist);
+		__blk_run_queue(q);
+
+		wait_event(mbtd->bkops_wait_q,
+			   mbtd->bkops_stage == BKOPS_STAGE_4);
+
+		bkops_stat->ignore_card_bkops_status = false;
+		test_iosched_mark_test_completion();
+		break;
+
+	case BKOPS_URGENT_LEVEL_2_TWO_REQS:
+		mq->wr_packing_enabled = false;
+		bkops_stat->ignore_card_bkops_status = true;
+		card->ext_csd.raw_bkops_status = 2;
+		mbtd->bkops_stage = BKOPS_STAGE_1;
+
+		ret = test_iosched_add_wr_rd_test_req(0, WRITE,
+				td->start_sector,
+				TEST_REQUEST_NUM_OF_BIOS,
+				TEST_PATTERN_5A,
+				NULL);
+		if (ret) {
+			test_pr_err("%s: failed to add a write request",
+					__func__);
+			ret = -EINVAL;
+			break;
+		}
+
+		ret = test_iosched_add_wr_rd_test_req(0, WRITE,
+				td->start_sector,
+				TEST_REQUEST_NUM_OF_BIOS,
+				TEST_PATTERN_5A,
+				bkops_end_io_fn);
+		if (ret) {
+			test_pr_err("%s: failed to add a write request",
+					__func__);
+			ret = -EINVAL;
+			break;
+		}
+
+		td->next_req = list_entry(td->test_queue.next,
+				struct test_request, queuelist);
+		__blk_run_queue(q);
+		wait_event(mbtd->bkops_wait_q,
+			   mbtd->bkops_stage == BKOPS_STAGE_2);
+		card->ext_csd.raw_bkops_status = 0;
+
+		ret = test_iosched_add_wr_rd_test_req(0, WRITE,
+				td->start_sector,
+				TEST_REQUEST_NUM_OF_BIOS,
+				TEST_PATTERN_5A,
+				bkops_end_io_final_fn);
+		if (ret) {
+			test_pr_err("%s: failed to add a write request",
+					__func__);
+			ret = -EINVAL;
+			break;
+		}
+
+		td->next_req = list_entry(td->test_queue.prev,
+				struct test_request, queuelist);
+		__blk_run_queue(q);
+
+		wait_event(mbtd->bkops_wait_q,
+			   mbtd->bkops_stage == BKOPS_STAGE_4);
+
+		bkops_stat->ignore_card_bkops_status = false;
+		test_iosched_mark_test_completion();
+
+		break;
+	default:
+		test_pr_err("%s: wrong testcase: %d", __func__,
+			    mbtd->test_info.testcase);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
 static bool message_repeat;
 static int test_open(struct inode *inode, struct file *file)
 {
@@ -1809,6 +2315,121 @@
 	.read = write_packing_control_test_read,
 };
 
+static ssize_t write_discard_sanitize_test_write(struct file *file,
+				const char __user *buf,
+				size_t count,
+				loff_t *ppos)
+{
+	int ret = 0;
+	int i = 0;
+	int number = -1;
+
+	sscanf(buf, "%d", &number);
+	if (number <= 0)
+		number = 1;
+
+	test_pr_info("%s: -- write_discard_sanitize TEST --\n", __func__);
+
+	memset(&mbtd->test_info, 0, sizeof(struct test_info));
+
+	mbtd->test_group = TEST_GENERAL_GROUP;
+
+	mbtd->test_info.data = mbtd;
+	mbtd->test_info.prepare_test_fn = prepare_write_discard_sanitize_read;
+	mbtd->test_info.get_test_case_str_fn = get_test_case_str;
+	mbtd->test_info.timeout_msec = SANITIZE_TEST_TIMEOUT;
+
+	for (i = 0 ; i < number ; ++i) {
+		test_pr_info("%s: Cycle # %d / %d\n", __func__, i+1, number);
+		test_pr_info("%s: ===================", __func__);
+
+		mbtd->test_info.testcase = TEST_WRITE_DISCARD_SANITIZE_READ;
+		ret = test_iosched_start_test(&mbtd->test_info);
+
+		if (ret)
+			break;
+	}
+
+	return count;
+}
+
+const struct file_operations write_discard_sanitize_test_ops = {
+	.open = test_open,
+	.write = write_discard_sanitize_test_write,
+};
+
+static ssize_t bkops_test_write(struct file *file,
+				const char __user *buf,
+				size_t count,
+				loff_t *ppos)
+{
+	int ret = 0;
+	int i = 0, j;
+	int number = -1;
+
+	test_pr_info("%s: -- bkops_test TEST --", __func__);
+
+	sscanf(buf, "%d", &number);
+
+	if (number <= 0)
+		number = 1;
+
+	mbtd->test_group = TEST_BKOPS_GROUP;
+
+	memset(&mbtd->test_info, 0, sizeof(struct test_info));
+
+	mbtd->test_info.data = mbtd;
+	mbtd->test_info.prepare_test_fn = prepare_bkops;
+	mbtd->test_info.check_test_result_fn = check_bkops_result;
+	mbtd->test_info.get_test_case_str_fn = get_test_case_str;
+	mbtd->test_info.run_test_fn = run_bkops;
+	mbtd->test_info.timeout_msec = BKOPS_TEST_TIMEOUT;
+	mbtd->test_info.post_test_fn = bkops_post_test;
+
+	for (i = 0 ; i < number ; ++i) {
+		test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+		test_pr_info("%s: ===================", __func__);
+		for (j = BKOPS_MIN_TESTCASE ;
+				j <= BKOPS_MAX_TESTCASE ; j++) {
+			mbtd->test_info.testcase = j;
+			ret = test_iosched_start_test(&mbtd->test_info);
+			if (ret)
+				break;
+		}
+	}
+
+	test_pr_info("%s: Completed all the test cases.", __func__);
+
+	return count;
+}
+
+static ssize_t bkops_test_read(struct file *file,
+			       char __user *buffer,
+			       size_t count,
+			       loff_t *offset)
+{
+	memset((void *)buffer, 0, count);
+
+	snprintf(buffer, count,
+		 "\nbkops_test\n========================\n"
+		 "Description:\n"
+		 "This test simulates BKOPS status from card\n"
+		 "and verifies that:\n"
+		 " - Starting BKOPS delayed work, level 1\n"
+		 " - Starting BKOPS delayed work, level 1, with HPI\n"
+		 " - Cancel starting BKOPS delayed work, "
+		 " when a request is received\n"
+		 " - Starting BKOPS urgent, level 2,3\n"
+		 " - Starting BKOPS urgent with 2 requests\n");
+	return strnlen(buffer, count);
+}
+
+const struct file_operations bkops_test_ops = {
+	.open = test_open,
+	.write = bkops_test_write,
+	.read = bkops_test_read,
+};
+
 static void mmc_block_test_debugfs_cleanup(void)
 {
 	debugfs_remove(mbtd->debug.random_test_seed);
@@ -1816,6 +2437,8 @@
 	debugfs_remove(mbtd->debug.err_check_test);
 	debugfs_remove(mbtd->debug.send_invalid_packed_test);
 	debugfs_remove(mbtd->debug.packing_control_test);
+	debugfs_remove(mbtd->debug.discard_sanitize_test);
+	debugfs_remove(mbtd->debug.bkops_test);
 }
 
 static int mmc_block_test_debugfs_init(void)
@@ -1877,6 +2500,27 @@
 	if (!mbtd->debug.packing_control_test)
 		goto err_nomem;
 
+	mbtd->debug.discard_sanitize_test =
+		debugfs_create_file("write_discard_sanitize_test",
+				    S_IRUGO | S_IWUGO,
+				    tests_root,
+				    NULL,
+				    &write_discard_sanitize_test_ops);
+	if (!mbtd->debug.discard_sanitize_test) {
+		mmc_block_test_debugfs_cleanup();
+		return -ENOMEM;
+	}
+
+	mbtd->debug.bkops_test =
+		debugfs_create_file("bkops_test",
+				    S_IRUGO | S_IWUGO,
+				    tests_root,
+				    NULL,
+				    &bkops_test_ops);
+
+	if (!mbtd->debug.bkops_test)
+		goto err_nomem;
+
 	return 0;
 
 err_nomem:
@@ -1924,6 +2568,7 @@
 		return -ENODEV;
 	}
 
+	init_waitqueue_head(&mbtd->bkops_wait_q);
 	mbtd->bdt.init_fn = mmc_block_test_probe;
 	mbtd->bdt.exit_fn = mmc_block_test_remove;
 	INIT_LIST_HEAD(&mbtd->bdt.list);
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 0592f9d..b24620b 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -254,6 +254,7 @@
 	card->dev.release = mmc_release_card;
 	card->dev.type = type;
 
+	spin_lock_init(&card->bkops_info.bkops_stats.lock);
 	spin_lock_init(&card->wr_pack_stats.lock);
 
 	return card;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7e03e5a..b91f3d1 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -77,6 +77,30 @@
 	removable,
 	"MMC/SD cards are removable and may be removed during suspend");
 
+#define MMC_UPDATE_BKOPS_STATS_HPI(stats)	\
+	do {					\
+		spin_lock(&stats.lock);		\
+		if (stats.enabled)		\
+			stats.hpi++;		\
+		spin_unlock(&stats.lock);	\
+	} while (0);
+#define MMC_UPDATE_BKOPS_STATS_SUSPEND(stats)	\
+	do {					\
+		spin_lock(&stats.lock);		\
+		if (stats.enabled)		\
+			stats.suspend++;	\
+		spin_unlock(&stats.lock);	\
+	} while (0);
+#define MMC_UPDATE_STATS_BKOPS_SEVERITY_LEVEL(stats, level)		\
+	do {								\
+		if (level <= 0 || level > BKOPS_NUM_OF_SEVERITY_LEVELS)	\
+			break;						\
+		spin_lock(&stats.lock);					\
+		if (stats.enabled)					\
+			stats.bkops_level[level-1]++;			\
+		spin_unlock(&stats.lock);				\
+	} while (0);
+
 /*
  * Internal function. Schedule delayed work in the MMC work queue.
  */
@@ -279,6 +303,29 @@
 	host->ops->request(host, mrq);
 }
 
+void mmc_blk_init_bkops_statistics(struct mmc_card *card)
+{
+	int i;
+	struct mmc_bkops_stats *bkops_stats;
+
+	if (!card)
+		return;
+
+	bkops_stats = &card->bkops_info.bkops_stats;
+
+	spin_lock(&bkops_stats->lock);
+
+	for (i = 0 ; i < BKOPS_NUM_OF_SEVERITY_LEVELS ; ++i)
+		bkops_stats->bkops_level[i] = 0;
+
+	bkops_stats->suspend = 0;
+	bkops_stats->hpi = 0;
+	bkops_stats->enabled = true;
+
+	spin_unlock(&bkops_stats->lock);
+}
+EXPORT_SYMBOL(mmc_blk_init_bkops_statistics);
+
 /**
  * mmc_start_delayed_bkops() - Start a delayed work to check for
  *      the need of non urgent BKOPS
@@ -349,8 +396,8 @@
 
 	err = mmc_read_bkops_status(card);
 	if (err) {
-		pr_err("%s: Failed to read bkops status: %d\n",
-		       mmc_hostname(card->host), err);
+		pr_err("%s: %s: Failed to read bkops status: %d\n",
+		       mmc_hostname(card->host), __func__, err);
 		goto out;
 	}
 
@@ -367,8 +414,11 @@
 	 * work, before going to suspend
 	 */
 	if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
-	    from_exception)
+	    from_exception) {
+		pr_debug("%s: %s: Level 1 from exception, exit",
+			 mmc_hostname(card->host), __func__);
 		goto out;
+	}
 
 	if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
 		timeout = MMC_BKOPS_MAX_TIMEOUT;
@@ -381,10 +431,12 @@
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal);
 	if (err) {
-		pr_warn("%s: Error %d starting bkops\n",
-			mmc_hostname(card->host), err);
+		pr_warn("%s: %s: Error %d when starting bkops\n",
+			mmc_hostname(card->host), __func__, err);
 		goto out;
 	}
+	MMC_UPDATE_STATS_BKOPS_SEVERITY_LEVEL(card->bkops_info.bkops_stats,
+					card->ext_csd.raw_bkops_status);
 
 	/*
 	 * For urgent bkops status (LEVEL_2 and more)
@@ -608,8 +660,11 @@
 		if (host->card && mmc_card_mmc(host->card) &&
 		    ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) ||
 		     (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) &&
-		    (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT))
+		    (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) {
 			mmc_start_bkops(host->card, true);
+			pr_debug("%s: %s: completed BKOPs due to exception",
+				 mmc_hostname(host), __func__);
+		}
 	}
 
 	if (!err && areq)
@@ -620,7 +675,7 @@
 
 	/* Cancel a prepared request if it was not started. */
 	if ((err || start_err) && areq)
-			mmc_post_req(host, areq->mrq, -EINVAL);
+		mmc_post_req(host, areq->mrq, -EINVAL);
 
 	if (err)
 		host->areq = NULL;
@@ -773,6 +828,8 @@
 		err = 0;
 	}
 
+	MMC_UPDATE_BKOPS_STATS_HPI(card->bkops_info.bkops_stats);
+
 out:
 	mmc_release_host(card->host);
 	return err;
@@ -794,6 +851,12 @@
 		return -ENOMEM;
 	}
 
+	if (card->bkops_info.bkops_stats.ignore_card_bkops_status) {
+		pr_debug("%s: skipping read raw_bkops_status in unittest mode",
+			 __func__);
+		return 0;
+	}
+
 	mmc_claim_host(card->host);
 	err = mmc_send_ext_csd(card, ext_csd);
 	mmc_release_host(card->host);
@@ -1438,6 +1501,49 @@
 	mmc_set_ios(host);
 	mmc_host_clk_release(host);
 }
+
+static void mmc_poweroff_notify(struct mmc_host *host)
+{
+	struct mmc_card *card;
+	unsigned int timeout;
+	unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION;
+	int err = 0;
+
+	card = host->card;
+	mmc_claim_host(host);
+
+	/*
+	 * Send power notify command only if card
+	 * is mmc and notify state is powered ON
+	 */
+	if (card && mmc_card_mmc(card) &&
+	    (card->poweroff_notify_state == MMC_POWERED_ON)) {
+
+		if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
+			notify_type = EXT_CSD_POWER_OFF_SHORT;
+			timeout = card->ext_csd.generic_cmd6_time;
+			card->poweroff_notify_state = MMC_POWEROFF_SHORT;
+		} else {
+			notify_type = EXT_CSD_POWER_OFF_LONG;
+			timeout = card->ext_csd.power_off_longtime;
+			card->poweroff_notify_state = MMC_POWEROFF_LONG;
+		}
+
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				 EXT_CSD_POWER_OFF_NOTIFICATION,
+				 notify_type, timeout);
+
+		if (err && err != -EBADMSG)
+			pr_err("Device failed to respond within %d poweroff time.",
+				   timeout);
+			pr_err("Forcefully powering down the device\n");
+
+		/* Set the card state to no notification after the poweroff */
+		card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
+	}
+	 mmc_release_host(host);
+}
+
 /*
  * Apply power to the MMC stack.  This is a two-stage process.
  * First, we enable power to the card without the clock running.
@@ -1495,11 +1601,29 @@
 
 void mmc_power_off(struct mmc_host *host)
 {
+	int err = 0;
 	mmc_host_clk_hold(host);
 
 	host->ios.clock = 0;
 	host->ios.vdd = 0;
 
+	mmc_poweroff_notify(host);
+	/*
+	 * For eMMC 4.5 device send AWAKE command before
+	 * POWER_OFF_NOTIFY command, because in sleep state
+	 * eMMC 4.5 devices respond to only RESET and AWAKE cmd
+	 */
+	if (host->card && mmc_card_is_sleep(host->card) &&
+	    host->bus_ops->resume) {
+		err = host->bus_ops->resume(host);
+
+		if (!err)
+			mmc_poweroff_notify(host);
+		else
+			pr_warning("%s: error %d during resume",
+					   mmc_hostname(host), err);
+			pr_warning(" (continue with poweroff sequence)\n");
+	}
 
 	/*
 	 * Reset ocr mask to be the highest possible voltage supported for
@@ -2030,15 +2154,6 @@
 }
 EXPORT_SYMBOL(mmc_can_secure_erase_trim);
 
-int mmc_can_poweroff_notify(const struct mmc_card *card)
-{
-	return card &&
-		mmc_card_mmc(card) &&
-		card->host->bus_ops->poweroff_notify &&
-		(card->poweroff_notify_state == MMC_POWERED_ON);
-}
-EXPORT_SYMBOL(mmc_can_poweroff_notify);
-
 int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 			    unsigned int nr)
 {
@@ -2431,15 +2546,6 @@
 
 	mmc_bus_get(host);
 	if (host->bus_ops && !host->bus_dead) {
-		mmc_claim_host(host);
-		if (mmc_can_poweroff_notify(host->card)) {
-			int err = host->bus_ops->poweroff_notify(host,
-						MMC_PW_OFF_NOTIFY_LONG);
-			if (err)
-				pr_info("%s: error [%d] in poweroff notify\n",
-					mmc_hostname(host), err);
-		}
-		mmc_release_host(host);
 		/* Calling bus_ops->remove() with a claimed host can deadlock */
 		if (host->bus_ops->remove)
 			host->bus_ops->remove(host);
@@ -2475,15 +2581,6 @@
 
 	if (host->bus_ops->power_save)
 		ret = host->bus_ops->power_save(host);
-	mmc_claim_host(host);
-	if (mmc_can_poweroff_notify(host->card)) {
-		int err = host->bus_ops->poweroff_notify(host,
-					MMC_PW_OFF_NOTIFY_SHORT);
-		if (err)
-			pr_info("%s: error [%d] in poweroff notify\n",
-				mmc_hostname(host), err);
-	}
-	mmc_release_host(host);
 
 	mmc_bus_put(host);
 
@@ -2526,11 +2623,8 @@
 
 	mmc_bus_get(host);
 
-	if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) {
+	if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
 		err = host->bus_ops->awake(host);
-		if (!err)
-			mmc_card_clr_sleep(host->card);
-	}
 
 	mmc_bus_put(host);
 
@@ -2547,11 +2641,8 @@
 
 	mmc_bus_get(host);
 
-	if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep) {
+	if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep)
 		err = host->bus_ops->sleep(host);
-		if (!err)
-			mmc_card_set_sleep(host->card);
-	}
 
 	mmc_bus_put(host);
 
@@ -2679,6 +2770,8 @@
 						goto stop_bkops_err;
 				}
 				err = host->bus_ops->suspend(host);
+				MMC_UPDATE_BKOPS_STATS_SUSPEND(host->
+						card->bkops_info.bkops_stats);
 			}
 			if (!(host->card && mmc_card_sdio(host->card)))
 				mmc_release_host(host);
@@ -2795,21 +2888,13 @@
 			break;
 		}
 		host->rescan_disable = 1;
+		host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
 		spin_unlock_irqrestore(&host->lock, flags);
 		if (cancel_delayed_work_sync(&host->detect))
 			wake_unlock(&host->detect_wake_lock);
 
 		if (!host->bus_ops || host->bus_ops->suspend)
 			break;
-		mmc_claim_host(host);
-		if (mmc_can_poweroff_notify(host->card)) {
-			int err = host->bus_ops->poweroff_notify(host,
-						MMC_PW_OFF_NOTIFY_SHORT);
-			if (err)
-				pr_info("%s: error [%d] in poweroff notify\n",
-					mmc_hostname(host), err);
-		}
-		mmc_release_host(host);
 
 		/* Calling bus_ops->remove() with a claimed host can deadlock */
 		if (host->bus_ops->remove)
@@ -2832,6 +2917,7 @@
 			break;
 		}
 		host->rescan_disable = 0;
+		host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
 		spin_unlock_irqrestore(&host->lock, flags);
 		mmc_detect_change(host, 0);
 
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 22f6043..85d2737 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -25,7 +25,6 @@
 	int (*power_save)(struct mmc_host *);
 	int (*power_restore)(struct mmc_host *);
 	int (*alive)(struct mmc_host *);
-	int (*poweroff_notify)(struct mmc_host *, int notify);
 };
 
 void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 4022ccc..ddb562e 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -484,6 +484,113 @@
 	.write		= mmc_wr_pack_stats_write,
 };
 
+static int mmc_bkops_stats_open(struct inode *inode, struct file *filp)
+{
+	struct mmc_card *card = inode->i_private;
+
+	filp->private_data = card;
+
+	card->bkops_info.bkops_stats.print_stats = 1;
+	return 0;
+}
+
+static ssize_t mmc_bkops_stats_read(struct file *filp, char __user *ubuf,
+				     size_t cnt, loff_t *ppos)
+{
+	struct mmc_card *card = filp->private_data;
+	struct mmc_bkops_stats *bkops_stats;
+	int i;
+	char *temp_buf;
+
+	if (!card)
+		return cnt;
+
+	bkops_stats = &card->bkops_info.bkops_stats;
+
+	if (!bkops_stats->print_stats)
+		return 0;
+
+	if (!bkops_stats->enabled) {
+		pr_info("%s: bkops statistics are disabled\n",
+			 mmc_hostname(card->host));
+		goto exit;
+	}
+
+	temp_buf = kmalloc(TEMP_BUF_SIZE, GFP_KERNEL);
+	if (!temp_buf)
+		goto exit;
+
+	spin_lock(&bkops_stats->lock);
+
+	memset(ubuf, 0, cnt);
+
+	snprintf(temp_buf, TEMP_BUF_SIZE, "%s: bkops statistics:\n",
+		mmc_hostname(card->host));
+	strlcat(ubuf, temp_buf, cnt);
+
+	for (i = 0 ; i < BKOPS_NUM_OF_SEVERITY_LEVELS ; ++i) {
+		snprintf(temp_buf, TEMP_BUF_SIZE,
+			 "%s: BKOPS: due to level %d: %u\n",
+		 mmc_hostname(card->host), i, bkops_stats->bkops_level[i]);
+		strlcat(ubuf, temp_buf, cnt);
+	}
+
+	snprintf(temp_buf, TEMP_BUF_SIZE,
+		 "%s: BKOPS: stopped due to HPI: %u\n",
+		 mmc_hostname(card->host), bkops_stats->hpi);
+	strlcat(ubuf, temp_buf, cnt);
+
+	snprintf(temp_buf, TEMP_BUF_SIZE,
+		 "%s: BKOPS: how many time host was suspended: %u\n",
+		 mmc_hostname(card->host), bkops_stats->suspend);
+	strlcat(ubuf, temp_buf, cnt);
+
+	spin_unlock(&bkops_stats->lock);
+
+	kfree(temp_buf);
+
+	pr_info("%s", ubuf);
+
+exit:
+	if (bkops_stats->print_stats == 1) {
+		bkops_stats->print_stats = 0;
+		return strnlen(ubuf, cnt);
+	}
+
+	return 0;
+}
+
+static ssize_t mmc_bkops_stats_write(struct file *filp,
+				      const char __user *ubuf, size_t cnt,
+				      loff_t *ppos)
+{
+	struct mmc_card *card = filp->private_data;
+	int value;
+	struct mmc_bkops_stats *bkops_stats;
+
+	if (!card)
+		return cnt;
+
+	bkops_stats = &card->bkops_info.bkops_stats;
+
+	sscanf(ubuf, "%d", &value);
+	if (value) {
+		mmc_blk_init_bkops_statistics(card);
+	} else {
+		spin_lock(&bkops_stats->lock);
+		bkops_stats->enabled = false;
+		spin_unlock(&bkops_stats->lock);
+	}
+
+	return cnt;
+}
+
+static const struct file_operations mmc_dbg_bkops_stats_fops = {
+	.open		= mmc_bkops_stats_open,
+	.read		= mmc_bkops_stats_read,
+	.write		= mmc_bkops_stats_write,
+};
+
 void mmc_add_card_debugfs(struct mmc_card *card)
 {
 	struct mmc_host	*host = card->host;
@@ -522,6 +629,12 @@
 					 &mmc_dbg_wr_pack_stats_fops))
 			goto err;
 
+	if (mmc_card_mmc(card) && (card->ext_csd.rev >= 6) &&
+	    card->ext_csd.bkops_en)
+		if (!debugfs_create_file("bkops_stats", S_IRUSR, root, card,
+					 &mmc_dbg_bkops_stats_fops))
+			goto err;
+
 	return;
 
 err:
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index ca8b01c..50af7fa 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1356,40 +1356,6 @@
 	return err;
 }
 
-static int mmc_poweroff_notify(struct mmc_host *host, int notify)
-{
-	struct mmc_card *card;
-	unsigned int timeout;
-	unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION;
-	int err;
-
-	card = host->card;
-
-	if (notify == MMC_PW_OFF_NOTIFY_SHORT) {
-		notify_type = EXT_CSD_POWER_OFF_SHORT;
-		timeout = card->ext_csd.generic_cmd6_time;
-	} else if (notify == MMC_PW_OFF_NOTIFY_LONG) {
-		notify_type = EXT_CSD_POWER_OFF_LONG;
-		timeout = card->ext_csd.power_off_longtime;
-	} else {
-		pr_info("%s: mmc_poweroff_notify called "
-		        "with notify type %d\n", mmc_hostname(host), notify);
-		return -EINVAL;
-	}
-
-	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-			 EXT_CSD_POWER_OFF_NOTIFICATION,
-			 notify_type, timeout);
-
-	if (err)
-		pr_err("%s: Device failed to respond within %d "
-		       "poweroff timeout.\n", mmc_hostname(host), timeout);
-	else
-		card->poweroff_notify_state =
-					MMC_NO_POWER_NOTIFICATION;
-
-	return err;
-}
 /*
  * Host is being removed. Free up the current card.
  */
@@ -1453,26 +1419,13 @@
 	BUG_ON(!host->card);
 
 	mmc_claim_host(host);
-	if (mmc_can_poweroff_notify(host->card) &&
-		(host->caps2 & MMC_CAP2_POWER_OFF_VCCQ_DURING_SUSPEND)) {
-		err = mmc_poweroff_notify(host, MMC_PW_OFF_NOTIFY_SHORT);
-	} else {
-		if (mmc_card_can_sleep(host))
-			/*
-			 * If sleep command has error it doesn't mean host
-			 * cannot suspend, but a deeper low power state
-			 * transition for the card has failed. Ignore
-			 * sleep errors so that the suspend is not aborted.
-			 * In error case, mmc_resume() takes care of
-			 * complete intialization of the card.
-			 */
-			mmc_card_sleep(host);
-		else if (!mmc_host_is_spi(host))
-			mmc_deselect_cards(host);
-	}
-	if (!err)
-		host->card->state &=
-			~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
+	if (mmc_card_can_sleep(host)) {
+		err = mmc_card_sleep(host);
+		if (!err)
+			mmc_card_set_sleep(host->card);
+	} else if (!mmc_host_is_spi(host))
+		mmc_deselect_cards(host);
+	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 	mmc_release_host(host);
 
 	return err;
@@ -1550,7 +1503,6 @@
 	.resume = NULL,
 	.power_restore = mmc_power_restore,
 	.alive = mmc_alive,
-	.poweroff_notify = mmc_poweroff_notify,
 };
 
 static const struct mmc_bus_ops mmc_ops_unsafe = {
@@ -1562,7 +1514,6 @@
 	.resume = mmc_resume,
 	.power_restore = mmc_power_restore,
 	.alive = mmc_alive,
-	.poweroff_notify = mmc_poweroff_notify,
 };
 
 static void mmc_attach_bus_ops(struct mmc_host *host)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 0c3f994..da38122 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -500,6 +500,10 @@
 	help
 	  Select Y to enable Slot 3.
 
+config MMC_MSM_SDC3_POLLING
+	boolean "Qualcomm SDC3 support"
+	depends on MMC_MSM
+
 config MMC_MSM_SDC3_8_BIT_SUPPORT
 	boolean "Qualcomm SDC3 8bit support"
 	depends on MMC_MSM_SDC3_SUPPORT
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index bd374f6..ab3fc46 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1790,6 +1790,11 @@
 	if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
 		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
+	if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY)
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
+	else
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
+
 	if (host->pdata->blk_settings) {
 		mmc->max_segs = host->pdata->blk_settings->max_segs;
 		mmc->max_blk_size = host->pdata->blk_settings->max_blk_size;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2f1a0dc..2f7a2f3 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2582,6 +2582,19 @@
 		mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
 
 	/*
+	 * If Power Off Notify capability is enabled by the host,
+	 * set notify to short power off notify timeout value.
+	 */
+	if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY)
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
+	else
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
+
+	/* Initial value for re-tuning timer count */
+	host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
+			      SDHCI_RETUNING_TIMER_COUNT_SHIFT;
+
+	/*
 	 * In case Re-tuning Timer is not disabled, the actual value of
 	 * re-tuning timer will be 2 ^ (n - 1).
 	 */
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 17ff067..fdfe468 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -556,10 +556,6 @@
 		/* allow modem and roothub to wake up suspended system */
 		device_set_wakeup_enable(&udev->dev, 1);
 		device_set_wakeup_enable(&udev->parent->dev, 1);
-
-		/* set default autosuspend timeout for modem and roothub */
-		pm_runtime_set_autosuspend_delay(&udev->dev, 1000);
-		pm_runtime_set_autosuspend_delay(&udev->parent->dev, 200);
 	}
 
 out:
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index c474e36..376750f 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -290,8 +290,7 @@
 
 config BATTERY_MSM
 	tristate "MSM battery"
-	depends on ARCH_MSM
-	default m
+	depends on ARCH_MSM && MSM_ONCRPCROUTER
 	help
 	  Say Y to enable support for the battery in Qualcomm MSM.
 
diff --git a/drivers/power/msm_battery.c b/drivers/power/msm_battery.c
index 5abc032..f8186b1 100644
--- a/drivers/power/msm_battery.c
+++ b/drivers/power/msm_battery.c
@@ -1405,8 +1405,10 @@
 	msm_batt_info.msm_psy_batt = &msm_psy_batt;
 
 #ifndef CONFIG_BATTERY_MSM_FAKE
-	rc = msm_batt_register(BATTERY_LOW, BATTERY_ALL_ACTIVITY,
-			       BATTERY_CB_ID_ALL_ACTIV, BATTERY_ALL_ACTIVITY);
+	rc = msm_batt_register(msm_batt_info.voltage_fail_safe,
+			       BATTERY_ALL_ACTIVITY,
+			       BATTERY_CB_ID_ALL_ACTIV,
+			       BATTERY_ALL_ACTIVITY);
 	if (rc < 0) {
 		dev_err(&pdev->dev,
 			"%s: msm_batt_register failed rc = %d\n", __func__, rc);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 01448b7..a6a1776 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -2903,6 +2903,12 @@
 		handle_start_ext_chg(chip);
 	else
 		handle_stop_ext_chg(chip);
+
+	if (!chip->ext_psy) {
+		power_supply_changed(&chip->dc_psy);
+		power_supply_changed(&chip->batt_psy);
+	}
+
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index e48257a..1b9426a 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -480,6 +480,9 @@
 	struct pm8xxx_ccadc_chip *chip = data;
 	int rc;
 
+	if (!the_chip)
+		goto out;
+
 	pr_debug("irq = %d triggered\n", irq);
 	data_msb = chip->ccadc_offset >> 8;
 	data_lsb = chip->ccadc_offset;
@@ -488,6 +491,7 @@
 						data_msb, data_lsb, 0);
 	disable_irq_nosync(chip->eoc_irq);
 
+out:
 	return IRQ_HANDLED;
 }
 
@@ -685,7 +689,6 @@
 		goto free_chip;
 	}
 
-
 	disable_irq_nosync(chip->eoc_irq);
 
 	platform_set_drvdata(pdev, chip);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index ba4c855..61f4946 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -47,6 +47,24 @@
 EXPORT_SYMBOL_GPL(power_supply_set_current_limit);
 
 /**
+ * power_supply_set_charging_enabled - enable or disable charging
+ * @psy:	the power supply to control
+ * @enable:	sets enable property of power supply
+ */
+int power_supply_set_charging_enabled(struct power_supply *psy, bool enable)
+{
+	const union power_supply_propval ret = {enable,};
+
+	if (psy->set_property)
+		return psy->set_property(psy,
+				POWER_SUPPLY_PROP_CHARGING_ENABLED,
+				&ret);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(power_supply_set_charging_enabled);
+
+/**
  * power_supply_set_present - set present state of the power supply
  * @psy:	the power supply to control
  * @enable:	sets present property of power supply
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 4368e7d..7eb285b 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -138,6 +138,7 @@
 	POWER_SUPPLY_ATTR(health),
 	POWER_SUPPLY_ATTR(present),
 	POWER_SUPPLY_ATTR(online),
+	POWER_SUPPLY_ATTR(charging_enabled),
 	POWER_SUPPLY_ATTR(technology),
 	POWER_SUPPLY_ATTR(cycle_count),
 	POWER_SUPPLY_ATTR(voltage_max),
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 0185a3e..8d5244b 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -94,6 +94,11 @@
 
 #define QPNP_CHARGER_DEV_NAME	"qcom,qpnp-charger"
 
+/* Status bits and masks */
+#define CHGR_BOOT_DONE			BIT(7)
+#define CHGR_CHG_EN			BIT(7)
+#define CHGR_ON_BAT_FORCE_BIT		BIT(0)
+
 /* Interrupt definitions */
 /* smbb_chg_interrupts */
 #define CHG_DONE_IRQ			BIT(7)
@@ -198,7 +203,7 @@
 };
 
 static struct qpnp_chg_chip *the_chip;
-static int charging_disabled;
+static bool charging_disabled;
 
 static struct of_device_id qpnp_charger_match_table[] = {
 	{ .compatible = QPNP_CHARGER_DEV_NAME, },
@@ -396,7 +401,7 @@
 qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
-	int rc, usb_present;
+	int rc;
 
 	rc = qpnp_chg_masked_write(chip,
 		chip->chgr_base + CHGR_CHG_FAILED,
@@ -405,14 +410,6 @@
 	if (rc)
 		pr_err("Failed to write chg_fail clear bit!\n");
 
-	/* Hack: recheck usbin_valid status after chg_fail triggered */
-	usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
-	pr_debug("usb_status: %d\n", usb_present);
-	if (usb_present)
-		qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid_irq,
-			_chip);
-
-
 	return IRQ_HANDLED;
 }
 
@@ -433,6 +430,7 @@
 };
 
 static enum power_supply_property msm_batt_power_props[] = {
+	POWER_SUPPLY_PROP_CHARGING_ENABLED,
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_CHARGE_TYPE,
 	POWER_SUPPLY_PROP_HEALTH,
@@ -692,6 +690,24 @@
 }
 
 static int
+qpnp_chg_charge_dis(struct qpnp_chg_chip *chip, int disable)
+{
+	/* This bit forces the charger to run off of the battery rather
+	 * than a connected charger */
+	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
+			CHGR_ON_BAT_FORCE_BIT,
+			disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
+}
+
+static int
+qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
+{
+	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
+			CHGR_CHG_EN,
+			enable ? CHGR_CHG_EN : 0, 1);
+}
+
+static int
 qpnp_batt_power_get_property(struct power_supply *psy,
 				       enum power_supply_property psp,
 				       union power_supply_propval *val)
@@ -736,6 +752,9 @@
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_full_design(chip);
 		break;
+	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+		val->intval = !charging_disabled;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -743,27 +762,28 @@
 	return 0;
 }
 
-#define CHGR_BOOT_DONE	BIT(7)
-#define CHGR_CHG_EN	BIT(7)
-#define CHGR_ON_BAT_FORCE_BIT	BIT(0)
-#define CHGR_BAT_IF_CONST_RDS_EN	BIT(7)
-#define CHGR_BAT_IF_VCP_EN	BIT(0)
 static int
-qpnp_chg_charge_dis(struct qpnp_chg_chip *chip, int disable)
+qpnp_batt_power_set_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  const union power_supply_propval *val)
 {
-	/* This bit forces the charger to run off of the battery rather
-	 * than a connected charger */
-	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
-			CHGR_ON_BAT_FORCE_BIT,
-			disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
-}
+	struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
+								batt_psy);
 
-static int
-qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
-{
-	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
-			CHGR_CHG_EN,
-			enable ? CHGR_CHG_EN : 0, 1);
+	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);
+		charging_disabled = !(val->intval);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	power_supply_changed(&chip->batt_psy);
+	return 0;
 }
 
 static int
@@ -782,7 +802,7 @@
 		qpnp_chg_charge_dis(chip, charging_disabled);
 	return 0;
 }
-module_param_call(disabled, qpnp_chg_set_disable_status_param, param_get_uint,
+module_param_call(disabled, qpnp_chg_set_disable_status_param, param_get_bool,
 					&charging_disabled, 0644);
 
 #define QPNP_CHG_VINMIN_MIN_MV		3400
@@ -1234,6 +1254,7 @@
 	chip->batt_psy.properties = msm_batt_power_props;
 	chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props);
 	chip->batt_psy.get_property = qpnp_batt_power_get_property;
+	chip->batt_psy.set_property = qpnp_batt_power_set_property;
 	chip->batt_psy.external_power_changed =
 				qpnp_batt_external_power_changed;
 
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d082273..e70924c 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -91,3 +91,19 @@
 	help
 	  Enable this to plug the SPEAr thermal sensor driver into the Linux
 	  thermal framework
+
+config THERMAL_QPNP
+	tristate "Qualcomm Plug-and-Play PMIC Temperature Alarm"
+	depends on THERMAL
+	depends on OF
+	depends on SPMI
+	depends on OF_SPMI
+	help
+	  This enables a thermal Sysfs driver for Qualcomm plug-and-play (QPNP)
+	  PMIC devices. It shows up in Sysfs as a thermal zone with multiple
+	  trip points. The temperature reported by the thermal zone reflects the
+	  real time die temperature if an ADC is present or an estimate of the
+	  temperature based upon the over temperature stage value if no ADC is
+	  available. If allowed via compile time configuration; enabling the
+	  thermal zone device via the mode file results in shifting PMIC over
+	  temperature shutdown control from hardware to software.
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index f7e7cc6..3b2b3a8 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -10,3 +10,4 @@
 obj-$(CONFIG_THERMAL_MONITOR)	+= msm_thermal.o
 obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
 obj-$(CONFIG_THERMAL_TSENS8974)	+= msm8974-tsens.o
+obj-$(CONFIG_THERMAL_QPNP)	+= qpnp-temp-alarm.o
diff --git a/drivers/thermal/qpnp-temp-alarm.c b/drivers/thermal/qpnp-temp-alarm.c
new file mode 100644
index 0000000..499d67e
--- /dev/null
+++ b/drivers/thermal/qpnp-temp-alarm.c
@@ -0,0 +1,721 @@
+/*
+ * 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
+ * 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/module.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/thermal.h>
+#include <linux/qpnp/qpnp-adc.h>
+
+#define QPNP_TM_DRIVER_NAME "qcom,qpnp-temp-alarm"
+
+enum qpnp_tm_registers {
+	QPNP_TM_REG_TYPE		= 0x04,
+	QPNP_TM_REG_SUBTYPE		= 0x05,
+	QPNP_TM_REG_STATUS		= 0x08,
+	QPNP_TM_REG_SHUTDOWN_CTRL1	= 0x40,
+	QPNP_TM_REG_SHUTDOWN_CTRL2	= 0x42,
+	QPNP_TM_REG_ALARM_CTRL		= 0x46,
+};
+
+#define QPNP_TM_TYPE			0x09
+#define QPNP_TM_SUBTYPE			0x08
+
+#define STATUS_STAGE_MASK		0x03
+
+#define SHUTDOWN_CTRL1_OVERRIDE_STAGE3	0x80
+#define SHUTDOWN_CTRL1_OVERRIDE_STAGE2	0x40
+#define SHUTDOWN_CTRL1_THRESHOLD_MASK	0x03
+
+#define SHUTDOWN_CTRL2_CLEAR_STAGE3	0x80
+#define SHUTDOWN_CTRL2_CLEAR_STAGE2	0x40
+
+#define ALARM_CTRL_FORCE_ENABLE		0x80
+#define ALARM_CTRL_FOLLOW_HW_ENABLE	0x01
+
+#define TEMP_STAGE_STEP			20000	/* Stage step: 20.000 C */
+#define TEMP_STAGE_HYSTERESIS		2000
+
+#define TEMP_THRESH_MIN			105000	/* Threshold Min: 105 C */
+#define TEMP_THRESH_STEP		5000	/* Threshold step: 5 C */
+
+#define THRESH_MIN			0
+#define THRESH_MAX			3
+
+/* Trip points from most critical to least critical */
+#define TRIP_STAGE3			0
+#define TRIP_STAGE2			1
+#define TRIP_STAGE1			2
+#define TRIP_NUM			3
+
+enum qpnp_tm_adc_type {
+	QPNP_TM_ADC_NONE,	/* Estimates temp based on overload level. */
+	QPNP_TM_ADC_QPNP_ADC,
+};
+
+/*
+ * Temperature in millicelcius reported during stage 0 if no ADC is present and
+ * no value has been specified via device tree.
+ */
+#define DEFAULT_NO_ADC_TEMP		37000
+
+struct qpnp_tm_chip {
+	struct delayed_work		irq_work;
+	struct spmi_device		*spmi_dev;
+	struct thermal_zone_device	*tz_dev;
+	const char			*tm_name;
+	enum qpnp_tm_adc_type		adc_type;
+	unsigned long			temperature;
+	enum thermal_device_mode	mode;
+	unsigned int			thresh;
+	unsigned int			stage;
+	unsigned int			prev_stage;
+	int				irq;
+	enum qpnp_vadc_channels		adc_channel;
+	u16				base_addr;
+	bool				allow_software_override;
+};
+
+/* Delay between TEMP_STAT IRQ going high and status value changing in ms. */
+#define STATUS_REGISTER_DELAY_MS       40
+
+enum pmic_thermal_override_mode {
+	SOFTWARE_OVERRIDE_DISABLED = 0,
+	SOFTWARE_OVERRIDE_ENABLED,
+};
+
+static inline int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *buf,
+				int len)
+{
+	int rc;
+
+	rc = spmi_ext_register_readl(chip->spmi_dev->ctrl,
+			chip->spmi_dev->sid, chip->base_addr + addr, buf, len);
+
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: spmi_ext_register_readl() failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
+			__func__, chip->spmi_dev->sid, chip->base_addr + addr,
+			len, rc);
+
+	return rc;
+}
+
+static inline int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 *buf,
+				int len)
+{
+	int rc;
+
+	rc = spmi_ext_register_writel(chip->spmi_dev->ctrl,
+			chip->spmi_dev->sid, chip->base_addr + addr, buf, len);
+
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: spmi_ext_register_writel() failed. sid=%d, addr=%04X, len=%d, rc=%d\n",
+			__func__, chip->spmi_dev->sid, chip->base_addr + addr,
+			len, rc);
+
+	return rc;
+}
+
+
+static inline int qpnp_tm_shutdown_override(struct qpnp_tm_chip *chip,
+			    enum pmic_thermal_override_mode mode)
+{
+	int rc = 0;
+	u8 reg;
+
+	if (chip->allow_software_override) {
+		reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
+
+		if (mode == SOFTWARE_OVERRIDE_ENABLED)
+			reg |= SHUTDOWN_CTRL1_OVERRIDE_STAGE2
+				| SHUTDOWN_CTRL1_OVERRIDE_STAGE3;
+
+		rc = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg, 1);
+	}
+
+	return rc;
+}
+
+static int qpnp_tm_update_temp(struct qpnp_tm_chip *chip)
+{
+	struct qpnp_vadc_result adc_result;
+	int rc;
+
+	rc = qpnp_vadc_read(chip->adc_channel, &adc_result);
+	if (!rc)
+		chip->temperature = adc_result.physical;
+	else
+		dev_err(&chip->spmi_dev->dev, "%s: qpnp_vadc_read(%d) failed, rc=%d\n",
+			__func__, chip->adc_channel, rc);
+
+	return rc;
+}
+
+/*
+ * This function initializes the internal temperature value based on only the
+ * current thermal stage and threshold.
+ */
+static int qpnp_tm_init_temp_no_adc(struct qpnp_tm_chip *chip)
+{
+	int rc;
+	u8 reg;
+
+	rc = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg, 1);
+	if (rc < 0)
+		return rc;
+
+	chip->stage = reg & STATUS_STAGE_MASK;
+
+	if (chip->stage)
+		chip->temperature = chip->thresh * TEMP_THRESH_STEP +
+			   (chip->stage - 1) * TEMP_STAGE_STEP +
+			   TEMP_THRESH_MIN;
+
+	return 0;
+}
+
+/*
+ * This function updates the internal temperature value based on the
+ * current thermal stage and threshold as well as the previous stage
+ */
+static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
+{
+	unsigned int stage;
+	int rc;
+	u8 reg;
+
+	rc = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg, 1);
+	if (rc < 0)
+		return rc;
+
+	stage = reg & STATUS_STAGE_MASK;
+
+	if (stage > chip->stage) {
+		/* increasing stage, use lower bound */
+		chip->temperature = (stage - 1) * TEMP_STAGE_STEP
+				+ chip->thresh * TEMP_THRESH_STEP
+				+ TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
+	} else if (stage < chip->stage) {
+		/* decreasing stage, use upper bound */
+		chip->temperature = stage * TEMP_STAGE_STEP
+				+ chip->thresh * TEMP_THRESH_STEP
+				- TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
+	}
+
+	chip->stage = stage;
+
+	return 0;
+}
+
+static int qpnp_tz_get_temp_no_adc(struct thermal_zone_device *thermal,
+				     unsigned long *temperature)
+{
+	struct qpnp_tm_chip *chip = thermal->devdata;
+	int rc;
+
+	if (!temperature)
+		return -EINVAL;
+
+	rc = qpnp_tm_update_temp_no_adc(chip);
+	if (rc < 0)
+		return rc;
+
+	*temperature = chip->temperature;
+
+	return 0;
+}
+
+static int qpnp_tz_get_temp_qpnp_adc(struct thermal_zone_device *thermal,
+				      unsigned long *temperature)
+{
+	struct qpnp_tm_chip *chip = thermal->devdata;
+	int rc;
+
+	if (!temperature)
+		return -EINVAL;
+
+	rc = qpnp_tm_update_temp(chip);
+	if (rc < 0) {
+		dev_err(&chip->spmi_dev->dev, "%s: %s: adc read failed, rc = %d\n",
+			__func__, chip->tm_name, rc);
+		return rc;
+	}
+
+	*temperature = chip->temperature;
+
+	return 0;
+}
+
+static int qpnp_tz_get_mode(struct thermal_zone_device *thermal,
+			      enum thermal_device_mode *mode)
+{
+	struct qpnp_tm_chip *chip = thermal->devdata;
+
+	if (!mode)
+		return -EINVAL;
+
+	*mode = chip->mode;
+
+	return 0;
+}
+
+static int qpnp_tz_set_mode(struct thermal_zone_device *thermal,
+			      enum thermal_device_mode mode)
+{
+	struct qpnp_tm_chip *chip = thermal->devdata;
+	int rc = 0;
+
+	if (mode != chip->mode) {
+		if (mode == THERMAL_DEVICE_ENABLED)
+			rc = qpnp_tm_shutdown_override(chip,
+				SOFTWARE_OVERRIDE_ENABLED);
+		else
+			rc = qpnp_tm_shutdown_override(chip,
+				SOFTWARE_OVERRIDE_DISABLED);
+
+		chip->mode = mode;
+	}
+
+	return rc;
+}
+
+static int qpnp_tz_get_trip_type(struct thermal_zone_device *thermal,
+				   int trip, enum thermal_trip_type *type)
+{
+	if (trip < 0 || !type)
+		return -EINVAL;
+
+	switch (trip) {
+	case TRIP_STAGE3:
+		*type = THERMAL_TRIP_CRITICAL;
+		break;
+	case TRIP_STAGE2:
+		*type = THERMAL_TRIP_HOT;
+		break;
+	case TRIP_STAGE1:
+		*type = THERMAL_TRIP_HOT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int qpnp_tz_get_trip_temp(struct thermal_zone_device *thermal,
+				   int trip, unsigned long *temperature)
+{
+	struct qpnp_tm_chip *chip = thermal->devdata;
+	int thresh_temperature;
+
+	if (trip < 0 || !temperature)
+		return -EINVAL;
+
+	thresh_temperature = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN;
+
+	switch (trip) {
+	case TRIP_STAGE3:
+		thresh_temperature += 2 * TEMP_STAGE_STEP;
+		break;
+	case TRIP_STAGE2:
+		thresh_temperature += TEMP_STAGE_STEP;
+		break;
+	case TRIP_STAGE1:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*temperature = thresh_temperature;
+
+	return 0;
+}
+
+static int qpnp_tz_get_crit_temp(struct thermal_zone_device *thermal,
+				   unsigned long *temperature)
+{
+	struct qpnp_tm_chip *chip = thermal->devdata;
+
+	if (!temperature)
+		return -EINVAL;
+
+	*temperature = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN +
+		2 * TEMP_STAGE_STEP;
+
+	return 0;
+}
+
+static struct thermal_zone_device_ops qpnp_thermal_zone_ops_no_adc = {
+	.get_temp = qpnp_tz_get_temp_no_adc,
+	.get_mode = qpnp_tz_get_mode,
+	.set_mode = qpnp_tz_set_mode,
+	.get_trip_type = qpnp_tz_get_trip_type,
+	.get_trip_temp = qpnp_tz_get_trip_temp,
+	.get_crit_temp = qpnp_tz_get_crit_temp,
+};
+
+static struct thermal_zone_device_ops qpnp_thermal_zone_ops_qpnp_adc = {
+	.get_temp = qpnp_tz_get_temp_qpnp_adc,
+	.get_mode = qpnp_tz_get_mode,
+	.set_mode = qpnp_tz_set_mode,
+	.get_trip_type = qpnp_tz_get_trip_type,
+	.get_trip_temp = qpnp_tz_get_trip_temp,
+	.get_crit_temp = qpnp_tz_get_crit_temp,
+};
+
+static void qpnp_tm_work(struct work_struct *work)
+{
+	struct delayed_work *dwork
+		= container_of(work, struct delayed_work, work);
+	struct qpnp_tm_chip *chip
+		= container_of(dwork, struct qpnp_tm_chip, irq_work);
+	int rc;
+	u8 reg;
+
+	if (chip->adc_type == QPNP_TM_ADC_NONE) {
+		rc = qpnp_tm_update_temp_no_adc(chip);
+		if (rc < 0)
+			goto bail;
+	} else {
+		rc = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg, 1);
+		if (rc < 0)
+			goto bail;
+
+		chip->stage = reg & STATUS_STAGE_MASK;
+
+		rc = qpnp_tm_update_temp(chip);
+		if (rc < 0)
+			goto bail;
+	}
+
+	if (chip->stage != chip->prev_stage) {
+		chip->prev_stage = chip->stage;
+
+		pr_crit("%s: PMIC Temp Alarm - stage=%u, threshold=%u, temperature=%lu mC\n",
+			chip->tm_name, chip->stage, chip->thresh,
+			chip->temperature);
+
+		thermal_zone_device_update(chip->tz_dev);
+
+		/* Notify user space */
+		sysfs_notify(&chip->tz_dev->device.kobj, NULL, "type");
+	}
+
+bail:
+	return;
+}
+
+static irqreturn_t qpnp_tm_isr(int irq, void *data)
+{
+	struct qpnp_tm_chip *chip = data;
+
+	schedule_delayed_work(&chip->irq_work,
+			msecs_to_jiffies(STATUS_REGISTER_DELAY_MS) + 1);
+
+	return IRQ_HANDLED;
+}
+
+static int qpnp_tm_init_reg(struct qpnp_tm_chip *chip)
+{
+	int rc = 0;
+	u8 reg;
+
+	if (chip->thresh < THRESH_MIN || chip->thresh > THRESH_MAX) {
+		/* Read hardware threshold value if configuration is invalid. */
+		rc = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg, 1);
+		if (rc < 0)
+			return rc;
+		chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK;
+	}
+
+	/*
+	 * Set threshold and disable software override of stage 2 and 3
+	 * shutdowns.
+	 */
+	reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
+	rc = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg, 1);
+	if (rc < 0)
+		return rc;
+
+	/* Enable the thermal alarm PMIC module in always-on mode. */
+	reg = ALARM_CTRL_FORCE_ENABLE;
+	rc = qpnp_tm_write(chip, QPNP_TM_REG_ALARM_CTRL, &reg, 1);
+
+	return rc;
+}
+
+static int __devinit qpnp_tm_probe(struct spmi_device *spmi)
+{
+	struct device_node *node;
+	struct resource *res;
+	struct qpnp_tm_chip *chip;
+	struct thermal_zone_device_ops *tz_ops;
+	char *tm_name;
+	u32 default_temperature;
+	int rc = 0;
+	u8 raw_type[2], type, subtype;
+
+	if (!spmi || !(&spmi->dev) || !spmi->dev.of_node) {
+		dev_err(&spmi->dev, "%s: device tree node not found\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	node = spmi->dev.of_node;
+
+	chip = kzalloc(sizeof(struct qpnp_tm_chip), GFP_KERNEL);
+	if (!chip) {
+		dev_err(&spmi->dev, "%s: Can't allocate qpnp_tm_chip\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	dev_set_drvdata(&spmi->dev, chip);
+
+	res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&spmi->dev, "%s: node is missing base address\n",
+			__func__);
+		rc = -EINVAL;
+		goto free_chip;
+	}
+	chip->base_addr	= res->start;
+	chip->spmi_dev	= spmi;
+
+	chip->irq = spmi_get_irq(spmi, NULL, 0);
+	if (chip->irq < 0) {
+		rc = chip->irq;
+		dev_err(&spmi->dev, "%s: node is missing irq, rc=%d\n",
+			__func__, rc);
+		goto free_chip;
+	}
+
+	chip->tm_name = of_get_property(node, "label", NULL);
+	if (chip->tm_name == NULL) {
+		dev_err(&spmi->dev, "%s: node is missing label\n",
+			__func__);
+		rc = -EINVAL;
+		goto free_chip;
+	}
+
+	tm_name = kstrdup(chip->tm_name, GFP_KERNEL);
+	if (tm_name == NULL) {
+		dev_err(&spmi->dev, "%s: could not allocate memory for label\n",
+			__func__);
+		rc = -ENOMEM;
+		goto free_chip;
+	}
+	chip->tm_name = tm_name;
+
+	INIT_DELAYED_WORK(&chip->irq_work, qpnp_tm_work);
+
+	/* These bindings are optional, so it is okay if they are not found. */
+	chip->thresh = THRESH_MAX + 1;
+	rc = of_property_read_u32(node, "qcom,threshold-set", &chip->thresh);
+	if (!rc && (chip->thresh < THRESH_MIN || chip->thresh > THRESH_MAX))
+		dev_err(&spmi->dev, "%s: invalid qcom,threshold-set=%u specified\n",
+			__func__, chip->thresh);
+
+	chip->adc_type = QPNP_TM_ADC_NONE;
+	rc = of_property_read_u32(node, "qcom,channel-num", &chip->adc_channel);
+	if (!rc) {
+		if (chip->adc_channel < 0 || chip->adc_channel >= ADC_MAX_NUM) {
+			dev_err(&spmi->dev, "%s: invalid qcom,channel-num=%d specified\n",
+				__func__, chip->adc_channel);
+		} else {
+			chip->adc_type = QPNP_TM_ADC_QPNP_ADC;
+			rc = qpnp_vadc_is_ready();
+			if (rc) {
+				/* Probe retry, do not print an error message */
+				goto err_cancel_work;
+			}
+		}
+	}
+
+	if (chip->adc_type == QPNP_TM_ADC_QPNP_ADC)
+		tz_ops = &qpnp_thermal_zone_ops_qpnp_adc;
+	else
+		tz_ops = &qpnp_thermal_zone_ops_no_adc;
+
+	chip->allow_software_override
+		= of_property_read_bool(node, "qcom,allow-override");
+
+	default_temperature = DEFAULT_NO_ADC_TEMP;
+	rc = of_property_read_u32(node, "qcom,default-temp",
+					&default_temperature);
+	chip->temperature = default_temperature;
+
+	rc = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, raw_type, 2);
+	if (rc) {
+		dev_err(&spmi->dev, "%s: could not read type register, rc=%d\n",
+			__func__, rc);
+		goto err_cancel_work;
+	}
+	type = raw_type[0];
+	subtype = raw_type[1];
+
+	if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) {
+		dev_err(&spmi->dev, "%s: invalid type=%02X or subtype=%02X register value\n",
+			__func__, type, subtype);
+		rc = -ENODEV;
+		goto err_cancel_work;
+	}
+
+	rc = qpnp_tm_init_reg(chip);
+	if (rc) {
+		dev_err(&spmi->dev, "%s: qpnp_tm_init_reg() failed, rc=%d\n",
+			__func__, rc);
+		goto err_cancel_work;
+	}
+
+	if (chip->adc_type == QPNP_TM_ADC_NONE) {
+		rc = qpnp_tm_init_temp_no_adc(chip);
+		if (rc) {
+			dev_err(&spmi->dev, "%s: qpnp_tm_init_temp_no_adc() failed, rc=%d\n",
+				__func__, rc);
+			goto err_cancel_work;
+		}
+	}
+
+	/* Start in HW control; switch to SW control when user changes mode. */
+	chip->mode = THERMAL_DEVICE_DISABLED;
+	rc = qpnp_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
+	if (rc) {
+		dev_err(&spmi->dev, "%s: qpnp_tm_shutdown_override() failed, rc=%d\n",
+			__func__, rc);
+		goto err_cancel_work;
+	}
+
+	chip->tz_dev = thermal_zone_device_register(tm_name, TRIP_NUM, chip,
+			tz_ops, 0, 0, 0, 0);
+	if (chip->tz_dev == NULL) {
+		dev_err(&spmi->dev, "%s: thermal_zone_device_register() failed.\n",
+			__func__);
+		rc = -ENODEV;
+		goto err_cancel_work;
+	}
+
+	rc = request_irq(chip->irq, qpnp_tm_isr, IRQF_TRIGGER_RISING, tm_name,
+			chip);
+	if (rc < 0) {
+		dev_err(&spmi->dev, "%s: request_irq(%d) failed: %d\n",
+			__func__, chip->irq, rc);
+		goto err_free_tz;
+	}
+
+	return 0;
+
+err_free_tz:
+	thermal_zone_device_unregister(chip->tz_dev);
+err_cancel_work:
+	cancel_delayed_work_sync(&chip->irq_work);
+	kfree(chip->tm_name);
+free_chip:
+	dev_set_drvdata(&spmi->dev, NULL);
+	kfree(chip);
+	return rc;
+}
+
+static int __devexit qpnp_tm_remove(struct spmi_device *spmi)
+{
+	struct qpnp_tm_chip *chip = dev_get_drvdata(&spmi->dev);
+
+	dev_set_drvdata(&spmi->dev, NULL);
+	thermal_zone_device_unregister(chip->tz_dev);
+	kfree(chip->tm_name);
+	qpnp_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
+	free_irq(chip->irq, chip);
+	cancel_delayed_work_sync(&chip->irq_work);
+	kfree(chip);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int qpnp_tm_suspend(struct device *dev)
+{
+	struct qpnp_tm_chip *chip = dev_get_drvdata(dev);
+
+	/* Clear override bits in suspend to allow hardware control */
+	qpnp_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
+
+	return 0;
+}
+
+static int qpnp_tm_resume(struct device *dev)
+{
+	struct qpnp_tm_chip *chip = dev_get_drvdata(dev);
+
+	/* Override hardware actions so software can control */
+	if (chip->mode == THERMAL_DEVICE_ENABLED)
+		qpnp_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_ENABLED);
+
+	return 0;
+}
+
+static const struct dev_pm_ops qpnp_tm_pm_ops = {
+	.suspend = qpnp_tm_suspend,
+	.resume = qpnp_tm_resume,
+};
+
+#define QPNP_TM_PM_OPS	(&qpnp_tm_pm_ops)
+#else
+#define QPNP_TM_PM_OPS	NULL
+#endif
+
+static struct of_device_id qpnp_tm_match_table[] = {
+	{ .compatible = QPNP_TM_DRIVER_NAME, },
+	{}
+};
+
+static const struct spmi_device_id qpnp_tm_id[] = {
+	{ QPNP_TM_DRIVER_NAME, 0 },
+	{}
+};
+
+static struct spmi_driver qpnp_tm_driver = {
+	.driver = {
+		.name		= QPNP_TM_DRIVER_NAME,
+		.of_match_table	= qpnp_tm_match_table,
+		.owner		= THIS_MODULE,
+		.pm		= QPNP_TM_PM_OPS,
+	},
+	.probe	  = qpnp_tm_probe,
+	.remove	  = __devexit_p(qpnp_tm_remove),
+	.id_table = qpnp_tm_id,
+};
+
+int __init qpnp_tm_init(void)
+{
+	return spmi_driver_register(&qpnp_tm_driver);
+}
+
+static void __exit qpnp_tm_exit(void)
+{
+	spmi_driver_unregister(&qpnp_tm_driver);
+}
+
+module_init(qpnp_tm_init);
+module_exit(qpnp_tm_exit);
+
+MODULE_DESCRIPTION("QPNP PMIC Temperature Alarm driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index 81f3d54..8debc36 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -183,8 +183,8 @@
 
 /* Parity configuration */
 #define NO_PARITY 0x0
-#define EVEN_PARITY 0x1
-#define ODD_PARITY 0x2
+#define EVEN_PARITY 0x2
+#define ODD_PARITY 0x1
 #define SPACE_PARITY 0x3
 
 #define UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK 0xffffff80
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 0c81904..4f098f1 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -615,6 +615,7 @@
 	qdss->function.unbind = qdss_unbind;
 	qdss->function.set_alt = qdss_set_alt;
 	qdss->function.disable = qdss_disable;
+	spin_lock_init(&qdss->lock);
 	INIT_LIST_HEAD(&qdss->ctrl_read_pool);
 	INIT_LIST_HEAD(&qdss->ctrl_write_pool);
 	INIT_WORK(&qdss->qdss_work, usb_qdss_work_func);
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 3d6ceaa..649fe14 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -225,26 +225,26 @@
 	NULL,
 };
 
-static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {
 	.bLength =              sizeof gser_ss_bulk_comp_desc,
 	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 };
 
-static struct usb_descriptor_header *gser_ss_function[] __initdata = {
+static struct usb_descriptor_header *gser_ss_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_ss_in_desc,
 	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 3c57df4..7e62c19 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -925,7 +925,7 @@
 	int		rc = 0;
 
 
-#ifndef CONFIG_USB_ANDROID_MASS_STORAGE
+#if !defined(CONFIG_USB_G_ANDROID)
 	/* disabled in android because we need to allow closing the backing file
 	 * if the media was removed
 	 */
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 6fe9e58..cd02489 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1144,6 +1144,14 @@
 
 #endif	/* CONFIG_PM */
 
+static void ehci_msm_set_autosuspend_delay(struct usb_device *dev)
+{
+	if (!dev->parent) /*for root hub no delay*/
+		pm_runtime_set_autosuspend_delay(&dev->dev, 0);
+	else
+		pm_runtime_set_autosuspend_delay(&dev->dev, 200);
+}
+
 static struct hc_driver msm_hsic_driver = {
 	.description		= hcd_name,
 	.product_desc		= "Qualcomm EHCI Host Controller using HSIC",
@@ -1194,6 +1202,8 @@
 
 	.enable_ulpi_control	= ehci_msm_enable_ulpi_control,
 	.disable_ulpi_control	= ehci_msm_disable_ulpi_control,
+
+	.set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
 };
 
 static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index b1b7763..2d95945 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -31,6 +31,8 @@
 #define DRIVER_DESC	"USB host diag bridge driver"
 #define DRIVER_VERSION	"1.0"
 
+#define AUTOSUSP_DELAY_WITH_USB 1000
+
 struct diag_bridge {
 	struct usb_device	*udev;
 	struct usb_interface	*ifc;
@@ -42,6 +44,7 @@
 	struct mutex		ifc_mutex;
 	struct diag_bridge_ops	*ops;
 	struct platform_device	*pdev;
+	unsigned		default_autosusp_delay;
 
 	/* debugging counters */
 	unsigned long		bytes_to_host;
@@ -68,6 +71,12 @@
 	dev->ops = ops;
 	dev->err = 0;
 
+#ifdef CONFIG_PM_RUNTIME
+	dev->default_autosusp_delay = dev->udev->dev.power.autosuspend_delay;
+#endif
+	pm_runtime_set_autosuspend_delay(&dev->udev->dev,
+			AUTOSUSP_DELAY_WITH_USB);
+
 	kref_get(&dev->kref);
 
 	return 0;
@@ -101,6 +110,10 @@
 
 	usb_kill_anchored_urbs(&dev->submitted);
 	dev->ops = 0;
+
+	pm_runtime_set_autosuspend_delay(&dev->udev->dev,
+			dev->default_autosusp_delay);
+
 	kref_put(&dev->kref, diag_bridge_delete);
 }
 EXPORT_SYMBOL(diag_bridge_close);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 26f1b84..18f8729 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1015,6 +1015,7 @@
 	if (!atomic_read(&motg->in_lpm))
 		return 0;
 
+	disable_irq(motg->irq);
 	wake_lock(&motg->wlock);
 
 	/* Vote for TCXO when waking up the phy */
@@ -1105,6 +1106,7 @@
 		enable_irq(motg->async_int);
 		motg->async_int = 0;
 	}
+	enable_irq(motg->irq);
 
 	/* If ASYNC IRQ is present then keep it enabled only during LPM */
 	if (motg->async_irq)
@@ -4020,10 +4022,6 @@
 			if (ret)
 				goto remove_phy;
 		}
-	} else {
-		ret = msm_otg_register_power_supply(pdev, motg);
-		if (ret)
-			goto remove_phy;
 	}
 
 	return 0;
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index a73b3ad..8190f2d 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -594,7 +594,7 @@
 void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
 void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv);
 void mdp4_overlay_dmae_xy(struct mdp4_overlay_pipe *pipe);
-int mdp4_overlay_pipe_staged(int mixer);
+int mdp4_overlay_pipe_staged(struct mdp4_overlay_pipe *pipe);
 void mdp4_lcdc_primary_vsyn(void);
 void mdp4_overlay0_done_lcdc(int cndx);
 void mdp4_overlay0_done_mddi(int cndx);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index ab27267..6c0c830 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1568,36 +1568,19 @@
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
-int mdp4_overlay_pipe_staged(int mixer)
+int mdp4_overlay_pipe_staged(struct mdp4_overlay_pipe *pipe)
 {
-	uint32 data, mask, i, off;
-	int p1, p2;
+	uint32 data, mask;
+	int mixer;
 
-	if (mixer == MDP4_MIXER2)
-		off = 0x100F0;
-	else
-		off = 0x10100;
+	mixer = pipe->mixer_num;
+	data = ctrl->mixer_cfg[mixer];
 
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	data = inpdw(MDP_BASE + off);
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	p1 = 0;
-	p2 = 0;
-	for (i = 0; i < 8; i++) {
-		mask = data & 0x0f;
-		if (mask) {
-			if (mask <= 4)
-				p1++;
-			else
-				p2++;
-		}
-		data >>= 4;
-	}
+	mask = 0x0f;
+	mask <<= (4 * pipe->pipe_num);
+	data &= mask;
 
-	if (mixer)
-		return p2;
-	else
-		return p1;
+	return data;
 }
 
 int mdp4_mixer_info(int mixer_num, struct mdp_mixer_info *info)
@@ -2434,6 +2417,11 @@
 	 * zorder 2 == stage 2 == 4
 	 */
 	if (req->id == MSMFB_NEW_REQUEST) {  /* new request */
+		if (mdp4_overlay_pipe_staged(pipe)) {
+			pr_err("%s: ndx=%d still staged\n", __func__,
+						pipe->pipe_ndx);
+			return -EPERM;
+		}
 		pipe->pipe_used++;
 		pipe->mixer_num = mixer;
 		pr_debug("%s: zorder=%d pipe ndx=%d num=%d\n", __func__,
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 5daa3ad..c5442a7 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -1129,14 +1129,18 @@
 	unsigned long flags;
 	long long tick;
 
+	mutex_lock(&mfd->dma->ov_mutex);
 	vctrl = &vsync_ctrl_db[cndx];
 
-	if (!mfd->panel_power_on)
+	if (!mfd->panel_power_on) {
+		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
+	}
 
 	pipe = vctrl->base_pipe;
 	if (pipe == NULL) {
 		pr_err("%s: NO base pipe\n", __func__);
+		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
 	}
 
@@ -1144,6 +1148,7 @@
 	if (!vctrl->clk_enabled) {
 		pr_err("%s: mdp clocks disabled\n", __func__);
 		mutex_unlock(&vctrl->update_lock);
+		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
 
 	}
@@ -1166,12 +1171,9 @@
 	}
 
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
-
-	mutex_lock(&mfd->dma->ov_mutex);
 	mdp4_dsi_cmd_pipe_commit(cndx, 0);
+	mdp4_dsi_cmd_wait4vsync(cndx, &tick);
+	mdp4_overlay_mdp_perf_upd(mfd, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
 
-	mdp4_dsi_cmd_wait4vsync(cndx, &tick);
-
-	mdp4_overlay_mdp_perf_upd(mfd, 0);
 }
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 8bffb51..a83c340 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -194,8 +194,6 @@
 	}
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 
-	mdp4_overlay_mdp_perf_upd(vctrl->mfd, 1);
-
 	if (vctrl->blt_change) {
 		pipe = vctrl->base_pipe;
 		spin_lock_irqsave(&vctrl->spin_lock, flags);
@@ -1079,11 +1077,15 @@
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 
+	mutex_lock(&mfd->dma->ov_mutex);
+
 	vctrl = &vsync_ctrl_db[cndx];
 	pipe = vctrl->base_pipe;
 
-	if (!pipe || !mfd->panel_power_on)
+	if (!pipe || !mfd->panel_power_on) {
+		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
+	}
 
 	pr_debug("%s: cpu=%d pid=%d\n", __func__,
 			smp_processor_id(), current->pid);
@@ -1102,10 +1104,7 @@
 
 	mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
-
-	mutex_lock(&mfd->dma->ov_mutex);
 	mdp4_dsi_video_pipe_commit(cndx, 0);
-	mutex_unlock(&mfd->dma->ov_mutex);
 
 	if (pipe->ov_blt_addr)
 		mdp4_dsi_video_wait4ov(cndx);
@@ -1113,5 +1112,6 @@
 		mdp4_dsi_video_wait4dmap(cndx);
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
+	mutex_unlock(&mfd->dma->ov_mutex);
 }
 
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index c049d14..8a2d72a 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -55,14 +55,6 @@
 static int first_pixel_start_x;
 static int first_pixel_start_y;
 
-void mdp4_dtv_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
-{
-#ifdef BYPASS4
-	if (hdmi_prim_display)
-		dtv_pipe = pipe;
-#endif
-}
-
 #define MAX_CONTROLLER	1
 
 static struct vsycn_ctrl {
@@ -375,6 +367,24 @@
 	spin_lock_init(&vctrl->spin_lock);
 }
 
+void mdp4_dtv_base_swap(int cndx, struct mdp4_overlay_pipe *pipe)
+{
+	struct vsycn_ctrl *vctrl;
+
+	if (!hdmi_prim_display) {
+		pr_err("%s: failed, hdmi is not primary\n", __func__);
+		return;
+	}
+
+	if (cndx >= MAX_CONTROLLER) {
+		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+		return;
+	}
+
+	vctrl = &vsync_ctrl_db[cndx];
+	vctrl->base_pipe = pipe;
+}
+
 static int mdp4_dtv_start(struct msm_fb_data_type *mfd)
 {
 	int dtv_width;
@@ -1057,8 +1067,11 @@
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 
-	if (!mfd->panel_power_on)
+	mutex_lock(&mfd->dma->ov_mutex);
+	if (!mfd->panel_power_on) {
+		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
+	}
 
 	vctrl = &vsync_ctrl_db[cndx];
 	if (vctrl->base_pipe == NULL)
@@ -1068,6 +1081,7 @@
 
 	if (pipe == NULL) {
 		pr_warn("%s: dtv_pipe == NULL\n", __func__);
+		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
 	}
 
@@ -1083,8 +1097,6 @@
 		mdp4_dtv_pipe_queue(0, pipe);
 	}
 	mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
-
-	mutex_lock(&mfd->dma->ov_mutex);
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 	mdp4_dtv_pipe_commit(cndx, 0);
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 9a3f022..9e0c411 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -965,12 +965,15 @@
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 
+	mutex_lock(&mfd->dma->ov_mutex);
 
 	vctrl = &vsync_ctrl_db[cndx];
 	pipe = vctrl->base_pipe;
 
-	if (!pipe || !mfd->panel_power_on)
+	if (!pipe || !mfd->panel_power_on) {
+		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
+	}
 
 	pr_debug("%s: cpu=%d pid=%d\n", __func__,
 			smp_processor_id(), current->pid);
@@ -990,9 +993,8 @@
 
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 
-	mutex_lock(&mfd->dma->ov_mutex);
+
 	mdp4_lcdc_pipe_commit(cndx, 0);
-	mutex_unlock(&mfd->dma->ov_mutex);
 
 	if (pipe->ov_blt_addr)
 		mdp4_lcdc_wait4ov(cndx);
@@ -1000,4 +1002,5 @@
 		mdp4_lcdc_wait4dmap(cndx);
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
+	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdss/mdss_wb.c b/drivers/video/msm/mdss/mdss_wb.c
index a26d339..d4c924f 100644
--- a/drivers/video/msm/mdss/mdss_wb.c
+++ b/drivers/video/msm/mdss/mdss_wb.c
@@ -73,7 +73,7 @@
 	pdata->panel_info.type = WRITEBACK_PANEL;
 	pdata->panel_info.clk_rate = 74250000;
 	pdata->panel_info.pdest = DISPLAY_3;
-	pdata->panel_info.out_format = MDP_Y_CBCR_H2V2;
+	pdata->panel_info.out_format = MDP_Y_CBCR_H2V2_VENUS;
 
 	pdata->on = mdss_wb_on;
 	pdata->off = mdss_wb_off;
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 8e8caf7..2dea611 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -207,8 +207,16 @@
 void wcd9xxx_enable_irq(struct wcd9xxx *wcd9xxx, int irq);
 void wcd9xxx_disable_irq(struct wcd9xxx *wcd9xxx, int irq);
 void wcd9xxx_disable_irq_sync(struct wcd9xxx *wcd9xxx, int irq);
-#ifdef CONFIG_OF
+#if defined(CONFIG_WCD9310_CODEC) || \
+	defined(CONFIG_WCD9304_CODEC) || \
+	defined(CONFIG_WCD9320_CODEC)
 int __init wcd9xxx_irq_of_init(struct device_node *node,
 			       struct device_node *parent);
-#endif /* CONFIG_OF */
+#else
+static inline int __init wcd9xxx_irq_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	return 0;
+}
+#endif
 #endif
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 477733c..30ca87c 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -229,6 +229,20 @@
 #define MMC_BLK_DATA_AREA_GP	(1<<2)
 };
 
+#define BKOPS_NUM_OF_SEVERITY_LEVELS	3
+#define BKOPS_SEVERITY_1_INDEX		0
+#define BKOPS_SEVERITY_2_INDEX		1
+#define BKOPS_SEVERITY_3_INDEX		2
+struct mmc_bkops_stats {
+	spinlock_t		lock;
+	bool			enabled;
+	unsigned int		hpi;    /* hpi issued   */
+	unsigned int		suspend;/* card sleed issued */
+	bool			print_stats;
+	unsigned int bkops_level[BKOPS_NUM_OF_SEVERITY_LEVELS];
+	bool			ignore_card_bkops_status;
+};
+
 /**
  * struct mmc_bkops_info - BKOPS data
  * @dw:	Idle time bkops delayed work
@@ -249,6 +263,7 @@
 	unsigned int		host_suspend_tout_ms;
 	unsigned int		delay_ms;
 	unsigned int		min_sectors_to_queue_delayed_work;
+	struct mmc_bkops_stats  bkops_stats;    /* BKOPS statistics */
 /*
  * A default time for checking the need for non urgent BKOPS once mmcqd
  * is idle.
@@ -311,10 +326,11 @@
 #define MMC_QUIRK_LONG_READ_TIME (1<<9)		/* Data read time > CSD says */
 						/* byte mode */
 #define MMC_QUIRK_INAND_DATA_TIMEOUT  (1<<8)    /* For incorrect data timeout */
-	unsigned int    	poweroff_notify_state;	/* eMMC4.5 notify
-							   feature */
+	unsigned int    poweroff_notify_state;	/* eMMC4.5 notify feature */
 #define MMC_NO_POWER_NOTIFICATION	0
 #define MMC_POWERED_ON			1
+#define MMC_POWEROFF_SHORT		2
+#define MMC_POWEROFF_LONG		3
 
 	unsigned int		erase_size;	/* erase size in sectors */
  	unsigned int		erase_shift;	/* if erase unit is power 2 */
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 2795734..7247696 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -173,7 +173,6 @@
 extern int mmc_can_discard(struct mmc_card *card);
 extern int mmc_can_sanitize(struct mmc_card *card);
 extern int mmc_can_secure_erase_trim(struct mmc_card *card);
-extern int mmc_can_poweroff_notify(const struct mmc_card *card);
 extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 				   unsigned int nr);
 extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
@@ -197,6 +196,8 @@
 
 extern int mmc_detect_card_removed(struct mmc_host *host);
 
+extern void mmc_blk_init_bkops_statistics(struct mmc_card *card);
+
 /**
  *	mmc_claim_host - exclusively claim a host
  *	@host: mmc host to claim
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 9e536be..8f0a756 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -241,6 +241,7 @@
 #define MMC_CAP2_BROKEN_VOLTAGE	(1 << 7)	/* Use the broken voltage */
 #define MMC_CAP2_DETECT_ON_ERR	(1 << 8)	/* On I/O err check card removal */
 #define MMC_CAP2_HC_ERASE_SZ	(1 << 9)	/* High-capacity erase size */
+
 #define MMC_CAP2_PACKED_RD	(1 << 10)	/* Allow packed read */
 #define MMC_CAP2_PACKED_WR	(1 << 11)	/* Allow packed write */
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
@@ -249,9 +250,11 @@
 
 #define MMC_CAP2_SANITIZE	(1 << 13)		/* Support Sanitize */
 #define MMC_CAP2_INIT_BKOPS	    (1 << 15)	/* Need to set BKOPS_EN */
-#define MMC_CAP2_POWER_OFF_VCCQ_DURING_SUSPEND	(1 << 16)
-
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
+	unsigned int        power_notify_type;
+#define MMC_HOST_PW_NOTIFY_NONE		0
+#define MMC_HOST_PW_NOTIFY_SHORT	1
+#define MMC_HOST_PW_NOTIFY_LONG		2
 
 	int			clk_requests;	/* internal reference counter */
 	unsigned int		clk_delay;	/* number of MCI clk hold cycles */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 92888c3..237a92e 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -427,11 +427,4 @@
 #define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
 #define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */
 
-/*
- * MMC Poweroff Notify types
- */
-#define MMC_PW_OFF_NOTIFY_NONE		0
-#define MMC_PW_OFF_NOTIFY_SHORT		1
-#define MMC_PW_OFF_NOTIFY_LONG		2
-
 #endif /* LINUX_MMC_MMC_H */
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index e7f06b5..e907f4a 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -39,7 +39,14 @@
 			(AUDIO_MAX_COMMON_IOCTL_NUM+16), unsigned)
 #define AUDIO_SET_AFE_RX_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+17), unsigned)
-
+#define AUDIO_SET_VOCPROC_COL_CAL	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+18), unsigned)
+#define AUDIO_SET_VOCSTRM_COL_CAL	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+19), unsigned)
+#define AUDIO_SET_VOCVOL_COL_CAL	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+20), unsigned)
+#define AUDIO_SET_VOCPROC_DEV_CFG_CAL	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+21), unsigned)
 
 #define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+30)
 
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 730c7b2..46724eb 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -89,6 +89,7 @@
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_CHARGING_ENABLED,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
diff --git a/include/linux/tsif_api.h b/include/linux/tsif_api.h
index fc4d20b..0c18228 100644
--- a/include/linux/tsif_api.h
+++ b/include/linux/tsif_api.h
@@ -3,8 +3,7 @@
  *
  * Kernel API
  *
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights
- * reserved.
+ * Copyright (c) 2009-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
@@ -124,11 +123,13 @@
  * Should be called prior to any other tsif_XXX function.
  */
 void *tsif_attach(int id, void (*notify)(void *client_data), void *client_data);
+
 /**
  * tsif_detach - detach from device
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
  */
 void tsif_detach(void *cookie);
+
 /**
  * tsif_get_info - get data buffer info
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
@@ -140,6 +141,7 @@
  * using data; since data buffer will be re-allocated on tsif_start()
  */
 void tsif_get_info(void *cookie, void **pdata, int *psize);
+
 /**
  * tsif_set_mode - set TSIF mode
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
@@ -150,6 +152,7 @@
  * Mode may be changed only when TSIF device is stopped.
  */
 int tsif_set_mode(void *cookie, int mode);
+
 /**
  * tsif_set_time_limit - set TSIF time limit
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
@@ -160,6 +163,7 @@
  * Time limit may be changed only when TSIF device is stopped.
  */
 int tsif_set_time_limit(void *cookie, u32 value);
+
 /**
  * tsif_set_buf_config - configure data buffer
  *
@@ -180,6 +184,7 @@
  *   stats
  */
 int tsif_set_buf_config(void *cookie, u32 pkts_in_chunk, u32 chunks_in_buf);
+
 /**
  * tsif_get_state - query current data buffer information
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
@@ -188,6 +193,51 @@
  * @state:     if not NULL, state will be stored here
  */
 void tsif_get_state(void *cookie, int *ri, int *wi, enum tsif_state *state);
+
+/**
+ * tsif_set_clk_inverse - set whether to inverse the clock signal.
+ * @cookie:   TSIF cookie previously obtained with tsif_attach()
+ * @inverse:  1 to inverse the clock, 0 otherwise. Default is 0.
+ *
+ * Return      error code
+ *
+ * Setting may be changed only when TSIF device is stopped.
+ */
+int tsif_set_clk_inverse(void *cookie, int inverse);
+
+/**
+ * tsif_set_data_inverse - set whether to inverse the data signal.
+ * @cookie:   TSIF cookie previously obtained with tsif_attach()
+ * @inverse:  1 to inverse the clock, 0 otherwise. Default is 0.
+ *
+ * Return      error code
+ *
+ * Setting may be changed only when TSIF device is stopped.
+ */
+int tsif_set_data_inverse(void *cookie, int inverse);
+
+/**
+ * tsif_set_sync_inverse - set whether to inverse the sync signal.
+ * @cookie:   TSIF cookie previously obtained with tsif_attach()
+ * @inverse:  1 to inverse the clock, 0 otherwise. Default is 0.
+ *
+ * Return      error code
+ *
+ * Setting may be changed only when TSIF device is stopped.
+ */
+int tsif_set_sync_inverse(void *cookie, int inverse);
+
+/**
+ * tsif_set_enable_inverse - set whether to inverse the enable signal.
+ * @cookie:   TSIF cookie previously obtained with tsif_attach()
+ * @inverse:  1 to inverse the clock, 0 otherwise. Default is 0.
+ *
+ * Return      error code
+ *
+ * Setting may be changed only when TSIF device is stopped.
+ */
+int tsif_set_enable_inverse(void *cookie, int inverse);
+
 /**
  * tsif_start - start data acquisition
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
@@ -195,6 +245,7 @@
  * Return      error code
  */
 int tsif_start(void *cookie);
+
 /**
  * tsif_stop - stop data acquisition
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
@@ -203,6 +254,7 @@
  * query data buffer info using tsif_get_info() and reset its data pointers.
  */
 void tsif_stop(void *cookie);
+
 /**
  * tsif_reclaim_packets - inform that buffer space may be reclaimed
  * @cookie:    TSIF cookie previously obtained with tsif_attach()
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 3f0c862..6d684ef 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -184,6 +184,11 @@
 
 	uint32_t				bus_client_handle;
 
+	int						domain_num;
+	struct device			*vc_iommu_ctx;
+	struct device			*vp_iommu_ctx;
+	struct iommu_domain		*iommu_vcap_domain;
+
 	struct vcap_client_data *vc_client;
 	struct vcap_client_data *vp_client;
 
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 602fe59..14ccf3e 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -267,6 +267,11 @@
 
 #define MGMT_OP_LE_CANCEL_CREATE_CONN_WHITE_LIST	0xE005
 
+#define MGMT_OP_LE_CANCEL_CREATE_CONN	0xE006
+struct mgmt_cp_le_cancel_create_conn {
+	bdaddr_t	bdaddr;
+} __packed;
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16 opcode;
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 2ee5ff7..182da1c 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -66,6 +66,7 @@
 
 #define SYNC_IO_MODE	0x0001
 #define ASYNC_IO_MODE	0x0002
+#define COMPRESSED_IO	0x0040
 #define NT_MODE        0x0400
 
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d7deaaf..28eb7ea 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2073,6 +2073,40 @@
 	return err;
 }
 
+static int le_cancel_create_conn(struct sock *sk, u16 index,
+	unsigned char *data, u16 len)
+{
+	struct mgmt_cp_le_cancel_create_conn *cp = (void *) data;
+	struct hci_dev *hdev;
+	int err = 0;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_LE_CANCEL_CREATE_CONN,
+							EINVAL);
+
+	hdev = hci_dev_get(index);
+
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_LE_CANCEL_CREATE_CONN,
+							ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_LE_CANCEL_CREATE_CONN,
+						ENETDOWN);
+		goto failed;
+	}
+
+	hci_le_cancel_create_connect(hdev, &cp->bdaddr);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+return err;
+}
+
 static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
 								u16 len)
 {
@@ -2664,6 +2698,9 @@
 	case MGMT_OP_LE_CANCEL_CREATE_CONN_WHITE_LIST:
 		err = le_cancel_create_conn_white_list(sk, index);
 		break;
+	case MGMT_OP_LE_CANCEL_CREATE_CONN:
+		err = le_cancel_create_conn(sk, index, buf + sizeof(*hdr), len);
+		break;
 	default:
 		BT_DBG("Unknown op %u", opcode);
 		err = cmd_status(sk, index, opcode, 0x01);
diff --git a/sound/soc/msm/apq8064-i2s.c b/sound/soc/msm/apq8064-i2s.c
index e309370..795b421 100644
--- a/sound/soc/msm/apq8064-i2s.c
+++ b/sound/soc/msm/apq8064-i2s.c
@@ -2690,8 +2690,7 @@
 
 static void __exit msm_audio_exit(void)
 {
-	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
-				 (socinfo_get_id() == 130)) {
+	if (!soc_class_is_apq8064() || socinfo_get_id() == 130) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 1316a0e..4fe002b 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -2076,7 +2076,7 @@
 {
 	int ret;
 	u32	version = socinfo_get_platform_version();
-	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
+	if (!soc_class_is_apq8064() ||
 		(socinfo_get_id() == 130) ||
 		(machine_is_apq8064_mtp() &&
 		(SOCINFO_VERSION_MINOR(version) == 1))) {
@@ -2117,8 +2117,7 @@
 
 static void __exit msm_audio_exit(void)
 {
-	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
-				 (socinfo_get_id() == 130)) {
+	if (!soc_class_is_apq8064() || socinfo_get_id() == 130) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 23703f2..7656f9f 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -140,6 +140,7 @@
 static int msm_slim_0_tx_ch = 1;
 static int msm_hdmi_rx_ch = 8;
 static int mi2s_rate_variable;
+static int hdmi_rate_variable;
 static struct clk *codec_clk;
 static int clk_users;
 
@@ -523,6 +524,8 @@
 static const char * const hdmi_rx_ch_text[] = {"Two", "Three", "Four",
 					"Five", "Six", "Seven", "Eight"};
 static const char * const mi2s_rate[] = {"Default", "Variable"};
+static const char * const hdmi_rate[] = {"Default", "Variable"};
+
 
 
 static const struct soc_enum msm_enum[] = {
@@ -531,6 +534,7 @@
 	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
 	SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
 	SOC_ENUM_SINGLE_EXT(2, mi2s_rate),
+	SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
 
 };
 
@@ -606,6 +610,21 @@
 	return 0;
 }
 
+static int msm_hdmi_rate_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	hdmi_rate_variable = ucontrol->value.integer.value[0];
+	pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
+	return 0;
+}
+
+static int msm_hdmi_rate_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = hdmi_rate_variable;
+	return 0;
+}
+
 static const struct snd_kcontrol_new tabla_msm_controls[] = {
 	SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
 		msm_set_spk),
@@ -618,6 +637,9 @@
 	SOC_ENUM_EXT("SEC RX Rate", msm_enum[4],
 					msm_mi2s_rate_get,
 					msm_mi2s_rate_put),
+	SOC_ENUM_EXT("HDMI RX Rate", msm_enum[5],
+					msm_hdmi_rate_get,
+					msm_hdmi_rate_put),
 
 };
 
@@ -867,7 +889,9 @@
 	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
 			channels->min, channels->max);
 
-	rate->min = rate->max = 48000;
+	/*Configure the sample rate as 48000 KHz for the LPCM playback*/
+	if (!hdmi_rate_variable)
+		rate->min = rate->max = 48000;
 	channels->min =  channels->max = msm_hdmi_rx_ch;
 
 	return 0;
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index a3c59b9..8202982 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -202,6 +202,7 @@
 			wake_up(&the_locks.eos_wait);
 			atomic_set(&prtd->eos, 0);
 		}
+		atomic_set(&prtd->pending_buffer, 1);
 		break;
 	case ASM_DATA_EVENT_READ_DONE: {
 		pr_debug("ASM_DATA_EVENT_READ_DONE\n");
@@ -1208,6 +1209,7 @@
 				prtd->cmd_ack = 1;
 				wake_up(&the_locks.eos_wait);
 				atomic_set(&prtd->eos, 0);
+				atomic_set(&prtd->pending_buffer, 1);
 			}
 
 			/* A unlikely race condition possible with FLUSH
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
index 2b3dd5f..1995f1a 100644
--- a/sound/soc/msm/msm-dai-q6-hdmi.c
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -91,11 +91,25 @@
 	u32 channel_allocation = 0;
 	u32 level_shift  = 0; /* 0dB */
 	bool down_mix = FALSE;
+	int sample_rate = 48000;
 
 	dai_data->channels = params_channels(params);
 	dai_data->rate = params_rate(params);
 	dai_data->port_config.hdmi_multi_ch.reserved = 0;
 
+	switch (dai_data->rate) {
+	case 48000:
+		sample_rate = HDMI_SAMPLE_RATE_48KHZ;
+		break;
+	case 44100:
+		sample_rate = HDMI_SAMPLE_RATE_44_1KHZ;
+		break;
+	case 32000:
+		sample_rate = HDMI_SAMPLE_RATE_32KHZ;
+		break;
+	}
+	hdmi_msm_audio_sample_rate_reset(sample_rate);
+
 	switch (dai_data->channels) {
 	case 2:
 		channel_allocation  = 0;
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 76b7597..b3db9e1 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -1307,7 +1307,7 @@
 {
 	int ret;
 
-	if (!cpu_is_msm8930() && !cpu_is_msm8930aa() && !cpu_is_msm8627()) {
+	if (!soc_class_is_msm8930()) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return -ENODEV ;
 	}
@@ -1346,7 +1346,7 @@
 
 static void __exit msm8930_audio_exit(void)
 {
-	if (!cpu_is_msm8930() && !cpu_is_msm8930aa() && !cpu_is_msm8627()) {
+	if (!soc_class_is_msm8930()) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index da7a129..ad78255 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1745,7 +1745,7 @@
 {
 	int ret;
 
-	if (!cpu_is_msm8960() && !cpu_is_msm8960ab()) {
+	if (!soc_class_is_msm8960()) {
 		pr_debug("%s: Not the right machine type\n", __func__);
 		return -ENODEV ;
 	}
@@ -1818,7 +1818,7 @@
 
 static void __exit msm8960_audio_exit(void)
 {
-	if (!cpu_is_msm8960() && !cpu_is_msm8960ab()) {
+	if (!soc_class_is_msm8960()) {
 		pr_debug("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 01a9538..d85bbbc 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -148,17 +148,14 @@
 				((unsigned int)buf[0].phys
 				+ (prtd->out_head * prtd->pcm_count)));
 
-		if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
+		if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
 			time_stamp_flag = SET_TIMESTAMP;
-			memcpy(&output_meta_data, (char *)(buf->data +
+		else
+			time_stamp_flag = NO_TIMESTAMP;
+		memcpy(&output_meta_data, (char *)(buf->data +
 			prtd->out_head * prtd->pcm_count),
 			COMPRE_OUTPUT_METADATA_SIZE);
-		} else {
-			time_stamp_flag = NO_TIMESTAMP;
-			memset(&output_meta_data, 0,
-				 COMPRE_OUTPUT_METADATA_SIZE);
-			output_meta_data.frame_size = prtd->pcm_count;
-		}
+
 		buffer_length = output_meta_data.frame_size;
 		pr_debug("meta_data_length: %d, frame_length: %d\n",
 			 output_meta_data.meta_data_length,
@@ -257,17 +254,13 @@
 				__func__, prtd->out_head,
 				((unsigned int)buf[0].phys
 				+ (prtd->out_head * prtd->pcm_count)));
-			if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
+			if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
 				time_stamp_flag = SET_TIMESTAMP;
-				memcpy(&output_meta_data, (char *)(buf->data +
+			else
+				time_stamp_flag = NO_TIMESTAMP;
+			memcpy(&output_meta_data, (char *)(buf->data +
 				prtd->out_head * prtd->pcm_count),
 				COMPRE_OUTPUT_METADATA_SIZE);
-			} else {
-				time_stamp_flag = NO_TIMESTAMP;
-				memset(&output_meta_data, 0,
-				 COMPRE_OUTPUT_METADATA_SIZE);
-				output_meta_data.frame_size = prtd->pcm_count;
-			}
 			buffer_length = output_meta_data.frame_size;
 			pr_debug("meta_data_length: %d, frame_length: %d\n",
 				 output_meta_data.meta_data_length,
@@ -774,7 +767,8 @@
 		}
 	}
 
-	ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
+	ret = q6asm_set_io_mode(prtd->audio_client,
+					(COMPRESSED_IO | ASYNC_IO_MODE));
 	if (ret < 0) {
 		pr_err("%s: Set IO mode failed\n", __func__);
 		return -ENOMEM;
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 0466eb6..6acc136 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -51,6 +51,24 @@
 
 static struct adm_ctl			this_adm;
 
+static void adm_callback_debug_print(struct apr_client_data *data)
+{
+	uint32_t *payload;
+	payload = data->payload;
+
+	if (data->payload_size >= 8)
+		pr_debug("%s: code = 0x%x PL#0[%x], PL#1[%x], size = %d\n",
+			__func__, data->opcode, payload[0], payload[1],
+			data->payload_size);
+	else if (data->payload_size >= 4)
+		pr_debug("%s: code = 0x%x PL#0[%x], size = %d\n",
+			__func__, data->opcode, payload[0],
+			data->payload_size);
+	else
+		pr_debug("%s: code = 0x%x, size = %d\n",
+			__func__, data->opcode, data->payload_size);
+}
+
 static int32_t adm_callback(struct apr_client_data *data, void *priv)
 {
 	uint32_t *payload;
@@ -86,10 +104,7 @@
 		return 0;
 	}
 
-	pr_debug("%s: code = 0x%x PL#0[%x], PL#1[%x], size = %d\n", __func__,
-			data->opcode, payload[0], payload[1],
-					data->payload_size);
-
+	adm_callback_debug_print(data);
 	if (data->payload_size) {
 		index = q6audio_get_port_index(data->token);
 		if (index < 0 || index >= Q6_AFE_MAX_PORTS) {
@@ -99,6 +114,10 @@
 		}
 		if (data->opcode == APR_BASIC_RSP_RESULT) {
 			pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
+			if (payload[1] != 0) {
+				pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
+					__func__, payload[0], payload[1]);
+			}
 			switch (payload[0]) {
 			case ADM_CMD_SET_PP_PARAMS_V5:
 				if (rtac_make_adm_callback(
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 072e293..875bf47 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -476,9 +476,13 @@
 	return;
 }
 
-int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode)
+int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode1)
 {
+	uint32_t mode;
+
 	ac->io_mode &= 0xFF00;
+	mode = (mode1 & 0xF);
+
 	pr_debug("%s ac->mode after anding with FF00:0x[%x],\n",
 		__func__, ac->io_mode);
 	if (ac == NULL) {
@@ -486,7 +490,7 @@
 		return -EINVAL;
 	}
 	if ((mode == ASYNC_IO_MODE) || (mode == SYNC_IO_MODE)) {
-		ac->io_mode |= mode;
+		ac->io_mode |= mode1;
 		pr_debug("%s:Set Mode to 0x[%x]\n", __func__, ac->io_mode);
 		return 0;
 	} else {
@@ -2961,6 +2965,7 @@
 	struct audio_port_data     *port;
 	u32 lbuf_addr_lsw;
 	u32 liomode;
+	u32 io_compressed;
 
 	if (!ac || ac->apr == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
@@ -2981,9 +2986,12 @@
 	write.timestamp_msw = param->msw_ts;
 	write.timestamp_lsw = param->lsw_ts;
 	liomode = (ASYNC_IO_MODE | NT_MODE);
+	io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
 
 	if (ac->io_mode == liomode)
 		lbuf_addr_lsw = (write.buf_addr_lsw - 32);
+	else if (ac->io_mode == io_compressed)
+		lbuf_addr_lsw = (write.buf_addr_lsw - 0x40);
 	else
 		lbuf_addr_lsw = write.buf_addr_lsw;