Merge "power: qpnp-bms: report 100 SoC when battery is gone"
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
index d930799..3d70a9b 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
@@ -62,6 +62,28 @@
 				1.  This value shift is necessary to work around
 				limitations in the regulator framework which
 				treat 0 uV as an error.
+- qcom,use-voltage-floor-corner:  Flag that signifies if regulator_set_voltage
+				calls should modify the floor corner parameter
+				instead of the voltage parameter.  When used,
+				voltages specified inside of the regulator
+				framework represent corners that have been
+				incremented by 1.  The properties
+				qcom,use-voltage-corner and
+				qcom,use-voltage-floor-corner are mutually
+				exclusive.  Only one may be specified for a
+				given regulator.
+- qcom,always-send-voltage:    Flag which indicates that updates to the voltage
+				or voltage corner set point should always be
+				sent immediately to the RPM.  If this flag is
+				not specified, then voltage set point updates
+				are only sent if the given regulator has also
+				been enabled by a Linux consumer.
+- qcom,always-send-current:    Flag which indicates that updates to the load
+				current should always be sent immediately to the
+				RPM.  If this flag is not specified, then load
+				current updates are only sent if the given
+				regulator has also been enabled by a Linux
+				consumer.
 The following properties specify initial values for parameters to be sent to the
 RPM in regulator requests.
 - qcom,init-enable:            0 = regulator disabled
@@ -94,25 +116,9 @@
 					BIT(2) = follow HW2_EN signal
 					BIT(3) = follow HW3_EN signal
 					BIT(4) = follow PMIC awake state
-- qcom,init-frequency:         Switching frequency in MHz for SMPS regulators.
-				Supported values are:
-					 0 = Don't care about frequency used
-					 1 = 19.20
-					 2 = 9.60
-					 3 = 6.40
-					 4 = 4.80
-					 5 = 3.84
-					 6 = 3.20
-					 7 = 2.74
-					 8 = 2.40
-					 9 = 2.13
-					10 = 1.92
-					11 = 1.75
-					12 = 1.60
-					13 = 1.48
-					14 = 1.37
-					15 = 1.28
-					16 = 1.20
+- qcom,init-frequency:         Switching frequency divisor for SMPS regulators.
+				Supported values are n = 0 to 31 where
+				freq = 19.2 MHz / (n + 1).
 - qcom,init-head-room:         Voltage head room in mV required for the
 				regulator.  This head room value should be used
 				in situations where the device connected to the
@@ -165,6 +171,10 @@
 					0 = Allow RPM to utilize LDO bypass mode
 						if possible
 					1 = Disallow LDO bypass mode
+- qcom,init-voltage-floor-corner:  Minimum performance corner to use if any
+				processor in the system is awake.  This property
+				supports the same values as
+				qcom,init-voltage-corner.
 
 All properties specified within the core regulator framework can also be used in
 second level nodes.  These bindings can be found in:
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
new file mode 100644
index 0000000..c012eec
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
@@ -0,0 +1,32 @@
+Qualcomm SPM Regulators
+
+spm-regulator is a regulator device which supports PMIC processor supply
+regulators via the SPM module.
+
+Required properties:
+- compatible:      Must be "qcom,spm-regulator"
+- reg:             Specifies the SPMI address and size for this regulator device
+- regulator-name:  A string used as a descriptive name for the regulator
+
+Required structure:
+- A qcom,spm-regulator node must be a child of an SPMI node that has specified
+	the spmi-slave-container property
+
+All properties specified within the core regulator framework can also be used.
+These bindings can be found in regulator.txt.
+
+Example:
+	qcom,spmi@fc4c0000 {
+
+		qcom,pm8226@1 {
+			spmi-slave-container;
+
+			spm-regulator@1700 {
+				compatible = "qcom,spm-regulator";
+				regulator-name = "8226_s2";
+				reg = <0x1700 0x100>;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1275000>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
new file mode 100644
index 0000000..34c344a
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -0,0 +1,27 @@
+QPNP-MISC
+
+QPNP-MISC provides a way to read the PMIC part number and revision.
+
+Required properties:
+- compatible : should be "qcom,qpnp-misc"
+- reg : offset and length of the PMIC peripheral register map.
+
+Example:
+	qcom,spmi@fc4c0000 {
+		#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,misc@900 {
+				compatible = "qcom,qpnp-misc";
+				reg = <0x900 0x100>;
+			};
+		}
+	};
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index d5937cf..87281f7 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -12,6 +12,8 @@
 		      Required "interrupt-names" are "hc_irq" and "pwr_irq".
   - <supply-name>-supply: phandle to the regulator device tree node
 			  Required "supply-name" are "vdd" and "vdd-io".
+  - qcom,clk-rates: this is an array that specifies supported SDHC clock
+		    frequencies for a slot, Units - Hz.
 
 Required alias:
 - The slot number is specified via an alias with the following format
@@ -112,6 +114,7 @@
                 qcom,bus-width = <4>;
 		qcom,nonremovable;
 		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
 
 		gpios = <&msmgpio 40 0>, /* CLK */
 			<&msmgpio 39 0>, /* CMD */
@@ -120,7 +123,6 @@
 			<&msmgpio 36 0>, /* DATA2 */
 			<&msmgpio 35 0>; /* DATA3 */
 		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
-		qcom,cpu-dma-latency-us = <200>;
 	};
 
 	sdhc_2: qcom,sdhc@f98a4900 {
@@ -143,6 +145,7 @@
 		vdd-io-supply = <&pm8941_l13>;
 
                 qcom,bus-width = <4>;
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
 
 		qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
 		qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
diff --git a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
index 7b9feae..6c3e98e 100644
--- a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
+++ b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
@@ -2,15 +2,15 @@
 
 Required properties:
     - compatible: Can be "qca,ar6004-sdio" for SDIO device and
-    "qca,ar6004-hsic" for HSIC devcie.
+    "qca,ar6004-hsic" for HSIC device. For AR6003, "qca,ar6003-sdio" can be
+    used.
     - qca,chip-pwd-l-gpios: specify GPIO for CHIP_PWD_L.
 
 Optional Properties:
     - cell-index: WLAN Hardware index.
     - qca,pm-enable-gpios: Specify this GPIO if internal PMU needs to be used.
-    - qca,ar6004-vbatt-supply: Specify this if VBATT is provided through a
-    regulator.
-    - qca,ar6004-vdd-io-supply: Specify this if VDD-IO is provided through a
+    - qca,vbatt-supply: Specify this if VBATT is provided through a regulator.
+    - qca,vdd-io-supply: Specify this if VDD-IO is provided through a
     regulator.
 
 Example:
@@ -20,5 +20,5 @@
 		compatible = "qca,ar6004-sdio";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
-		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+		qca,vdd-io-supply = <&pm8019_l11>;
 	};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 320c3e4a..d174157 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -22,6 +22,11 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		pm8941_misc: qcom,misc@900 {
+			compatible = "qcom,qpnp-misc";
+			reg = <0x900 0x100>;
+		};
+
 		qcom,revid@100 {
 			compatible = "qcom,qpnp-revid";
 			reg = <0x100 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 800cd8f..c303061 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -89,6 +89,28 @@
 	};
 
 	sound {
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"AMIC1", "MIC BIAS1 Internal1",
+			"MIC BIAS1 Internal1", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic",
+			"DMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic1",
+			"DMIC2", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic2",
+			"DMIC3", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic3",
+			"DMIC4", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic4";
+
 		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
 		qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
 	};
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 3d1fe19..a18bad3 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -89,6 +89,20 @@
 	};
 
 	sound {
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS1 External",
+			"MIC BIAS1 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic";
+
 		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
 		qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
 	};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 4fa37d6..e137ee2 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -89,6 +89,20 @@
 	};
 
 	sound {
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS1 External",
+			"MIC BIAS1 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic";
+
 		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
 		qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
 	};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index c39d987..448a5be 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,18 +10,16 @@
  * GNU General Public License for more details.
  */
 
-/* QPNP controlled regulators: */
+/* SPM controlled regulators: */
 
 &spmi_bus {
 	qcom,pm8226@1 {
-		pm8226_s2: regulator@1700 {
-			status = "okay";
+		pm8226_s2: spm-regulator@1700 {
+			compatible = "qcom,spm-regulator";
 			regulator-name = "8226_s2";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
-			regulator-min-microvolt = <1050000>;
-			regulator-max-microvolt = <1150000>;
-			regulator-always-on;
+			reg = <0x1700 0x100>;
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <1275000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index ae2a135..5f51520 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -227,29 +227,6 @@
 	sound {
 		compatible = "qcom,msm8226-audio-tapan";
 		qcom,model = "msm8226-tapan-snd-card";
-
-		qcom,audio-routing =
-			"RX_BIAS", "MCLK",
-			"LDO_H", "MCLK",
-			"SPK_OUT", "MCLK",
-			"SPK_OUT", "EXT_VDD_SPKR",
-			"AMIC1", "MIC BIAS1 Internal1",
-			"MIC BIAS1 Internal1", "Handset Mic",
-			"AMIC2", "MIC BIAS2 External",
-			"MIC BIAS2 External", "Headset Mic",
-			"AMIC3", "MIC BIAS2 External",
-			"MIC BIAS2 External", "ANCRight Headset Mic",
-			"AMIC4", "MIC BIAS2 External",
-			"MIC BIAS2 External", "ANCLeft Headset Mic",
-			"DMIC1", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Digital Mic1",
-			"DMIC2", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Digital Mic2",
-			"DMIC3", "MIC BIAS3 External",
-			"MIC BIAS3 External", "Digital Mic3",
-			"DMIC4", "MIC BIAS3 External",
-			"MIC BIAS3 External", "Digital Mic4";
-
 		qcom,tapan-mclk-clk-freq = <9600000>;
 	};
 
@@ -402,7 +379,35 @@
 	qcom,msm-pcm-hostless {
 		compatible = "qcom,msm-pcm-hostless";
 	};
+	qcom,pronto@fb21b000 {
+		compatible = "qcom,pil-pronto";
+		reg = <0xfb21b000 0x3000>,
+		      <0xfc401700 0x4>,
+		      <0xfd485300 0xc>;
+		reg-names = "pmu_base", "clk_base", "halt_base";
+		interrupts = <0 149 1>;
+		vdd_pronto_pll-supply = <&pm8226_l12>;
 
+		qcom,firmware-name = "wcnss";
+	};
+	qcom,wcnss-wlan@fb000000 {
+		compatible = "qcom,wcnss_wlan";
+		reg = <0xfb000000 0x280000>;
+		reg-names = "wcnss_mmio";
+		interrupts = <0 145 0 0 146 0>;
+		interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+		qcom,pronto-vddmx-supply = <&pm8226_l3>;
+		qcom,pronto-vddcx-supply = <&pm8226_s1>;
+		qcom,pronto-vddpx-supply = <&pm8226_l6>;
+		qcom,iris-vddxo-supply = <&pm8226_l10>;
+		qcom,iris-vddrfa-supply = <&pm8226_l24>;
+		qcom,iris-vddpa-supply = <&pm8226_l16>;
+		qcom,iris-vdddig-supply = <&pm8226_l24>;
+
+		gpios = <&msmgpio 40 0>, <&msmgpio 41 0>, <&msmgpio 42 0>, <&msmgpio 43 0>, <&msmgpio 44 0>;
+		qcom,has_pronto_hw;
+	};
 	qcom,wdt@f9017000 {
 		compatible = "qcom,msm-watchdog";
 		reg = <0xf9017000 0x1000>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
new file mode 100644
index 0000000..390c02a
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8610 CDP";
+	compatible = "qcom,msm8610-cdp", "qcom,msm8610";
+	qcom,msm-id = <147 1 0>;
+
+	serial@f991f000 {
+		status = "ok";
+	};
+};
+
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
new file mode 100644
index 0000000..70ac0e8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8610 MTP";
+	compatible = "qcom,msm8610-mtp", "qcom,msm8610";
+	qcom,msm-id = <147 8 0>;
+
+	serial@f991f000 {
+		status = "ok";
+	};
+};
+
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 5eff79c..b125138 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -93,6 +93,15 @@
 			qcom,use-voltage-corner;
 			compatible = "qcom,rpm-regulator-smd";
 		};
+		pm8841_s2_floor_corner: regulator-s2-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8841_s2_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
 	};
 
 	rpm-regulator-smpb3 {
@@ -121,6 +130,15 @@
 			regulator-max-microvolt = <7>;
 			qcom,init-voltage-corner = <3>; /* SVS SOC */
 		};
+		pm8841_s4_floor_corner: regulator-s4-floor-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8841_s4_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
 	};
 
 	rpm-regulator-smpa1 {
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 2cfb192..24b68b5 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -28,11 +28,12 @@
 		qcom,saw2-spm-dly= <0x3C102800>;
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
-		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
-			30 06 26 30 0F];
-		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
-			E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+				0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
 	};
 
 	qcom,spm@f9099000 {
@@ -50,11 +51,12 @@
 		qcom,saw2-spm-dly= <0x3C102800>;
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
-		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
-			30 06 26 30 0F];
-		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+				0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
 	};
 
 	qcom,spm@f90a9000 {
@@ -72,11 +74,12 @@
 		qcom,saw2-spm-dly= <0x3C102800>;
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
-		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
-			30 06 26 30 0F];
-		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+				0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
 	};
 
 	qcom,spm@f90b9000 {
@@ -94,11 +97,12 @@
 		qcom,saw2-spm-dly= <0x3C102800>;
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
-		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
-			30 06 26 30 0F];
-		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+				0b 00 42 1b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+				10 0b 30 06 26 30 0f];
 	};
 
 	qcom,spm@f9012000 {
@@ -122,10 +126,9 @@
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
 		qcom,saw2-spm-cmd-ret = [1f 00 20 03 22 00 0f];
-		qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 42 07 78 80 44 22 50
-				3b 60 02 32 50 0f];
-		qcom,saw2-spm-cmd-pc = [00 10 32 60 70 80 b0 11 42 07 01 b0 78
-				80 12 44 50 3b 60 02 32 50 0f];
+		qcom,saw2-spm-cmd-gdhs = [00 20 32 42 07 44 22 50 02 32 50 0f];
+		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
+				50 02 32 50 0f];
 	};
 
 	qcom,lpm-resources {
@@ -423,7 +426,6 @@
 		reg = <0xfe805664 0x40>;
 		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
-		qcom,saw-turns-off-pll;
 
 		qcom,cpu-sleep-status@f9088008{
 			compatible = "qcom,cpu-sleep-status";
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 3eed989..c7d35a5 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -351,6 +351,7 @@
 		reg-names = "hc_mem", "core_mem";
 		interrupts = <0 123 0>, <0 138 0>;
 		interrupt-names = "hc_irq", "pwr_irq";
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
 		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
 		qcom,cpu-dma-latency-us = <200>;
 
@@ -377,6 +378,7 @@
 		interrupts = <0 125 0>, <0 221 0>;
 		interrupt-names = "hc_irq", "pwr_irq";
 
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
 		qcom,bus-width = <4>;
 		qcom,cpu-dma-latency-us = <200>;
 
@@ -410,6 +412,7 @@
 			<&msmgpio 35 0>; /* DATA3 */
 		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
 
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
 		qcom,bus-width = <4>;
 		qcom,cpu-dma-latency-us = <200>;
 
@@ -443,6 +446,7 @@
 			<&msmgpio 92 0>; /* DATA3 */
 		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
 
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
 		qcom,bus-width = <4>;
 		qcom,cpu-dma-latency-us = <200>;
 
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 9172029..b06419d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -140,31 +140,27 @@
 
 		qcom,pipe0 {
 			label = "hsusb-ipa-out-0";
-			qcom,usb-bam-mem-type = <0>;
+			qcom,usb-bam-mem-type = <2>;
 			qcom,bam-type = <1>;
 			qcom,dir = <0>;
 			qcom,pipe-num = <0>;
 			qcom,peer-bam = <2>;
 			qcom,src-bam-physical-address = <0xf9a44000>;
 			qcom,src-bam-pipe-index = <1>;
-			qcom,data-fifo-offset = <0x2200>;
-			qcom,data-fifo-size = <0x1e00>;
-			qcom,descriptor-fifo-offset = <0x2100>;
-			qcom,descriptor-fifo-size = <0x100>;
+			qcom,data-fifo-size = <0x8000>;
+			qcom,descriptor-fifo-size = <0x2000>;
 		};
 		qcom,pipe1 {
 			label = "hsusb-ipa-in-0";
-			qcom,usb-bam-mem-type = <0>;
+			qcom,usb-bam-mem-type = <2>;
 			qcom,bam-type = <1>;
 			qcom,dir = <1>;
 			qcom,pipe-num = <0>;
 			qcom,peer-bam = <2>;
 			qcom,dst-bam-physical-address = <0xf9a44000>;
 			qcom,dst-bam-pipe-index = <0>;
-			qcom,data-fifo-offset = <0x300>;
-			qcom,data-fifo-size = <0x1e00>;
-			qcom,descriptor-fifo-offset = <0>;
-			qcom,descriptor-fifo-size = <0x300>;
+			qcom,data-fifo-size = <0x8000>;
+			qcom,descriptor-fifo-size = <0x2000>;
 		};
 		qcom,pipe2 {
 			label = "hsusb-qdss-in-0";
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 663e937..2f5f7f0 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -292,6 +292,7 @@
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
 CONFIG_QPNP_REVID=y
+CONFIG_QPNP_MISC=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 2de81d4d1..4aebfdb 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -297,6 +297,7 @@
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
 CONFIG_QPNP_REVID=y
+CONFIG_QPNP_MISC=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index f7d993f..18b1c5a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -428,6 +428,7 @@
 	select ARM_HAS_SG_CHAIN
 	select REGULATOR
 	select MSM_RPM_REGULATOR_SMD
+	select MSM_SPM_REGULATOR
 
 config ARCH_MSM8226
 	bool "MSM8226"
@@ -463,6 +464,7 @@
 	select ARM_HAS_SG_CHAIN
 	select REGULATOR
 	select MSM_RPM_REGULATOR_SMD
+	select MSM_SPM_REGULATOR
 	select MSM_JTAG_MM if CORESIGHT_ETM
 endmenu
 
@@ -1823,7 +1825,6 @@
 config MSM_HW3D
 	tristate "MSM Hardware 3D Register Driver"
 	depends on ANDROID_PMEM
-	default y
 	help
 	  Provides access to registers needed by the userspace OpenGL|ES
 	  library.
@@ -2062,6 +2063,16 @@
 	  be used on systems which contain an RPM which communicates with the
 	  application processor over SMD.
 
+config MSM_SPM_REGULATOR
+	bool "SPM regulator driver"
+	depends on REGULATOR && SPMI && OF_SPMI
+	help
+	  Enable support for the SPM regulator driver which is used for
+	  setting voltages of processor supply regulators via the SPM module
+	  found inside of the MSM chips.  The SPM regulator driver can be used
+	  on MSM systems where the APSS processor cores are supplied by their
+	  own PMIC regulator.
+
 config MSM_SMCMOD
 	tristate "Secure Monitor Call (SMC) Module"
 	default n
@@ -2895,4 +2906,9 @@
 	 display init, total boot time.
 	 This figures are reported in mpm sleep clock cycles and have a
 	 resolution of 31 bits as 1 bit is used as an overflow check.
+
+config MSM_XPU_ERR_FATAL
+	bool "Configure XPU violations as fatal errors"
+	help
+	 Select if XPU violations have to be configured as fatal errors.
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 161ee3d..d3acbc7 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -79,6 +79,7 @@
 obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_gpio.o
 obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_gpio_test.o smp2p_spinlock_test.o
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
+obj-$(CONFIG_MSM_XPU_ERR_FATAL) += scm-xpu.o
 obj-$(CONFIG_MSM_SECURE_IO) += scm-io.o
 obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
 obj-$(CONFIG_MSM_PIL) += scm-pas.o
@@ -209,6 +210,7 @@
 endif
 
 obj-$(CONFIG_MSM_RPM_REGULATOR_SMD) += rpm-regulator-smd.o
+obj-$(CONFIG_MSM_SPM_REGULATOR) += spm-regulator.o
 
 ifdef CONFIG_MSM_SUBSYSTEM_RESTART
 	obj-y += subsystem_notif.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index fcbd74d..73ea435 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -57,7 +57,7 @@
 	{ 1,  300000, PLL0,    4, 2,   1150000,   1150000, 4 },
 	{ 1,  384000, ACPUPLL, 5, 0,   1150000,   1150000, 4 },
 	{ 1,  600000, PLL0,    4, 0,   1150000,   1150000, 6 },
-	{ 1,  787200, ACPUPLL, 5, 0,   1150000,   1150000, 6 },
+	{ 1,  787200, ACPUPLL, 5, 0,   1150000,   1150000, 7 },
 	{ 0,  998400, ACPUPLL, 5, 0,   1150000,   1150000, 7 },
 	{ 0, 1190400, ACPUPLL, 5, 0,   1150000,   1150000, 7 },
 	{ 0 }
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 0654a0d..b3364b0 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -3531,19 +3531,6 @@
 }
 #endif
 
-static struct android_pmem_platform_data android_pmem_pdata = {
-	.name = "pmem",
-	.allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_device = {
-	.name = "android_pmem",
-	.id = 0,
-	.dev = { .platform_data = &android_pmem_pdata },
-};
-
 #ifndef CONFIG_SPI_QSD
 static int lcdc_gpio_array_num[] = {
 				45, /* spi_clk */
@@ -4021,32 +4008,6 @@
 	.id     = -1,
 };
 
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
-       .name = "pmem_adsp",
-       .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-       .cached = 0,
-	.memory_type = MEMTYPE_EBI0,
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
-       .name = "pmem_audio",
-       .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-       .cached = 0,
-	.memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_adsp_device = {
-       .name = "android_pmem",
-       .id = 2,
-       .dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static struct platform_device android_pmem_audio_device = {
-       .name = "android_pmem",
-       .id = 4,
-       .dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
 		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -5395,7 +5356,6 @@
 #ifdef CONFIG_I2C_SSBI
 	&msm_device_ssbi7,
 #endif
-	&android_pmem_device,
 	&msm_fb_device,
 #ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
 	&msm_v4l2_video_overlay_device,
@@ -5407,8 +5367,6 @@
 	&msm_rotator_device,
 #endif
 	&lcdc_sharp_panel_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
 	&msm_device_i2c,
 	&msm_device_i2c_2,
 	&msm_device_uart_dm1,
@@ -7234,39 +7192,6 @@
 #endif
 }
 
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-
-	android_pmem_adsp_pdata.size = size;
-	android_pmem_audio_pdata.size = pmem_audio_size;
-	android_pmem_pdata.size = pmem_sf_size;
-#endif
-#endif
-}
-
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
-	msm7x30_reserve_table[p->memory_type].size += p->size;
-}
-#endif
-#endif
-
-static void __init reserve_pmem_memory(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	reserve_memory_for(&android_pmem_adsp_pdata);
-	reserve_memory_for(&android_pmem_audio_pdata);
-	reserve_memory_for(&android_pmem_pdata);
-	msm7x30_reserve_table[MEMTYPE_EBI0].size += pmem_kernel_ebi0_size;
-#endif
-#endif
-}
-
 static void __init reserve_mdp_memory(void)
 {
 	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
@@ -7294,8 +7219,6 @@
 static void __init msm7x30_calculate_reserve_sizes(void)
 {
 	fix_sizes();
-	size_pmem_devices();
-	reserve_pmem_memory();
 	reserve_mdp_memory();
 	size_ion_devices();
 	reserve_ion_memory();
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 9648320..cd06bb8 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -344,6 +344,7 @@
 
 static struct pll_vote_clk gpll0_clk_src = {
 	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+	.en_mask = BIT(0),
 	.status_reg = (void __iomem *)GPLL0_STATUS_REG,
 	.status_mask = BIT(17),
 	.soft_vote = &soft_vote_gpll0,
@@ -360,6 +361,7 @@
 
 static struct pll_vote_clk gpll0_activeonly_clk_src = {
 	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+	.en_mask = BIT(0),
 	.status_reg = (void __iomem *)GPLL0_STATUS_REG,
 	.status_mask = BIT(17),
 	.soft_vote = &soft_vote_gpll0,
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
index 2fdd99c..f460a4e 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
@@ -28,12 +28,6 @@
 #define MPQ8092_QGIC_DIST_PHYS	0xF9000000
 #define MPQ8092_QGIC_DIST_SIZE	SZ_4K
 
-#define MPQ8092_QGIC_CPU_PHYS	0xF9002000
-#define MPQ8092_QGIC_CPU_SIZE	SZ_4K
-
-#define MPQ8092_APCS_GCC_PHYS	0xF9011000
-#define MPQ8092_APCS_GCC_SIZE	SZ_4K
-
 #define MPQ8092_TLMM_PHYS	0xFD510000
 #define MPQ8092_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
index 81b3c48..ac3e912 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -28,9 +28,6 @@
 #define MSM8226_QGIC_DIST_PHYS	0xF9000000
 #define MSM8226_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM8226_QGIC_CPU_PHYS	0xF9002000
-#define MSM8226_QGIC_CPU_SIZE	SZ_4K
-
 #define MSM8226_APCS_GCC_PHYS	0xF9011000
 #define MSM8226_APCS_GCC_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index 594b1cc..ec3c210 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -28,12 +28,6 @@
 #define MSM8974_QGIC_DIST_PHYS	0xF9000000
 #define MSM8974_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM8974_QGIC_CPU_PHYS	0xF9002000
-#define MSM8974_QGIC_CPU_SIZE	SZ_4K
-
-#define MSM8974_APCS_GCC_PHYS	0xF9011000
-#define MSM8974_APCS_GCC_SIZE	SZ_4K
-
 #define MSM8974_TLMM_PHYS	0xFD510000
 #define MSM8974_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 341bbe3..9a8bfc1 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -28,12 +28,6 @@
 #define MSM9625_QGIC_DIST_PHYS	0xF9000000
 #define MSM9625_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM9625_QGIC_CPU_PHYS	0xF9002000
-#define MSM9625_QGIC_CPU_SIZE	SZ_4K
-
-#define MSM9625_APCS_GCC_PHYS	0xF9011000
-#define MSM9625_APCS_GCC_SIZE	SZ_4K
-
 #define MSM9625_TMR_PHYS	0xF9021000
 #define MSM9625_TMR_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
index 8283622..0a33055 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
@@ -28,9 +28,6 @@
 #define MSMZINC_QGIC_DIST_PHYS	0xF9000000
 #define MSMZINC_QGIC_DIST_SIZE	SZ_4K
 
-#define MSMZINC_QGIC_CPU_PHYS	0xF9002000
-#define MSMZINC_QGIC_CPU_SIZE	SZ_4K
-
 #define MSMZINC_TLMM_PHYS	0xFD510000
 #define MSMZINC_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 9cf9517..d3706cd 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,15 +47,14 @@
 
 #define MSM8625_WARM_BOOT_PHYS  0x0FD00000
 
-
-#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
-	defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
-	defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM7X27) || \
-	defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
-	defined(CONFIG_ARCH_MSM8625) || defined(CONFIG_ARCH_MSM7X30) || \
-	defined(CONFIG_ARCH_MSM9625) || defined(CONFIG_ARCH_MPQ8092) || \
-	defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610) || \
-	defined(CONFIG_ARCH_MSMZINC)
+/* Legacy single-target iomap */
+#if defined(CONFIG_ARCH_QSD8X50)
+#include "msm_iomap-8x50.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "msm_iomap-8x60.h"
+#elif defined(CONFIG_ARCH_FSM9XXX)
+#include "msm_iomap-fsm9xxx.h"
+#else
 
 /* Unified iomap */
 
@@ -136,18 +135,6 @@
 #include "msm_iomap-8226.h"
 #include "msm_iomap-8610.h"
 
-#else
-/* Legacy single-target iomap */
-#if defined(CONFIG_ARCH_QSD8X50)
-#include "msm_iomap-8x50.h"
-#elif defined(CONFIG_ARCH_MSM8X60)
-#include "msm_iomap-8x60.h"
-#elif defined(CONFIG_ARCH_FSM9XXX)
-#include "msm_iomap-fsm9xxx.h"
-#else
-#error "Target compiled without IO map\n"
-#endif
-
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index ff1b3c5..45f2646 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -74,6 +74,10 @@
 	of_machine_is_compatible("qcom,msm8610-sim")
 #define machine_is_msm8610_rumi()		\
 	of_machine_is_compatible("qcom,msm8610-rumi")
+#define machine_is_msm8610_mtp()		\
+	of_machine_is_compatible("qcom,msm8610-mtp")
+#define machine_is_msm8610_cdp()		\
+	of_machine_is_compatible("qcom,msm8610-cdp")
 #define early_machine_is_msmzinc()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
 #define machine_is_msmzinc_sim()		\
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index c71a79a..19c7acd 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -301,8 +301,6 @@
 #ifdef CONFIG_ARCH_MSM8974
 static struct map_desc msm_8974_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM8974),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSM8974),
-	MSM_CHIP_DEVICE(APCS_GCC, MSM8974),
 	MSM_CHIP_DEVICE(TLMM, MSM8974),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
 	{
@@ -326,7 +324,6 @@
 #ifdef CONFIG_ARCH_MSMZINC
 static struct map_desc msm_zinc_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSMZINC),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSMZINC),
 	MSM_CHIP_DEVICE(TLMM, MSMZINC),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
@@ -488,9 +485,7 @@
 
 #ifdef CONFIG_ARCH_MSM9625
 static struct map_desc msm9625_io_desc[] __initdata = {
-	MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM9625),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSM9625),
 	MSM_CHIP_DEVICE(TLMM, MSM9625),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM9625),
 	MSM_CHIP_DEVICE(TMR, MSM9625),
@@ -515,8 +510,6 @@
 #ifdef CONFIG_ARCH_MPQ8092
 static struct map_desc mpq8092_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
-	MSM_CHIP_DEVICE(QGIC_CPU, MPQ8092),
-	MSM_CHIP_DEVICE(APCS_GCC, MPQ8092),
 	MSM_CHIP_DEVICE(TLMM, MPQ8092),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
@@ -538,7 +531,6 @@
 #ifdef CONFIG_ARCH_MSM8226
 static struct map_desc msm_8226_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM8226),
-	MSM_CHIP_DEVICE(QGIC_CPU, MSM8226),
 	MSM_CHIP_DEVICE(APCS_GCC, MSM8226),
 	MSM_CHIP_DEVICE(TLMM, MSM8226),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8226),
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index ea874bd..d81dbb4 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -34,6 +34,7 @@
 #include <mach/smem_log.h>
 #include <mach/subsystem_notif.h>
 #include <mach/msm_ipc_router.h>
+#include <mach/msm_ipc_logging.h>
 
 #include "ipc_router.h"
 #include "modem_notifier.h"
@@ -52,15 +53,21 @@
 module_param_named(debug_mask, msm_ipc_router_debug_mask,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
 
+static void *ipc_rtr_log_ctxt;
+#define IPC_RTR_LOG_PAGES 5
 #define DIAG(x...) pr_info("[RR] ERROR " x)
 
 #if defined(DEBUG)
 #define D(x...) do { \
+if (ipc_rtr_log_ctxt) \
+	ipc_log_string(ipc_rtr_log_ctxt, x); \
 if (msm_ipc_router_debug_mask & RTR_DBG) \
 	pr_info(x); \
 } while (0)
 
 #define RR(x...) do { \
+if (ipc_rtr_log_ctxt) \
+	ipc_log_string(ipc_rtr_log_ctxt, x); \
 if (msm_ipc_router_debug_mask & R2R_MSG) \
 	pr_info("[RR] "x); \
 } while (0)
@@ -1660,10 +1667,10 @@
 		}
 
 		hdr = (struct rr_header *)(head_skb->data);
-		RR("- ver=%d type=%d src=%d:%08x crx=%d siz=%d dst=%d:%08x\n",
-		   hdr->version, hdr->type, hdr->src_node_id, hdr->src_port_id,
-		   hdr->confirm_rx, hdr->size, hdr->dst_node_id,
-		   hdr->dst_port_id);
+		RAW("ver=%d type=%d src=%d:%08x crx=%d siz=%d dst=%d:%08x\n",
+		     hdr->version, hdr->type, hdr->src_node_id,
+		     hdr->src_port_id, hdr->confirm_rx, hdr->size,
+		     hdr->dst_node_id, hdr->dst_port_id);
 
 		if (hdr->version != IPC_ROUTER_VERSION) {
 			pr_err("version %d != %d\n",
@@ -2867,6 +2874,12 @@
 	struct msm_ipc_routing_table_entry *rt_entry;
 
 	msm_ipc_router_debug_mask |= SMEM_LOG;
+	ipc_rtr_log_ctxt = ipc_log_context_create(IPC_RTR_LOG_PAGES,
+						  "ipc_router");
+	if (!ipc_rtr_log_ctxt)
+		pr_err("%s: Unable to create IPC logging for IPC RTR",
+			__func__);
+
 	msm_ipc_router_workqueue =
 		create_singlethread_workqueue("msm_ipc_router");
 	if (!msm_ipc_router_workqueue)
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 5f11806..786dad8 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -191,6 +191,10 @@
 		BUG_ON(mr_candidate == NULL);
 		/* bump mt up against the top of the region */
 		mt->start = mr_candidate->base + mr_candidate->size - mt->size;
+		ret = memblock_reserve(mt->start, mt->size);
+		BUG_ON(ret);
+		ret = memblock_free(mt->start, mt->size);
+		BUG_ON(ret);
 		ret = memblock_remove(mt->start, mt->size);
 		BUG_ON(ret);
 	}
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 2ceb06d..599b24c 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -58,6 +58,7 @@
 #define RMB_PMI_CODE_LENGTH		0x18
 
 #define VDD_MSS_UV			1050000
+#define MAX_VDD_MSS_UV			1150000
 #define MAX_VDD_MX_UV			1150000
 
 #define PROXY_TIMEOUT_MS		10000
@@ -739,7 +740,7 @@
 	if (IS_ERR(q6->vreg_mx))
 		return PTR_ERR(q6->vreg_mx);
 
-	ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, VDD_MSS_UV);
+	ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, MAX_VDD_MSS_UV);
 	if (ret)
 		dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
 
diff --git a/arch/arm/mach-msm/qdsp5/adsp_driver.c b/arch/arm/mach-msm/qdsp5/adsp_driver.c
index d83a140..eb9c388 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_driver.c
@@ -25,7 +25,6 @@
 #include <linux/module.h>
 #include "adsp.h"
 #include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
 #include <mach/debug_mm.h>
 
 struct adsp_ion_info {
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index 4d03dca..62d6d58 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/android_pmem.h>
 
 #include <mach/qdsp5/qdsp5vdeccmdi.h>
 #include "adsp.h"
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index 7819395..608f544 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -16,7 +16,6 @@
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/uaccess.h>
@@ -110,7 +109,6 @@
 	audpp_cmd_cfg_object_params_eqalizer eq;
 	struct audrec_session_info session_info;
 	/*pmem info*/
-	int pmem_fd;
 	unsigned long paddr;
 	unsigned long kvaddr;
 	unsigned long pmem_len;
@@ -1136,7 +1134,6 @@
 {
 	int rc = 0;
 	unsigned long flags = 0;
-	struct msm_audio_pmem_info info;
 
 	MM_DBG("%s\n", __func__);
 
@@ -1156,23 +1153,6 @@
 			MM_ERR("AUDPP returned err =%d\n", rc);
 		spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
 		break;
-	case AUDIO_REGISTER_PMEM:
-		MM_DBG("AUDIO_REGISTER_PMEM\n");
-		if (copy_from_user(&info, (void *) arg, sizeof(info))) {
-			MM_ERR("Cannot copy from user\n");
-			return -EFAULT;
-		}
-		rc = get_pmem_file(info.fd, &acdb_data.paddr,
-					&acdb_data.kvaddr,
-					&acdb_data.pmem_len,
-					&acdb_data.file);
-		if (rc == 0)
-			acdb_data.pmem_fd = info.fd;
-		break;
-	case AUDIO_DEREGISTER_PMEM:
-		if (acdb_data.pmem_fd)
-			put_pmem_file(acdb_data.file);
-		break;
 	case AUDIO_SET_ACDB_BLK:
 		MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
 		rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
index 7249bb1..ad74ca3 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
 #include <linux/export.h>
 #include "adsp.h"
 #include <mach/debug_mm.h>
@@ -87,71 +86,6 @@
 	res;							\
 })
 
-static int adsp_pmem_check(struct msm_adsp_module *module,
-		void *vaddr, unsigned long len)
-{
-	struct adsp_pmem_region *region_elt;
-	struct hlist_node *node;
-	struct adsp_pmem_region t = { .vaddr = vaddr, .len = len };
-
-	hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
-		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
-		    OVERLAPS(region_elt, &t)) {
-			MM_ERR("module %s:"
-				" region (vaddr %p len %ld)"
-				" clashes with registered region"
-				" (vaddr %p paddr %p len %ld)\n",
-				module->name,
-				vaddr, len,
-				region_elt->vaddr,
-				(void *)region_elt->paddr,
-				region_elt->len);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int adsp_pmem_add(struct msm_adsp_module *module,
-			 struct adsp_pmem_info *info)
-{
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct adsp_pmem_region *region;
-	int rc = -EINVAL;
-
-	mutex_lock(&module->pmem_regions_lock);
-	region = kmalloc(sizeof(*region), GFP_KERNEL);
-	if (!region) {
-		rc = -ENOMEM;
-		goto end;
-	}
-	INIT_HLIST_NODE(&region->list);
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		goto end;
-	}
-
-	rc = adsp_pmem_check(module, info->vaddr, len);
-	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		goto end;
-	}
-
-	region->vaddr = info->vaddr;
-	region->paddr = paddr;
-	region->kvaddr = kvaddr;
-	region->len = len;
-	region->file = file;
-
-	hlist_add_head(&region->list, &module->pmem_regions);
-end:
-	mutex_unlock(&module->pmem_regions_lock);
-	return rc;
-}
-
 static int adsp_pmem_lookup_vaddr(struct msm_adsp_module *module, void **addr,
 		     unsigned long len, struct adsp_pmem_region **region)
 {
@@ -417,24 +351,6 @@
 	return rc;
 }
 
-static int adsp_pmem_del(struct msm_adsp_module *module)
-{
-	struct hlist_node *node, *tmp;
-	struct adsp_pmem_region *region;
-
-	mutex_lock(&module->pmem_regions_lock);
-	hlist_for_each_safe(node, tmp, &module->pmem_regions) {
-		region = hlist_entry(node, struct adsp_pmem_region, list);
-		hlist_del(node);
-		put_pmem_file(region->file);
-		kfree(region);
-	}
-	mutex_unlock(&module->pmem_regions_lock);
-	BUG_ON(!hlist_empty(&module->pmem_regions));
-
-	return 0;
-}
-
 static long adsp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct adsp_device *adev = filp->private_data;
@@ -466,21 +382,11 @@
 		return adsp_set_clkrate(adev->module, clk_rate);
 	}
 
-	case ADSP_IOCTL_REGISTER_PMEM: {
-		struct adsp_pmem_info info;
-		if (copy_from_user(&info, (void *) arg, sizeof(info)))
-			return -EFAULT;
-		return adsp_pmem_add(adev->module, &info);
-	}
-
 	case ADSP_IOCTL_ABORT_EVENT_READ:
 		adev->abort = 1;
 		wake_up(&adev->event_wait);
 		break;
 
-	case ADSP_IOCTL_UNREGISTER_PMEM:
-		return adsp_pmem_del(adev->module);
-
 	default:
 		break;
 	}
@@ -498,8 +404,6 @@
 	/* clear module before putting it to avoid race with open() */
 	adev->module = NULL;
 
-	rc = adsp_pmem_del(module);
-
 	msm_adsp_put(module);
 	return rc;
 }
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac.c b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
index 883da2b..fbce5d6 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
@@ -30,7 +30,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/msm_audio_aac.h>
 #include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
index a878e12..cf1f58d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
@@ -26,7 +26,6 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/msm_audio_aac.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <mach/msm_memtypes.h>
 
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
index 5d7cfd7..85378be 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
@@ -16,7 +16,6 @@
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/uaccess.h>
@@ -1287,7 +1286,6 @@
 {
 	int rc = 0;
 	unsigned long flags = 0;
-	struct msm_audio_pmem_info info;
 
 	MM_DBG("%s\n", __func__);
 
@@ -1308,23 +1306,6 @@
 			MM_ERR("AUDPP returned err =%d\n", rc);
 		spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
 		break;
-	case AUDIO_REGISTER_PMEM:
-		MM_DBG("AUDIO_REGISTER_PMEM\n");
-		if (copy_from_user(&info, (void *) arg, sizeof(info))) {
-			MM_ERR("Cannot copy from user\n");
-			return -EFAULT;
-		}
-		rc = get_pmem_file(info.fd, &acdb_data.paddr,
-					&acdb_data.kvaddr,
-					&acdb_data.pmem_len,
-					&acdb_data.file);
-		if (rc == 0)
-			acdb_data.pmem_fd = info.fd;
-		break;
-	case AUDIO_DEREGISTER_PMEM:
-		if (acdb_data.pmem_fd)
-			put_pmem_file(acdb_data.file);
-		break;
 	case AUDIO_SET_ACDB_BLK:
 		MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
 		rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
index 7cc3e29..632aa0d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
@@ -34,7 +34,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
index c8b4171..bd4f6e1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
@@ -37,7 +37,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
index 66d0a9e..e5706c7 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
@@ -37,7 +37,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
index 2d9327e..ed946f9 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
@@ -32,7 +32,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_fm.c b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
index cffa7e7..27548ac 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_fm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
@@ -29,7 +29,6 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_audio.h>
 #include <asm/atomic.h>
 #include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
index 0390edf..bda2e4d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
@@ -1095,103 +1094,6 @@
 	return rc;
 }
 
-static int audmp3_pmem_check(struct audio *audio,
-		void *vaddr, unsigned long len)
-{
-	struct audmp3_pmem_region *region_elt;
-	struct audmp3_pmem_region t = { .vaddr = vaddr, .len = len };
-
-	list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
-		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
-		    OVERLAPS(region_elt, &t)) {
-			MM_ERR("region (vaddr %p len %ld)"
-				" clashes with registered region"
-				" (vaddr %p paddr %p len %ld)\n",
-				vaddr, len,
-				region_elt->vaddr,
-				(void *)region_elt->paddr,
-				region_elt->len);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int audmp3_pmem_add(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct audmp3_pmem_region *region;
-	int rc = -EINVAL;
-
-	MM_DBG("\n"); /* Macro prints the file name and function */
-	region = kmalloc(sizeof(*region), GFP_KERNEL);
-
-	if (!region) {
-		rc = -ENOMEM;
-		goto end;
-	}
-
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		goto end;
-	}
-
-	rc = audmp3_pmem_check(audio, info->vaddr, len);
-	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		goto end;
-	}
-
-	region->vaddr = info->vaddr;
-	region->fd = info->fd;
-	region->paddr = paddr;
-	region->kvaddr = kvaddr;
-	region->len = len;
-	region->file = file;
-	region->ref_cnt = 0;
-	MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
-			region->vaddr, region->len);
-	list_add_tail(&region->list, &audio->pmem_region_queue);
-end:
-	return rc;
-}
-
-static int audmp3_pmem_remove(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	struct audmp3_pmem_region *region;
-	struct list_head *ptr, *next;
-	int rc = -EINVAL;
-
-	MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audmp3_pmem_region, list);
-
-		if ((region->fd == info->fd) &&
-		    (region->vaddr == info->vaddr)) {
-			if (region->ref_cnt) {
-				MM_DBG("region %p in use ref_cnt %d\n",
-						region, region->ref_cnt);
-				break;
-			}
-			MM_DBG("remove region fd %d vaddr %p \n",
-					info->fd, info->vaddr);
-			list_del(&region->list);
-			put_pmem_file(region->file);
-			kfree(region);
-			rc = 0;
-			break;
-		}
-	}
-
-	return rc;
-}
-
 static int audmp3_pmem_lookup_vaddr(struct audio *audio, void *addr,
 		     unsigned long len, struct audmp3_pmem_region **region)
 {
@@ -1688,25 +1590,6 @@
 		break;
 	}
 
-	case AUDIO_REGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_REGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audmp3_pmem_add(audio, &info);
-			break;
-		}
-
-	case AUDIO_DEREGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_DEREGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audmp3_pmem_remove(audio, &info);
-			break;
-		}
 	case AUDIO_ASYNC_WRITE:
 		if (audio->drv_status & ADRV_STATUS_FSYNC)
 			rc = -EBUSY;
@@ -2105,21 +1988,6 @@
 	return rc;
 }
 
-static void audmp3_reset_pmem_region(struct audio *audio)
-{
-	struct audmp3_pmem_region *region;
-	struct list_head *ptr, *next;
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audmp3_pmem_region, list);
-		list_del(&region->list);
-		put_pmem_file(region->file);
-		kfree(region);
-	}
-
-	return;
-}
-
 static int audio_release(struct inode *inode, struct file *file)
 {
 	struct audio *audio = file->private_data;
@@ -2130,7 +1998,6 @@
 	audio_disable(audio);
 	audio->drv_ops.out_flush(audio);
 	audio->drv_ops.in_flush(audio);
-	audmp3_reset_pmem_region(audio);
 
 	msm_adsp_put(audio->audplay);
 	audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_out.c b/arch/arm/mach-msm/qdsp5v2/audio_out.c
index e5c59ba..712c9f3 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_out.c
@@ -30,7 +30,6 @@
 #include <linux/wakelock.h>
 #include <linux/memory_alloc.h>
 #include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
 #include <linux/pm_qos.h>
 
 #include <mach/msm_adsp.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
index ea8fc83..cbd2913 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
@@ -30,7 +30,6 @@
 #include <linux/delay.h>
 #include <linux/earlysuspend.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/memory_alloc.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
@@ -743,99 +742,6 @@
 	return rc;
 }
 
-static int audpcm_pmem_check(struct audio *audio,
-		void *vaddr, unsigned long len)
-{
-	struct audpcm_pmem_region *region_elt;
-	struct audpcm_pmem_region t = { .vaddr = vaddr, .len = len };
-
-	list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
-		if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
-		    OVERLAPS(region_elt, &t)) {
-			MM_ERR("region (vaddr %p len %ld)"
-				" clashes with registered region"
-				" (vaddr %p paddr %p len %ld)\n",
-				vaddr, len,
-				region_elt->vaddr,
-				(void *)region_elt->paddr,
-				region_elt->len);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int audpcm_pmem_add(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	unsigned long paddr, kvaddr, len;
-	struct file *file;
-	struct audpcm_pmem_region *region;
-	int rc = -EINVAL;
-
-	MM_DBG("\n"); /* Macro prints the file name and function */
-	region = kmalloc(sizeof(*region), GFP_KERNEL);
-	if (!region)
-		return -ENOMEM;
-
-	if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
-		kfree(region);
-		return -EINVAL;
-	}
-
-	rc = audpcm_pmem_check(audio, info->vaddr, len);
-	if (rc < 0) {
-		put_pmem_file(file);
-		kfree(region);
-		return rc;
-	}
-
-	region->vaddr = info->vaddr;
-	region->fd = info->fd;
-	region->paddr = paddr;
-	region->kvaddr = kvaddr;
-	region->len = len;
-	region->file = file;
-	region->ref_cnt = 0;
-	MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
-			region->vaddr, region->len);
-	list_add_tail(&region->list, &audio->pmem_region_queue);
-	return rc;
-}
-
-static int audpcm_pmem_remove(struct audio *audio,
-	struct msm_audio_pmem_info *info)
-{
-	struct audpcm_pmem_region *region;
-	struct list_head *ptr, *next;
-	int rc = -EINVAL;
-
-	MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audpcm_pmem_region, list);
-
-		if ((region->fd == info->fd) &&
-		    (region->vaddr == info->vaddr)) {
-			if (region->ref_cnt) {
-				MM_DBG("region %p in use ref_cnt %d\n", region,
-						region->ref_cnt);
-				break;
-			}
-			MM_DBG("remove region fd %d vaddr %p \n", info->fd,
-					info->vaddr);
-			list_del(&region->list);
-			put_pmem_file(region->file);
-			kfree(region);
-			rc = 0;
-			break;
-		}
-	}
-
-	return rc;
-}
-
 static int audpcm_pmem_lookup_vaddr(struct audio *audio, void *addr,
 		     unsigned long len, struct audpcm_pmem_region **region)
 {
@@ -1124,26 +1030,6 @@
 		rc = audpp_pause(audio->dec_id, (int) arg);
 		break;
 
-	case AUDIO_REGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_REGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audpcm_pmem_add(audio, &info);
-			break;
-		}
-
-	case AUDIO_DEREGISTER_PMEM: {
-			struct msm_audio_pmem_info info;
-			MM_DBG("AUDIO_DEREGISTER_PMEM\n");
-			if (copy_from_user(&info, (void *) arg, sizeof(info)))
-				rc = -EFAULT;
-			else
-				rc = audpcm_pmem_remove(audio, &info);
-			break;
-		}
-
 	case AUDIO_ASYNC_WRITE:
 		if (audio->drv_status & ADRV_STATUS_FSYNC)
 			rc = -EBUSY;
@@ -1344,21 +1230,6 @@
 	return rc;
 }
 
-static void audpcm_reset_pmem_region(struct audio *audio)
-{
-	struct audpcm_pmem_region *region;
-	struct list_head *ptr, *next;
-
-	list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
-		region = list_entry(ptr, struct audpcm_pmem_region, list);
-		list_del(&region->list);
-		put_pmem_file(region->file);
-		kfree(region);
-	}
-
-	return;
-}
-
 static int audio_release(struct inode *inode, struct file *file)
 {
 	struct audio *audio = file->private_data;
@@ -1369,7 +1240,6 @@
 	auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->dec_id);
 	audio_disable(audio);
 	audio->drv_ops.out_flush(audio);
-	audpcm_reset_pmem_region(audio);
 
 	msm_adsp_put(audio->audplay);
 	audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
index bb360be..33ca7a1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
@@ -33,7 +33,6 @@
 #include <linux/debugfs.h>
 #include <linux/earlysuspend.h>
 #include <linux/list.h>
-#include <linux/android_pmem.h>
 #include <linux/slab.h>
 #include <linux/msm_audio.h>
 #include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
index 84cfed6..44fc10f 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
@@ -35,7 +35,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_audio.h>
 #include <linux/slab.h>
 #include <linux/msm_audio_wmapro.h>
diff --git a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
index 5895867..9143b5a 100644
--- a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/wakelock.h>
-#include <linux/android_pmem.h>
 #include <linux/gpio.h>
 #include <linux/pm_qos.h>
 
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
index 24d2117..1cb9775 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
@@ -32,7 +32,6 @@
 #include <linux/wakelock.h>
 #include <linux/pm_qos.h>
 
-#include <linux/android_pmem.h>
 #include <linux/msm_q6vdec.h>
 
 #include <mach/cpuidle.h>
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6venc.c b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
index 4704ae7..a2b4b6e 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6venc.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
@@ -22,7 +22,6 @@
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include <linux/wakelock.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_q6venc.h>
 #include <linux/pm_qos.h>
 
diff --git a/arch/arm/mach-msm/qdsp6/q6audio.c b/arch/arm/mach-msm/qdsp6/q6audio.c
index f660bdc..9404c3d 100644
--- a/arch/arm/mach-msm/qdsp6/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/q6audio.c
@@ -22,7 +22,6 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/wakelock.h>
-#include <linux/android_pmem.h>
 #include <linux/firmware.h>
 #include <linux/miscdevice.h>
 #include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6v2/fm.c b/arch/arm/mach-msm/qdsp6v2/fm.c
index 3d72b97..23bb716 100644
--- a/arch/arm/mach-msm/qdsp6v2/fm.c
+++ b/arch/arm/mach-msm/qdsp6v2/fm.c
@@ -30,7 +30,6 @@
 #include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
-#include <linux/android_pmem.h>
 #include <linux/msm_audio.h>
 #include <asm/atomic.h>
 #include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 8c96b1a..55ce4b1 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -69,6 +69,7 @@
 	RPM_REGULATOR_PARAM_FREQ_REASON,
 	RPM_REGULATOR_PARAM_CORNER,
 	RPM_REGULATOR_PARAM_BYPASS,
+	RPM_REGULATOR_PARAM_FLOOR_CORNER,
 	RPM_REGULATOR_PARAM_MAX,
 };
 
@@ -108,12 +109,13 @@
 	PARAM(MODE_SMPS,       0,  1,  0,  0, "ssmd", 0, 2,          "qcom,init-smps-mode"),
 	PARAM(PIN_CTRL_ENABLE, 1,  1,  1,  0, "pcen", 0, 0xF,        "qcom,init-pin-ctrl-enable"),
 	PARAM(PIN_CTRL_MODE,   1,  1,  1,  0, "pcmd", 0, 0x1F,       "qcom,init-pin-ctrl-mode"),
-	PARAM(FREQUENCY,       0,  1,  0,  1, "freq", 0, 16,         "qcom,init-frequency"),
+	PARAM(FREQUENCY,       0,  1,  0,  1, "freq", 0, 31,         "qcom,init-frequency"),
 	PARAM(HEAD_ROOM,       1,  0,  0,  1, "hr",   0, 0x7FFFFFFF, "qcom,init-head-room"),
 	PARAM(QUIET_MODE,      0,  1,  0,  0, "qm",   0, 2,          "qcom,init-quiet-mode"),
 	PARAM(FREQ_REASON,     0,  1,  0,  1, "resn", 0, 8,          "qcom,init-freq-reason"),
 	PARAM(CORNER,          1,  1,  0,  0, "corn", 0, 6,          "qcom,init-voltage-corner"),
 	PARAM(BYPASS,          1,  0,  0,  0, "bypa", 0, 1,          "qcom,init-disallow-bypass"),
+	PARAM(FLOOR_CORNER,    1,  1,  0,  0, "vfc",  0, 6,          "qcom,init-voltage-floor-corner"),
 };
 
 struct rpm_vreg_request {
@@ -147,6 +149,8 @@
 	struct list_head	list;
 	bool			set_active;
 	bool			set_sleep;
+	bool			always_send_voltage;
+	bool			always_send_current;
 	struct rpm_vreg_request	req;
 	int			system_load;
 	int			min_uV;
@@ -390,6 +394,13 @@
 	return rc;
 }
 
+#define RPM_VREG_AGGR_MIN(_idx, _param_aggr, _param_reg) \
+{ \
+	_param_aggr[RPM_REGULATOR_PARAM_##_idx] \
+	 = min(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
+		_param_reg[RPM_REGULATOR_PARAM_##_idx]); \
+}
+
 #define RPM_VREG_AGGR_MAX(_idx, _param_aggr, _param_reg) \
 { \
 	_param_aggr[RPM_REGULATOR_PARAM_##_idx] \
@@ -410,20 +421,6 @@
 }
 
 /*
- * The RPM treats freq=0 as a special value meaning that this consumer does not
- * care what the SMPS switching freqency is.
- */
-#define RPM_REGULATOR_FREQ_DONT_CARE 0
-
-static inline void rpm_vreg_freqency_aggr(u32 *freq, u32 consumer_freq)
-{
-	if (consumer_freq != RPM_REGULATOR_FREQ_DONT_CARE
-		&& (consumer_freq < *freq
-			|| *freq == RPM_REGULATOR_FREQ_DONT_CARE))
-		*freq = consumer_freq;
-}
-
-/*
  * Aggregation is performed on each parameter based on the way that the RPM
  * aggregates that type internally between RPM masters.
  */
@@ -436,13 +433,13 @@
 	RPM_VREG_AGGR_MAX(MODE_SMPS, param_aggr, param_reg);
 	RPM_VREG_AGGR_OR(PIN_CTRL_ENABLE, param_aggr, param_reg);
 	RPM_VREG_AGGR_OR(PIN_CTRL_MODE, param_aggr, param_reg);
-	rpm_vreg_freqency_aggr(&param_aggr[RPM_REGULATOR_PARAM_FREQUENCY],
-		param_reg[RPM_REGULATOR_PARAM_FREQUENCY]);
+	RPM_VREG_AGGR_MIN(FREQUENCY, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(HEAD_ROOM, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(QUIET_MODE, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(FREQ_REASON, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
 	RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
+	RPM_VREG_AGGR_MAX(FLOOR_CORNER, param_aggr, param_reg);
 }
 
 static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
@@ -633,8 +630,12 @@
 	prev_voltage = reg->req.param[RPM_REGULATOR_PARAM_VOLTAGE];
 	RPM_VREG_SET_PARAM(reg, VOLTAGE, min_uV);
 
-	/* Only send a new voltage if the regulator is currently enabled. */
-	if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	/*
+	 * Only send a new voltage if the regulator is currently enabled or
+	 * if the regulator has been configured to always send voltage updates.
+	 */
+	if (reg->always_send_voltage
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -687,8 +688,13 @@
 	prev_corner = reg->req.param[RPM_REGULATOR_PARAM_CORNER];
 	RPM_VREG_SET_PARAM(reg, CORNER, corner);
 
-	/* Only send a new voltage if the regulator is currently enabled. */
-	if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	/*
+	 * Only send a new voltage corner if the regulator is currently enabled
+	 * or if the regulator has been configured to always send voltage
+	 * updates.
+	 */
+	if (reg->always_send_voltage
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -709,6 +715,61 @@
 		+ RPM_REGULATOR_CORNER_NONE;
 }
 
+static int rpm_vreg_set_voltage_floor_corner(struct regulator_dev *rdev,
+				int min_uV, int max_uV, unsigned *selector)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+	int rc = 0;
+	int corner;
+	u32 prev_corner;
+
+	/*
+	 * Translate from values which work as inputs in the
+	 * regulator_set_voltage function to the actual corner values
+	 * sent to the RPM.
+	 */
+	corner = min_uV - RPM_REGULATOR_CORNER_NONE;
+
+	if (corner < params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min
+	    || corner > params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max) {
+		vreg_err(reg, "corner=%d is not within allowed range: [%u, %u]\n",
+			corner, params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min,
+			params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max);
+		return -EINVAL;
+	}
+
+	rpm_vreg_lock(reg->rpm_vreg);
+
+	prev_corner = reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER];
+	RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, corner);
+
+	/*
+	 * Only send a new voltage floor corner if the regulator is currently
+	 * enabled or if the regulator has been configured to always send
+	 * voltage updates.
+	 */
+	if (reg->always_send_voltage
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+		rc = rpm_vreg_aggregate_requests(reg);
+
+	if (rc) {
+		vreg_err(reg, "set voltage corner failed, rc=%d", rc);
+		RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, prev_corner);
+	}
+
+	rpm_vreg_unlock(reg->rpm_vreg);
+
+	return rc;
+}
+
+static int rpm_vreg_get_voltage_floor_corner(struct regulator_dev *rdev)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+
+	return reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER]
+		+ RPM_REGULATOR_CORNER_NONE;
+}
+
 static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
 	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
@@ -737,8 +798,13 @@
 		return -EINVAL;
 	}
 
-	/* Only send a new mode value if the regulator is currently enabled. */
-	if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	/*
+	 * Only send a new load current value if the regulator is currently
+	 * enabled or if the regulator has been configured to always send
+	 * current updates.
+	 */
+	if (reg->always_send_current
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -1035,6 +1101,18 @@
 	.enable_time		= rpm_vreg_enable_time,
 };
 
+static struct regulator_ops ldo_floor_corner_ops = {
+	.enable			= rpm_vreg_enable,
+	.disable		= rpm_vreg_disable,
+	.is_enabled		= rpm_vreg_is_enabled,
+	.set_voltage		= rpm_vreg_set_voltage_floor_corner,
+	.get_voltage		= rpm_vreg_get_voltage_floor_corner,
+	.set_mode		= rpm_vreg_set_mode,
+	.get_mode		= rpm_vreg_get_mode,
+	.get_optimum_mode	= rpm_vreg_get_optimum_mode,
+	.enable_time		= rpm_vreg_enable_time,
+};
+
 static struct regulator_ops smps_ops = {
 	.enable			= rpm_vreg_enable,
 	.disable		= rpm_vreg_disable,
@@ -1059,6 +1137,18 @@
 	.enable_time		= rpm_vreg_enable_time,
 };
 
+static struct regulator_ops smps_floor_corner_ops = {
+	.enable			= rpm_vreg_enable,
+	.disable		= rpm_vreg_disable,
+	.is_enabled		= rpm_vreg_is_enabled,
+	.set_voltage		= rpm_vreg_set_voltage_floor_corner,
+	.get_voltage		= rpm_vreg_get_voltage_floor_corner,
+	.set_mode		= rpm_vreg_set_mode,
+	.get_mode		= rpm_vreg_get_mode,
+	.get_optimum_mode	= rpm_vreg_get_optimum_mode,
+	.enable_time		= rpm_vreg_enable_time,
+};
+
 static struct regulator_ops switch_ops = {
 	.enable			= rpm_vreg_enable,
 	.disable		= rpm_vreg_disable,
@@ -1192,12 +1282,30 @@
 	 * is specified in the device node (SMPS and LDO only).
 	 */
 	if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
+		if (of_property_read_bool(node,
+				"qcom,use-voltage-floor-corner")) {
+			dev_err(dev, "%s: invalid properties: both qcom,use-voltage-corner and qcom,use-voltage-floor-corner specified\n",
+				__func__);
+			goto fail_free_reg;
+		}
+
 		if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
 			reg->rdesc.ops = &smps_corner_ops;
 		else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
 			reg->rdesc.ops = &ldo_corner_ops;
+	} else if (of_property_read_bool(node,
+			"qcom,use-voltage-floor-corner")) {
+		if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
+			reg->rdesc.ops = &smps_floor_corner_ops;
+		else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
+			reg->rdesc.ops = &ldo_floor_corner_ops;
 	}
 
+	reg->always_send_voltage
+		= of_property_read_bool(node, "qcom,always-send-voltage");
+	reg->always_send_current
+		= of_property_read_bool(node, "qcom,always-send-current");
+
 	if (regulator_type == RPM_REGULATOR_SMD_TYPE_VS)
 		reg->rdesc.n_voltages = 0;
 	else
diff --git a/arch/arm/mach-msm/scm-xpu.c b/arch/arm/mach-msm/scm-xpu.c
new file mode 100644
index 0000000..0c38842
--- /dev/null
+++ b/arch/arm/mach-msm/scm-xpu.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <mach/scm.h>
+
+#define ERR_FATAL_ENABLE 0x0
+#define ERR_FATAL_DISABLE 0x1
+#define ERR_FATAL_READ 0x2
+#define XPU_ERR_FATAL 0xe
+
+static int __init xpu_err_fatal_init(void)
+{
+	int ret, response;
+	struct {
+		unsigned int config;
+		unsigned int spare;
+	} cmd;
+	cmd.config = ERR_FATAL_ENABLE;
+	cmd.spare = 0;
+
+	ret = scm_call(SCM_SVC_MP, XPU_ERR_FATAL, &cmd, sizeof(cmd), &response,
+			sizeof(response));
+
+	if (ret != 0)
+		pr_warn("Failed to set XPU violations as fatal errors: %d\n",
+			ret);
+	else
+		pr_info("Configuring XPU violations to be fatal errors\n");
+
+	return ret;
+}
+early_initcall(xpu_err_fatal_init);
diff --git a/arch/arm/mach-msm/spm-regulator.c b/arch/arm/mach-msm/spm-regulator.c
new file mode 100644
index 0000000..00817c0
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.c
@@ -0,0 +1,405 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include "spm.h"
+#include "spm-regulator.h"
+
+#define SPM_REGULATOR_DRIVER_NAME "qcom,spm-regulator"
+
+struct voltage_range {
+	int min_uV;
+	int set_point_min_uV;
+	int max_uV;
+	int step_uV;
+};
+
+/* Properties for FTS2 type QPNP PMIC regulators. */
+
+static const struct voltage_range fts2_range0 = {0, 350000, 1275000,  5000};
+static const struct voltage_range fts2_range1 = {0, 700000, 2040000, 10000};
+
+/* Specifies the PMIC internal slew rate in uV/us. */
+#define QPNP_FTS2_SLEW_RATE		6000
+
+#define QPNP_FTS2_REG_TYPE		0x04
+#define QPNP_FTS2_REG_SUBTYPE		0x05
+#define QPNP_FTS2_REG_VOLTAGE_RANGE	0x40
+#define QPNP_FTS2_REG_VOLTAGE_SETPOINT	0x41
+
+#define QPNP_FTS2_TYPE			0x1C
+#define QPNP_FTS2_SUBTYPE		0x08
+
+struct spm_vreg {
+	struct regulator_desc		rdesc;
+	struct regulator_dev		*rdev;
+	struct spmi_device		*spmi_dev;
+	const struct voltage_range	*range;
+	int				uV;
+	int				last_set_uV;
+	unsigned			vlevel;
+	unsigned			last_set_vlevel;
+	bool				online;
+	u16				spmi_base_addr;
+};
+
+static int _spm_regulator_set_voltage(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+	int rc;
+
+	if (vreg->vlevel == vreg->last_set_vlevel)
+		return 0;
+
+	rc = msm_spm_apcs_set_vdd(vreg->vlevel);
+	if (rc) {
+		pr_err("%s: msm_spm_set_vdd failed %d\n", vreg->rdesc.name, rc);
+		return rc;
+	}
+
+	if (vreg->uV > vreg->last_set_uV) {
+		/* Wait for voltage to stabalize. */
+		udelay(DIV_ROUND_UP(vreg->uV - vreg->last_set_uV,
+					QPNP_FTS2_SLEW_RATE));
+	}
+	vreg->last_set_uV = vreg->uV;
+	vreg->last_set_vlevel = vreg->vlevel;
+
+	return rc;
+}
+
+static int spm_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
+					int max_uV, unsigned *selector)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+	const struct voltage_range *range = vreg->range;
+	int uV = min_uV;
+	unsigned vlevel;
+
+	if (uV < range->set_point_min_uV && max_uV >= range->set_point_min_uV)
+		uV = range->set_point_min_uV;
+
+	if (uV < range->set_point_min_uV || uV > range->max_uV) {
+		pr_err("%s: request v=[%d, %d] is outside possible v=[%d, %d]\n",
+			vreg->rdesc.name, min_uV, max_uV,
+			range->set_point_min_uV, range->max_uV);
+		return -EINVAL;
+	}
+
+	vlevel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV);
+	uV = vlevel * range->step_uV + range->min_uV;
+
+	if (uV > max_uV) {
+		pr_err("%s: request v=[%d, %d] cannot be met by any set point\n",
+			vreg->rdesc.name, min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	vreg->vlevel = vlevel;
+	vreg->uV = uV;
+	*selector = vlevel -
+		(vreg->range->set_point_min_uV - vreg->range->min_uV)
+			/ vreg->range->step_uV;
+
+	if (!vreg->online)
+		return 0;
+
+	return _spm_regulator_set_voltage(rdev);
+}
+
+static int spm_regulator_get_voltage(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	return vreg->uV;
+}
+
+static int spm_regulator_list_voltage(struct regulator_dev *rdev,
+					unsigned selector)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	if (selector >= vreg->rdesc.n_voltages)
+		return 0;
+
+	return selector * vreg->range->step_uV + vreg->range->set_point_min_uV;
+}
+
+static int spm_regulator_enable(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+	int rc;
+
+	rc = _spm_regulator_set_voltage(rdev);
+
+	if (!rc)
+		vreg->online = true;
+
+	return rc;
+}
+
+static int spm_regulator_disable(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	vreg->online = false;
+
+	return 0;
+}
+
+static int spm_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+	return vreg->online;
+}
+
+static struct regulator_ops spm_regulator_ops = {
+	.get_voltage	= spm_regulator_get_voltage,
+	.set_voltage	= spm_regulator_set_voltage,
+	.list_voltage	= spm_regulator_list_voltage,
+	.enable		= spm_regulator_enable,
+	.disable	= spm_regulator_disable,
+	.is_enabled	= spm_regulator_is_enabled,
+};
+
+static int qpnp_fts2_check_type(struct spm_vreg *vreg)
+{
+	int rc;
+	u8 type[2];
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_TYPE, type, 2);
+	if (rc) {
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (type[0] != QPNP_FTS2_TYPE || type[1] != QPNP_FTS2_SUBTYPE) {
+		dev_err(&vreg->spmi_dev->dev, "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
+			__func__, type[0], type[1]);
+		return -ENODEV;
+	}
+
+	return rc;
+}
+
+static int qpnp_fts2_init_range(struct spm_vreg *vreg)
+{
+	int rc;
+	u8 reg = 0;
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_RANGE, &reg, 1);
+	if (rc) {
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage range register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (reg == 0x00) {
+		vreg->range = &fts2_range0;
+	} else if (reg == 0x01) {
+		vreg->range = &fts2_range1;
+	} else {
+		dev_err(&vreg->spmi_dev->dev, "%s: voltage range=%d is invalid\n",
+			__func__, reg);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int qpnp_fts2_init_voltage(struct spm_vreg *vreg)
+{
+	int rc;
+	u8 reg = 0;
+
+	rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+		vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_SETPOINT, &reg, 1);
+	if (rc) {
+		dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	vreg->vlevel = reg;
+	vreg->uV = vreg->vlevel * vreg->range->step_uV + vreg->range->min_uV;
+	vreg->last_set_uV = vreg->uV;
+
+	return rc;
+}
+
+static int __devinit spm_regulator_probe(struct spmi_device *spmi)
+{
+	struct device_node *node = spmi->dev.of_node;
+	struct regulator_init_data *init_data;
+	struct spm_vreg *vreg;
+	struct resource *res;
+	int rc;
+
+	if (!node) {
+		dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+		return -ENODEV;
+	}
+
+	vreg = devm_kzalloc(&spmi->dev, sizeof(*vreg), GFP_KERNEL);
+	if (!vreg) {
+		pr_err("allocation failed.\n");
+		return -ENOMEM;
+	}
+	vreg->spmi_dev = spmi;
+
+	res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&spmi->dev, "%s: node is missing base address\n",
+			__func__);
+		return -EINVAL;
+	}
+	vreg->spmi_base_addr = res->start;
+
+	rc = qpnp_fts2_check_type(vreg);
+	if (rc)
+		return rc;
+
+	/*
+	 * The FTS2 regulator must be initialized to range 0 or range 1 during
+	 * PMIC power on sequence.  Once it is set, it cannot be changed
+	 * dynamically.
+	 */
+	rc = qpnp_fts2_init_range(vreg);
+	if (rc)
+		return rc;
+
+	rc = qpnp_fts2_init_voltage(vreg);
+	if (rc)
+		return rc;
+
+	init_data = of_get_regulator_init_data(&spmi->dev, node);
+	if (!init_data) {
+		dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+				__func__);
+		return -ENOMEM;
+	}
+	init_data->constraints.input_uV = init_data->constraints.max_uV;
+	init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS
+						| REGULATOR_CHANGE_VOLTAGE;
+
+	if (!init_data->constraints.name) {
+		dev_err(&spmi->dev, "%s: node is missing regulator name\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	vreg->rdesc.name	= init_data->constraints.name;
+	vreg->rdesc.type	= REGULATOR_VOLTAGE;
+	vreg->rdesc.owner	= THIS_MODULE;
+	vreg->rdesc.ops		= &spm_regulator_ops;
+	vreg->rdesc.n_voltages
+		= (vreg->range->max_uV - vreg->range->set_point_min_uV)
+			/ vreg->range->step_uV + 1;
+
+	vreg->rdev = regulator_register(&vreg->rdesc, &spmi->dev,
+					init_data, vreg, node);
+	if (IS_ERR(vreg->rdev)) {
+		rc = PTR_ERR(vreg->rdev);
+		dev_err(&spmi->dev, "%s: regulator_register failed, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	dev_set_drvdata(&spmi->dev, vreg);
+
+	pr_info("name=%s, range=%d\n", vreg->rdesc.name,
+		(vreg->range == &fts2_range0) ? 0 : 1);
+
+	return rc;
+}
+
+static int __devexit spm_regulator_remove(struct spmi_device *spmi)
+{
+	struct spm_vreg *vreg = dev_get_drvdata(&spmi->dev);
+
+	regulator_unregister(vreg->rdev);
+
+	return 0;
+}
+
+static struct of_device_id spm_regulator_match_table[] = {
+	{ .compatible = SPM_REGULATOR_DRIVER_NAME, },
+	{}
+};
+
+static const struct spmi_device_id spm_regulator_id[] = {
+	{ SPM_REGULATOR_DRIVER_NAME, 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(spmi, spm_regulator_id);
+
+static struct spmi_driver spm_regulator_driver = {
+	.driver = {
+		.name		= SPM_REGULATOR_DRIVER_NAME,
+		.of_match_table = spm_regulator_match_table,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= spm_regulator_probe,
+	.remove		= __devexit_p(spm_regulator_remove),
+	.id_table	= spm_regulator_id,
+};
+
+/**
+ * spm_regulator_init() - register spmi driver for spm-regulator
+ *
+ * This initialization function should be called in systems in which driver
+ * registration ordering must be controlled precisely.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int __init spm_regulator_init(void)
+{
+	static bool has_registered;
+
+	if (has_registered)
+		return 0;
+	else
+		has_registered = true;
+
+	return spmi_driver_register(&spm_regulator_driver);
+}
+EXPORT_SYMBOL(spm_regulator_init);
+
+static void __exit spm_regulator_exit(void)
+{
+	spmi_driver_unregister(&spm_regulator_driver);
+}
+
+arch_initcall(spm_regulator_init);
+module_exit(spm_regulator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SPM regulator driver");
+MODULE_ALIAS("platform:spm-regulator");
diff --git a/arch/arm/mach-msm/spm-regulator.h b/arch/arm/mach-msm/spm-regulator.h
new file mode 100644
index 0000000..394aecc
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+#define _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+
+#include <linux/err.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_MSM_SPM_REGULATOR
+int __init spm_regulator_init(void);
+#else
+static inline int __init spm_regulator_init(void) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
index 11dc436..84e8df5 100644
--- a/arch/arm/mach-msm/tz_log.c
+++ b/arch/arm/mach-msm/tz_log.c
@@ -708,23 +708,18 @@
 	 */
 	tzdiag_phy_iobase = readl_relaxed(virt_iobase);
 
-	if (!pdev->dev.of_node) {
+	/*
+	 * Map the 4KB diagnostic information area
+	 */
+	tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
+				tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
 
-		/*
-		 * Map the 4KB diagnostic information area
-		 */
-		tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
-					tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
-
-		if (!tzdbg.virt_iobase) {
-			dev_err(&pdev->dev,
-				"%s: ERROR could not ioremap: start=%p, len=%u\n",
-				__func__, (void *) tzdiag_phy_iobase,
-				DEBUG_MAX_RW_BUF);
-			return -ENXIO;
-		}
-	} else {
-		tzdbg.virt_iobase = virt_iobase;
+	if (!tzdbg.virt_iobase) {
+		dev_err(&pdev->dev,
+			"%s: ERROR could not ioremap: start=%p, len=%u\n",
+			__func__, (void *) tzdiag_phy_iobase,
+			DEBUG_MAX_RW_BUF);
+		return -ENXIO;
 	}
 
 	ptr = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f385fc4..1c8a25d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -708,12 +708,12 @@
 
 	if (arch_is_coherent() || nommu()) {
 		__dma_free_buffer(page, size);
+	} else if (__free_from_pool(cpu_addr, size)) {
+		return;
 	} else if (!IS_ENABLED(CONFIG_CMA)) {
 		__dma_free_remap(cpu_addr, size, false);
 		__dma_free_buffer(page, size);
 	} else {
-		if (__free_from_pool(cpu_addr, size))
-			return;
 		/*
 		 * Non-atomic allocations cannot be freed with IRQs disabled
 		 */
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index ed91480..45c9023 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -227,7 +227,7 @@
 
 	pr_info("Found %s, memory base %lx, size %ld MiB\n", uname,
 		(unsigned long)base, (unsigned long)size / SZ_1M);
-	dma_contiguous_reserve_area(size, &base, 0, name);
+	dma_contiguous_reserve_area(size, &base, MEMBLOCK_ALLOC_ANYWHERE, name);
 
 	return 0;
 }
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index fe8cf57..583add9 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -41,6 +41,7 @@
 #define CRYPTO_CONFIG_RESET 0xE001F
 #define QCE_MAX_NUM_DSCR    0x400
 #define QCE_SIZE_BAM_DSCR   0x08
+#define QCE_SECTOR_SIZE	    0x200
 
 static DEFINE_MUTEX(bam_register_cnt);
 struct bam_registration_info {
@@ -445,6 +446,7 @@
 	uint32_t enck_size_in_word = 0;
 	uint32_t key_size;
 	bool use_hw_key = false;
+	bool use_pipe_key = false;
 	uint32_t encr_cfg = 0;
 	uint32_t ivsize = creq->ivsize;
 	int i;
@@ -456,6 +458,7 @@
 		key_size = creq->encklen;
 
 	_byte_stream_to_net_words(enckey32, creq->enckey, key_size);
+	pce = cmdlistinfo->go_proc;
 
 	/* check for null key. If null, use hw key*/
 	enck_size_in_word = key_size/sizeof(uint32_t);
@@ -463,15 +466,22 @@
 		if (enckey32[i] != 0)
 			break;
 	}
-	pce = cmdlistinfo->go_proc;
 	if (i == enck_size_in_word) {
 		use_hw_key = true;
 		pce->addr = (uint32_t)(CRYPTO_GOPROC_QC_KEY_REG +
 						pce_dev->phy_iobase);
-	} else {
+	}
+	if (use_hw_key == false) {
+		for (i = 0; i < enck_size_in_word; i++) {
+			if (enckey32[i] != 0xFFFFFFFF)
+				break;
+		}
+		if (i == enck_size_in_word)
+			use_pipe_key = true;
+	}
+	if (use_hw_key == false)
 		pce->addr = (uint32_t)(CRYPTO_GOPROC_REG +
 						pce_dev->phy_iobase);
-	}
 
 	if ((creq->op == QCE_REQ_AEAD) && (creq->mode == QCE_MODE_CCM)) {
 		uint32_t authklen32 = creq->encklen/sizeof(uint32_t);
@@ -600,7 +610,10 @@
 
 			/* write xts du size */
 			pce = cmdlistinfo->encr_xts_du_size;
-			pce->data = creq->cryptlen;
+			if (use_pipe_key == true)
+				pce->data = QCE_SECTOR_SIZE;
+			else
+				pce->data = creq->cryptlen;
 		}
 		if (creq->mode !=  QCE_MODE_ECB) {
 			if (creq->mode ==  QCE_MODE_XTS)
@@ -653,6 +666,10 @@
 		break;
 	} /* end of switch (creq->mode)  */
 
+	if (use_pipe_key)
+		encr_cfg |= (CRYPTO_USE_PIPE_KEY_ENCR_ENABLED
+					<< CRYPTO_USE_PIPE_KEY_ENCR);
+
 	/* write encr seg cfg */
 	pce = cmdlistinfo->encr_seg_cfg;
 	if ((creq->alg == CIPHER_ALG_DES) || (creq->alg == CIPHER_ALG_3DES)) {
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 1f73d47..33e6fed 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -54,6 +54,11 @@
 		.name	= ION_VMALLOC_HEAP_NAME,
 	},
 	{
+		.id	= ION_SYSTEM_CONTIG_HEAP_ID,
+		.type	= ION_HEAP_TYPE_SYSTEM_CONTIG,
+		.name	= ION_KMALLOC_HEAP_NAME,
+	},
+	{
 		.id	= ION_CP_MM_HEAP_ID,
 		.type	= ION_HEAP_TYPE_SECURE_DMA,
 		.name	= ION_MM_HEAP_NAME,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index d7bf36e..a76ed87 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -470,7 +470,7 @@
 	int offset = type0_pkt_offset(*ptr);
 	int i;
 
-	for (i = 0; i < size; i++, offset++) {
+	for (i = 0; i < size - 1; i++, offset++) {
 
 		/* Visiblity stream buffer */
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index e939c2b..e1b978f 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -27,7 +27,6 @@
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
 #endif
 
-static struct msm_actuator_ctrl_t msm_actuator_t;
 static struct msm_actuator msm_vcm_actuator_table;
 static struct msm_actuator msm_piezo_actuator_table;
 
@@ -618,103 +617,21 @@
 	.close = msm_actuator_close,
 };
 
-static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
-	const struct i2c_device_id *id)
+static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
 {
-	int rc = 0;
-	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+	struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
+	void __user *argp = (void __user *)arg;
 	CDBG("Enter\n");
-
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		pr_err("i2c_check_functionality failed\n");
-		goto probe_failure;
+	CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+		return msm_actuator_get_subdev_id(a_ctrl, argp);
+	case VIDIOC_MSM_ACTUATOR_CFG:
+		return msm_actuator_config(a_ctrl, argp);
+	default:
+		return -ENOIOCTLCMD;
 	}
-
-	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
-	CDBG("client = %x\n", (unsigned int) client);
-	act_ctrl_t->i2c_client.client = client;
-	/* Set device type as I2C */
-	act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
-	act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
-
-	/* Assign name for sub device */
-	snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
-		"%s", act_ctrl_t->i2c_driver->driver.name);
-
-	/* Initialize sub device */
-	v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
-		act_ctrl_t->i2c_client.client,
-		act_ctrl_t->act_v4l2_subdev_ops);
-	v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
-	act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
-	act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-	media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
-	act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
-	act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
-	msm_sd_register(&act_ctrl_t->msm_sd);
-	CDBG("succeeded\n");
-	CDBG("Exit\n");
-
-probe_failure:
-	return rc;
-}
-
-static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
-{
-	int32_t rc = 0;
-	struct msm_camera_cci_client *cci_client = NULL;
-	CDBG("Enter\n");
-
-	if (!pdev->dev.of_node) {
-		pr_err("of_node NULL\n");
-		return -EINVAL;
-	}
-
-	rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
-		&pdev->id);
-	CDBG("cell-index %d, rc %d\n", pdev->id, rc);
-	if (rc < 0) {
-		pr_err("failed rc %d\n", rc);
-		return rc;
-	}
-
-	rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
-		&msm_actuator_t.cci_master);
-	CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t.cci_master, rc);
-	if (rc < 0) {
-		pr_err("failed rc %d\n", rc);
-		return rc;
-	}
-
-	msm_actuator_t.cam_name = pdev->id;
-
-	/* Set platform device handle */
-	msm_actuator_t.pdev = pdev;
-	/* Set device type as platform device */
-	msm_actuator_t.act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
-	msm_actuator_t.i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
-	msm_actuator_t.i2c_client.cci_client = kzalloc(sizeof(
-		struct msm_camera_cci_client), GFP_KERNEL);
-	if (!msm_actuator_t.i2c_client.cci_client) {
-		pr_err("failed no memory\n");
-		return -ENOMEM;
-	}
-
-	cci_client = msm_actuator_t.i2c_client.cci_client;
-	cci_client->cci_subdev = msm_cci_get_subdev();
-	v4l2_subdev_init(&msm_actuator_t.msm_sd.sd,
-		msm_actuator_t.act_v4l2_subdev_ops);
-	v4l2_set_subdevdata(&msm_actuator_t.msm_sd.sd, &msm_actuator_t);
-	msm_actuator_t.msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
-	msm_actuator_t.msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-	snprintf(msm_actuator_t.msm_sd.sd.name,
-		ARRAY_SIZE(msm_actuator_t.msm_sd.sd.name), "msm_actuator");
-	media_entity_init(&msm_actuator_t.msm_sd.sd.entity, 0, NULL, 0);
-	msm_actuator_t.msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
-	msm_actuator_t.msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
-	msm_sd_register(&msm_actuator_t.msm_sd);
-	CDBG("Exit\n");
-	return rc;
 }
 
 static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
@@ -735,64 +652,6 @@
 	return rc;
 }
 
-static const struct i2c_device_id msm_actuator_i2c_id[] = {
-	{"msm_actuator", (kernel_ulong_t)&msm_actuator_t},
-	{ }
-};
-
-static struct i2c_driver msm_actuator_i2c_driver = {
-	.id_table = msm_actuator_i2c_id,
-	.probe  = msm_actuator_i2c_probe,
-	.remove = __exit_p(msm_actuator_i2c_remove),
-	.driver = {
-		.name = "msm_actuator",
-	},
-};
-
-static const struct of_device_id msm_actuator_dt_match[] = {
-	{.compatible = "qcom,actuator", .data = &msm_actuator_t},
-	{}
-};
-
-MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
-
-static struct platform_driver msm_actuator_platform_driver = {
-	.driver = {
-		.name = "qcom,actuator",
-		.owner = THIS_MODULE,
-		.of_match_table = msm_actuator_dt_match,
-	},
-};
-
-static int __init msm_actuator_init_module(void)
-{
-	int32_t rc = 0;
-	CDBG("Enter\n");
-	rc = platform_driver_probe(msm_actuator_t.pdriver,
-		msm_actuator_platform_probe);
-	if (!rc)
-		return rc;
-	CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
-	return i2c_add_driver(msm_actuator_t.i2c_driver);
-}
-
-static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
-			unsigned int cmd, void *arg)
-{
-	struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
-	void __user *argp = (void __user *)arg;
-	CDBG("Enter\n");
-	CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
-	switch (cmd) {
-	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
-		return msm_actuator_get_subdev_id(a_ctrl, argp);
-	case VIDIOC_MSM_ACTUATOR_CFG:
-		return msm_actuator_config(a_ctrl, argp);
-	default:
-		return -ENOIOCTLCMD;
-	}
-}
-
 static int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
 {
 	int rc = 0;
@@ -817,17 +676,156 @@
 	.core = &msm_actuator_subdev_core_ops,
 };
 
-static struct msm_actuator_ctrl_t msm_actuator_t = {
-	.i2c_driver = &msm_actuator_i2c_driver,
-	.pdriver = &msm_actuator_platform_driver,
-	.act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
+static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	int rc = 0;
+	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+	CDBG("Enter\n");
 
-	.curr_step_pos = 0,
-	.curr_region_index = 0,
-	.actuator_mutex = &msm_actuator_mutex,
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("i2c_check_functionality failed\n");
+		goto probe_failure;
+	}
 
+	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
+	CDBG("client = %x\n", (unsigned int) client);
+	act_ctrl_t->i2c_client.client = client;
+	/* Set device type as I2C */
+	act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
+	act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
+	act_ctrl_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+	act_ctrl_t->actuator_mutex = &msm_actuator_mutex;
+	/* Assign name for sub device */
+	snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
+		"%s", act_ctrl_t->i2c_driver->driver.name);
+
+	/* Initialize sub device */
+	v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
+		act_ctrl_t->i2c_client.client,
+		act_ctrl_t->act_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
+	act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+	act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
+	act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+	msm_sd_register(&act_ctrl_t->msm_sd);
+	CDBG("succeeded\n");
+	CDBG("Exit\n");
+
+probe_failure:
+	return rc;
+}
+
+static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	struct msm_camera_cci_client *cci_client = NULL;
+	struct msm_actuator_ctrl_t *msm_actuator_t = NULL;
+	CDBG("Enter\n");
+
+	if (!pdev->dev.of_node) {
+		pr_err("of_node NULL\n");
+		return -EINVAL;
+	}
+
+	msm_actuator_t = kzalloc(sizeof(struct msm_actuator_ctrl_t),
+		GFP_KERNEL);
+	if (!msm_actuator_t) {
+		pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
+		&pdev->id);
+	CDBG("cell-index %d, rc %d\n", pdev->id, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
+		&msm_actuator_t->cci_master);
+	CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t->cci_master, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	msm_actuator_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+	msm_actuator_t->actuator_mutex = &msm_actuator_mutex;
+	msm_actuator_t->cam_name = pdev->id;
+
+	/* Set platform device handle */
+	msm_actuator_t->pdev = pdev;
+	/* Set device type as platform device */
+	msm_actuator_t->act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+	msm_actuator_t->i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
+	msm_actuator_t->i2c_client.cci_client = kzalloc(sizeof(
+		struct msm_camera_cci_client), GFP_KERNEL);
+	if (!msm_actuator_t->i2c_client.cci_client) {
+		pr_err("failed no memory\n");
+		return -ENOMEM;
+	}
+
+	cci_client = msm_actuator_t->i2c_client.cci_client;
+	cci_client->cci_subdev = msm_cci_get_subdev();
+	v4l2_subdev_init(&msm_actuator_t->msm_sd.sd,
+		msm_actuator_t->act_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&msm_actuator_t->msm_sd.sd, msm_actuator_t);
+	msm_actuator_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+	msm_actuator_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(msm_actuator_t->msm_sd.sd.name,
+		ARRAY_SIZE(msm_actuator_t->msm_sd.sd.name), "msm_actuator");
+	media_entity_init(&msm_actuator_t->msm_sd.sd.entity, 0, NULL, 0);
+	msm_actuator_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	msm_actuator_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+	msm_sd_register(&msm_actuator_t->msm_sd);
+	CDBG("Exit\n");
+	return rc;
+}
+
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+	{"msm_actuator", (kernel_ulong_t)NULL},
+	{ }
 };
 
+static struct i2c_driver msm_actuator_i2c_driver = {
+	.id_table = msm_actuator_i2c_id,
+	.probe  = msm_actuator_i2c_probe,
+	.remove = __exit_p(msm_actuator_i2c_remove),
+	.driver = {
+		.name = "msm_actuator",
+	},
+};
+
+static const struct of_device_id msm_actuator_dt_match[] = {
+	{.compatible = "qcom,actuator", .data = NULL},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
+
+static struct platform_driver msm_actuator_platform_driver = {
+	.driver = {
+		.name = "qcom,actuator",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_actuator_dt_match,
+	},
+};
+
+static int __init msm_actuator_init_module(void)
+{
+	int32_t rc = 0;
+	CDBG("Enter\n");
+	rc = platform_driver_probe(&msm_actuator_platform_driver,
+		msm_actuator_platform_probe);
+	if (!rc)
+		return rc;
+	CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&msm_actuator_i2c_driver);
+}
+
 static struct msm_actuator msm_vcm_actuator_table = {
 	.act_type = ACTUATOR_VCM,
 	.func_tbl = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e8096d1..2573a16 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -639,6 +639,15 @@
 	  to the fuse block. Currently this is supported only
 	  on FSM targets.
 
+config QPNP_MISC
+	tristate "QPNP Misc Peripheral"
+	depends on SPMI
+	help
+	  Say 'y' here to include support for the Qualcomm QPNP MISC
+	  peripheral. The MISC peripheral holds the USB ID interrupt
+	  and the driver provides an API to check if this interrupt
+	  is available on the current PMIC chip.
+
 config USB_HSIC_SMSC_HUB
 	tristate "Support for HSIC based MSM on-chip SMSC3503 HUB"
 	depends on USB_EHCI_MSM_HSIC
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f80f3f2..327d1ec 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -70,3 +70,4 @@
 obj-$(CONFIG_QSEECOM) += qseecom.o
 obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
 obj-$(CONFIG_TI_DRV2667) += ti_drv2667.o
+obj-$(CONFIG_QPNP_MISC) += qpnp-misc.o
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
new file mode 100644
index 0000000..608be81
--- /dev/null
+++ b/drivers/misc/qpnp-misc.c
@@ -0,0 +1,167 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/qpnp-misc.h>
+
+#define QPNP_MISC_DEV_NAME "qcom,qpnp-misc"
+
+#define REVID_REVISION2	0x1
+
+static DEFINE_MUTEX(qpnp_misc_dev_list_mutex);
+static LIST_HEAD(qpnp_misc_dev_list);
+
+/**
+ * struct qpnp_misc_dev - holds controller device specific information
+ * @list:			Doubly-linked list parameter linking to other
+ *				qpnp_misc devices.
+ * @mutex:			Mutex lock that is used to ensure mutual
+ *				exclusion between probing and accessing misc
+ *				driver information
+ * @dev:			Device pointer to the misc device
+ * @resource:			Resource pointer that holds base address
+ * @spmi:			Spmi pointer which holds spmi information
+ */
+struct qpnp_misc_dev {
+	struct list_head		list;
+	struct mutex			mutex;
+	struct device			*dev;
+	struct resource			*resource;
+	struct spmi_device		*spmi;
+};
+
+static struct of_device_id qpnp_misc_match_table[] = {
+	{ .compatible = QPNP_MISC_DEV_NAME },
+	{}
+};
+
+static u8 qpnp_read_byte(struct spmi_device *spmi, u16 addr)
+{
+	int rc;
+	u8 val;
+
+	rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, &val, 1);
+	if (rc) {
+		pr_err("SPMI read failed rc=%d\n", rc);
+		return 0;
+	}
+	return val;
+}
+
+#define REV2_IRQ_AVAILABLE_VERSION	2
+static bool __misc_irqs_available(struct qpnp_misc_dev *dev)
+{
+	u8 rev2;
+
+	rev2 = qpnp_read_byte(dev->spmi,
+		dev->resource->start + REVID_REVISION2);
+	pr_debug("rev2 0x%x\n", rev2);
+
+	if (rev2 >= REV2_IRQ_AVAILABLE_VERSION)
+		return 1;
+
+	return 0;
+}
+
+int qpnp_misc_irqs_available(struct device *consumer_dev)
+{
+	struct device_node *misc_node = NULL;
+	struct qpnp_misc_dev *mdev = NULL;
+	struct qpnp_misc_dev *mdev_found = NULL;
+
+	misc_node = of_parse_phandle(consumer_dev->of_node, "qcom,misc-ref", 0);
+	if (!misc_node) {
+		pr_debug("Could not find qcom,misc-ref property in %s\n",
+			consumer_dev->of_node->full_name);
+		return 0;
+	}
+
+	mutex_lock(&qpnp_misc_dev_list_mutex);
+	list_for_each_entry(mdev, &qpnp_misc_dev_list, list) {
+		if (mdev->dev->of_node == misc_node) {
+			mdev_found = mdev;
+			break;
+		}
+	}
+	mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+	if (!mdev_found) {
+		/* No MISC device was found. This API should only
+		 * be called by drivers which have specified the
+		 * misc phandle in their device tree node */
+		pr_err("no probed misc device found\n");
+		return -EPROBE_DEFER;
+	}
+
+	return __misc_irqs_available(mdev_found);
+}
+
+static int __devinit qpnp_misc_probe(struct spmi_device *spmi)
+{
+	struct resource *resource;
+	struct qpnp_misc_dev *mdev = ERR_PTR(-EINVAL);
+
+	resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+	if (!resource) {
+		pr_err("Unable to get spmi resource for MISC\n");
+		return -EINVAL;
+	}
+
+	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+	if (!mdev) {
+		pr_err("allocation failed\n");
+		return -ENOMEM;
+	}
+
+	mdev->spmi = spmi;
+	mdev->dev = &(spmi->dev);
+	mdev->resource = resource;
+
+	mutex_lock(&qpnp_misc_dev_list_mutex);
+	list_add_tail(&mdev->list, &qpnp_misc_dev_list);
+	mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+	pr_debug("probed successfully\n");
+	return 0;
+}
+
+static struct spmi_driver qpnp_misc_driver = {
+	.probe	= qpnp_misc_probe,
+	.driver	= {
+		.name		= QPNP_MISC_DEV_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= qpnp_misc_match_table,
+	},
+};
+
+static int __init qpnp_misc_init(void)
+{
+	return spmi_driver_register(&qpnp_misc_driver);
+}
+
+static void __exit qpnp_misc_exit(void)
+{
+	return spmi_driver_unregister(&qpnp_misc_driver);
+}
+
+module_init(qpnp_misc_init);
+module_exit(qpnp_misc_exit);
+
+MODULE_DESCRIPTION(QPNP_MISC_DEV_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" QPNP_MISC_DEV_NAME);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index b2a3a38..2769709 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -103,6 +103,10 @@
 	0xFFFFBBBB, 0xFFFF77FF, 0xFF7777FF, 0xEEDDBB77
 };
 
+static int disable_slots;
+/* root can write, others read */
+module_param(disable_slots, int, S_IRUGO|S_IWUSR);
+
 /* This structure keeps information per regulator */
 struct sdhci_msm_reg_data {
 	/* voltage regulator handle */
@@ -199,13 +203,14 @@
 	u32 caps2;
 
 	unsigned long mmc_bus_width;
-	u32 max_clk;
 	struct sdhci_msm_slot_reg_data *vreg_data;
 	bool nonremovable;
 	struct sdhci_msm_pin_data *pin_data;
 	u32 cpu_dma_latency_us;
 	int status_gpio; /* card detection GPIO that is configured as IRQ */
 	struct sdhci_msm_bus_voting_data *voting_data;
+	u32 *sup_clk_table;
+	unsigned char sup_clk_cnt;
 };
 
 struct sdhci_msm_bus_vote {
@@ -233,6 +238,7 @@
 	u32 curr_io_level;
 	struct completion pwr_irq_completion;
 	struct sdhci_msm_bus_vote msm_bus_vote;
+	u32 clk_rate; /* Keeps track of current clock rate that is set */
 };
 
 enum vdd_io_level {
@@ -552,9 +558,18 @@
 	int size = sizeof(tuning_block_64); /* Tuning pattern size in bytes */
 	int rc;
 	struct mmc_host *mmc = host->mmc;
+	struct mmc_ios	ios = host->mmc->ios;
+
+	/*
+	 * Tuning is required for SDR104 and HS200 cards and if clock frequency
+	 * is greater than 100MHz in these modes.
+	 */
+	if (host->clock <= (100 * 1000 * 1000) ||
+		!(ios.timing == MMC_TIMING_MMC_HS200 ||
+		ios.timing == MMC_TIMING_UHS_SDR104))
+		return 0;
 
 	pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
-	/* Tuning is only required for SDR104 modes */
 	spin_lock_irqsave(&host->lock, flags);
 
 	if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
@@ -1076,6 +1091,8 @@
 	u32 bus_width = 0;
 	u32 cpu_dma_latency;
 	int len, i;
+	int clk_table_len;
+	u32 *clk_table = NULL;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
@@ -1099,6 +1116,18 @@
 				&cpu_dma_latency))
 		pdata->cpu_dma_latency_us = cpu_dma_latency;
 
+	if (sdhci_msm_dt_get_array(dev, "qcom,clk-rates",
+			&clk_table, &clk_table_len, 0)) {
+		dev_err(dev, "failed parsing supported clock rates\n");
+		goto out;
+	}
+	if (!clk_table || !clk_table_len) {
+		dev_err(dev, "Invalid clock table\n");
+		goto out;
+	}
+	pdata->sup_clk_table = clk_table;
+	pdata->sup_clk_cnt = clk_table_len;
+
 	pdata->vreg_data = devm_kzalloc(dev, sizeof(struct
 						    sdhci_msm_slot_reg_data),
 					GFP_KERNEL);
@@ -1124,8 +1153,6 @@
 		goto out;
 	}
 
-	of_property_read_u32(np, "qcom,max-clk-rate", &pdata->max_clk);
-
 	len = of_property_count_strings(np, "qcom,bus-speed-mode");
 
 	for (i = 0; i < len; i++) {
@@ -1834,16 +1861,58 @@
 	return SDHCI_MSM_MAX_SEGMENTS;
 }
 
-void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
 {
-	int rc;
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
-	unsigned long flags;
 
-	if (clock && !atomic_read(&msm_host->clks_on)) {
-		pr_debug("%s: request to enable clock at rate %u\n",
-				mmc_hostname(host->mmc), clock);
+	return msm_host->pdata->sup_clk_table[0];
+}
+
+static unsigned int sdhci_msm_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	int max_clk_index = msm_host->pdata->sup_clk_cnt;
+
+	return msm_host->pdata->sup_clk_table[max_clk_index - 1];
+}
+
+static unsigned int sdhci_msm_get_sup_clk_rate(struct sdhci_host *host,
+						u32 req_clk)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	unsigned int sel_clk = -1;
+	unsigned char cnt;
+
+	if (req_clk < sdhci_msm_get_min_clock(host)) {
+		sel_clk = sdhci_msm_get_min_clock(host);
+		return sel_clk;
+	}
+
+	for (cnt = 0; cnt < msm_host->pdata->sup_clk_cnt; cnt++) {
+		if (msm_host->pdata->sup_clk_table[cnt] > req_clk) {
+			break;
+		} else if (msm_host->pdata->sup_clk_table[cnt] == req_clk) {
+			sel_clk = msm_host->pdata->sup_clk_table[cnt];
+			break;
+		} else {
+			sel_clk = msm_host->pdata->sup_clk_table[cnt];
+		}
+	}
+	return sel_clk;
+}
+
+static int sdhci_msm_prepare_clocks(struct sdhci_host *host, bool enable)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	int rc = 0;
+
+	if (enable && !atomic_read(&msm_host->clks_on)) {
+		pr_debug("%s: request to enable clocks\n",
+				mmc_hostname(host->mmc));
 		if (!IS_ERR_OR_NULL(msm_host->bus_clk)) {
 			rc = clk_prepare_enable(msm_host->bus_clk);
 			if (rc) {
@@ -1867,9 +1936,8 @@
 			goto disable_pclk;
 		}
 		mb();
-		atomic_set(&msm_host->clks_on, 1);
 
-	} else if (!clock && atomic_read(&msm_host->clks_on)) {
+	} else if (!enable && atomic_read(&msm_host->clks_on)) {
 		pr_debug("%s: request to disable clocks\n",
 				mmc_hostname(host->mmc));
 		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
@@ -1879,11 +1947,8 @@
 			clk_disable_unprepare(msm_host->pclk);
 		if (!IS_ERR_OR_NULL(msm_host->bus_clk))
 			clk_disable_unprepare(msm_host->bus_clk);
-		atomic_set(&msm_host->clks_on, 0);
 	}
-	spin_lock_irqsave(&host->lock, flags);
-	host->clock = clock;
-	spin_unlock_irqrestore(&host->lock, flags);
+	atomic_set(&msm_host->clks_on, enable);
 	goto out;
 disable_pclk:
 	if (!IS_ERR_OR_NULL(msm_host->pclk))
@@ -1892,7 +1957,52 @@
 	if (!IS_ERR_OR_NULL(msm_host->bus_clk))
 		clk_disable_unprepare(msm_host->bus_clk);
 out:
-	return;
+	return rc;
+}
+
+static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	int rc;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	struct mmc_ios	curr_ios = host->mmc->ios;
+	u32 sup_clock, ddr_clock;
+
+	if (!clock) {
+		sdhci_msm_prepare_clocks(host, false);
+		host->clock = clock;
+		return;
+	}
+
+	rc = sdhci_msm_prepare_clocks(host, true);
+	if (rc)
+		return;
+
+	sup_clock = sdhci_msm_get_sup_clk_rate(host, clock);
+	if (curr_ios.timing == MMC_TIMING_UHS_DDR50) {
+		/*
+		 * The SDHC requires internal clock frequency to be double the
+		 * actual clock that will be set for DDR mode. The controller
+		 * uses the faster clock(100MHz) for some of its parts and send
+		 * the actual required clock (50MHz) to the card.
+		 */
+		ddr_clock = clock * 2;
+		sup_clock = sdhci_msm_get_sup_clk_rate(host,
+				ddr_clock);
+	}
+	if (sup_clock != msm_host->clk_rate) {
+		pr_debug("%s: %s: setting clk rate to %u\n",
+				mmc_hostname(host->mmc), __func__, sup_clock);
+		rc = clk_set_rate(msm_host->clk, sup_clock);
+		if (rc) {
+			pr_err("%s: %s: Failed to set rate %u for host-clk : %d\n",
+					mmc_hostname(host->mmc), __func__,
+					sup_clock, rc);
+			return;
+		}
+		msm_host->clk_rate = sup_clock;
+		host->clock = clock;
+	}
 }
 
 static int sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
@@ -1915,6 +2025,17 @@
 		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
 	else if (uhs == MMC_TIMING_UHS_DDR50)
 		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+	/*
+	 * When clock frquency is less than 100MHz, the feedback clock must be
+	 * provided and DLL must not be used so that tuning can be skipped. To
+	 * provide feedback clock, the mode selection can be any value less
+	 * than 3'b011 in bits [2:0] of HOST CONTROL2 register.
+	 */
+	if (host->clock <= (100 * 1000 * 1000) &&
+			(uhs == MMC_TIMING_MMC_HS200 ||
+			uhs == MMC_TIMING_UHS_SDR104))
+		ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+
 	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
 
 	return 0;
@@ -1928,6 +2049,8 @@
 	.get_max_segments = sdhci_msm_max_segs,
 	.set_clock = sdhci_msm_set_clock,
 	.platform_bus_voting = sdhci_msm_bus_voting,
+	.get_min_clock = sdhci_msm_get_min_clock,
+	.get_max_clock = sdhci_msm_get_max_clock,
 };
 
 static int __devinit sdhci_msm_probe(struct platform_device *pdev)
@@ -1962,6 +2085,19 @@
 
 	/* Extract platform data */
 	if (pdev->dev.of_node) {
+		ret = of_alias_get_id(pdev->dev.of_node, "sdhc");
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to get slot index %d\n",
+				ret);
+			goto pltfm_free;
+		}
+		if (disable_slots & (1 << (ret - 1))) {
+			dev_info(&pdev->dev, "%s: Slot %d disabled\n", __func__,
+				ret);
+			ret = -ENODEV;
+			goto pltfm_free;
+		}
+
 		msm_host->pdata = sdhci_msm_populate_pdata(&pdev->dev);
 		if (!msm_host->pdata) {
 			dev_err(&pdev->dev, "DT parsing error\n");
@@ -2005,7 +2141,15 @@
 	if (ret)
 		goto pclk_disable;
 
+	/* Set to the minimum supported clock frequency */
+	ret = clk_set_rate(msm_host->clk, sdhci_msm_get_min_clock(host));
+	if (ret) {
+		dev_err(&pdev->dev, "MClk rate set failed (%d)\n", ret);
+		goto clk_disable;
+	}
+	msm_host->clk_rate = sdhci_msm_get_min_clock(host);
 	atomic_set(&msm_host->clks_on, 1);
+
 	/* Setup regulators */
 	ret = sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, true);
 	if (ret) {
@@ -2037,6 +2181,8 @@
 	 */
 	host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 	host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE;
+	host->quirks |= SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
+	host->quirks2 |= SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK;
 	host->quirks2 |= SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING;
 
 	host_version = readl_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
@@ -2109,6 +2255,7 @@
 	msm_host->mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
 	msm_host->mmc->caps2 |= MMC_CAP2_INIT_BKOPS;
 	msm_host->mmc->caps2 |= MMC_CAP2_POWEROFF_NOTIFY;
+	msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE;
 
 	if (msm_host->pdata->nonremovable)
 		msm_host->mmc->caps |= MMC_CAP_NONREMOVABLE;
@@ -2148,15 +2295,6 @@
 		goto free_cd_gpio;
 	}
 
-	 /* Set core clk rate, optionally override from dts */
-	if (msm_host->pdata->max_clk)
-		host->max_clk = msm_host->pdata->max_clk;
-	ret = clk_set_rate(msm_host->clk, host->max_clk);
-	if (ret) {
-		dev_err(&pdev->dev, "MClk rate set failed (%d)\n", ret);
-		goto remove_host;
-	}
-
 	msm_host->msm_bus_vote.max_bus_bw.show = show_sdhci_max_bus_bw;
 	msm_host->msm_bus_vote.max_bus_bw.store = store_sdhci_max_bus_bw;
 	sysfs_attr_init(&msm_host->msm_bus_vote.max_bus_bw.attr);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index dcfe8a7..c247ae9 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1209,6 +1209,9 @@
 	if (real_div)
 		host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div;
 
+	if (host->quirks2 & SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK)
+		div = 0;
+
 	clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
 	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
 		<< SDHCI_DIVIDER_HI_SHIFT;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f3b39d4a..84672d7 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -32,6 +32,7 @@
 #include <linux/uaccess.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/qpnp-misc.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/regulator/consumer.h>
 #include <linux/power_supply.h>
@@ -2395,17 +2396,30 @@
 	if (msm->ext_xceiv.otg_capability) {
 		msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
 		if (msm->pmic_id_irq > 0) {
-			ret = devm_request_irq(&pdev->dev, msm->pmic_id_irq,
-					       dwc3_pmic_id_irq,
-					       IRQF_TRIGGER_RISING |
-					       IRQF_TRIGGER_FALLING,
-					       "dwc3_msm_pmic_id", msm);
-			if (ret) {
-				dev_err(&pdev->dev, "irqreq IDINT failed\n");
+			/* check if PMIC ID IRQ is supported */
+			ret = qpnp_misc_irqs_available(&pdev->dev);
+
+			if (ret == -EPROBE_DEFER) {
+				/* qpnp hasn't probed yet; defer dwc probe */
 				goto disable_hs_ldo;
+			} else if (ret == 0) {
+				msm->pmic_id_irq = 0;
+			} else {
+				ret = devm_request_irq(&pdev->dev,
+						       msm->pmic_id_irq,
+						       dwc3_pmic_id_irq,
+						       IRQF_TRIGGER_RISING |
+						       IRQF_TRIGGER_FALLING,
+						       "dwc3_msm_pmic_id", msm);
+				if (ret) {
+					dev_err(&pdev->dev, "irqreq IDINT failed\n");
+					goto disable_hs_ldo;
+				}
+				enable_irq_wake(msm->pmic_id_irq);
 			}
-			enable_irq_wake(msm->pmic_id_irq);
-		} else {
+		}
+
+		if (msm->pmic_id_irq <= 0) {
 			/* If no PMIC ID IRQ, use ADC for ID pin detection */
 			queue_work(system_nrt_wq, &msm->init_adc_work.work);
 			device_create_file(&pdev->dev, &dev_attr_adc_enable);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 207fbf3..dd41638 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -82,6 +82,7 @@
 	u8 clk_ena;
 	u8 fs_ena;
 	u8 vsync_ena;
+	unsigned long min_mdp_clk;
 
 	u32 res_init;
 	u32 bus_hdl;
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index abef27d..7dc4f49 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -333,6 +333,9 @@
 		return -ENODEV;
 	}
 
+	debugfs_create_u32("min_mdp_clk", 0644, mdd->root,
+		(u32 *)&mdata->min_mdp_clk);
+
 	mdata->debug_data = mdd;
 
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index a8eeec6..749afd8 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -520,11 +520,15 @@
 	return ret;
 }
 
-void mdss_mdp_set_clk_rate(unsigned long min_clk_rate)
+void mdss_mdp_set_clk_rate(unsigned long rate)
 {
 	struct mdss_data_type *mdata = mdss_res;
 	unsigned long clk_rate;
 	struct clk *clk = mdss_mdp_get_clk(MDSS_CLK_MDP_SRC);
+	unsigned long min_clk_rate;
+
+	min_clk_rate = max(rate, mdata->min_mdp_clk);
+
 	if (clk) {
 		mutex_lock(&mdp_clk_lock);
 		if (min_clk_rate < mdata->max_mdp_clk_rate)
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 43456ca..14c1e52 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -122,6 +122,7 @@
 	u32 flush_bits;
 
 	u32 play_cnt;
+	u32 underrun_cnt;
 
 	u16 width;
 	u16 height;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index e2c3b23..dab8674 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -244,12 +244,17 @@
 
 		rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_OFF, NULL);
 		WARN(rc, "intf %d timegen off error (%d)\n", ctl->intf_num, rc);
+
+		mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,
+			ctl->intf_num);
 	}
 
 	mdss_mdp_video_set_vsync_handler(ctl, NULL);
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
 				   NULL, NULL);
+	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+				   NULL, NULL);
 
 	ctx->ref_cnt--;
 	ctl->priv_data = NULL;
@@ -304,6 +309,17 @@
 	return rc;
 }
 
+static void mdss_mdp_video_underrun_intr_done(void *arg)
+{
+	struct mdss_mdp_ctl *ctl = arg;
+	if (unlikely(!ctl))
+		return;
+
+	ctl->underrun_cnt++;
+	pr_warn("display underrun detected for ctl=%d count=%d\n", ctl->num,
+			ctl->underrun_cnt);
+}
+
 static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
 {
 	struct mdss_mdp_video_ctx *ctx;
@@ -332,6 +348,8 @@
 		pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num);
 
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+		mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);
 		mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
 		wmb();
 
@@ -390,6 +408,8 @@
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
 				   mdss_mdp_video_vsync_intr_done, ctl);
+	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+				   mdss_mdp_video_underrun_intr_done, ctl);
 
 	itp.width = pinfo->xres + pinfo->lcdc.xres_pad;
 	itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 4699e0d..7ff6414 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -81,14 +81,22 @@
 
 static int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe)
 {
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 	u32 num_blks = 0, reserved = 0;
 	struct mdss_mdp_plane_sizes ps;
 	int i, rc;
 
-	rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format, pipe->src.w,
-				pipe->src.h, &ps);
-	if (rc)
-		return rc;
+	if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
+			pipe->src_fmt->is_yuv) {
+		ps.num_planes = 2;
+		ps.ystride[0] = pipe->src.w;
+		ps.ystride[1] = pipe->src.w;
+	} else {
+		rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
+				pipe->src.w, pipe->src.h, &ps);
+		if (rc)
+			return rc;
+	}
 
 	if ((ps.num_planes > 1) && (pipe->type == MDSS_MDP_PIPE_TYPE_RGB))
 		return -EINVAL;
@@ -98,7 +106,7 @@
 		num_blks = DIV_ROUND_UP(2 * ps.ystride[i],
 			mdss_res->smp_mb_size);
 
-		if (mdss_res->mdp_rev == MDSS_MDP_HW_REV_100)
+		if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
 			num_blks = roundup_pow_of_two(num_blks);
 
 		pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
@@ -124,7 +132,7 @@
 {
 	int i;
 	mutex_lock(&mdss_mdp_smp_lock);
-	for (i = 0; i < pipe->src_planes.num_planes; i++)
+	for (i = 0; i < MAX_PLANES; i++)
 		mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
 	mutex_unlock(&mdss_mdp_smp_lock);
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 1c0d306..077b4e4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -35,6 +35,10 @@
 	MDP_INTR_VSYNC_INTF_1,
 	MDP_INTR_VSYNC_INTF_2,
 	MDP_INTR_VSYNC_INTF_3,
+	MDP_INTR_UNDERRUN_INTF_0,
+	MDP_INTR_UNDERRUN_INTF_1,
+	MDP_INTR_UNDERRUN_INTF_2,
+	MDP_INTR_UNDERRUN_INTF_3,
 	MDP_INTR_PING_PONG_0,
 	MDP_INTR_PING_PONG_1,
 	MDP_INTR_PING_PONG_2,
@@ -56,6 +60,9 @@
 {
 	int index = -1;
 	switch (intr_type) {
+	case MDSS_MDP_IRQ_INTF_UNDER_RUN:
+		index = MDP_INTR_UNDERRUN_INTF_0 + (intf_num - MDSS_MDP_INTF0);
+		break;
 	case MDSS_MDP_IRQ_INTF_VSYNC:
 		index = MDP_INTR_VSYNC_INTF_0 + (intf_num - MDSS_MDP_INTF0);
 		break;
@@ -128,6 +135,18 @@
 	if (isr == 0)
 		goto mdp_isr_done;
 
+	if (isr & MDSS_MDP_INTR_INTF_0_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_0);
+
+	if (isr & MDSS_MDP_INTR_INTF_1_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_1);
+
+	if (isr & MDSS_MDP_INTR_INTF_2_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_2);
+
+	if (isr & MDSS_MDP_INTR_INTF_3_UNDERRUN)
+		mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_3);
+
 	if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE)
 		mdss_mdp_intr_done(MDP_INTR_PING_PONG_0);
 
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index add65ac..2341068 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -103,8 +103,6 @@
 	return postpone_send;
 }
 
-
-
 void mhl_msc_send_work(struct work_struct *work)
 {
 	struct mhl_tx_ctrl *mhl_ctrl =
@@ -202,7 +200,6 @@
 	return 0;
 }
 
-
 int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
 			 struct msc_command_struct *req)
 {
@@ -286,8 +283,6 @@
 	return 0;
 }
 
-
-
 int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
 			 u8 sub_cmd, u8 cmd_data)
 {
@@ -315,7 +310,6 @@
 	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_PRIORITY_SEND);
 }
 
-
 int mhl_msc_read_devcap(struct mhl_tx_ctrl *mhl_ctrl, u8 offset)
 {
 	struct msc_command_struct req;
@@ -340,7 +334,6 @@
 	return ret;
 }
 
-
 static void mhl_handle_input(struct mhl_tx_ctrl *mhl_ctrl,
 			     u8 key_code, u16 input_key_code)
 {
@@ -352,8 +345,6 @@
 	input_sync(mhl_ctrl->input);
 }
 
-
-
 int mhl_rcp_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 key_code)
 {
 	u8 index = key_code & 0x7f;
@@ -392,7 +383,6 @@
 	return 0;
 }
 
-
 static int mhl_rap_action(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
 {
 	switch (action_code) {
@@ -400,7 +390,14 @@
 		mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
 		break;
 	case MHL_RAP_CONTENT_OFF:
-		mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+		/*
+		 * instead of only disabling tmds
+		 * send power button press - CONTENT_OFF
+		 */
+		input_report_key(mhl_ctrl->input, KEY_VENDOR, 1);
+		input_sync(mhl_ctrl->input);
+		input_report_key(mhl_ctrl->input, KEY_VENDOR, 0);
+		input_sync(mhl_ctrl->input);
 		break;
 	default:
 		break;
@@ -413,9 +410,9 @@
 	u8 error_code;
 	bool tmds_en;
 
+	tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
 	switch (action_code) {
 	case MHL_RAP_POLL:
-		tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
 		if (tmds_en)
 			error_code = MHL_RAPK_NO_ERROR;
 		else
@@ -423,8 +420,12 @@
 		break;
 	case MHL_RAP_CONTENT_ON:
 	case MHL_RAP_CONTENT_OFF:
-		mhl_rap_action(mhl_ctrl, action_code);
-		error_code = MHL_RAPK_NO_ERROR;
+		if (tmds_en) {
+			mhl_rap_action(mhl_ctrl, action_code);
+			error_code = MHL_RAPK_NO_ERROR;
+		} else {
+			error_code = MHL_RAPK_UNSUPPORTED_ACTION_CODE;
+		}
 		break;
 	default:
 		error_code = MHL_RAPK_UNRECOGNIZED_ACTION_CODE;
@@ -437,7 +438,6 @@
 		error_code);
 }
 
-
 int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
 			 u8 sub_cmd, u8 cmd_data)
 {
diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h
index 41f7c29..2ad1ab2 100644
--- a/include/drm/kgsl_drm.h
+++ b/include/drm/kgsl_drm.h
@@ -86,7 +86,7 @@
 struct drm_kgsl_gem_create_from_ion)
 
 /* Maximum number of sub buffers per GEM object */
-#define DRM_KGSL_GEM_MAX_BUFFERS 2
+#define DRM_KGSL_GEM_MAX_BUFFERS 3
 
 /* Memory types - these define the source and caching policies
    of the GEM memory chunk */
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index f26b903..a5f36b5 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -110,7 +110,12 @@
 #define SDHCI_QUIRK2_SLOW_INT_CLR			(1<<2)
 /* Ignore CMD CRC errors for tuning commands */
 #define SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING		(1<<3)
-
+/*
+ * If the base clock can be scalable, then there should be no further
+ * clock dividing as the input clock itself will be scaled down to
+ * required frequency.
+ */
+#define SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK		(1<<4)
 
 	int irq;		/* Device IRQ */
 	void __iomem *ioaddr;	/* Mapped address */
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index a683ed4..95c4e6a 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -40,6 +40,7 @@
 	ION_CP_MFC_HEAP_ID = 12,
 	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
 	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+	ION_SYSTEM_CONTIG_HEAP_ID = 21,
 	ION_ADSP_HEAP_ID = 22,
 	ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
 	ION_SF_HEAP_ID = 24,
@@ -90,6 +91,7 @@
 
 #define ION_ADSP_HEAP_NAME	"adsp"
 #define ION_VMALLOC_HEAP_NAME	"vmalloc"
+#define ION_KMALLOC_HEAP_NAME	"kmalloc"
 #define ION_AUDIO_HEAP_NAME	"audio"
 #define ION_SF_HEAP_NAME	"sf"
 #define ION_MM_HEAP_NAME	"mm"
diff --git a/include/linux/qpnp-misc.h b/include/linux/qpnp-misc.h
new file mode 100644
index 0000000..b241e5d
--- /dev/null
+++ b/include/linux/qpnp-misc.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QPNP_MISC_H
+#define __QPNP_MISC_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_QPNP_MISC
+/**
+ * qpnp_misc_irqs_available - check if IRQs are available
+ *
+ * @consumer_dev: device struct
+ *
+ * This function returns true if the MISC interrupts are available
+ * based on a check in the MISC peripheral revision registers.
+ *
+ * Any consumer of this function needs to reference a MISC device phandle
+ * using the qcom,misc-ref in their device tree node.
+ */
+
+int qpnp_misc_irqs_available(struct device *consumer_dev);
+#else
+static int qpnp_misc_irq_available(struct device *consumer_dev)
+{
+	return 0;
+}
+#endif
+#endif
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 78d1749..80738ba 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -338,6 +338,7 @@
 	s32 dmic_5_6_clk_cnt;
 
 	u32 anc_slot;
+	bool anc_func;
 
 	/*track taiko interface type*/
 	u8 intf_type;
@@ -505,6 +506,56 @@
 	return 0;
 }
 
+static int taiko_get_anc_func(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = (taiko->anc_func == true ? 1 : 0);
+	return 0;
+}
+
+static int taiko_put_anc_func(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	mutex_lock(&dapm->codec->mutex);
+	taiko->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
+
+	dev_dbg(codec->dev, "%s: anc_func %x", __func__, taiko->anc_func);
+
+	if (taiko->anc_func == true) {
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
+		snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
+		snd_soc_dapm_enable_pin(dapm, "ANC EAR");
+		snd_soc_dapm_disable_pin(dapm, "HPHR");
+		snd_soc_dapm_disable_pin(dapm, "HPHL");
+		snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
+		snd_soc_dapm_disable_pin(dapm, "EAR PA");
+		snd_soc_dapm_disable_pin(dapm, "EAR");
+	} else {
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+		snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+		snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+		snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+		snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+		snd_soc_dapm_enable_pin(dapm, "HPHR");
+		snd_soc_dapm_enable_pin(dapm, "HPHL");
+		snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
+		snd_soc_dapm_enable_pin(dapm, "EAR PA");
+		snd_soc_dapm_enable_pin(dapm, "EAR");
+	}
+	snd_soc_dapm_sync(dapm);
+	mutex_unlock(&dapm->codec->mutex);
+	return 0;
+}
+
 static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -915,6 +966,15 @@
 		SOC_ENUM_SINGLE_EXT(2, taiko_ear_pa_gain_text),
 };
 
+static const char *const taiko_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum taiko_anc_func_enum =
+		SOC_ENUM_SINGLE_EXT(2, taiko_anc_func_text);
+
+static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum tabla_ear_pa_gain_enum[] = {
+		SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
+};
+
 /*cut of frequency for high pass filter*/
 static const char * const cf_text[] = {
 	"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
@@ -1054,8 +1114,10 @@
 	SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
 	SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
 
-	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, taiko_get_anc_slot,
+	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
 		taiko_put_anc_slot),
+	SOC_ENUM_EXT("ANC Function", taiko_anc_func_enum, taiko_get_anc_func,
+		taiko_put_anc_func),
 	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
 	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
 	SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
@@ -2184,101 +2246,6 @@
 	return 0;
 }
 
-static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	const char *filename;
-	const struct firmware *fw;
-	int i;
-	int ret;
-	int num_anc_slots;
-	struct anc_header *anc_head;
-	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
-	u32 anc_writes_size = 0;
-	int anc_size_remaining;
-	u32 *anc_ptr;
-	u16 reg;
-	u8 mask, val;
-
-	pr_debug("%s %d\n", __func__, event);
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-
-		filename = "wcd9320/wcd9320_anc.bin";
-
-		ret = request_firmware(&fw, filename, codec->dev);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
-				ret);
-			return -ENODEV;
-		}
-
-		if (fw->size < sizeof(struct anc_header)) {
-			dev_err(codec->dev, "Not enough data\n");
-			release_firmware(fw);
-			return -ENOMEM;
-		}
-
-		/* First number is the number of register writes */
-		anc_head = (struct anc_header *)(fw->data);
-		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
-		anc_size_remaining = fw->size - sizeof(struct anc_header);
-		num_anc_slots = anc_head->num_anc_slots;
-
-		if (taiko->anc_slot >= num_anc_slots) {
-			dev_err(codec->dev, "Invalid ANC slot selected\n");
-			release_firmware(fw);
-			return -EINVAL;
-		}
-
-		for (i = 0; i < num_anc_slots; i++) {
-
-			if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
-				dev_err(codec->dev, "Invalid register format\n");
-				release_firmware(fw);
-				return -EINVAL;
-			}
-			anc_writes_size = (u32)(*anc_ptr);
-			anc_size_remaining -= sizeof(u32);
-			anc_ptr += 1;
-
-			if (anc_writes_size * TAIKO_PACKED_REG_SIZE
-				> anc_size_remaining) {
-				dev_err(codec->dev, "Invalid register format\n");
-				release_firmware(fw);
-				return -ENOMEM;
-			}
-
-			if (taiko->anc_slot == i)
-				break;
-
-			anc_size_remaining -= (anc_writes_size *
-				TAIKO_PACKED_REG_SIZE);
-			anc_ptr += anc_writes_size;
-		}
-		if (i == num_anc_slots) {
-			dev_err(codec->dev, "Selected ANC slot not present\n");
-			release_firmware(fw);
-			return -ENOMEM;
-		}
-
-		for (i = 0; i < anc_writes_size; i++) {
-			TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
-				mask, val);
-			snd_soc_write(codec, reg, val);
-		}
-		release_firmware(fw);
-
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
-		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
-		break;
-	}
-	return 0;
-}
-
 static int taiko_codec_config_mad(struct snd_soc_codec *codec)
 {
 	int ret;
@@ -2780,6 +2747,106 @@
 	return 0;
 }
 
+static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	const char *filename;
+	const struct firmware *fw;
+	int i;
+	int ret;
+	int num_anc_slots;
+	struct anc_header *anc_head;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	u32 anc_writes_size = 0;
+	int anc_size_remaining;
+	u32 *anc_ptr;
+	u16 reg;
+	u8 mask, val, old_val;
+
+
+	if (taiko->anc_func == 0)
+		return 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		filename = "wcd9320/wcd9320_anc.bin";
+
+		ret = request_firmware(&fw, filename, codec->dev);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+				ret);
+			return -ENODEV;
+		}
+
+		if (fw->size < sizeof(struct anc_header)) {
+			dev_err(codec->dev, "Not enough data\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+
+		/* First number is the number of register writes */
+		anc_head = (struct anc_header *)(fw->data);
+		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+		anc_size_remaining = fw->size - sizeof(struct anc_header);
+		num_anc_slots = anc_head->num_anc_slots;
+
+		if (taiko->anc_slot >= num_anc_slots) {
+			dev_err(codec->dev, "Invalid ANC slot selected\n");
+			release_firmware(fw);
+			return -EINVAL;
+		}
+		for (i = 0; i < num_anc_slots; i++) {
+			if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -EINVAL;
+			}
+			anc_writes_size = (u32)(*anc_ptr);
+			anc_size_remaining -= sizeof(u32);
+			anc_ptr += 1;
+
+			if (anc_writes_size * TAIKO_PACKED_REG_SIZE
+				> anc_size_remaining) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -ENOMEM;
+			}
+
+			if (taiko->anc_slot == i)
+				break;
+
+			anc_size_remaining -= (anc_writes_size *
+				TAIKO_PACKED_REG_SIZE);
+			anc_ptr += anc_writes_size;
+		}
+		if (i == num_anc_slots) {
+			dev_err(codec->dev, "Selected ANC slot not present\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+		for (i = 0; i < anc_writes_size; i++) {
+			TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+				mask, val);
+			old_val = snd_soc_read(codec, reg);
+			snd_soc_write(codec, reg, (old_val & ~mask) |
+				(val & mask));
+		}
+		release_firmware(fw);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		msleep(40);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
+		snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
+		msleep(20);
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+		snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+		break;
+	}
+	return 0;
+}
+
 static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
 			      struct snd_kcontrol *kcontrol, int event)
 {
@@ -2835,6 +2902,46 @@
 	return 0;
 }
 
+static int taiko_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = taiko_hph_pa_event(w, kcontrol, event);
+		if (w->shift == 4) {
+			ret |= taiko_codec_enable_anc(w, kcontrol, event);
+			msleep(50);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (w->shift == 4) {
+			snd_soc_update_bits(codec,
+					TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x30);
+			msleep(30);
+		}
+		ret = taiko_hph_pa_event(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		if (w->shift == 5) {
+			snd_soc_update_bits(codec,
+					TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
+			msleep(40);
+		}
+		if (w->shift == 5) {
+			snd_soc_update_bits(codec,
+					TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
+			ret |= taiko_codec_enable_anc(w, kcontrol, event);
+		}
+	case SND_SOC_DAPM_POST_PMD:
+		ret = taiko_hph_pa_event(w, kcontrol, event);
+		break;
+	}
+	return ret;
+}
+
 static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
 	4, 0, NULL, 0),
@@ -3022,9 +3129,10 @@
 	{"EAR_PA_MIXER", NULL, "DAC1"},
 	{"DAC1", NULL, "RX_BIAS"},
 
+	{"ANC EAR", NULL, "ANC EAR PA"},
+	{"ANC EAR PA", NULL, "EAR_PA_MIXER"},
 	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
 	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
-	{"ANC", NULL, "ANC1 FB MUX"},
 
 	/* Headset (RX MIX1 and RX MIX2) */
 	{"HEADPHONE", NULL, "HPHL"},
@@ -3038,18 +3146,28 @@
 	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
 	{"HPHR DAC", NULL, "RX_BIAS"},
 
-	{"ANC", NULL, "ANC1 MUX"},
-	{"ANC", NULL, "ANC2 MUX"},
+	{"ANC HEADPHONE", NULL, "ANC HPHL"},
+	{"ANC HEADPHONE", NULL, "ANC HPHR"},
+
+	{"ANC HPHL", NULL, "HPHL_PA_MIXER"},
+	{"ANC HPHR", NULL, "HPHR_PA_MIXER"},
+
 	{"ANC1 MUX", "ADC1", "ADC1"},
 	{"ANC1 MUX", "ADC2", "ADC2"},
 	{"ANC1 MUX", "ADC3", "ADC3"},
 	{"ANC1 MUX", "ADC4", "ADC4"},
+	{"ANC1 MUX", "DMIC1", "DMIC1"},
+	{"ANC1 MUX", "DMIC2", "DMIC2"},
+	{"ANC1 MUX", "DMIC3", "DMIC3"},
+	{"ANC1 MUX", "DMIC4", "DMIC4"},
+	{"ANC1 MUX", "DMIC5", "DMIC5"},
+	{"ANC1 MUX", "DMIC6", "DMIC6"},
 	{"ANC2 MUX", "ADC1", "ADC1"},
 	{"ANC2 MUX", "ADC2", "ADC2"},
 	{"ANC2 MUX", "ADC3", "ADC3"},
 	{"ANC2 MUX", "ADC4", "ADC4"},
 
-	{"ANC", NULL, "CDC_CONN"},
+	{"ANC HPHR", NULL, "CDC_CONN"},
 
 	{"DAC1", "Switch", "CLASS_H_DSM MUX"},
 	{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
@@ -3095,8 +3213,8 @@
 
 	{"RX1 CHAIN", NULL, "RX1 MIX2"},
 	{"RX2 CHAIN", NULL, "RX2 MIX2"},
-	{"RX1 CHAIN", NULL, "ANC"},
-	{"RX2 CHAIN", NULL, "ANC"},
+	{"RX1 MIX2", NULL, "ANC1 MUX"},
+	{"RX2 MIX2", NULL, "ANC2 MUX"},
 
 	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
 	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
@@ -3429,6 +3547,14 @@
 		(reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
 		return 1;
 
+	/* ANC filter registers are not cacheable */
+	if ((reg >= TAIKO_A_CDC_ANC1_IIR_B1_CTL) &&
+		(reg <= TAIKO_A_CDC_ANC1_LPF_B2_CTL))
+		return 1;
+	if ((reg >= TAIKO_A_CDC_ANC2_IIR_B1_CTL) &&
+		(reg <= TAIKO_A_CDC_ANC2_LPF_B2_CTL))
+		return 1;
+
 	/* Digital gain register is not cacheable so we have to write
 	 * the setting even it is the same
 	 */
@@ -4457,6 +4583,32 @@
 	return 0;
 }
 
+static int taiko_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret = 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = taiko_codec_enable_anc(w, kcontrol, event);
+		msleep(50);
+		snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x10);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x00);
+		msleep(40);
+		ret |= taiko_codec_enable_anc(w, kcontrol, event);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+		break;
+	}
+	return ret;
+}
 
 /* Todo: Have seperate dapm widgets for I2S and Slimbus.
  * Might Need to have callbacks registered only for slimbus
@@ -4754,10 +4906,20 @@
 	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
 	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
 
-	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
-		taiko_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
-		SND_SOC_DAPM_POST_PMD),
-
+	SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
+	SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
+		taiko_codec_enable_anc_hph,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
+		taiko_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_OUTPUT("ANC EAR"),
+	SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+		taiko_codec_enable_anc_ear,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
 
 	SND_SOC_DAPM_INPUT("AMIC2"),
@@ -5700,6 +5862,14 @@
 	(void) taiko_setup_irqs(taiko);
 
 	atomic_set(&kp_taiko_priv, (unsigned long)taiko);
+	mutex_lock(&dapm->codec->mutex);
+	snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+	snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+	snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+	snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+	snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+	snd_soc_dapm_sync(dapm);
+	mutex_unlock(&dapm->codec->mutex);
 
 	codec->ignore_pmdown_time = 1;
 	return ret;